Creating a Playlist with WMDMApp
To create a new playlist in WMDMApp, first click the target device in the device list box in the left pane. The item list box in the right pane will display the contents of the device.
Select one or more items to include in the new playlist. (You can select multiple items by pressing the CTRL key while clicking items in the list box.) When you are finished selecting items, click the File menu, and then click CreatePlaylist. A new playlist object is created on the device and appears in the list box in the right pane.
To review the references contained in this newly created playlist or any playlist object on the device, right-click the playlist in the list box in the right pane, and then select Properties. In the properties dialog box, the references list box is populated with the names of the items referenced by this playlist.
WMDMApp can create and enumerate the item references contained in playlists. The following function, _OnCreatePlaylist, is responsible for the creation of a new playlist. It allocates and prepares an array of IWMDMStorage pointers corresponding to the items selected by the user, creates a playlist object, passes the array to SetReferences on the playlist object, and then frees the IWMDMStorage pointer array.
VOID _OnCreatePlaylist( WPARAM wParam, LPARAM lParam )
{
CProgress cProgress;
HRESULT hr = S_OK;
INT i;
INT *pnSelItems = NULL;
INT nNumSel = 0;
INT idxStg = 0;
WCHAR wszName[MAX_PATH] = L"DefaultPlaylistName";
BOOL fProgressVisible = FALSE;
IWMDMMetaData* pIWMDMMetaData = NULL;
IWMDMStorage3* pStg3 = NULL;
IWMDMStorageControl3* pStorageControl = NULL;
IWMDMStorage4* pPlaylist = NULL;
IWMDMStorage** ppIStorage = NULL;
// Get the number of selected items.
// Explain usage and exit if there are no items selected.
//
// Call with NULL instead of pnSelItems for prefix
g_cDevFiles.GetSelectedItems( NULL, &nNumSel );
if( 0 == nNumSel )
{
MsgBoxContainerUsage(L"Playlist");
goto lExit;
}
// Get a name for the playlist from the user.
INT_PTR nRet = DlgNamePlaylist(wszName);
ExitOnTrue(nRet == IDCANCEL);
// Allocate space to hold the selected items.
//
pnSelItems = new INT[ nNumSel ];
ExitOnNull( pnSelItems );
// Get the selected file(s) to delete.
//
ExitOnTrue( -1 == g_cDevFiles.GetSelectedItems(pnSelItems, &nNumSel) );
// Create a progress dialog box.
//
ExitOnFalse( cProgress.Create(g_hwndMain) );
fProgressVisible = TRUE;
// Set operation progress values.
//
cProgress.SetOperation( L"Creating playlist..." );
cProgress.SetRange( 0, nNumSel );
cProgress.SetCount( 0, nNumSel );
cProgress.SetBytes( -1, -1 );
ppIStorage = new IWMDMStorage*[nNumSel];
ExitOnNull( ppIStorage );
for( i=nNumSel-1; i >= 0; i-- )
{
CItemData *pStorage;
// Get the storage object for the item being added to the playlist.
//
pStorage = (CItemData *)ListView_GetLParam( g_cDevFiles.GetHwnd_LV(), pnSelItems[i] );
if( NULL != pStorage && NULL != pStorage->m_pStorage)
{
// Set the name of the object and show the progress dialog
//
cProgress.SetDetails( pStorage->m_szName );
ppIStorage[idxStg] = pStorage->m_pStorage;
ppIStorage[idxStg]->AddRef();
idxStg++;
}
cProgress.IncCount();
cProgress.IncPos( 1 );
cProgress.Show( TRUE );
}
if( idxStg )
{
HTREEITEM hItem = NULL;
CItemData* pItemData = NULL;
IWMDMStorage* pInStorage = NULL;
IWMDMStorage* pNewStorage = NULL;
// Get the selected device/storage.
//
hItem = g_cDevices.GetSelectedItem( NULL );
ExitOnNull( hItem );
// Get the itemdata class associated with the hItem and
// retrieve the IWMDMStorage for it.
//
pItemData = (CItemData *) TreeView_GetLParam( g_cDevices.GetHwnd_TV(), hItem );
ExitOnNull( pItemData );
pInStorage = ( pItemData->m_fIsDevice ? pItemData->m_pRootStorage : pItemData->m_pStorage );
ExitOnNull( pInStorage );
// Acquire the storage control interface.
//
hr = pInStorage->QueryInterface(
IID_IWMDMStorageControl3,
reinterpret_cast<void**>(&pStorageControl)
);
ExitOnFail(hr);
// Add an new album using abstract album type
// in the metadata for the new storage object.
DWORD dw = 0;
hr = pInStorage->QueryInterface(IID_IWMDMStorage3, (void **)&pStg3);
ExitOnFail(hr);
hr = pStg3->CreateEmptyMetadataObject(&pIWMDMMetaData);
ExitOnFail(hr);
dw = WMDM_FORMATCODE_ABSTRACTAUDIOVIDEOPLAYLIST;
hr = pIWMDMMetaData->AddItem(WMDM_TYPE_DWORD, g_wszWMDMFormatCode, (BYTE *)&dw, sizeof(dw));
ExitOnFail(hr);
hr = pStorageControl->Insert3(WMDM_MODE_BLOCK | WMDM_CONTENT_FILE,
0,
NULL,
wszName,
NULL,
NULL,
pIWMDMMetaData,
NULL,
&pNewStorage);
ExitOnFail(hr);
SafeRelease(pIWMDMMetaData);
hr = pNewStorage->QueryInterface( IID_IWMDMStorage4, reinterpret_cast<void**>(&pPlaylist));
pNewStorage->Release();
ExitOnFail(hr);
hr = pPlaylist->SetReferences(idxStg, ppIStorage);
ExitOnFail(hr);
CItemData *pItem = new CItemData;
if( pItem )
{
hr = pItem->Init( pPlaylist );
if( SUCCEEDED(hr) )
{
g_cDevFiles.AddItem( pItem );
}
else
{
delete pItem;
}
}
}
g_cDevices.UpdateSelection( NULL, FALSE );
lExit:
if (fProgressVisible)
{
cProgress.Show( FALSE );
cProgress.Destroy();
}
SafeRelease(pPlaylist);
SafeRelease(pStg3);
SafeRelease(pIWMDMMetaData);
SafeRelease(pStorageControl);
if( pnSelItems )
{
delete[] pnSelItems;
}
for (i = 0; i < idxStg; i++)
{
if (ppIStorage[i] != NULL)
{
ppIStorage[i]->Release();
ppIStorage[i] = NULL;
}
}
if (ppIStorage)
{
delete[] ppIStorage;
}
if (FAILED(hr))
{
MsgBoxDisplayError(hr);
}
}
Enumerating the references contained in a playlist item for display in the item properties dialog box is accomplished by the following function, UpdateReferenceList. First, it obtains the IWMDMStorage4 interface for the object in question. GetReferences retrieves an array of IWMDMStorage pointers that access the referenced objects. The reference list box is populated by looping through these reference objects, calling GetName on each and putting the resulting string into the references list box.
Notice that this function assumes that the selected object is a playlist type object and calls GetReferences. That is okay. If the object is not a playlist object, GetReferences returns 0 references for the object.
void UpdateReferenceList( HWND hDlg, CItemData* pItem )
{
HRESULT hr = S_OK;
IWMDMStorage* pStorage = NULL;
IWMDMStorage4* pPlaylist = NULL;
IWMDMStorage** ppReferences = NULL;
DWORD dwRefs = 0;
ExitOnNull(pItem);
ListBox_AddString(GetDlgItem(hDlg, IDC_REFERENCES), L"This item contains no references.");
if (pItem->m_fIsDevice || (NULL == pItem->m_pStorage))
{
return;
}
hr = pItem->m_pStorage->QueryInterface(IID_IWMDMStorage4, reinterpret_cast<void**>(&pPlaylist));
ExitOnFail(hr);
hr = pPlaylist->GetReferences(&dwRefs, &ppReferences);
ExitOnFail(hr);
ListBox_ResetContent(GetDlgItem(hDlg, IDC_REFERENCES));
for (DWORD i = 0; i < dwRefs; i++)
{
WCHAR wszName[MAX_PATH] = L"";
if (NULL != ppReferences[i])
{
hr = ppReferences[i]->GetName(wszName, MAX_PATH);
if (SUCCEEDED(hr))
{
ListBox_AddString(GetDlgItem(hDlg, IDC_REFERENCES), wszName);
}
}
}
lExit:
SafeRelease(pPlaylist);
if (ppReferences)
{
for (i = 0; i < dwRefs; i++)
{
SafeRelease(ppReferences[i]);
}
::CoTaskMemFree(ppReferences);
}
}
See Also