The custom audio player agent for
this section includes a simple playlist, which includes both locally
stored and remote audio files. The class is called BackgroundAudioPlayerAgent
,
and it is located in the WPUnleashed.BackgroundAudio project, within
the BackgroundAudio solution in the downloadable sample code.
A static list of audio tracks defines the playlist, shown in the following excerpt:
static readonly List<AudioTrack> playList
= new List<AudioTrack>
{
new AudioTrack(new Uri("AudioFiles/Audio01.wma",
UriKind.Relative),
"Ringtone 1", // title
"Windows Phone", // artist
"Windows Phone Ringtones", // album
null),
/* ... */
/* A remote URI. */
new AudioTrack(new Uri("http://example.com/track.mp3",
UriKind.Absolute),
"Episode 29",
"Windows Phone Radio",
"Windows Phone Radio Podcast",
null)
};
Tip
AudioPlayerAgents
remain active during playback. This allows the creation of dynamic
playlists. During playback, you could retrieve a playlist on a
background thread from a remote server.
If providing playback of local media files,
the files must be copied to isolated storage before they can be played
by the background audio player. The IIsolatedStorageUtility
is a custom interface that abstracts access to isolated storage. It is used by the BackgroundAudioPlayerAgent
to detect whether the media files have already been written to isolated
storage; if not, it is used to copy the sample files. The downloadable
sample code contains all the code for the IIsolatedStorageUtility
and its default implementation IsolatedStorageUtility
. See the following excerpt:
internal static void CopyAudioToIsolatedStorage(
IIsolatedStorageUtility isolatedStorageUtility)
{
ArgumentValidator.AssertNotNull(
isolatedStorageUtility, "isolatedStorageUtility");
/* If a file exists, do not copy. */
if (isolatedStorageUtility.FileExists("AudioFiles/Audio01.wma"))
{
return;
}
string[] files = new[] { "Audio01.wma", "Audio02.wma", "Audio03.wma" };
var sourceToDestinations = from file in files
let path = "AudioFiles/" + file
select new KeyValuePair<string, string>(path, path);
isolatedStorageUtility.CopyApplicationResourcesToIsolatedStorage(
sourceToDestinations);
}
The custom BackgroundAudioPlayerAgent
keeps track of the current track number using a static int
field. This is made possible because, unlike its ScheduledTaskAgent
counterpart, the process for an AudioPlayerAgent
is not terminated when NotifyComplete
is called.
The track number field is used to select the correct track to play when the user requests the previous or next track, as shown:
void PlayNextTrack(BackgroundAudioPlayer player)
{
if (++trackNumber >= playList.Count)
{
trackNumber = 0;
}
PlayTrack(player);
}
void PlayPreviousTrack(BackgroundAudioPlayer player)
{
if (--trackNumber < 0)
{
trackNumber = playList.Count - 1;
}
PlayTrack(player);
}
A PlayTrack
method is used to toggle the play state of the BackgroundAudioPlayer
, as shown:
void PlayTrack(BackgroundAudioPlayer player)
{
if (player.PlayerState == PlayState.Paused)
{
player.Play();
}
else
{
player.Track = playList[trackNumber];
}
}
During playback, when the BackgroundAudioPlayer.Track
property is set, the track does not begin immediate playback, but rather the BackgroundAudioPlayer
is placed into a TrackReady
state, and the AudioPlayerAgent.OnPlayStateChanged
method is called. You see how this fits together in a moment.