diff options
Diffstat (limited to 'pjmedia')
-rw-r--r-- | pjmedia/src/pjmedia-audiodev/coreaudio_dev.c | 137 |
1 files changed, 50 insertions, 87 deletions
diff --git a/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c b/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c index ad9c554f..89ae70ce 100644 --- a/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c +++ b/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c @@ -125,6 +125,8 @@ struct coreaudio_stream unsigned resample_buf_size; }; +/* Static variable */ +static struct coreaudio_factory *cf_instance = NULL; /* Prototypes */ static pj_status_t ca_factory_init(pjmedia_aud_dev_factory *f); @@ -286,7 +288,7 @@ static pj_status_t ca_factory_init(pjmedia_aud_dev_factory *f) } /* Initialize the Audio Session */ - ostatus = AudioSessionInitialize(NULL, NULL, interruptionListener, cf); + ostatus = AudioSessionInitialize(NULL, NULL, interruptionListener, NULL); if (ostatus != kAudioSessionNoError) { PJ_LOG(4, (THIS_FILE, "Error: cannot initialize audio session services (%i)", @@ -313,6 +315,8 @@ static pj_status_t ca_factory_init(pjmedia_aud_dev_factory *f) "Error: cannot listen for audio route change " "notifications (%i)", ostatus)); } + + cf_instance = cf; #endif PJ_LOG(4, (THIS_FILE, "core audio initialized")); @@ -334,13 +338,16 @@ static pj_status_t ca_factory_destroy(pjmedia_aud_dev_factory *f) AudioSessionRemovePropertyListenerWithUserData( kAudioSessionProperty_AudioRouteChange, propListener, cf); #endif - + if (cf->pool) { pj_pool_release(cf->pool); cf->pool = NULL; } if (cf->mutex) { + pj_mutex_lock(cf->mutex); + cf_instance = NULL; + pj_mutex_unlock(cf->mutex); pj_mutex_destroy(cf->mutex); cf->mutex = NULL; } @@ -1052,8 +1059,6 @@ static void propListener(void *inClientData, { struct coreaudio_factory *cf = (struct coreaudio_factory*)inClientData; struct stream_list *it, *itBegin; - pj_status_t status; - OSStatus ostatus; CFDictionaryRef routeDictionary; CFNumberRef reason; SInt32 reasonVal; @@ -1069,14 +1074,8 @@ static void propListener(void *inClientData, CFSTR(kAudioSession_AudioRouteChangeKey_Reason)); CFNumberGetValue(reason, kCFNumberSInt32Type, &reasonVal); - if (reasonVal == kAudioSessionRouteChangeReason_CategoryChange) { - PJ_LOG(3, (THIS_FILE, "audio route changed due to category change, " - "ignoring...")); - return; - } - if (reasonVal == kAudioSessionRouteChangeReason_Override) { - PJ_LOG(3, (THIS_FILE, "audio route changed due to user override, " - "ignoring...")); + if (reasonVal != kAudioSessionRouteChangeReason_OldDeviceUnavailable) { + PJ_LOG(3, (THIS_FILE, "ignoring audio route change...")); return; } @@ -1085,83 +1084,67 @@ static void propListener(void *inClientData, pj_mutex_lock(cf->mutex); itBegin = &cf->streams; for (it = itBegin->next; it != itBegin; it = it->next) { - pj_bool_t running = it->stream->running; - if (it->stream->interrupted) continue; + /* This does not seem necessary anymore. Just make sure + * that your application can receive remote control + * events by adding the code: + * [[UIApplication sharedApplication] + * beginReceivingRemoteControlEvents]; + * Otherwise audio route change (such as headset plug/unplug) + * will not be processed while your application is in the + * background mode. + */ + /* status = ca_stream_stop((pjmedia_aud_stream *)it->stream); - - ostatus = AudioUnitUninitialize(it->stream->io_units[0]); - ostatus = AudioComponentInstanceDispose(it->stream->io_units[0]); - - status = create_audio_unit(it->stream->cf->io_comp, 0, - it->stream->param.dir, - it->stream, &it->stream->io_units[0]); - if (status != PJ_SUCCESS) { - PJ_LOG(3, (THIS_FILE, - "Error: failed to create a replacement audio unit (%i)", - status)); - continue; - } - - if (running) { - status = ca_stream_start((pjmedia_aud_stream *)it->stream); - } + status = ca_stream_start((pjmedia_aud_stream *)it->stream); if (status != PJ_SUCCESS) { PJ_LOG(3, (THIS_FILE, "Error: failed to restart the audio unit (%i)", status)); continue; } - PJ_LOG(3, (THIS_FILE, "core audio unit successfully reinstantiated")); + PJ_LOG(3, (THIS_FILE, "core audio unit successfully restarted")); + */ } pj_mutex_unlock(cf->mutex); } static void interruptionListener(void *inClientData, UInt32 inInterruption) { - struct coreaudio_factory *cf = (struct coreaudio_factory*)inClientData; struct stream_list *it, *itBegin; pj_status_t status; - OSStatus ostatus; - pj_assert(cf); PJ_LOG(3, (THIS_FILE, "Session interrupted! --- %s ---", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption")); - pj_mutex_lock(cf->mutex); - itBegin = &cf->streams; + if (!cf_instance) + return; + + pj_mutex_lock(cf_instance->mutex); + itBegin = &cf_instance->streams; for (it = itBegin->next; it != itBegin; it = it->next) { - if (!it->stream->running) - continue; - if (inInterruption == kAudioSessionEndInterruption && it->stream->interrupted == PJ_TRUE) { - ostatus = AudioUnitUninitialize(it->stream->io_units[0]); - ostatus = AudioComponentInstanceDispose(it->stream->io_units[0]); - - status = create_audio_unit(it->stream->cf->io_comp, 0, - it->stream->param.dir, - it->stream, &it->stream->io_units[0]); - if (status != PJ_SUCCESS) { - PJ_LOG(3, (THIS_FILE, - "Error: failed to create a replacement " - "audio unit (%i)", ostatus)); - continue; - } - + /* Make sure that your application can receive remote control + * events by adding the code: + * [[UIApplication sharedApplication] + * beginReceivingRemoteControlEvents]; + * Otherwise audio unit will fail to restart while your + * application is in the background mode. + */ status = ca_stream_start((pjmedia_aud_stream*)it->stream); if (status != PJ_SUCCESS) { PJ_LOG(3, (THIS_FILE, "Error: failed to restart the audio unit (%i)", - ostatus)); - continue; + status)); + continue; } - PJ_LOG(3, (THIS_FILE, "core audio unit successfully " - "reinstantiated")); + PJ_LOG(3, (THIS_FILE, "core audio unit successfully resumed" + " after interruption")); } else if (inInterruption == kAudioSessionBeginInterruption && it->stream->running == PJ_TRUE) { @@ -1169,7 +1152,7 @@ static void interruptionListener(void *inClientData, UInt32 inInterruption) it->stream->interrupted = PJ_TRUE; } } - pj_mutex_unlock(cf->mutex); + pj_mutex_unlock(cf_instance->mutex); } #endif @@ -1524,6 +1507,10 @@ static pj_status_t ca_factory_create_stream(pjmedia_aud_dev_factory *f, ca_stream_set_cap(&strm->base, PJMEDIA_AUD_DEV_CAP_EC, ¶m->ec_enabled); + } else { + pj_bool_t ec = PJ_FALSE; + ca_stream_set_cap(&strm->base, + PJMEDIA_AUD_DEV_CAP_EC, &ec); } strm->io_units[0] = strm->io_units[1] = NULL; @@ -1956,8 +1943,6 @@ static pj_status_t ca_stream_start(pjmedia_aud_stream *strm) struct coreaudio_stream *stream = (struct coreaudio_stream*)strm; OSStatus ostatus; UInt32 i; - pj_bool_t should_activate; - struct stream_list *it, *itBegin; if (stream->running) return PJ_SUCCESS; @@ -1974,6 +1959,10 @@ static pj_status_t ca_stream_start(pjmedia_aud_stream *strm) return PJMEDIA_AUDIODEV_ERRNO_FROM_COREAUDIO(ostatus); } +#if !COREAUDIO_MAC + AudioSessionSetActive(true); +#endif + for (i = 0; i < 2; i++) { if (stream->io_units[i] == NULL) break; ostatus = AudioOutputUnitStart(stream->io_units[i]); @@ -1984,29 +1973,7 @@ static pj_status_t ca_stream_start(pjmedia_aud_stream *strm) } } - /* - * Make sure this stream is not in the list of running streams. - * If this is the 1st stream that is running we need to activate - * the audio session. - */ - pj_mutex_lock(stream->cf->mutex); - pj_assert(!pj_list_empty(&stream->cf->streams)); - pj_assert(!pj_list_empty(&stream->list_entry)); - should_activate = PJ_TRUE; - itBegin = &stream->cf->streams; - for (it = itBegin->next; it != itBegin; it = it->next) { - if (it->stream->running) { - should_activate = PJ_FALSE; - break; - } - } stream->running = PJ_TRUE; - pj_mutex_unlock(stream->cf->mutex); - -#if !COREAUDIO_MAC - if (should_activate) - AudioSessionSetActive(true); -#endif PJ_LOG(4, (THIS_FILE, "core audio stream started")); @@ -2035,11 +2002,7 @@ static pj_status_t ca_stream_stop(pjmedia_aud_stream *strm) } } - /* - * Make sure this stream is not in the list of running streams. - * If this is the 1st stream that is running we need to activate - * the audio session. - */ + /* Check whether we need to deactivate the audio session. */ pj_mutex_lock(stream->cf->mutex); pj_assert(!pj_list_empty(&stream->cf->streams)); pj_assert(!pj_list_empty(&stream->list_entry)); |