]> git.sesse.net Git - vlc/blobdiff - modules/audio_output/auhal.c
auhal: use own thread for notification loop
[vlc] / modules / audio_output / auhal.c
index c5de5592f2170cedf0e7c30218bc673bcf45c6b1..50f5411e1cd80fb950f9a3a0a565d71a78c8f28d 100644 (file)
@@ -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)
 {