X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faudio_output%2Fauhal.c;h=50f5411e1cd80fb950f9a3a0a565d71a78c8f28d;hb=626174f3b9d86559db9c66ede56abd15a3d7ea5e;hp=c5de5592f2170cedf0e7c30218bc673bcf45c6b1;hpb=be64714e9899b498b68e6edbf1afe2f89b12ff5c;p=vlc diff --git a/modules/audio_output/auhal.c b/modules/audio_output/auhal.c index c5de5592f2..50f5411e1c 100644 --- a/modules/audio_output/auhal.c +++ b/modules/audio_output/auhal.c @@ -202,6 +202,19 @@ static int Open(vlc_object_t *obj) p_aout->device_select = SwitchAudioDevice; p_sys->device_list = CFArrayCreate(kCFAllocatorDefault, NULL, 0, NULL); + /* + * Force an own run loop for callbacks. + * + * According to rtaudio, this is absolutely necessary since 10.6 to get correct notifications. + * It might fix issues when using the module as a library where a proper loop is not setup already. + */ + CFRunLoopRef theRunLoop = NULL; + AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal,kAudioObjectPropertyElementMaster }; + err = AudioObjectSetPropertyData(kAudioObjectSystemObject, &property, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop); + if (err != noErr) { + msg_Err(p_aout, "failed to set the run loop property [%4.4s]", (char *)&err); + } + /* Attach a listener so that we are notified of a change in the device setup */ AudioObjectPropertyAddress audioDevicesAddress = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &audioDevicesAddress, DevicesListener, (void *)p_aout); @@ -330,7 +343,7 @@ static int Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt) p_sys->b_selected_dev_is_default = true; AudioObjectID defaultDeviceID = 0; - UInt32 propertySize = 0; + UInt32 propertySize = sizeof(AudioObjectID); AudioObjectPropertyAddress defaultDeviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster }; propertySize = sizeof(AudioObjectID); err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultDeviceAddress, 0, NULL, &propertySize, &defaultDeviceID); @@ -1062,6 +1075,7 @@ static void Stop(audio_output_t *p_aout) if (p_sys->b_changed_mixing && p_sys->sfmt_revert.mFormatID != kAudioFormat60958AC3) { int b_mix; Boolean b_writeable = false; + i_param_size = sizeof(int); /* Revert mixable to true if we are allowed to */ AudioObjectPropertyAddress audioDeviceSupportsMixingAddress = { kAudioDevicePropertySupportsMixing , kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster }; err = AudioObjectIsPropertySettable(p_sys->i_selected_dev, &audioDeviceSupportsMixingAddress, &b_writeable); @@ -1274,7 +1288,7 @@ static int SwitchAudioDevice(audio_output_t *p_aout, const char *name) static int VolumeSet(audio_output_t * p_aout, float volume) { struct aout_sys_t *p_sys = p_aout->sys; - OSStatus ostatus; + OSStatus ostatus = 0; if(p_sys->b_digital) return VLC_EGENERIC; @@ -1283,12 +1297,14 @@ static int VolumeSet(audio_output_t * p_aout, float volume) aout_VolumeReport(p_aout, volume); /* Set volume for output unit */ - ostatus = AudioUnitSetParameter(p_sys->au_unit, - kHALOutputParam_Volume, - kAudioUnitScope_Global, - 0, - volume * volume * volume, - 0); + if(!p_sys->b_mute) { + ostatus = AudioUnitSetParameter(p_sys->au_unit, + kHALOutputParam_Volume, + kAudioUnitScope_Global, + 0, + volume * volume * volume, + 0); + } if (var_InheritBool(p_aout, "volume-save")) config_PutInt(p_aout, "auhal-volume", lroundf(volume * AOUT_VOLUME_DEFAULT)); @@ -1551,7 +1567,7 @@ static OSStatus DeviceAliveListener(AudioObjectID inObjectID, UInt32 inNumberAd } /* - * Callback when current device is not alive anymore + * Callback when default audio device changed */ static OSStatus DefaultDeviceChangedListener(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void *inClientData) { @@ -1564,17 +1580,39 @@ static OSStatus DefaultDeviceChangedListener(AudioObjectID inObjectID, UInt32 i return -1; if (!p_aout->sys->b_selected_dev_is_default) - return 0; + return noErr; + + AudioObjectID defaultDeviceID = 0; + UInt32 propertySize = sizeof(AudioObjectID); + AudioObjectPropertyAddress defaultDeviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster }; + propertySize = sizeof(AudioObjectID); + OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultDeviceAddress, 0, NULL, &propertySize, &defaultDeviceID); + if (err != noErr) { + msg_Err(p_aout, "could not get default audio device [%4.4s]", (char *)&err); + return -1; + } + + msg_Dbg(p_aout, "default device changed to %i", defaultDeviceID); - msg_Dbg(p_aout, "default device changed, resetting aout"); + /* Default device is changed by the os to allow other apps to play sound while in digital + mode. But this should not affect ourself. */ + if (p_aout->sys->b_digital) { + msg_Dbg(p_aout, "ignore, as digital mode is active"); + return noErr; + } + + /* Also ignore events which announce the same device id */ + if(defaultDeviceID == p_aout->sys->i_selected_dev) + return noErr; + + msg_Dbg(p_aout, "default device actually changed, resetting aout"); aout_RestartRequest(p_aout, AOUT_RESTART_OUTPUT); return noErr; } - /* - * Callback when default audio device changed + * Callback when physical formats for device change */ static OSStatus StreamsChangedListener(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void *inClientData) { @@ -1633,7 +1671,7 @@ static OSStatus StreamsChangedListener(AudioObjectID inObjectID, UInt32 inNumbe } /* - * StreamListener: check whether the device's physical format changes on-the-fly (unlikely) + * StreamListener: check whether the device's physical format change is complete */ static OSStatus StreamListener(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void *inClientData) {