diff options
author | Stefano Pigozzi <stefano.pigozzi@gmail.com> | 2015-02-14 12:43:55 +0100 |
---|---|---|
committer | Stefano Pigozzi <stefano.pigozzi@gmail.com> | 2015-02-14 12:51:15 +0100 |
commit | 70802d519f9130696959346aa413f7faeeed7621 (patch) | |
tree | 130639c7880b1495b2b43d31480705733989c899 /audio/out | |
parent | 9aaec7cffb2fb1543d4c3cabb55165f606c0b87d (diff) | |
download | mpv-70802d519f9130696959346aa413f7faeeed7621.tar.bz2 mpv-70802d519f9130696959346aa413f7faeeed7621.tar.xz |
ao_coreaudio: add support for hotplug notifications
This commit adds notifications for hot plugging of devices. It also extends
the old behaviour of the `audio-out-detected-device` property which is now
backed by the hotplugging code. This allows clients to be notified when the
actual audio output device changes.
Maybe hotplugging should be supported for ao_coreaudio_exclusive too, but it's
device selection code is a bit fragile.
Diffstat (limited to 'audio/out')
-rw-r--r-- | audio/out/ao.c | 10 | ||||
-rw-r--r-- | audio/out/ao.h | 2 | ||||
-rw-r--r-- | audio/out/ao_coreaudio.c | 107 |
3 files changed, 96 insertions, 23 deletions
diff --git a/audio/out/ao.c b/audio/out/ao.c index a2fa2fb104..c7065f386a 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -450,11 +450,6 @@ bool ao_untimed(struct ao *ao) return ao->untimed; } -const char *ao_get_detected_device(struct ao *ao) -{ - return ao->detected_device; -} - // --- struct ao_hotplug { @@ -502,6 +497,11 @@ bool ao_hotplug_check_update(struct ao_hotplug *hp) return false; } +const char *ao_hotplug_get_detected_device(struct ao_hotplug *hp) +{ + return hp->ao->detected_device; +} + // The return value is valid until the next call to this API. struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp) { diff --git a/audio/out/ao.h b/audio/out/ao.h index 7b85ec80ba..3a028bb402 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -80,7 +80,6 @@ void ao_uninit(struct ao *ao); void ao_get_format(struct ao *ao, struct mp_audio *format); const char *ao_get_name(struct ao *ao); const char *ao_get_description(struct ao *ao); -const char *ao_get_detected_device(struct ao *ao); bool ao_untimed(struct ao *ao); int ao_play(struct ao *ao, void **data, int samples, int flags); int ao_control(struct ao *ao, enum aocontrol cmd, void *arg); @@ -100,6 +99,7 @@ struct ao_hotplug *ao_hotplug_create(struct mpv_global *global, struct input_ctx *input_ctx); void ao_hotplug_destroy(struct ao_hotplug *hp); bool ao_hotplug_check_update(struct ao_hotplug *hp); +const char *ao_hotplug_get_detected_device(struct ao_hotplug *hp); struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp); void ao_print_devices(struct mpv_global *global, struct mp_log *log); diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index 0eab220421..99f0572723 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -143,14 +143,7 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg) static bool init_chmap(struct ao *ao); static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd); -static int init(struct ao *ao) -{ - if (AF_FORMAT_IS_IEC61937(ao->format)) { - MP_WARN(ao, "detected IEC61937, redirecting to coreaudio_exclusive\n"); - ao->redirect = "coreaudio_exclusive"; - return CONTROL_ERROR; - } - +static bool reinit_device(struct ao *ao) { struct priv *p = ao->priv; OSStatus err = ca_select_device(ao, ao->device, &p->device); @@ -161,6 +154,23 @@ static int init(struct ao *ao) CHECK_CA_ERROR("failed to get device UID"); ao->detected_device = talloc_steal(ao, uid); + return true; + +coreaudio_error: + return false; +} + +static int init(struct ao *ao) +{ + if (AF_FORMAT_IS_IEC61937(ao->format)) { + MP_WARN(ao, "detected IEC61937, redirecting to coreaudio_exclusive\n"); + ao->redirect = "coreaudio_exclusive"; + return CONTROL_ERROR; + } + + if (!reinit_device(ao)) + goto coreaudio_error; + if (!init_chmap(ao)) goto coreaudio_error; @@ -361,6 +371,67 @@ static void uninit(struct ao *ao) AudioComponentInstanceDispose(p->audio_unit); } +static OSStatus hotplug_cb(AudioObjectID id, UInt32 naddr, + const AudioObjectPropertyAddress addr[], + void *ctx) { + reinit_device(ctx); + ao_hotplug_event(ctx); + return noErr; +} + +static uint32_t hotplug_properties[] = { + kAudioHardwarePropertyDevices, + kAudioHardwarePropertyDefaultOutputDevice +}; + +static int hotplug_init(struct ao *ao) +{ + if (!reinit_device(ao)) + goto coreaudio_error; + + OSStatus err = noErr; + for (int i = 0; i < MP_ARRAY_SIZE(hotplug_properties); i++) { + AudioObjectPropertyAddress addr = { + hotplug_properties[i], + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster + }; + err = AudioObjectAddPropertyListener( + kAudioObjectSystemObject, &addr, hotplug_cb, (void *)ao); + if (err != noErr) { + char *c1 = fourcc_repr(ao, hotplug_properties[i]); + char *c2 = fourcc_repr(ao, err); + MP_ERR(ao, "failed to set device listener %s (%s)", c1, c2); + goto coreaudio_error; + } + } + + return 0; + +coreaudio_error: + return -1; +} + +static void hotplug_uninit(struct ao *ao) +{ + OSStatus err = noErr; + for (int i = 0; i < MP_ARRAY_SIZE(hotplug_properties); i++) { + AudioObjectPropertyAddress addr = { + hotplug_properties[i], + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster + }; + err = AudioObjectRemovePropertyListener( + kAudioObjectSystemObject, &addr, hotplug_cb, (void *)ao); + if (err != noErr) { + char *c1 = fourcc_repr(ao, hotplug_properties[i]); + char *c2 = fourcc_repr(ao, err); + MP_ERR(ao, "failed to set device listener %s (%s)", c1, c2); + } + } +} + + // Channel Mapping functions static const int speaker_map[][2] = { { kAudioChannelLabel_Left, MP_SPEAKER_ID_FL }, @@ -513,13 +584,15 @@ coreaudio_error: #define OPT_BASE_STRUCT struct priv const struct ao_driver audio_out_coreaudio = { - .description = "CoreAudio AudioUnit", - .name = "coreaudio", - .uninit = uninit, - .init = init, - .control = control, - .pause = stop, - .resume = start, - .list_devs = ca_get_device_list, - .priv_size = sizeof(struct priv), + .description = "CoreAudio AudioUnit", + .name = "coreaudio", + .uninit = uninit, + .init = init, + .control = control, + .pause = stop, + .resume = start, + .hotplug_init = hotplug_init, + .hotplug_uninit = hotplug_uninit, + .list_devs = ca_get_device_list, + .priv_size = sizeof(struct priv), }; |