Background MIDI playback in iOS


#1

Hi all,

I hope this is just a stupid question.

I'm trying to port a JUCE app from OSX to iOS. The app plays only MIDI data, no audio and does not make use of an AudioDeviceManager. The problem is that while MIDI playback in background works flawlessly in OSX, it does not work at all in iOS. When the app returns to foreground, playback resumes.

I have properly set the UIBackgroundModes property in the iOS project, of course. From what I see in the debugger, the run() method of the playback thread it's simply not called while the app is in background.

Can someone help, please?


#2

Are you using the simulator? I'm not sure I've ever gotten MIDI to work there.


#3

Thanks for your answer. 

No, unfortunately. I am using an iPad with iOS 7.1.2.


#4

I am able to receive MIDI in the background, but I do not send from my app, so I can't reproduce your problem unfortunately. 


#5

OK, this is the solution I've found, also thanks to this post. Please Jules, do you confirm this is a safe way to do this?

I have added this to my app class header:

#if defined(JUCE_IOS)
    AudioDeviceManager   f_AudioDeviceManager;
    AudioSourcePlayer    f_FakeAudioSourcePlayer;
#endif

void  suspended ();
void  resumed   ();

and this to the implementation:

void App::initialize()
{
...
#if defined(JUCE_IOS)
   f_AudioDeviceManager.initialiseWithDefaultDevices(0, 1);
#endif
...
}
void App::shutdown()
{
...
#if defined(JUCE_IOS)
   f_AudioDeviceManager.removeAudioCallback(&f_FakeAudioSourcePlayer);
#endif
...
}
void App::suspended()
{
#if defined(JUCE_IOS)
    f_AudioDeviceManager.addAudioCallback(&f_FakeAudioSourcePlayer);
#endif
}

void App::resumed()
{
#if defined(JUCE_IOS)
    f_AudioDeviceManager.removeAudioCallback(&f_FakeAudioSourcePlayer);
#endif
}

#6

Seems inefficient to leave the audio running while the app is suspended, but I guess that if that's what it takes to force iOS to keep running, then that's what you'd need to do!


#7

Thanks Jules. This is what Apple says:

When the UIBackgroundModes key contains the audio value, the system’s media frameworks automatically prevent the corresponding app from being suspended when it moves to the background. As long as it is playing audio or video content or recording audio content, the app continues to run in the background. However, if recording or playback stops, the system suspends the app.

Well, I'm realizing that I could at least check if my app is actually in playback mode when it is suspended before calling addAudioCallback().
 


#8

Why not just run the dummy audio whenever your app is playing, and don't worry about whether or not it's suspended?


#9

I thought that this would reduce the consumption of resources.
 


#10

Yes, but switching it on/off adds complexity and possible fail-points to your app. Unless you've profiled it and actually measured a performance issue that justifies the extra complexity, then it's always best to keep things simple.


#11

OK, you convinced me :)


#12

Edit: Wrong post