iOS: Handle audio interruptions (e.g. incomming GSM call)
This commit is contained in:
parent
e2a41923f8
commit
4bf453344e
|
@ -54,6 +54,7 @@ int tdav_audiounit_handle_start(tdav_audiounit_handle_t* self);
|
|||
uint32_t tdav_audiounit_handle_get_frame_duration(tdav_audiounit_handle_t* self);
|
||||
int tdav_audiounit_handle_configure(tdav_audiounit_handle_t* self, tsk_bool_t consumer, uint32_t ptime, AudioStreamBasicDescription* audioFormat);
|
||||
int tdav_audiounit_handle_mute(tdav_audiounit_handle_t* self, tsk_bool_t mute);
|
||||
int tdav_audiounit_handle_interrupt(tdav_audiounit_handle_t* self, tsk_bool_t interrupt);
|
||||
int tdav_audiounit_handle_stop(tdav_audiounit_handle_t* self);
|
||||
int tdav_audiounit_handle_destroy(tdav_audiounit_handle_t** self);
|
||||
|
||||
|
|
|
@ -29,12 +29,36 @@
|
|||
|
||||
#include "tsk_debug.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
// deprecated in iOS7+
|
||||
static void _AudioSessionInterruptionListener(void * inClientData, UInt32 inInterruptionState)
|
||||
{
|
||||
switch(inInterruptionState) {
|
||||
case kAudioSessionBeginInterruption:
|
||||
{
|
||||
TSK_DEBUG_INFO("_AudioSessionInterruptionListener:kAudioSessionBeginInterruption");
|
||||
break;
|
||||
}
|
||||
case kAudioSessionEndInterruption:
|
||||
{
|
||||
TSK_DEBUG_INFO("_AudioSessionInterruptionListener:kAudioSessionEndInterruption");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
TSK_DEBUG_INFO("_AudioSessionInterruptionListener:%u", (unsigned int)inInterruptionState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tdav_apple_init()
|
||||
{
|
||||
// initialize audio session
|
||||
#if TARGET_OS_IPHONE
|
||||
OSStatus status;
|
||||
status = AudioSessionInitialize(NULL, NULL, NULL, NULL);
|
||||
status = AudioSessionInitialize(NULL, NULL, _AudioSessionInterruptionListener, NULL);
|
||||
if(status){
|
||||
TSK_DEBUG_ERROR("AudioSessionInitialize() failed with status code=%d", (int32_t)status);
|
||||
return -1;
|
||||
|
|
|
@ -61,6 +61,7 @@ typedef struct tdav_audiounit_instance_s
|
|||
unsigned producer:1;
|
||||
} prepared;
|
||||
unsigned started:1;
|
||||
unsigned interrupted:1;
|
||||
|
||||
TSK_DECLARE_SAFEOBJ;
|
||||
|
||||
|
@ -202,10 +203,11 @@ int tdav_audiounit_handle_start(tdav_audiounit_handle_t* self)
|
|||
}
|
||||
|
||||
tsk_safeobj_lock(inst);
|
||||
if(!inst->started && (status = AudioOutputUnitStart(inst->audioUnit))){
|
||||
if((!inst->started || inst->interrupted) && (status = AudioOutputUnitStart(inst->audioUnit))){
|
||||
TSK_DEBUG_ERROR("AudioOutputUnitStart failed with status=%ld", (signed long)status);
|
||||
}
|
||||
inst->started = (status == noErr) ? tsk_true : tsk_false;
|
||||
if (inst->started) inst->interrupted = 0;
|
||||
tsk_safeobj_unlock(inst);
|
||||
return status ? -2 : 0;
|
||||
}
|
||||
|
@ -234,7 +236,7 @@ int tdav_audiounit_handle_configure(tdav_audiounit_handle_t* self, tsk_bool_t co
|
|||
UInt32 size = sizeof(preferredBufferSize);
|
||||
status = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize);
|
||||
if(status != noErr){
|
||||
TSK_DEBUG_ERROR("AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration) failed with status=%ld", status);
|
||||
TSK_DEBUG_ERROR("AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration) failed with status=%d", (int)status);
|
||||
TSK_OBJECT_SAFE_FREE(inst);
|
||||
goto done;
|
||||
}
|
||||
|
@ -251,7 +253,7 @@ int tdav_audiounit_handle_configure(tdav_audiounit_handle_t* self, tsk_bool_t co
|
|||
UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
|
||||
status = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);
|
||||
if(status != noErr){
|
||||
TSK_DEBUG_ERROR("AudioSessionSetProperty(kAudioSessionProperty_AudioCategory) failed with status code=%ld", status);
|
||||
TSK_DEBUG_ERROR("AudioSessionSetProperty(kAudioSessionProperty_AudioCategory) failed with status code=%d", (int)status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -298,6 +300,40 @@ int tdav_audiounit_handle_mute(tdav_audiounit_handle_t* self, tsk_bool_t mute)
|
|||
#endif
|
||||
}
|
||||
|
||||
int tdav_audiounit_handle_interrupt(tdav_audiounit_handle_t* self, tsk_bool_t interrupt)
|
||||
{
|
||||
tdav_audiounit_instance_t* inst = (tdav_audiounit_instance_t*)self;
|
||||
if (!inst){
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
return -1;
|
||||
}
|
||||
OSStatus status = noErr;
|
||||
if (inst->interrupted != interrupt && inst->started) {
|
||||
if (interrupt) {
|
||||
status = AudioOutputUnitStop(inst->audioUnit);
|
||||
if (status != noErr) {
|
||||
TSK_DEBUG_ERROR("AudioOutputUnitStop failed with status=%ld", (signed long)status);
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = AudioSessionSetActive(true);
|
||||
if (status != noErr) {
|
||||
TSK_DEBUG_ERROR("AudioSessionSetActive failed with status=%ld", (signed long)status);
|
||||
goto bail;
|
||||
}
|
||||
status = AudioOutputUnitStart(inst->audioUnit);
|
||||
if (status != noErr) {
|
||||
TSK_DEBUG_ERROR("AudioOutputUnitStart failed with status=%ld", (signed long)status);
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
}
|
||||
inst->interrupted = interrupt ? 1: 0;
|
||||
bail:
|
||||
return (status != noErr) ? -2 : 0;
|
||||
}
|
||||
|
||||
int tdav_audiounit_handle_stop(tdav_audiounit_handle_t* self)
|
||||
{
|
||||
tdav_audiounit_instance_t* inst = (tdav_audiounit_instance_t*)self;
|
||||
|
@ -313,7 +349,7 @@ int tdav_audiounit_handle_stop(tdav_audiounit_handle_t* self)
|
|||
}
|
||||
inst->started = (status == noErr ? tsk_false : tsk_true);
|
||||
tsk_safeobj_unlock(inst);
|
||||
return status ? -2 : 0;
|
||||
return (status != noErr) ? -2 : 0;
|
||||
}
|
||||
|
||||
int tdav_audiounit_handle_destroy(tdav_audiounit_handle_t** self){
|
||||
|
@ -357,6 +393,7 @@ static tsk_object_t* tdav_audiounit_instance_dtor(tsk_object_t * self)
|
|||
tsk_safeobj_unlock(inst);
|
||||
|
||||
tsk_safeobj_deinit(inst);
|
||||
TSK_DEBUG_INFO("*** AudioUnit Instance destroyed ***");
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "tsk_debug.h"
|
||||
#include "tsk_memory.h"
|
||||
#include "tsk_string.h"
|
||||
|
||||
#define kNoDataError -1
|
||||
#define kRingPacketCount +10
|
||||
|
@ -100,6 +101,15 @@ static tsk_size_t tdav_consumer_audiounit_get(tdav_consumer_audiounit_t* self, v
|
|||
/* ============ Media Consumer Interface ================= */
|
||||
int tdav_consumer_audiounit_set(tmedia_consumer_t* self, const tmedia_param_t* param)
|
||||
{
|
||||
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
|
||||
if (param->plugin_type == tmedia_ppt_consumer) {
|
||||
if (param->value_type == tmedia_pvt_int32) {
|
||||
if (tsk_striequals(param->key, "interrupt")) {
|
||||
int32_t interrupt = *((uint8_t*)param->value) ? 1 : 0;
|
||||
return tdav_audiounit_handle_interrupt(consumer->audioUnitHandle, interrupt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tdav_consumer_audio_set(TDAV_CONSUMER_AUDIO(self), param);
|
||||
}
|
||||
|
||||
|
@ -401,6 +411,7 @@ static tsk_object_t* tdav_consumer_audiounit_dtor(tsk_object_t * self)
|
|||
|
||||
/* deinit base */
|
||||
tdav_consumer_audio_deinit(TDAV_CONSUMER_AUDIO(consumer));
|
||||
TSK_DEBUG_INFO("*** AudioUnit Consumer destroyed ***");
|
||||
}
|
||||
|
||||
return self;
|
||||
|
|
|
@ -82,10 +82,14 @@ int tdav_producer_audiounit_set(tmedia_producer_t* self, const tmedia_param_t* p
|
|||
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
|
||||
if(param->plugin_type == tmedia_ppt_producer){
|
||||
if(param->value_type == tmedia_pvt_int32){
|
||||
if(tsk_striequals(param->key, "mute")){
|
||||
if (tsk_striequals(param->key, "mute")) {
|
||||
producer->muted = TSK_TO_INT32((uint8_t*)param->value);
|
||||
return tdav_audiounit_handle_mute(((tdav_producer_audiounit_t*)self)->audioUnitHandle, producer->muted);
|
||||
}
|
||||
else if (tsk_striequals(param->key, "interrupt")) {
|
||||
int32_t interrupt = *((uint8_t*)param->value) ? 1 : 0;
|
||||
return tdav_audiounit_handle_interrupt(producer->audioUnitHandle, interrupt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tdav_producer_audio_set(TDAV_PRODUCER_AUDIO(self), param);
|
||||
|
@ -384,6 +388,8 @@ static tsk_object_t* tdav_producer_audiounit_dtor(tsk_object_t * self)
|
|||
}
|
||||
/* deinit base */
|
||||
tdav_producer_audio_deinit(TDAV_PRODUCER_AUDIO(producer));
|
||||
|
||||
TSK_DEBUG_INFO("*** AudioUnit Producer destroyed ***");
|
||||
}
|
||||
|
||||
return self;
|
||||
|
|
Loading…
Reference in New Issue