I've got an AVQueuePlayer which I'm creating from an array of 4 AVPlayerItems, and it all plays fine.
I want to do something when the last item in the queue finishes playing, I've looked a load of answers on here and this is the one that looks most promising for what I want: The best way to execute code AFTER a sound has finished playing
In my button handler i have this code:
static const NSString *ItemStatusContext;
[thePlayerItemA addObserver:self forKeyPath:@"status" options:0 context:&ItemStatusContext];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd)
name:AVPlayerItemDidPlayToEndTimeNotification
object:thePlayerItemA];
theQueuePlayer = [AVQueuePlayer playerWithPlayerItem:thePlayerItemA];
[theQueuePlayer play];
and then I have a function to handle playerItemDidReachEnd:
- (void)playerItemDidReachEnd:(NSNotification *)notification {
// Do stuff here
NSLog(@"IT REACHED THE END");
}
But when I run this I get an Internal Inconsistency Exception:
An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
Key path: status
Observed object: <AVPlayerItem: 0x735a130, asset = <AVURLAsset: 0x73559c0, URL = file://localhost/Users/mike/Library/Application%20Support/iPhone%20Simulator/5.0/Applications/A0DBEC13-2DA6-4887-B29D-B43A78E173B8/Phonics%2001.app/yes.mp3>>
Change: {
kind = 1;
}
What am I doing wrong?
This approach seems to work for me, within my button handler i've got a bunch of stuff to create URLs for the 4 mp3 files I want to play, then:
AVPlayerItem *thePlayerItemA = [[AVPlayerItem alloc] initWithURL:urlA];
AVPlayerItem *thePlayerItemB = [[AVPlayerItem alloc] initWithURL:urlB];
AVPlayerItem *thePlayerItemC = [[AVPlayerItem alloc] initWithURL:urlC];
AVPlayerItem *thePlayerItemD = [[AVPlayerItem alloc] initWithURL:urlD];
NSArray *theItems = [NSArray arrayWithObjects:thePlayerItemA, thePlayerItemB, thePlayerItemC, thePlayerItemD, nil];
theQueuePlayer = [AVQueuePlayer queuePlayerWithItems:theItems];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[theItems lastObject]];
[theQueuePlayer play];
After which I have implement the 'playerItemDidReachEnd' selector like this:
- (void)playerItemDidReachEnd:(NSNotification *)notification {
// Do stuff here
NSLog(@"IT REACHED THE END");
}
This queues up the 4 MP3 files and then when the last piece of audio has finished it calls the selector and my message appears in the console.
I hope that this is useful for someone else.