Windows phone has various media related classes which have proven to be very confusing for new developers. This article will try to shed some light on the matter and hopefully answer most questions beginners might have.

But before that, we need to define some terminology.

The media library is defined as the place where music, pictures and videos are stored in the phone. This is a special folder where apps only have limited access to.

The isolated storage is that place where the app can save things it needs to work properly.

The system media player is the media player which comes with the music+video hub.

A track is a music file located in the app’s isolated storage or outside the media library, whereas a “song” is a …music file located in the user’s media library

 

Capabilities

Developers can access the following data from their apps

  • The user song metadata.
  • Play one song or collections of songs.
  • Play tracks from remote servers, or from the app isolated storage.
  • Play videos from app’s isolated storage or from remote server.
  • Save songs in the user media library.

Developers cannot do the following

  • Access the stream of bytes belonging to a song outside the app’s isolated storage.
  • Read songs streams from the user’s music folder.
  • Access the user videos.
  • Save videos to media library.
  • Multiple media objects cannot play at the same time.

 

The SDK has several objects which apparently do the same thing. However, each object has a specialized task which it does better than the others.

Media Element

A media element is the only object which is part of the visual tree. This becomes an actual requirement in order for it to work. If the media element is not an object in the visual tree, it simply won’t work.

The main purpose of the media element is to play videos or music while the application is in the foreground. The media element will stop working when the application is deactivated.

There are also limitations on what videos it can play, regarding their frame per second and resolution.

The media element can implement media stream sources to play file formats which are not supported natively by windows phone.

Some interesting facts about the media element class

  • There can only be one media element playing at the same time
  • The media element cannot play more than 1 audio stream at the same time (use the SoundEffect class instead).
  • The media element can only play one audio stream and one video stream.

The Media Player launcher class

This is a launcher object which launches the system media player to play a song or a video. It is similar to a media element, however, it can’t implement media stream sources, and the application will be deactivated while the task is running.

 

The SoundEffect class

This class is mostly used to play quick sounds. It is the only way multiple sounds can be overlapped. However, it provides a fire and forget mechanism for playing WAV files only (short wav files). This is mostly used in games to play sounds when interacting with the UI.

The MediaPlayer class

Unlike the classes presented so far, the MediaPlayer is the first object to actually run in the background and the only object which has some degree of access to the user media library. It is used to play a song, or an existing playlist. Playlists are either generated automatically (songs are grouped by artist, album and genre) or a playlist which the user already created using the music+video hub.

Basically, the media player controls the system media player. While it brings the flexibility to use the user media library and its associated mechanisms, it is very rigid otherwise: you cannot create new playlists, and all its events won’t be registered unless the app is in the foreground and has an active FrameworkDispatcherService object running.

Apps cannot change the active queue after it has been set, without setting a new one. The Queue property of the MediaPlayer is immutable. So are all the SongCollection objects it needs in order to play. One can obtain these objects by using the MediaLibrary class.

All in all, the MediaPlayer class provides the following:

  • “Play only” access to user songs and playlists.
  • Start, stop, skip next and skip previous functions.
  • Song metadata, such as duration, artist, title, album.

What your app will not be able to do when using the MediaLibrary and MediaPlayer classes

  • Read the song byte stream.
  • Create new playlists.

Hopefully, all these limitations will be removed in the future.

The BackgroundAudioPlayer class

This is the only class which provides complete access to pretty much everything there is to know and do when playing music.

However, there is a catch: the objects it uses to play things, AudioTrack, requires an Uri to the file location. This means you will not be able to use the songs from the user media library or music folders, because you do not know the Uri (even if you use a media stream source, you still need the file location).

On the bright side, you can do whatever you want with the background audio player. You can stream from remote servers (by using an absolute Uri to the server in the audio track constructor), you can implement media stream sources to decode file formats which are not supported by windows phone out of the box.

And the best thing about it is that it runs in the background, completely independent from your application’s process, which means the player will still be active and register events even if the application has long been deactivated.

The behavior of the background audio agent is rather confusing for newcomers.

The actual class implemented by developers is a small agent which resides within a background process. An agent instance is created every time something needs to happen to the background audio player. Basically, if the user wants to skip to the next track the following chain of calls will occur: Constructor>OnUserAction

The agent instance only exists until it hits the NotifyComplete() method. This means you have to check for redundant operations in the constructor and make sure your fields don’t get reset every time you call the background audio player.

 

Since static fields are safely nested in the process heap, they can be used to share data between the various agent instances.

So if you want to create a playlist, you simply add a static list of AudioTracks as a field in the background audio agent.

The agent class comes preloaded with some code.

  protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)

This is a state machine which handles the various stages of playback.

The most interesting states here are the TrackEnded and TrackReady states. The first one signals the player to get a new track, while the second tells the player it is time to call the Play() method to play the new track.

Attention: Setting the audio track property to a new track does not have an immediate effect. The process is asynchronous, and until the TrackReady state is triggered, the player will still have its Track property set to the old value. Calling Play() or setting the track again will cause a chain reaction which will eventually crash the player.

Communication between the Background Audio Player and the app UI process is best done through the isolated storage of the app.

 

 

Conflicts

  • Either one of these class  will cancel any of the other.  This means a media element cannot play while the system media player is running and vice versa. Same goes to any combination between the classes. One of them will silence the others and obtain control of the playback devices.
  • If several applications implement their own background audio players, as a follow up to the above point, when one player starts, it will kill any other player already playing. If you want to save the state of your player, you have to use isolated storage files.

See Also

Another important place to find a huge amount of Windows Phone related articles is the TechNet Wiki itself. The best entry point is Windows Phone Resources on the TechNet Wiki.