AVAudioSequencer - How to be notified when playback ends - ios

I am using AVAudioSequencer with AVAudioEngine and I am having just one single problem: how do I get the sequencer to notify when a track or file has reached its end?
I know there is an AVAudioPlayerNodeCompletionHandler thing, but then, AVAudioSequencer is not derived from AVAudioPlayerNode.
So far, the only thing I could think of was periodically comparing the currentPositionInBeats property in AVAudioSequencer with the lengthInBeats property in AVMusicTrack (the isPlaying property in AVAudioSequencer just doesn't go false when the sequencer goes beyond this limit,) but I don't like polling.
Any help is appreciated.

Related

What's the difference between AVPlayer and AVAudioPlayer in terms of functionality?

I've been trying to use AVAudioPlayer to play remote MP3 files in my app and I've read some of the other answers on Stack Overflow but I still cannot get it to work. The common suggestion I'm reading is to use AVPlayer instead of AVAudioPlayer. I don't know why this is. Also, in one of the questions the accepted answer mentioned that one needs to create an instance of AVPlayer in order to use it in the app. What should I do?
What you've read is correct. Creating an instance of AVPlayer will allow you to successfully run your code.
You should initialize your AVPlayer outside of where you want to call it.
var myPlayer = AVPlayer()
Now, in a separate place in your code, try something like this:
func playAudio() {
//initialize whatever you have to (you seem to have that correct)
//now call myPlayer.play(), and that should work correctly
}
Let me know if this helps.

How to check if sound played in delphi?

I'm using SndPlaySound(pchar('wav.wav'), snd_ASync); function and it is works but I want to know when selected wav is still playing or already played. How to get a return value?
SND_ASYNC does not provide the information you are looking for. Use SND_SYNC instead. To avoid blocking your main thread, call sndPlaySound() in a worker thread.
Alternatively, have a look at Delphi's TMediaPlayer component. It can run asynchronously (set its Wait property to false), and you can use its OnNotify event (set its Notify property to true) to be told when its Play() method finishes playback.

Access an AVAudioPlayer on its current thread

I'm using a series of AVAudioPlayers concurrent with the main thread using dispatch_async. Before playing each one I must query, whether it is playing using its isPlaying method.
I am generally unfamiliar with multithreading, so how would I go about calling the isPlaying method on the thread that the AVAudioPlayer is currently working on?
You can access the property playing directly on main thread because the operation is read, so it is safe I think :)
But you can't use it to judge if playback has completed as document says : Important: Do not poll this property to determine when playback has completed, instead implement the specified delegate method
You should use delegate and implement the method - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag, if the method is called, it means the player stop.

endturnwithnextparticipants, how does it work?

I am making a turnbased game for iOS with game center, 2 participants per match. I would like to implement a time limit on every turn, so that a player don't have to wait forever for the other player to finish its turn. I have tried:
currentMatch endTurnWithNextParticipants:[[NSArray alloc] initWithObjects:nextParticipant,nil] turnTimeout:GKTurnTimeoutDefault matchData:data completionHandler:^(NSError *error)
but nothing happens, the player still has forever to do their turn, so I am obviously missing something here.
What happens when the time limit is reached? How does gamecenter handle this, and where should I handle this?
That method updates the data stored on Game Center for the current match.
According to Apple Docs:
If the next player to act does not take their turn in the specified interval, the next player in the array receives a notification to act. This process continues until a player takes a turn or the last player in the list is notified.
When this method is called, it creates a new background task to handle the request. The method then returns control to your game. Later, when the task is complete, Game Kit calls your completion handler. Keep in mind that the completion handler may be called on a thread other than the one originally used to invoke the method. This means that the code in your block needs to be thread-safe.
I think you need to also end the players go on their end programatically.

Assertion failure in -[MPMoviePlayerControllerNew _moviePlayerDidBecomeActiveNotification:]

I'm using multiple instances of MPMoviePlayerController,
Which does not allow playing more than one video at a time
(On different instances of course)
In order not to play two instances at the same time, i stop and dismiss previous player once a new one is playing.
After plying a few videos, it throws an exception which i can't catch because it caused by internal notifications sent between instances.
It seems that calling 'stop' method to a player which has loadState == MPMovieLoadStateUnknown, causes bad internal state and throws the exception.
So, the solution was not to allow stopping a player in that state (A player has this state for about a second when it initializes playback).
Here's a reference to the very helpful mail chain that helped me find it

Resources