The phone can store music, pictures, and
video. From the user’s perspective, these are stored in the Music and
Videos hub and the Pictures hub. You can work with these hubs in several
ways. You can access the music in the Music and Videos hub, you can
access the pictures in the Pictures hub, and you can register your
application to be included in both of these hubs.
1. Accessing Music
You can access the music on the phone directly using the MediaLibrary
class in the Microsoft.Xna.Framework
assembly. This class belongs to the Microsoft.Xna.Framework.Media
namespace. To use the MediaLibrary
class, you have to create an instance of the class. The default (that
is, empty) constructor creates an instance that contains a list of the
media on the phone itself. This class supports IDisposable
, so you must use care in calling Dispose
when you’re done with the class (usually via the using
clause):
using (var library = new MediaLibrary())
{
// use media library
}
Emulator Tip
The emulator doesn’t have any media. You should use an actual device to test the media library functionality.
The music library consists of the following types of objects:
• Artist: This is the name of the performer of a song or album.
• Album: This is a collection of songs from one or more artists.
• Genre: This is a named category for songs and albums.
• Song: This is a single piece of music that can belong to a genre, album, and artist.
• Playlist: This is a user-defined list of songs.
The MediaLibrary
class exposes these types of objects into collections that can be navigated (as shown in Figure 1). Although these are discrete collections, they each contain all the music in the collection.
FIGURE 1 Music library objects
On the MediaLibrary
class, each of these objects is exposed as collections (that support IEnumerable
), so simple iteration is straightforward:
using (var library = new MediaLibrary())
{
// use media library
foreach (var artist in library.Artists)
{
theList.Items.Add(artist.Name);
}
}
Because these collections support IEnumerable
, we can use LINQ against these as well:
using (var library = new MediaLibrary())
{
var qry = from artist in library.Artists
where artist.Name == "Shawn Twain"
select artist;
var shawn = qry.FirstOrDefault();
if (shawn != null)
{
// Retrieve the songs for that artist.
var hisSongs = shawn.Songs;
}
}
As this example shows, after you retrieve the
artist you’re looking for you can use the songs for a particular artist,
album, or genre. You can also add and delete from
the list of songs, but this functionality is implemented as extension
methods so you have to add the right namespace to get the APIs for
adding and deleting: Microsoft.Xna.Framework.Media.PhoneExtensions
.
After you have those extension methods, you can call SaveSong
to add a song:
using (var library = new MediaLibrary())
{
var meta = new SongMetadata()
{
Name = "Anne",
ArtistName = "Shawn Twain",
AlbumReleaseDate = DateTime.Parse("04/24/2000"),
AlbumArtistName = "Shawn Twain",
Duration = TimeSpan.FromSeconds(254),
TrackNumber = 4
};
library.SaveSong(new Uri("/Assets/02-anne.mp3", UriKind.Relative),
meta,
SaveSongOperation.CopyToLibrary);
}
Before you can add the song, you must first create a SongMetadata
object that contains information about the song, as shown here. After you have that, you can call SaveSong
to add the song to the library. The last parameter must specify whether
you want to copy or move the song (when your source to the song is in
the isolated storage).
You can also remove a song from the library using the Delete
method:
using (var library = new MediaLibrary())
{
var song = library.Songs.First();
library.Delete(song);
}
As you can see here, you must have a Song
object from the library and then call the Delete
method to remove it from the library.
2. Playing Music
Also built in to XNA’s media functionality is access to the media player on the phone, via the MediaPlayer
class. This is a static class that gives you access to what is playing
currently and allows you to queue up songs to be played. Because the
class throws events, you need to update the FrameworkDispatcher
:
public partial class MainPage : PhoneApplicationPage
{
DispatcherTimer _xnaTimer = new DispatcherTimer();
// Constructor
public MainPage()
{
InitializeComponent();
// Because we're using XNA's MediaPlayer, we need to
// Use the FrameworkDispatcher to allow events
_xnaTimer.Interval = TimeSpan.FromMilliseconds(50);
_xnaTimer.Tick += (s, a) => FrameworkDispatcher.Update();
_xnaTimer.Start();
}
...
}
After you do that, you can use the MediaPlayer
class to play a song:
using (var library = new MediaLibrary())
{
var qry = from artist in library.Artists
where artist.Name == "Shawn Twain"
select artist;
var shawn = qry.FirstOrDefault();
if (shawn != null)
{
// Retrieve the songs for that artist.
var hisSongs = shawn.Songs;
if (MediaPlayer.State != MediaState.Playing)
{
MediaPlayer.Play(hisSongs[0]);
}
}
}
You need to check the state of the MediaPlayer
before you can play new songs, but as long as a song isn’t currently playing, you can just play it by supplying the Song
object to the media player. If you have songs you want to play that are
not in the media library, you can create your own song objects using
the FromUri
static method:
var mySong = Song.FromUri("Bridges and Ghosts",
new Uri("song.mp3", UriKind.Relative));
if (MediaPlayer.State != MediaState.Playing)
{
MediaPlayer.Play(mySong);
}
The FromUri
method will take a
relative URI that picks up songs in your .xap file or an absolute URI to
add songs from anywhere on the Internet.
You can also supply a SongCollection
to play the entire collection:
// Retrieve the songs for that artist.
var hisSongs = shawn.Songs;
if (MediaPlayer.State != MediaState.Playing)
{
MediaPlayer.Play(hisSongs);
}
You are limited to playing only the SongCollection
s that already exist (for example, MediaLibrary
.Songs
, Artist
.Songs
, Playlist
.Songs
, and so on). There is no facility for creating your own list of songs to integrate with the MediaPlayer
class.
Playing Songs from Isolated Storage