Blog

Error -12986 and you

A customer recently got in touch with me with an odd problem — Talkie for iPhone was going silent on him. After a little diagnosis, it turned out the audio system was throwing up an undocumented error — -12986 — while starting up on his iPod Touch.

Some googling turned up this thread on Stack Overflow, which presented a solution for the AVAudioSession framework: It turns out, on recent SDKs (somewhere equal to or above 3.0), the audio system will refuse to start up if the session is set to a recording mode, with no input device available, spitting out this error. Alas, the error isn’t listed anywhere that I could find.

So, the way to fix it is to check whether there’s an input device available, then choose an audio category accordingly:

OSStatus status;
 
UInt32 inputAvailable=0;
UInt32 size = sizeof(inputAvailable);
AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable, 
                        &size, 
                        &inputAvailable);
UInt32 sessionCategory;
if ( inputAvailable ) {
    // Set the audio session category for simultaneous play and record
    sessionCategory = kAudioSessionCategory_PlayAndRecord;
} else {
    // Just playback
    sessionCategory = kAudioSessionCategory_MediaPlayback;
}
 
status = AudioSessionSetProperty (kAudioSessionProperty_AudioCategory,
                                  sizeof (sessionCategory),
                                  &sessionCategory);    
checkStatus(status);

It’s probably a good idea to respond when input becomes available or goes away, so add a property listener too:

void inputAvailablePropertyListener (void                      *inClientData,
                                     AudioSessionPropertyID    inID,
                                     UInt32                    inDataSize,
                                     const void                *inData) {
    if ( inID = kAudioSessionProperty_AudioInputAvailable ) {
        UInt32 *inputAvailable = (UInt32*)inData;
        UInt32 sessionCategory;
        if ( *inputAvailable ) {
            // Set the audio session category for simultaneous play and record
            sessionCategory = kAudioSessionCategory_PlayAndRecord;
        } else {
            // Just playback
            sessionCategory = kAudioSessionCategory_MediaPlayback;
        }
 
        OSStatus status = AudioSessionSetProperty (kAudioSessionProperty_AudioCategory,
                                                   sizeof (sessionCategory),
                                                   &sessionCategory);    
        checkStatus(status);
    }
}

then:

// Listen for audio input availability
status = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioInputAvailable,
                                         inputAvailablePropertyListener, 
                                         NULL);
, , . Bookmark the permalink. Both comments and trackbacks are currently closed.

One Comment

  1. Posted March 24, 2011 at 6:40 pm | Permalink

    Funny, this one got me too.