Add callback for device format change (CoreAudio)
parent
1a5220acf1
commit
1927dc7eaa
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "mac-helpers.h"
|
||||
|
||||
#define FORMAT_CHANGED kAudioStreamPropertyAvailablePhysicalFormats
|
||||
|
||||
#define SCOPE_OUTPUT kAudioUnitScope_Output
|
||||
#define SCOPE_INPUT kAudioUnitScope_Input
|
||||
#define SCOPE_GLOBAL kAudioUnitScope_Global
|
||||
|
@ -315,42 +317,29 @@ static void coreaudio_begin_reconnect(struct coreaudio_data *ca)
|
|||
"create thread, error code: %d", ret);
|
||||
}
|
||||
|
||||
static OSStatus disconnection_callback(
|
||||
static OSStatus notification_callback(
|
||||
AudioObjectID id,
|
||||
UInt32 num_addresses,
|
||||
const AudioObjectPropertyAddress addresses[],
|
||||
void *data)
|
||||
{
|
||||
struct coreaudio_data *ca = data;
|
||||
UInt32 alive = 0;
|
||||
UInt32 size = sizeof(alive);
|
||||
OSStatus stat;
|
||||
|
||||
stat = AudioObjectGetPropertyData(id, addresses, 0, NULL, &size,
|
||||
&alive);
|
||||
if (ca_success(stat, ca, "disconnection_callback", "get property")) {
|
||||
if (!alive) {
|
||||
coreaudio_stop(ca);
|
||||
coreaudio_uninit(ca);
|
||||
|
||||
blog(LOG_INFO, "coreaudio: device '%s' disconnected. "
|
||||
"attempting to reconnect",
|
||||
ca->device_name);
|
||||
blog(LOG_INFO, "coreaudio: device '%s' disconnected or format "
|
||||
"changed. attempting to reconnect", ca->device_name);
|
||||
|
||||
coreaudio_begin_reconnect(ca);
|
||||
}
|
||||
}
|
||||
|
||||
UNUSED_PARAMETER(id);
|
||||
UNUSED_PARAMETER(num_addresses);
|
||||
UNUSED_PARAMETER(addresses);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static const AudioObjectPropertyAddress alive_addr = {
|
||||
kAudioDevicePropertyDeviceIsAlive,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
static bool coreaudio_init_hooks(struct coreaudio_data *ca)
|
||||
{
|
||||
OSStatus stat;
|
||||
|
@ -359,12 +348,25 @@ static bool coreaudio_init_hooks(struct coreaudio_data *ca)
|
|||
.inputProcRefCon = ca
|
||||
};
|
||||
|
||||
stat = AudioObjectAddPropertyListener(ca->device_id, &alive_addr,
|
||||
disconnection_callback, ca);
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioDevicePropertyDeviceIsAlive,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
stat = AudioObjectAddPropertyListener(ca->device_id, &addr,
|
||||
notification_callback, ca);
|
||||
if (!ca_success(stat, ca, "coreaudio_init_hooks",
|
||||
"set disconnect callback"))
|
||||
return false;
|
||||
|
||||
addr.mSelector = FORMAT_CHANGED;
|
||||
stat = AudioObjectAddPropertyListener(ca->device_id, &addr,
|
||||
notification_callback, ca);
|
||||
if (!ca_success(stat, ca, "coreaudio_init_hooks",
|
||||
"set format change callback"))
|
||||
return false;
|
||||
|
||||
stat = set_property(ca->unit, kAudioOutputUnitProperty_SetInputCallback,
|
||||
SCOPE_GLOBAL, 0, &callback_info, sizeof(callback_info));
|
||||
if (!ca_success(stat, ca, "coreaudio_init_hooks", "set input callback"))
|
||||
|
@ -380,8 +382,18 @@ static void coreaudio_remove_hooks(struct coreaudio_data *ca)
|
|||
.inputProcRefCon = NULL
|
||||
};
|
||||
|
||||
AudioObjectRemovePropertyListener(ca->device_id, &alive_addr,
|
||||
disconnection_callback, ca);
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioDevicePropertyDeviceIsAlive,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
AudioObjectRemovePropertyListener(ca->device_id, &addr,
|
||||
notification_callback, ca);
|
||||
|
||||
addr.mSelector = FORMAT_CHANGED;
|
||||
AudioObjectRemovePropertyListener(ca->device_id, &addr,
|
||||
notification_callback, ca);
|
||||
|
||||
set_property(ca->unit, kAudioOutputUnitProperty_SetInputCallback,
|
||||
SCOPE_GLOBAL, 0, &callback_info, sizeof(callback_info));
|
||||
|
|
Loading…
Reference in New Issue