MPMusicPlayerController currentPlaybackTime is reset after calling play()

I am using MPMusicPlayerController to stream from Apple Music. When I set the currentPlaybackTime while the player is playing, everything works as intended. The player jumps to the given time and plays from there. If I pause the player first though, then set the currentPlaybackTime, start the player with play() again, currentPlaybackTime is reset to zero.


EDIT: My question is: How can I achieve seeking to a certain point while the player is paused (and then resume from there)? Am I missing something? Is it a bug?


let player = MPMusicPlayerController.applicationMusicPlayer()
player.setQueueWithStoreIDs(["some id"])
player.play()
player.currentPlaybackTime = 120
debugPrint(player.currentPlaybackTime) //prints 120


let player = MPMusicPlayerController.applicationMusicPlayer()
player.setQueueWithStoreIDs(["some id"])
player.play()
player.pause()
player.currentPlaybackTime = 120
player.play()
debugPrint(player.currentPlaybackTime) //prints 0

Replies

If its any comfort, I am doing similar, starting to play from an offset and around 1 out of every 5 times it ignores the currenPlaybackTime and just starts at the beginning. Saw some comments about setting after you call play, tried adding in prepareToPlay in various places, no particular improvement.


I am starting to wonder if its something stupid like the impreciseness of floats used for times is messing things up.





        self.currentCollection = MPMediaItemCollection(items: [mediaItem])
        MPMusicPlayerController.applicationMusicPlayer().beginGeneratingPlaybackNotifications()      
        MPMusicPlayerController.applicationMusicPlayer().setQueue(with: self.currentCollection!)
       
        self.playingItemStartOffset = startOffset
        self.playingItemDuration = duration
        self.playingItemEndOffset = startOffset + duration
       
        self.startPlayTimer()
       
        NotificationCenter.default.post(name: Notification.Name(rawValue: PlayerControllerNotification_Started), object: self, userInfo: nil)
        MPMusicPlayerController.applicationMusicPlayer().currentPlaybackTime = TimeInterval(startOffset)
        MPMusicPlayerController.applicationMusicPlayer().play()

I had just run into this exact problem. I managed to get around it with the follow code.


It creates a background thread that continuously checks the `currentPlaybackTime` of the player. As soon as `currentPlaybackTime` is not the time I set it to be I set `currentPlaybackTime` back to what I wanted.


It feels like a terrible hack but it's working for me so far.


MPMusicPlayerController *player = [MPMusicPlayerController systemMusicPlayer];
player.currentPlaybackTime = _startTime;
[player play];

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_async(queue, ^{
  while(true) {
    if (player.currentPlaybackTime != _startTime) {
      player.currentPlaybackTime = _startTime;
      break;
    }
  }
});

Hello


It is a bug introduced with iOS 11.3. It has been working for me for years, until iOS 11.3 (beta 5, 6).


currentplaybackrate is another victim of Apple's tinkering in the code with iOS 11.3 ...

Your "terrible" hack works for me, too. Thank you very much!


However in certain situations even this hack fails because of

"[SDKPlayback] -[MPMusicPlayerController setCurrentPlaybackTime:126.306] completed error: Error Domain=MPCPlayerRequestErrorDomain Code=1 "No commands provided." UserInfo={NSDebugDescription=No commands provided.}"


What is that?

I also occassionally receive the "No commands povided." error, I'm still trying to figure out why. For the sake of speculation, it's almost as if MPMediaPlayerController makes an assumption that all "seek" events are in response to a user-action on a system-provided UI, and it (only sometimes???) fails to seek because no such action took place... That's a bad theory.


Also, I believe a better solution to the original question is to do the following after manipulating the queue:


1) Call prepareToPlay() on the controller, with a completion block.

2) In the completion block, first call play(), and then set currentPlaybackTime.


I still get the occassional "No commands provided." error... Perhaps I'll try waiting 0.05 seconds after the completion block triggers before setting the current playback time? I'll report back if it works.

Did you ever get past the "No commands provided." error ? I'm running into the same issue...