Make Better Things



I like to make better things.

Headphone plug-in plug-out event in iOS

To get the headphone plug-in plug-out event we need to employ a property listener callback function. The system invokes the callback when a user plugs in or unplugs a headset, or docks or undoes the device – thereby adding or removing an audio connection. The system also invokes the property listener callback when a Bluetooth device connects or disconnects.

Defining a Property Listener Callback Function

To respond to a route change, a property listener callback function must:

  • Identify the nature of the route change
  • Branch, depending on the specific route change and the current audio context (for example, recording, playback, or stopped)
  • Take or invoke appropriate action

Here is the example of this type of callback function. To see a similar callback function in working project you should see AddMusic sample code by Apple.

void audioRouteChangeListenerCallback (
void                   *inUserData,                                 // 1
AudioSessionPropertyID inPropertyID,                                // 2
UInt32                 inPropertyValueSize,                         // 3
const void             *inPropertyValue                             // 4
)

{

if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return; // 5
MainViewController *controller = (MainViewController *) inUserData; // 6
if (controller.appSoundPlayer.playing == 0 ) {                      // 7
return;
} else {
CFDictionaryRef routeChangeDictionary = inPropertyValue;        // 8
CFNumberRef routeChangeReasonRef = CFDictionaryGetValue (routeChangeDictionary,CFSTR (kAudioSession_AudioRouteChangeKey_Reason));
SInt32 routeChangeReason;
CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason);
if (routeChangeReason ==  kAudioSessionRouteChangeReason_OldDeviceUnavailable) {  // 9

[controller.appSoundPlayer pause];
UIAlertView *routeChangeAlertView =    [[UIAlertView alloc] initWithTitle: @"Playback Route Changed"  message: @"Audio output was changed." delegate:nil cancelButtonTitle: @"Ok" otherButtonTitles:nil];
[routeChangeAlertView show];

}

}

}

Here’s how this code works:

  1. A pointer to data that you provide when initializing your audio session.In an Objective-C class file, such as a view controller class, you place the property listener callback function outside of the class implementation block. Because of this, the callback needs a reference to the controller object to be able to send messages to it. You provide this reference when initializing your audio session.
  2. The identifier for the property that this callback function gets notified about.
  3. The size, in bytes, of the data in the inPropertyValue parameter.
  4. The current value of the property that this callback function is monitoring. Because the property being monitored is the kAudioSessionProperty_AudioRouteChange property, this value is a CFDictionary object.
  5. Ensures that the callback was invoked for the correct audio session property change.
  6. Initializes a MainViewController object instance to the reference passed in by the inUserData parameter. This allows the callback to send messages to your view controller object—typically defined in the same file that implements the callback.
  7. If application sound is not playing, there’s nothing to do, so return.
  8. This line and the next several lines determine the reason for the route change. The one route change of interest in this playback-only example is that an output device, such as a headset, was removed.
  9. If an output device was indeed removed, then pause playback and display an alert that allows the user to stop or resume playback.

Registering Your Property Listener Callback with the Audio Session

Your application can listen for hardware and route change events by way of the property mechanism in Audio Session Services. For example, to listen for route change events, you register a callback function with your audio session object, as shown here.

AudioSessionPropertyID routeChangeID =  kAudioSessionProperty_AudioRouteChange;    // 1

AudioSessionAddPropertyListener (                                  // 2

routeChangeID,                                                 // 3

audioRouteChangeListenerCallback,                                      // 4

userData                                                       // 5

);

Here’s how this code works:

  1. Declares and initializes a variable to the identifier for the property you want to monitor.
  2. Registers your property listener callback function with your initialized audio session.
  3. The identifier for the property you want to monitor.
  4. A reference to your hardware listener callback function.
  5. Data you want the audio session to pass back to your callback function.