MediaPlayer: How to Check if it Has Control

Posted on Jul 10, 2012


I've been working with XNA's MediaPlayer class a lot lately, and I've come to learn many of the typical pitfalls associated with it. (Hint: There's approximately a million of them)

One of the biggest is the fact that it's so slow. I mean, it will literally slow your game to a crawl if you check Volume more than a few times every few seconds. However, I'm getting off-track here. Maybe I'll go into that in some other post.

For now, I'm going to post about something much more important. You see, XNA has this nifty feature that will mute either your Music category in XACT, or the MediaPlayer class, when the user starts to play music through the Guide. This is fantastic, and I've never had a problem with it (I'm an XACT man, myself), until I started using MediaPlayer for my Custom Playlists (so the user can play their own music in-game).

MediaPlayer pitfall #1,000,001: While MediaPlayer will mute your music when music is played through the Guide, it will not resume your music if that music from the Guide is turned off! Like a spoiled, bratty kid, it will do half of what it's told, but then firmly dig in and say "Screw you!".

So, then, how do we go about fixing this behavior?

I got to thinking, and realized that polling the MediaPlayer.GameHasControl will probably be slow, so checking it every frame was going to be a no-no. So, then I came up with this:

// Declarations
bool GuideWasVisible = false; // a bool we'll use to keep track of the last Guide status
 
bool MediaPlayerHasControl = true; // a bool we'll use to cache the
                                   // MediaPlayer.GameHasControl value
 
// The following should probably be wrapped in a class.
if(Guide.IsVisible)
{
   if(!GuideWasVisible)// since we'll set it anyway, we can use it to stop subsequent updates
      {
        if(MediaPlayer.GameHasControl) // check if the MediaPlayer has control
         {
            MediaPlayerHasControl = true;
         }
         else
         {
            MediaPlayerHasControl = false;
         }
         GuideWasVisible = true;// set GuideWasVisible, since the Guide is Open
      }
   }
 
if(GuideWasVisible && !Guide.IsVisible)
{
   bool MediaPlayerRegainedControl = false; // now we check if it gained control back
   if(MediaPlayer.GameHasControl) // check if the MediaPlayer has control
         {
            MediaPlayerRegainedControl = true;
         }
         else
         {
            MediaPlayerRegainedControl = false;
         }
   if(!MediaPlayerHasControl && MediaPlayerRegainedControl)
     {
        StartNewSong();// the MediaPlayer did not have control before, but now it does,
                       // so you can start a new song.
     }
   GuideWasVisible = false;// reset this, so it only does the MediaPlayer check once.
}

The code itself is pretty self-explanatory (but not especially clean, it can probably be improved), but I'll run through the gist of it.

Essentially, MediaPlayer is slow, so we can't check the GameHasControl flag every update. However, we can check it once, if the Guide gets opened, and check again when it's closed. This code hinges on the fact that a user must open the Guide to turn on their custom playlists.

Then, when it's first opened, we cache the current value of the MediaPlayer.GameHasControl. Then, when the Guide is closed, we check the current value of the MediaPlayer.GameHasControl, and compare it to the value when it was first opened. If the previous value was that it did NOT have control, and the current value is that it DOES have control, we start a new song, since the user stopped their Guide music.

Now, I will admit, this isn't without it's problems. First, if the user pauses the music from the Guide, the GameHasControl flag will still be false. Don't ask me why, I have no clue why it still does this.

Label that MediaPlayer pitfall #1,000,002.

Also, you will more-than-likely need to adjust the code to fit your needs. For instance, I pause my Jukebox class when it's detected that the game doesn't have control. I also set a flag when it has regained control to play a new song when the game is unpaused (as I pause when the Guide is opened).

At the end of the day, it's a workaround for a problem that shouldn't exist in the first place. It works -- but it's not ideal.



Loading Conversation