Multiple AVPlayers on Separate UIViewControllers - ios

I have multiple AVPlayers, each on separate UIViewControllers playing different songs.
I need to pause one AVPlayer whenever I play another one (otherwise the audio overlaps).
I would like to let the user traverse through the app while the music plays in the background, so pausing the AVPlayer on viewDidDisappear:(BOOL)animated, would not work.
What is the best way to access the controls of each separate AVPlayer?

In my opinion a singleton with only 1 AVPlayer solves this issue well. This way you guarantee that to play another song you have to stop the previous. Then, in that AVPLayerSingleton you have a private property called avPlayer. You can define two methods:
- (void)createPlayerWithSong:(NSString *)currentSong;
- (void)destroyPlayer
Then, in your createPlayerWithSong you can check if avPlayer is already created and destroy it and create a new one for each new song.

Couple of ways you could do it:
Create a shared singleton object that have weak properties that reference each AVPlayer. That way you can control it from anywhere.
OR
Use NSNotificationCenter to send notifications when you want to control an AVPlayer on a different view controller. This might get cumbersome if you have a lot of AVPlayers you want to control.

Related

MPMediaItem and AVPlayerItem playback sequence in background

I'm having an issue with playing sequences of different kinds of items in a background.
In an app I'm working on we've introduced playlists which contain both content provided by the app and Apple Music content.
For that use AVPlayer and MPMusicPlayerController respectively. We observe one player or the other (depending what content is now playing) and if the other kind of content comes next, we release the old player (if we can - MPMusicPlayerController is a singleton, so best we can do is stop it) and load item to another player.
The problem starts when the app leaves foreground. Once MPMusicPlayerController takes over it doesn't want to give up control, so if any AVPlayer content comes after MPMusicPlayerController content, the music stops.
One workaround that I've tried is playing with .mixWithOthers options when I set the category on AVAudioSession, however this creates new category of problems - I'm loosing lockscreen controls, therefore I'm also loosing airplay. One dirty trick that I've tried was setting .mixWithOthers 3 seconds before MPMediaItem ends, and then disabling it back once AVPlayer starts. Beside the fact that there're probably many different things that can go wrong here, MPMediaPlayerController still doesn't want to give me back the control over lockscreen controls.
Is there any way this could ever work on iOS 13?

Best strategy for managing audio instances to allow cross-fades, etc

I'm working on an iOS application that works with different pieces of audio. Each piece of audio is tied to a separate button (similar to the kind of functionality you'd see in a soundboard app).
In a simple soundboard application, you've got an instance of a player object (AVAudioPlayer or an AVAudioEngine player node) that gets fired whenever a button is pressed.
If you push buttonOne, then sound1 plays.
If you push buttonOne again while sound1 is still playing, then the current instance is interrupted and "replaced" with a new instance of sound1 that starts over at the beginning.
If you push buttonOne, THEN push buttonTwo before sound1 is finished, the instance of sound1 is interrupted and replaced with sound2, again, played from the beginning.
Suppose you're trying to enable cross-fading between the two sounds. You can just create two player instances, load the first sound into player1 and the second into player2, and cross fade between them.
Building on that, suppose you're trying to allow different combinations of sounds to play at the same time. Either the idea that a large number of sounds (maybe the whole soundboard) can all play without interrupting each other. Or, perhaps, the ability to have multiple sounds playing at the same time, e.g. sound1 is a music bed, and sound2...soundXX are sound effects that should be able to play over the music bed without interrupting it.
QUESTIONS: what is the best design strategy for managing your player instances in this situation? Suppose you have a 5 x 5 grid of buttons in your soundboard. If, hypothetically, you should be able to play all 25 sounds at the same time, would that require you to init 25 player instances at setup? (this seems very anti-DRY and not particularly efficient). Or is there some way to dynamically manage the number of instances you need (maybe with a lazy variable?) so that additional instances are only generated as needed, e.g. when you have x number of sounds playing and you start another, an additional instance is generated to contain the newly added sound?
what is the best design strategy for managing instances of AVAudioPlayer in this situation
None. You should be using AVAudioEngine. That's exactly what it is, a sound board / patch kit.
Or is there some way to dynamically manage the number of instances you need
If I have 25 ordered instances of a thing where one possibility is no instance at all, that sounds like an array of Optionals.

tvOS issue with Siri search deeplinking integration

I have an issue where when user is playing a video , while video is being player, he uses siri to search for a different movie, which will load its corresponding movie details page and then select to play that movie, which deeplinks to your app which is playing a movie, when i play a new selected movie and dismiss avplayer and avplayercontroller, audio from previous video still continues to play. somehow avplayer is not cleared although i clear all subviews from window and initialize its super view controller class again. I am cluless what can i do erase older instance of avplayer. Let me know if anyone has any suggestions or faced similar issue.
A few suggestions:
Are you subclassing AVPlayerViewController? If so, that's a bad idea. The API docs specifically say not to do that.
Add a deinit function. If it's not being called when the old AVPlayer is dismissed, you know you have a retention problem. This is often caused by registering for notifications or boundary time observers.
If you view controller has a reference to the AVPlayer object, you might try overriding the viewDidDisappear function to call player.pause() and then setting the player reference first to a new instance of AVPlayer() then to nil. Not sure why this helps, but sometimes it does.
Definitely implement #2 above. If deinit is not getting called, you most certainly have an issue.

AVQueuePlayer stops playing when I navigate to previous view

I have used AVQueuePlayer several times and the default behaviour is to continue playing when you change view, but in my case when I navigate to the previous view where I came from by segue, the player stops. I put a breakpoint after dealloc to see if the AVQueuePlayer is released and from what I can see it's not deallocated (I have a strong reference to it using property). Please help!!!
I am streaming audio using several links from a server, not playing local files. I created the url, used the url to make AVPlayerItems, and added the player items into array, I used this array to initiate the AVQueuePlayer. I used GCD to make sure my array is completely ready before I play the AVQueuePlayer.
As soon I click on back button it stops. I am pulling out my hair
Create a singleton class that provides an interface to the AVQueuePlayer. That way you will be sure that it's alive even when you pop your view controllers.

Multiple MPMoviePlayerController in one view

I have multiple MPMoviePlayerControllers in one view.
When a play one of them while there is already another one is playing,
the playing one is "Paused"(I'm not sure the real state it is, but more like "Stucked")
How can i know which one of the MPMoviePlayerControllers is Stucked?
Its restriction by apple, in single view controller only single movie player will get played. If one player is in play state and you are trying to play another then first player will get in pause/stop mode.

Resources