A playlist (.WPL, .M3U, etc.) is a text file which contains a list of filenames. This list is the "playlist". So transferring the playlist should be easy right? Well, yes it is - if you just want to transfer it as a text file...
However if you want the playlist semantics to be sent to the device as well, you need to go an extra step (well, several extra steps :). Let's take a look.
A .WPL playlist in WPD is an object of format WPD_OBJECT_FORMAT_WPLPLAYLIST. Similar WPD formats exist for .M3U, .MPL, .ASX, etc. To associate tracks with the playlist, you must make use of the WPD_OBJECT_REFERENCES parameter. The WPD_OBJECT_REFERENCES parameter is available for most container-style formats. It is of type IPortableDevicePropVariantCollection.
Now even though WPD_OBJECT_REFERENCES is of type IPortableDevicePropVariantCollection, it can only legally hold PROPVARIANTs of a specific vartype i.e. VT_LPWSTR. Each string must correspond to a valid WPD object ID - these will be the object IDs that you want to associate with the playlist.
Store | |-- o1 (Happy.wma) [WPD_OBJECT_FORMAT_WMA] |-- o2 (Sad.wma) [WPD_OBJECT_FORMAT_WMA]
Store | |-- o1 (Happy.wma) |-- o2 (Sad.wma) |-- o3 (Emotions.wpl) [WPD_OBJECT_FORMAT_WPLPLAYLIST]
LPWSTR pwszPlaylistObject = NULL; if (hr == S_OK) { // IMP: Add your code to transfer an object to the device and get back // a WPD object handle. We are assigning o3 just for this example pwszPlaylistObject = L"o3"; } CComPtr<IPortableDeviceProperties> spProperties; if (hr == S_OK) { // IMP: Add your code to obtain the Properties interface from the // Device interface } CComPtr<IPortableDeviceValues> spValues; CComPtr<IPortableDevicePropVariantCollection> spReferences; if (hr == S_OK) { // IMP: Add your code to CoCreate spValues and spReferences here } // Add o1 and o2 for the references 0 - your code will probably have // a list of object IDs that you obtained prior by enumeration PROPVARIANT pv = {0}; if (hr == S_OK) { pv.vt = VT_LPWSTR; pv.pwszVal = L"o1"; hr = spReferences->Add(&pv); } if (hr == S_OK) { pv.vt = VT_LPWSTR; pv.pwszVal = L"o2"; hr = spReferences->Add(&pv); } // Add the references to the values collection to send to the device if (hr == S_OK) { hr = spValues->SetIPortableDevicePropVariantCollectionValue( WPD_OBJECT_REFERENCES, spReferences); } // Set the references property on the Playlist object CComPtr<IPortableDeviceValues> spResults; if (hr == S_OK) { hr = spProperties->SetValues(pwszPlaylistObject, spValues, &spResults); }
Briefly - you need to create an instance of a PropVariantCollection and add the object IDs that need to be part of the playlist to that collection. Next add that PropVariantCollection to the Values bag that we need to send down to the device. Be sure to specify the REFERENCES propertykey. Finally, use the SetValues API call to send the new value to the device.
Note that:
As a curiosity, when you transfer the playlist object to the device, you can transfer just a 0-sized object using CreateObjectWithPropertiesOnly and skip the data since it isn't going to be processed by the device anyway.