Audio playback when screen is locked

Hi,

I’m trying to create an alarm clock for iPhone with OF. It should work on iOS 3 so my App is not running in the background. Instead I want it to have it run in the foreground while the screen is turned of (like many alarm clock or similar apps do.)

According to Apple (http://developer.apple.com/library/ios/#qa/qa1626/_index.html) I need to set the kAudioSessionProperty_AudioCategory to kAudioSessionCategory_MediaPlayback. This way the audio playback continues when screen is locked.

When I try this in a ‘normal’ Window-based Application (so, not OF) it works: sound keeps playing when switching off the screen with the button on top of the iPhone. But when I add the same code to my setup function in OF a EXC_BAD_ACCESS signal is received. May be it’s because I changed ‘self’ to ofxiPhoneGetAppDelegate(). But even adding the code to the AppDelegate’s applicationDidLaunchWithOptions gives the same EXC_BAD_ACCESS.

Any clues?

  
  
void interruptionListenerCallback(void *inClientData, UInt32 inInterruptionState) {  
	NSLog(@"interruptionListenerCallback");  
}  
  
//--------------------------------------------------------------  
void testApp::setup(){	  
	OSStatus result = AudioSessionInitialize(NULL, NULL, interruptionListenerCallback, ofxiPhoneGetAppDelegate());  
	UInt32 category = kAudioSessionCategory_MediaPlayback;  
	result = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);  
	AudioSessionSetActive(YES);  
  

I changed the initialize call to this:

  
  
OSStatus result = AudioSessionInitialize(NULL, NULL, NULL, NULL);  
  

now it works.

One more thing…

update & draw don’t seem to get called when the screen is locked. So somehow I need to use another event which keeps being called. I found that audioPlayerDidFinishPlaying part of AVAudioPlayerDelegate keeps getting called but can I use that to call the update() function?

  
  
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag  
{  
	NSLog(@"audioPlayerDidFinishPlaying");  
	// When the sound stops, wait 1 second and play it again - forever!  
	[NSThread sleepForTimeInterval:1.0f];  
	[player play];  
  
	//how to call an openFrameworks function from here?  
}  
  

If audioPlayerDidFinishPlaying is continually called, you may be able to try adding:

[ofxiPhoneGetAppDelegate() timerLoop];

which will call the timerLoop which calls update/draw.

Let us know how that works.

Hi Seth,

That works!
The framerate goes down to 3 fps but that’s because audioPlayerDidFinishPlaying only gets called after the audio file finished. So I guess if you use a very short silent audiofile you can increase the framerate.

  
  
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {  
	[player play];                          // restart sound again for the next audioPlayerDidFinishPlaying  
	[ofxiPhoneGetAppDelegate() timerLoop];  // call the timerLoop which calls update/draw.  
}  
  

However, XCode gives a warning ‘ofxiPhoneAppDelegate() may not respond to -timerLoop’ but as far as I can see it does respond correctly.

Thanks,
Rick

Great to hear rick, I might use something similar to this myself. Glad to hear it’s working.

I made a change in my code which gets rid of a warning:

  
  
@implementation Aap  
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {  
	[player play];                          // restart sound again for the next audioPlayerDidFinishPlaying  
	ofxiPhoneGetOFWindow()->timerLoop();    // call the timerLoop which calls update/draw.  
}  
@end  
  

Hey guys,

I have been struggling to get this working. It can’t seem to get it to work (changed th plist and everything)
Could you elaborate a bit more on how you implemented background sound in an OF project?
I am using my own objective c class with AVAudioPlayer for playing sound because I need access to the updatemeters method of this class.

Thanks a lot,

Cheers,
Wim