Reputation: 8327
How can I play more than one .m4a file consecutively?
Presently, my function starts playing one, using AudioServicesPlaySystemSound etc., uses AudioServicesAddSystemSoundCompletion to select a callback, and then returns. When the sound is done, the callback lets my software continue.
This is a LOT of coding whenever there is back to back sound.
Can my software start a .m4a playing, and SOMEHOW wait for it to complete, waiting waiting for its callback to set a flag? Can I use pthread software to do a wait loop with a multitasking pause?
Here's my code so far...
// Restore game_state to continue game after playing sound file. int game_state_after_sound; void play_sound_file_done ( SystemSoundID ssID, void calling_class ) { printf("\n play_sound_file_done."); // Sound is now done, so restore game_state and continue to manage_game from where left off: game_state = game_state_after_sound; [ (GeController)calling_class manage_game]; }
// Plays sound_file_m4a and returns after playing has completed.
-(void) play_sound_file: (NSString *) sound_file_m4a
{
printf("\n play_sound_file '%s' ", [sound_file_m4a UTF8String] );
NSString *soundPath = [[NSBundle mainBundle] pathForResource:sound_file_m4a ofType:@"m4a"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath: soundPath], &soundID);
AudioServicesPlaySystemSound (soundID);
AudioServicesAddSystemSoundCompletion ( soundID, NULL, NULL, play_sound_file_done, (void*)self );
game_state_after_sound = game_state;
game_state = DELAY_WHILE_PLAYING_SOUND;
}
********************************** AVPlayer work-in-progress...
But this produces no sound.
#import <AVFoundation/AVFfoundation.h>
-(void) play_queued_sounds: (NSString *) sound_file_m4a
{
printf("\n queue_sound_file: '%s' ", [sound_file_m4a UTF8String] );
AVPlayerItem *sound_file = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:sound_file_m4a ofType:@"m4a"]]];
AVQueuePlayer *player = [AVQueuePlayer queuePlayerWithItems:[NSArray arrayWithObjects:sound_file, nil]];
[player play];
return;
}
Upvotes: 2
Views: 3302
Reputation: 8327
I could not get the AVQueuePlayer solution to work.
GREAT SOLUTION: For each sound to play, spin up a thread that awaits then locks a mutex, then does AudioServicesPlaySystemSound. Just spin up a thread for each successive sound to play, and use the pthread mutex to delay each successive thread until the AudioServicesAddSystemSoundCompletion function unlocks the mutex. Works like a champ.
This is 21st century embedded programming: Throw threads at the problem!
Upvotes: -1
Reputation: 130222
This can be achieved quite easily in AVQueuePlayer
. You don't have to handle completion or anything, you just give it the AVPlayerItems that you want to play in sequence and call play. Here's an example:
#import <AVFoundation/AVFfoundation.h>
//AVPlayerItem *item1 = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"myFileName" ofType:@"m4a"]]];
EDIT: Use this instead
AVPlayerItem *item1 = [[AVPlayerItem alloc] initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[[NSString alloc] initWithFormat:@"2"] ofType:@"mp3"]]];
AVQueuePlayer *player = [AVQueuePlayer queuePlayerWithItems:[NSArray arrayWithObjects:item1, nil]];
[player play];
Just as an addition, this can also be achieved with items from the users iPod library using a MPMusicPlayerController
queued from the didPickMediaItems
delegate method of MPMediaPickerController
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
MPMusicPlayerController *player = [MPMusicPlayerController applicationMusicPlayer];
[player setQueueWithItemCollection:mediaItemCollection];
[player play];
}
Upvotes: 3