1. Problem
You need to integrate your application with the Music-Videos hub in your Windows Phone 7 device.
2. Solution
You have to use methods and properties provided by MediaHistory and MediaHistoryItem classes.
3. How It Works
The Music-Videos hub is
an aggregator application available from the Windows Phone 7 operating
system. It groups all the applications installed on the phone that
reproduce media files such as music and videos. The Music-Videos hub is
composed of four sections:
Zune: Contains links to music, video, podcasts, radio, and the Marketplace
History: Contains recently played media and content from third-party providers
New: Contains recent media either uploaded to the phone or downloaded from the Marketplace
Marquee: Contains the list of applications that manage media
So the last section is very
interesting. How can your application be included in the Marquee section
of the Music-Videos hub? The MSDN official documentation says that the
use of MediaHistory and MediaHistoryItem classes in your application will be detected during the certification process. If the application is accepted, the WMAppManifest.xml file is modified and the HubType attribute is added to the App tag. In this case, the application name will appear in the Marquee section, and the user can execute it from there.
You can manually add the HubType="1" attribute to the App tag in the WMAppManifest.xml file within your project in order to test the integration between your application and the Music-Videos hub.
|
|
The application must be
developed to correctly respond to the Music-Videos hub interactions.
These interactions can be summarized as follows:
When a media file is
played, it appears as Now Playing in the History section, next the Zune
section. It appears as a 358×358 pixel image that you must provide in
your solution. This image should represent your application, and you
must provide a title for the media file being played.
When another media file starts playing, the old one has to be inserted into the History section.
When an item is picked from the History section, your application will be executed and a QueryString will be provided with the information you stored in the PlayerContext collection. Your application has to manage this query string information and play the related media.
When
your application is executed from the Marquee section and a media file
is already playing, the application has to continue playing that media.
Everything noted in the preceding list is available from the MediaHistoryItem and MediaHistory classes.
The MediaHistory class contains the Instance property, which returns the current instance of that class. Indeed, MediaHistory cannot be instantiated because it is a sealed class. After retrieving the instance of the MediaHistory class, you can use its methods to add items into the History section of the Music-Videos hub.
The WriteRecentPlay method writes a MediaHistoryItem item into the History section. The WriteAcquiredItem method writes the provided MediaHistoryItem into the New section.
Finally, the NowPlaying
property is used to set the item that is presently playing in the
Music-Videos hub. When the user selects the Now Playing icon in the hub,
the application will be executed again (please note that we haven't
said it is tombstoned). However, this time the QueryString collection property will contain the key/value pair you added via the PlayerContext property provided by the MediaHistoryItem class. You can retrieve its value in the OnNavigatedTo event handler so as to play the media again.
So you have encountered the first property from the MediaHistoryItem class. There are other very useful properties, such as ImageStream (whicht has to contain the image of 358×358 pixels, as stated in preceding bullet list).
The image cannot be
greater than 16 kilobytes. Otherwise, the following exception will
occur: "System.ArgumentException: image stream size bigger than maximum
allowed 16384."
|
|
The Title property
enables you to set the string that will be displayed over the NowPlaying
icon. Usually this will be set to the media name, such as a song's
name. Even when you specify the item in the History and the New
sections, you still have to set the Title property that will be displayed in the Now Playing section.
NOTE
There is another property called Source
that the official documentation defines as unsupported, but if you
don't set this property to an empty string, you will not be able to add
the item to the Music-Videos hub.
4. The Code
To demonstrate the Music-Videos hub integration, we have created the MusicVideosHubIntegration Silverlight for Windows Phone 7 application. As you already learned in the previous recipes, you have to add the Microsoft.Xna.Framework.dll assembly and a class implementing the IApplicationService interface to periodically call the Update static method from the FrameworkDispatcher class.
The MainPage.xaml
file contains just a label to show the author and song that is playing.
The application bar provides buttons to play, pause, and stop the song.
In MainPage.xaml.cs, the core of the application code resides in the OnNavigatedTo method and in the Play button's Click event handler.
The OnNavigatedTo
method is called when the application is either first launched or
resumed from a tombstone. The first operation to perform is to check
whether the Media Player is already playing a song. If it is, the
application must continue to play that song. The song can be retrieved
via the ActiveSong property from the MediaQueue class. In turn, a MediaQueue object can be retrieved by the Queue property from the MediaPlayer class. Next, if the QueryString
property contains the key you have previously stored, it means that the
application has been executed from the hub. We previously stored the
song index, so you can easily retrieve it by pointing to that index in
the Songs collection. Finally, you update the text shown in the user interface and the related buttons' images. Please note that the s variable is a Song class-level field that is set through different classes' methods.
protected override void
OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (MediaPlayer.State == MediaState.Playing)
{
s = MediaPlayer.Queue.ActiveSong;
}
else if (NavigationContext.QueryString.ContainsKey(_key))
{
s = library.Songs[int.Parse(NavigationContext.QueryString[_key])];
MediaPlayer.Play(s);
}
if (s != null)
{
tbSong.Text = "Now playing " + s.Artist + " " + s.Name;
btnPlay.IconUri = new Uri("/Images/appbar.transport.pause.rest.jpg",
UriKind.Relative);
}
base.OnNavigatedTo(e);
}
In the btnPlay_Click event handler, the main part of the code checks whether the Songs
variable is null. If it is, either the song has not been provided by
the hub or the user has stopped the song from playing. In either case, a
shuffle is done to retrieve a song to be played.
The next operation is calling the Play method from the MediaPlayer class and calling the UpdateNowPlaying and UpdateHistory methods that accomplish the main Music-Videos hub integration job.
private void btnPlay_Click(object sender, EventArgs e)
{
if (MediaPlayer.State == MediaState.Playing)
{
MediaPlayer.Pause();
}
else
{
MediaHistory history = MediaHistory.Instance;
if (s == null)
{
s = DoShuffle();
if (s == null)
{
MessageBox.Show("The media library doesn't contain songs");
return;
}
}
tbSong.Text = "Now playing " + s.Artist + " " + s.Name;
MediaPlayer.Play(s);
UpdateNowPlaying();
UpdateHistory();
}
}
These methods are pretty similar; you have to set mandatory properties of the MediaHistoryItem object and either call the WriteRecentPlay method or set the NowPlaying property from the MediaHistory class.
NOTE
You can't use the same MediaHistoryItem object, but you need to create more than one instance for each item you want to add in the hub's sections.
In the UpdateNowPlaying method, you use another way to retrieve the stream data composing the image: the StreamResourceInfo class. An object of this class is returned from the GetResourceStream static method provided by the Application class. The GetResourceStream static method accepts a URI object that specifies where to find the resource. The StreamResourceInfo class provides the Stream property containing the image's stream data that you can assign to the ImageStream property of the MediaHistoryItem class.
NOTE
We used a JPEG image so as to reduce the image definition and provide a compatible image size.
Finally, you set the Source and Title properties and you add the song index to the PlayerContext
collection so that when the song is requested from the hub, your
application can retrieve it from the query string. This new object is
assigned to the NowPlaying property of the MediaHistory object that is retrieved with the Instance static property.
private void UpdateNowPlaying()
{
MediaHistoryItem nowPlaying = new MediaHistoryItem();
StreamResourceInfo sri = Application.GetResourceStream(
new Uri("NowPlayingIcon.jpg", UriKind.Relative));
nowPlaying.ImageStream = sri.Stream;
nowPlaying.Source = "";
nowPlaying.Title = s.Name;
nowPlaying.PlayerContext.Add(_key, songIndex.ToString());
MediaHistory history = MediaHistory.Instance;
history.NowPlaying = nowPlaying;
}
The same code is used for the UpdateHistory method, except the final call is to the WriteRecentPlay method instead of the NowPlaying property setting.
private void UpdateHistory()
{
MediaHistoryItem historyItem = new MediaHistoryItem();
StreamResourceInfo sri = Application.GetResourceStream(
new Uri("NowPlayingIcon.jpg", UriKind.Relative));
historyItem.ImageStream = sri.Stream;
historyItem.Source = "";
historyItem.Title = s.Name;
historyItem.PlayerContext.Add(_key, songIndex.ToString());
MediaHistory history = MediaHistory.Instance;
history.WriteRecentPlay(historyItem);
}
5. Usage
For this recipe, you
need a physical device, because the emulator doesn't provide the
Music-Videos hub. From Visual Studio 2010, select the Windows Phone 7
Device target output and then press Ctrl+F5. The application deploys to
the physical device and runs, as shown in Figure 1.
You can press the Play button on
the application bar so that a random song from your media library is
picked and played. Now press the Start button and go to the Music-Videos
hub, and you should see in the Now Playing section the application icon
and the song title (see Figure 2).
Press the Now Playing icon
from the hub, and the application executes again playing the song. Now
press the Stop button and then the Play button again so that another
song is played. Stop that song and then press the hardware Start button.
Go to the Music-Videos hub and see that the History section is
populated with an item. Sadly, there is no title describing the item,
but by clicking it, you can discover that our application is running and
the first song is being played.