From 7c0d3b9a50d282c91efc3a4c84a443aa1d1ff4a6 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 2 Jun 2015 21:07:13 +0200 Subject: ao_coreaudio_exclusive: react to device removal Listening to kAudioDevicePropertyDeviceHasChanged does not send any property change notifications when the device dies. Makes no sense, but I suppose in CoreAudio logic a dead/removed device can't send any notifications. This caused the player to essentially pause playback if the audio device was removed during playback. Fix by listening to the kAudioHardwarePropertyDevices property too, which will actually be sent in this specific case. Then, if querying the already dead device fails, we know we have to reload. --- audio/out/ao_coreaudio_exclusive.c | 39 ++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_coreaudio_exclusive.c b/audio/out/ao_coreaudio_exclusive.c index dd476458aa..a08db7622d 100644 --- a/audio/out/ao_coreaudio_exclusive.c +++ b/audio/out/ao_coreaudio_exclusive.c @@ -305,19 +305,34 @@ static OSStatus enable_property_listener(struct ao *ao, bool enabled) { struct priv *p = ao->priv; - AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) { - .mSelector = kAudioDevicePropertyDeviceHasChanged, - .mScope = kAudioObjectPropertyScopeGlobal, - .mElement = kAudioObjectPropertyElementMaster, - }; - - if (enabled) { - return AudioObjectAddPropertyListener( - p->device, &p_addr, property_listener_cb, ao); - } else { - return AudioObjectRemovePropertyListener( - p->device, &p_addr, property_listener_cb, ao); + uint32_t selectors[] = {kAudioDevicePropertyDeviceHasChanged, + kAudioHardwarePropertyDevices}; + AudioDeviceID devs[] = {p->device, + kAudioObjectSystemObject}; + assert(MP_ARRAY_SIZE(selectors) == MP_ARRAY_SIZE(devs)); + + OSStatus status = noErr; + for (int n = 0; n < MP_ARRAY_SIZE(devs); n++) { + AudioObjectPropertyAddress addr = { + .mScope = kAudioObjectPropertyScopeGlobal, + .mElement = kAudioObjectPropertyElementMaster, + .mSelector = selectors[n], + }; + AudioDeviceID device = devs[n]; + + OSStatus status2; + if (enabled) { + status2 = AudioObjectAddPropertyListener( + device, &addr, property_listener_cb, ao); + } else { + status2 = AudioObjectRemovePropertyListener( + device, &addr, property_listener_cb, ao); + } + if (status == noErr) + status = status2; } + + return status; } static OSStatus render_cb_compressed( -- cgit v1.2.3