4

I have an application that plays back music.

I'm using the following code to listen to playback state changes from the MPMusicPlayerController to update the UI. More precisely I toggle the look of the play button between play and pause.

NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];

[notificationCenter addObserver: self
                       selector: @selector (handle_NowPlayingItemChanged:)
                           name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification
                         object: self.musicPlayer];

[notificationCenter addObserver: self
                       selector: @selector (handle_PlaybackStateChanged:)
                           name: MPMusicPlayerControllerPlaybackStateDidChangeNotification
                         object: self.musicPlayer];

[self.musicPlayer beginGeneratingPlaybackNotifications];

This works great on an iPod Touch (iOS 5) and iPhone 3GS (iOS 5). Every time the playback state changes I get the following callback:

[JBMediaPlayer handle_PlaybackStateChanged:] :: playbackState: 1

where 1 means MPMusicPlaybackStatePlaying.

However if I run the same on a iPad 1 (iOS 5), iPad 2 (iOS 5) or iPad 3 (iOS 6) I get the following sequence instead of just one single callback:

-[JBMediaPlayer handle_PlaybackStateChanged:] :: playbackState: 1
-[JBMediaPlayer handle_PlaybackStateChanged:] :: playbackState: 2
-[JBMediaPlayer handle_PlaybackStateChanged:] :: playbackState: 1
-[JBMediaPlayer handle_PlaybackStateChanged:] :: playbackState: 2

where 2 means MPMusicPlaybackStatePaused and causes my application to display the wrong state in the UI, because the song is actually being played back.

The funny thing is, that once in a while the sequence is

-[JBMediaPlayer handle_PlaybackStateChanged:] :: playbackState: 1
-[JBMediaPlayer handle_PlaybackStateChanged:] :: playbackState: 2
-[JBMediaPlayer handle_PlaybackStateChanged:] :: playbackState: 1
-[JBMediaPlayer handle_PlaybackStateChanged:] :: playbackState: 2
-[JBMediaPlayer handle_PlaybackStateChanged:] :: playbackState: 1

which ends up correctly with 1 MPMusicPlaybackStatePlaying, however still doesn't make sense that the callback gets called 5 times, with alternating values.

Any ideas on how to solve this or suggestion what else I can test to narrow down the problem?


Since I haven't received an answer here so far, I also cross-posted the question to the Apple Developer Forum: https://devforums.apple.com/thread/158426

znq
  • 44,613
  • 41
  • 116
  • 144

2 Answers2

0

I think this is the same bug reported here:

Getting wrong playback state in MP Music Player Controller in ios 5

I posted a workaround for the bug in that question.

Community
  • 1
  • 1
pgkelley
  • 484
  • 1
  • 6
  • 9
  • And what should I do with this information? How can I get the correct state? Or how can I reset the player? – MetaImi Nov 27 '12 at 23:51
0

You can check real playback state using currentPlaybackRate property. MPMusicPlaybackStatePaused must match rate 0.0. An example how can it implemented is shown below...

- (void)musicPlayerControllerPlaybackStateDidChangeNotification:(NSNotification *)notification {
    float playbackRate = [((MPMusicPlayerController *)notification.object) currentPlaybackRate];
    MPMusicPlaybackState playbackState = (MPMusicPlaybackState)[notification.userInfo[@"MPMusicPlayerControllerPlaybackStateKey"] integerValue];
    switch (playbackState) {
        case MPMusicPlaybackStatePaused:
            if (playbackRate <= .0f) {
                self.playbackState = playbackState;
            }
            break;
        default:
            self.playbackState = playbackState;
            break;
    }
}

Thus it is possible to cut off false pause notification.

d0ping
  • 462
  • 4
  • 16