Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Gotchas when integrating with the Music and Video Hub in WP7

DZone's Guide to

Gotchas when integrating with the Music and Video Hub in WP7

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

If you are making a Windows Phone 7 app which can, or needs to, integrate with the Music & Video hub, Microsoft have provided some instructions on doing this:

http://windowsteamblog.com/windows_phone/b/wpdev/archive/2010/11/04/integrating-your-app-into-the-music-videos-hub.aspx
and
http://msdn.microsoft.com/en-us/library/ff769558(VS.92).aspx

There are however a few points which aren't currently (well) documented (yet):

MediaHistoryItem.Source


To integrate with the M + V Hub requires use of the MediaHistoryItem.

The MediaHistoryItem has a Source property which the Intellisense in Visual Studio tells us not to use:


If we don't set it though we get an error. Yes, even though we're told not to use it.
Infact, we have to set it to an empty string.

If we dig into the remarks for the property in MSDN we do find a note about this:
"Although this property is unsupported, you must set its value to "", meaning a blank string, whenever you instantiate a new MediaHistoryItem."

MediaHistoryItem.Title


Another property of the MediaHistoryItem is Title. This is a required property.

At this point it should be noted that there are 3 occasions to use the MediaHistoryItem: When adding a new item; When updating the Now Playing item; and when updating the recently played list.
For all of these scenarios you must set the Title to something, but it's only actually used when setting the "NowPlaying" item.


MediaHistoryItem.ImageStream


When specifying the stream of the image to use for the tile in the M + V hub, there is documentation about the Application Certification Requirements with regards to the images that are used but somewhat unhelpfully it's easy to miss that the stream must be smaller than the undocumented MaxImageSize.
This size is just 16KB.

System.ArgumentException: image stream size bigger than maximum allowed 16384

This may seem quite large for a an image just 358x358 or 173x173 pixels in size. (Your image will be resized and/or cropped if not the specified dimensions - but you may not get through Marketplace certification if you rely on this.)
You may hit an issue if you are using a complex image for the tile (which you have if using album artwork or a packshot image) and wish to maintain a high quality image.
If you have this issue you may wany to consider using a solider colour border around the image to allow you to maintain a higher image quality (meaning lower jpeg compression is needed).

MediaPlayerLauncher & WMDRM


MediaPlayerLauncher makes it easy to play WMV files from IsolatedStorage:

var mpl = new MediaPlayerLauncher
                {
                    Controls = MediaPlaybackControls.All,
                    Location = MediaLocationType.Data,
                    Media = new Uri("filename.wmv", UriKind.Relative)
                };
 
mpl.Show();
But if you're WMV file uses WMDRM, rather than PlayReady DRM then things get tricky.

Unfortunately, Silverlight doesn't support WMDRM, only PlayReady DRM.
Fortunately, Silverlight provides a way to override the use of WMDRM and use a PlayReady license server instead.
Unfortunatley, MediaPlayerLauncher doesn't support this.
Fortunately, one of the features of Silverlight 4 which was included in Silverlight on WP7 was the ability to support persistent PlayReady DRM licenses.

So what can we do?

Assuming we're able to issue persistent PlayReady licenses (a separate issue I won't discuss now) we can combine the use of MediaPlayerLauncher with the use of MediaElement.

We can use the MediaElement (which includes a LicenseAcquirer and in turn the LicenseServerUriOverride property) to get a PlayReady license.
<mediaelement name="forLicenseAcquisition" height="0" width="0" autoplay="False" mediafailed="forLicenseAcquisition_MediaFailed" mediaopened="forLicenseAcquisition_MediaOpened">
</mediaelement>
forLicenseAcquisition.LicenseAcquirer.LicenseServerUriOverride =
    new Uri(AppResources._RightManagerAddress + urlGetParams, UriKind.Absolute);
 
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
    var movieFileStream = store.OpenFile("filename.wmv", FileMode.Open, FileAccess.Read);
    forLicenseAcquisition.SetSource(movieFileStream);
 
    forLicenseAcquisition.Play();
}
Once the license has been received the MediaElement will start to play. We can then handle the event raised when the MediaElement starts to play.
In that handler we stop the playing via the MediaElement and then start it in the MediaPlayerLauncher.
private void forLicenseAcquisition_MediaOpened(object sender, RoutedEventArgs e)
{
    forLicenseAcquisition.Stop();
 
    // record that license acquired
 
    var mediaHistoryItem = new MediaHistoryItem();
    mediaHistoryItem.Title = "My Movie";
    mediaHistoryItem.Source = string.Empty; // Must be set but unused
 
    using (var store = IsolatedStorageFile.GetUserStoreForApplication())
    {
        mediaHistoryItem.ImageStream = store.OpenFile("tile_image.jpg", FileMode.Open, FileAccess.Read);
    }
 
    mediaHistoryItem.PlayerContext.Add("Movie_Title", "My Movie");
 
    MediaHistory.Instance.NowPlaying = mediaHistoryItem;
 
    var mpl = new MediaPlayerLauncher
    {
        Controls = MediaPlaybackControls.All,
        Location = MediaLocationType.Data,
        Media = new Uri("filename.wmv", UriKind.Relative)
    };
 
    mpl.Show();
}
This only works with a persistent license though. I don't see this being too much of an issue though as if the content is being loaded onto the device (phone) then the owner of the phone should (I would argue) be allowed to play the content at any time, even if they're not able to connect to the PlayReady server. (They will still need that connection the first time though.)

If doing this, it's also wise to handle the MediaElement Failed event in case there is a problem getting the license.
It's also wise to keep track of which content a license has been acquired for. This means that you can skip the need to use a MediaElement on future attempts to play the content. This means that content can be loaded and therefore start playing faster on subsequent times.

I hope someone will find the above useful. ;)

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}