Randomizing a Playlist
You can randomize a playlist to change the user experience each time a client connects. The following example illustrates how to randomly order the media elements in a playlist. The Shuffle subroutine is called recursively so that all nested child elements of a media element are also randomly ordered.
Visual Basic .NET Example
Imports Microsoft.WindowsMediaServices.Interop
Imports interop_msxml
Private Sub RandomizePlylst()
' Declare variables.
Dim Playlist As IXMLDOMDocument
Dim Root_Node As IXMLDOMNode
Dim Server As WMSServer
Try
' Create the WMSServer object.
Server = New WMSServer()
' Load an existing playlist.
Playlist = Server.CreatePlaylist
Playlist.load("c:\wmpub\wmroot\Playlist.wsx")
' Find the root node. The root node is the smil element.
Root_Node = Playlist.documentElement
' Call the Shuffle() subroutine.
Call Shuffle(Root_Node)
' Save the modified playlist.
Playlist.save("c:\wmpub\wmroot\ModifiedPlaylist.wsx")
Catch Err As Exception
' TODO: Exception handler goes here.
Finally
' TODO: Clean-up code goes here.
End Try
End Sub
Private Sub Shuffle(ByVal ParentNode As IXMLDOMNode)
' Declare variables.
Dim bHasChildren As Boolean
Dim ChildList As IXMLDOMNodeList
Dim lNumChildren As Long
Dim lNumChildrenInArray As Long
Dim lIndex As Long
Dim ChildNode As IXMLDOMNode
Dim NextRandomChildNode As IXMLDOMNode
Dim OldChild As IXMLDOMNode
Dim RandomList() As IXMLDOMNode
Try
' Determine whether the parent node has children. If so,
' the children must be shuffled. Exit the subroutine if
' the parent has no children.
bHasChildren = ParentNode.hasChildNodes
If Not bHasChildren Then Exit Sub
' Retrieve the child nodes.
ChildList = ParentNode.childNodes
lNumChildren = ChildList.length
If lNumChildren = 0 Then Exit Sub
' Dimension the RandomList() array.
ReDim RandomList(lNumChildren - 1)
' Remove all of the children so that you can
' insert them back later in a different order.
For lIndex = 0 To lNumChildren - 1
' When you remove a child, the number of children
' is decremented by one. Therefore, you must
' delete the first child.
ChildNode = ChildList.item(0)
OldChild = ParentNode.removeChild(ChildNode)
' Recursively randomize all children of the child
' element.
Call Shuffle(ChildNode)
' Store the children in an array.
RandomList(lIndex) = ChildNode
ChildNode = Nothing
Next
' Initialize the random number generator.
Randomize()
' Randomly insert each child into the playlist.
lNumChildrenInArray = lNumChildren
Do While lNumChildrenInArray > 0
' Randomly pick a child to insert.
lIndex = Int((lNumChildrenInArray - 1) * Rnd())
NextRandomChildNode = RandomList(lIndex)
' Append the child to the parent node.
OldChild = Nothing
OldChild = ParentNode.appendChild(NextRandomChildNode)
' Compact the child node list.
If lIndex = lNumChildrenInArray - 1 Then
RandomList(lIndex) = Nothing
Else
RandomList(lIndex) = Nothing
RandomList(lIndex) = RandomList(lNumChildrenInArray - 1)
RandomList(lNumChildrenInArray - 1) = Nothing
End If
' Decrement the loop counter.
lNumChildrenInArray = lNumChildrenInArray - 1
Loop
Catch Err As Exception
' TODO: Exception handler goes here.
Finally
' TODO: Clean-up code goes here.
End Try
End Sub
C# Example
using Microsoft.WindowsMediaServices.Interop;
using interop_msxml;
private void Randomize()
{
// Declare variables.
IXMLDOMDocument Playlist;
IXMLDOMNode Root_Node;
WMSServer Server;
try
{
// Create the WMSServer object.
Server = new WMSServerClass();
// Load an existing playlist.
Playlist = Server.CreatePlaylist();
Playlist.load("c:\\wmpub\\wmroot\\Playlist.wsx");
// Find the root node. The root node is the smil element.
Root_Node = Playlist.documentElement;
// Call the Shuffle() subroutine.
Shuffle(Root_Node);
// Save the modified playlist.
Playlist.save("c:\\wmpub\\wmroot\\ModifiedPlaylist.wsx");
}
catch (Exception)
{
// TODO: Exception handler goes here.
}
finally
{
// TODO: Clean-up code goes here.
}
}
private void Shuffle(IXMLDOMNode ParentNode)
{
// Declare variables.
bool bHasChildren;
long lNumChildren;
long lNumChildrenInArray;
long lIndex;
Random r = new Random();
IXMLDOMNodeList ChildList;
IXMLDOMNode ChildNode;
IXMLDOMNode NextRandomChildNode;
IXMLDOMNode OldChild;
IXMLDOMNode[] RandomList;
try
{
// Determine whether the parent node has children. If so,
// the children must be shuffled. Exit the subroutine if
// the parent has no children.
bHasChildren = ParentNode.hasChildNodes();
if (!bHasChildren)
return;
// Retrieve the child nodes.
ChildList = ParentNode.childNodes;
lNumChildren = ChildList.length;
if (lNumChildren == 0)
return;
// Dimension the RandomList() array.
RandomList = new IXMLDOMNode[lNumChildren];
// Remove all of the children so that you can
// insert them back later in a different order.
for (lIndex=0; lIndex<lNumChildren; lIndex++)
{
// When you remove a child, the number of children
// is decremented by one. Therefore, you must
// delete the first child.
ChildNode = ChildList[0];
OldChild = ParentNode.removeChild(ChildNode);
// Recursively randomize all children of the child
// element.
Shuffle(ChildNode);
// Store the children in an array.
RandomList[lIndex] = ChildNode;
ChildNode = null;
}
// Randomly insert each child into the playlist.
lNumChildrenInArray = lNumChildren;
while (lNumChildrenInArray > 0)
{
// Randomly pick a child to insert.
lIndex = r.Next(0, (int)(lNumChildrenInArray - 1));
NextRandomChildNode = RandomList[lIndex];
// Append the child to the parent node.
OldChild = null;
OldChild = ParentNode.appendChild(NextRandomChildNode);
// Compact the child node list.
if (lIndex == lNumChildrenInArray - 1)
{
RandomList[lIndex] = null;
}
else
{
RandomList[lIndex] = null;
RandomList[lIndex] = RandomList[lNumChildrenInArray - 1];
RandomList[lNumChildrenInArray - 1] = null;
}
// Decrement the loop counter.
lNumChildrenInArray = lNumChildrenInArray - 1;
}
}
catch (Exception)
{
// TODO: Exception handler goes here.
}
finally
{
// TODO: Clean-up code
}
}
C++ Example
// Include header files.
#include <windows.h>
#include "wmsserver.h"
#include <atlbase.h> // Includes CComBSTR and CComVariant.
#include <time.h>
// Declare functions.
void Randomize();
void Shuffle(IXMLDOMNode *pParentNode);
void Randomize()
{
// Declare variables.
IXMLDOMDocument *pPlaylist;
IXMLDOMNode *pRoot_Node;
IWMSServer *pServer;
CComVariant varFile, varPath;
VARIANT_BOOL bVal;
HRESULT hr;
// Initialize the COM library and retrieve a pointer
// to an IWMSServer interface.
hr = CoInitialize(NULL);
if (FAILED(hr)) goto EXIT;
hr = CoCreateInstance(CLSID_WMSServer,
NULL,
CLSCTX_ALL,
IID_IWMSServer,
(void **)&pServer);
if (FAILED(hr)) goto EXIT;
// Create a playlist object.
hr = pServer->CreatePlaylist(&pPlaylist);
if (FAILED(hr)) goto EXIT;
// Load an existing playlist.
varFile = "c:\\wmpub\\wmroot\\playlist.wsx";
hr = pPlaylist->load(varFile, &bVal);
if (FAILED(hr)) goto EXIT;
// Find the root node. The root node of a server-side
// playlist must be the smil element.
hr = pPlaylist->get_documentElement((IXMLDOMElement**)&pRoot_Node);
if (FAILED(hr)) goto EXIT;
// Call the Shuffle() subroutine.
Shuffle(pRoot_Node);
// Save the playlist.
varPath = "c:\\wmpub\\wmroot\\modifiedplaylist.wsx";
hr = pPlaylist->save(varPath);
if (FAILED(hr)) goto EXIT;
EXIT:
// TODO: Release temporary COM objects and uninitialize COM.
return;
}
void Shuffle(IXMLDOMNode *pParentNode)
{
// Declare variables.
IXMLDOMNodeList *pChildList;
IXMLDOMNode *pChildNode, *pNextRandomChildNode, *pOldChild, *pRandomList[256];
VARIANT_BOOL bHasChildren;
long lNumChildren, lNumChildrenInArray, lIndex, iFound[256];
HRESULT hr;
double r,x;
bool bFound = true;
int i;
// Initialize the array of "found" random integers to -1.
for (i=0; i<256; i++)
{
iFound[i] = -1;
}
// Determine whether the parent node has children. If so,
// the children must be shuffled. Exit the subroutine if
// the parent has no children.
hr = pParentNode->hasChildNodes(&bHasChildren);
if (FAILED(hr)) goto EXIT;
if (!bHasChildren)
return;
// Retrieve the child nodes.
hr = pParentNode->get_childNodes(&pChildList);
hr = pChildList->get_length(&lNumChildren);
if (FAILED(hr)) goto EXIT;
if (lNumChildren == 0)
return;
// Remove all of the children so that you can
// insert them back later in a different order.
for (lIndex=0; lIndex<lNumChildren; lIndex++)
{
// When you remove a child, the number of children
// is decremented by one. Therefore, you must
// delete the first child.
hr = pChildList->get_item(0, &pChildNode);
hr = pParentNode->removeChild(pChildNode, &pOldChild);
if (FAILED(hr)) goto EXIT;
// Recursively randomize all children of the child
// element.
Shuffle(pChildNode);
// Store the children in an array.
pRandomList[lIndex] = pChildNode;
pChildNode = NULL;
}
// Randomly insert each child into the playlist.
srand((unsigned)time(NULL));
lNumChildrenInArray = lNumChildren;
while (lNumChildrenInArray > 0)
{
// Randomly pick a child to insert.
do
{
r = ((double)rand() / (double)(RAND_MAX+1));
x = (r * (lNumChildren));
lIndex = (long)x;
// Search for the index value.
for (i=0; i<256; i++)
{
if (lIndex == iFound[i])
{
bFound = true;
break;
}
}
if (i == 256)
bFound = false;
} while (bFound == true);
// Reset bFound for the next iteration
bFound = true;
// Place the new index in the iFound array. This array
// identifies all of the random values used.
for (i=0; i<256; i++)
{
if (iFound[i] == -1)
{
iFound[i] = lIndex;
break;
}
}
pNextRandomChildNode = pRandomList[lIndex];
// Append the child to the parent node.
pOldChild = NULL;
pParentNode->appendChild(pNextRandomChildNode, &pOldChild);
// Decrement the loop counter.
lNumChildrenInArray = lNumChildrenInArray - 1;
}
EXIT:
// TODO: Release temporary COM objects and uninitialize COM.
return;
}
See Also (General)
See Also (Visual Basic .NET)
IWMSServerIWMSServer Object (Visual Basic .NET)
IXMLDOMDocumentIXMLDOMDocument Object (Visual Basic .NET)
IXMLDOMElementIXMLDOMElement Object (Visual Basic .NET)
IXMLDOMNodeListIXMLDOMNodeList Object (Visual Basic .NET)
See Also (C#)
IWMSServerIWMSServer Object (C#)
IXMLDOMDocumentIXMLDOMDocument Object (C#)
IXMLDOMElementIXMLDOMElement Object (C#)
IXMLDOMNodeListIXMLDOMNodeList Object (C#)
See Also (C++)
IWMSServerIWMSServer Interface
IXMLDOMDocumentIXMLDOMDocument Interface
IXMLDOMElementIXMLDOMElement Interface
IXMLDOMNodeListIXMLDOMNodeList Interface