[vlc-commits] auhal: reorganize listener registration for devices list and physical formats list

David Fuhrmann git at videolan.org
Wed Apr 10 17:34:47 CEST 2013


vlc | branch: master | David Fuhrmann <david.fuhrmann at googlemail.com> | Wed Apr 10 17:17:20 2013 +0200| [afc967f6b918d74c36ce14795b62035620097c75] | committer: David Fuhrmann

auhal: reorganize listener registration for devices list and physical formats list

- Fixes detection when spidf is available again, and resumes playing in spdif mode
  if this was selected before
- Fixes audio device list rebuilt if no audio is playing

refs #8286

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=afc967f6b918d74c36ce14795b62035620097c75
---

 modules/audio_output/auhal.c |  104 +++++++++++++++++++++++++++++++-----------
 1 file changed, 78 insertions(+), 26 deletions(-)

diff --git a/modules/audio_output/auhal.c b/modules/audio_output/auhal.c
index b520dc6..63e41ee 100644
--- a/modules/audio_output/auhal.c
+++ b/modules/audio_output/auhal.c
@@ -150,6 +150,7 @@ static OSStatus RenderCallbackSPDIF     (AudioDeviceID, const AudioTimeStamp *,
 static OSStatus HardwareListener        (AudioObjectID, UInt32, const AudioObjectPropertyAddress *, void *);
 static OSStatus StreamListener          (AudioObjectID, UInt32, const AudioObjectPropertyAddress *, void *);
 
+static int      RegisterAudioStreamsCallback(audio_output_t *, AudioDeviceID);
 static int      AudioDeviceHasOutput    (AudioDeviceID);
 static int      AudioDeviceSupportsDigital(audio_output_t *, AudioDeviceID);
 static int      AudioStreamSupportsDigital(audio_output_t *, AudioStreamID);
@@ -175,6 +176,8 @@ vlc_module_end ()
 
 static int Open(vlc_object_t *obj)
 {
+    OSStatus            err = noErr;
+
     audio_output_t *aout = (audio_output_t *)obj;
     aout_sys_t *sys = malloc(sizeof (*sys));
 
@@ -193,6 +196,13 @@ static int Open(vlc_object_t *obj)
     aout->sys->devices = NULL;
     aout->device_select = SwitchAudioDevice;
 
+
+    /* Attach a Listener so that we are notified of a change in the Device setup */
+    AudioObjectPropertyAddress audioDevicesAddress = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
+    err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &audioDevicesAddress, HardwareListener, (void *)aout);
+    if (err != noErr)
+        msg_Warn(aout, "failed to add listener for audio device configuration [%4.4s]", (char *)&err);
+
     RebuildDeviceList(aout);
 
     /* remember the volume */
@@ -209,6 +219,22 @@ static void Close(vlc_object_t *obj)
     audio_output_t *aout = (audio_output_t *)obj;
     aout_sys_t *sys = aout->sys;
 
+    OSStatus            err = noErr;
+
+    /* remove audio device callback */
+    AudioObjectPropertyAddress deviceAliveAddress = { kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
+    err = AudioObjectRemovePropertyListener(sys->i_selected_dev, &deviceAliveAddress, HardwareListener, (void *)aout);
+    if (err != noErr)
+        msg_Err(aout, "failed to remove audio device life checker: [%4.4s]", (char *)&err);
+
+    /* remove audio streams callback */
+    if (sys->i_stream_id > 0) {
+        AudioObjectPropertyAddress physicalFormatsAddress = { kAudioStreamPropertyAvailablePhysicalFormats, kAudioObjectPropertyScopeGlobal, 0 };
+        err = AudioObjectRemovePropertyListener(sys->i_stream_id, &physicalFormatsAddress, HardwareListener, (void *)aout);
+        if (err != noErr)
+            msg_Err(aout, "failed to remove audio device property streams callback: [%4.4s]", (char *)&err);
+    }
+
     config_PutPsz(aout, "auhal-audio-device", aout_DeviceGet(aout));
 
     for (struct audio_device_t * device = sys->devices, *next; device != NULL; device = next) {
@@ -819,13 +845,6 @@ static int StartSPDIF (audio_output_t * p_aout, audio_sample_format_t *fmt)
     }
     free(p_streams);
 
-    /* get notified when we don't have spdif-output anymore */
-    err = AudioObjectAddPropertyListener(p_sys->i_stream_id, &physicalFormatsAddress, HardwareListener, (void *)p_aout);
-    if (err != noErr) {
-        msg_Warn(p_aout, "could not set audio device property streams callback on device: %4.4s",
-                 (char *)&err);
-    }
-
     msg_Dbg(p_aout, STREAM_FORMAT_MSG("original stream format: ", p_sys->sfmt_revert));
 
     if (!AudioStreamChangeFormat(p_aout, p_sys->i_stream_id, p_sys->stream_format))
@@ -881,18 +900,6 @@ static void Stop(audio_output_t *p_aout)
     OSStatus            err = noErr;
     UInt32              i_param_size = 0;
 
-    AudioObjectPropertyAddress deviceAliveAddress = { kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
-    err = AudioObjectRemovePropertyListener(p_sys->i_selected_dev, &deviceAliveAddress, HardwareListener, (void *)p_aout);
-    if (err != noErr)
-        msg_Err(p_aout, "failed to remove audio device life checker: [%4.4s]", (char *)&err);
-
-    if (p_sys->b_digital) {
-        AudioObjectPropertyAddress physicalFormatsAddress = { kAudioStreamPropertyAvailablePhysicalFormats, kAudioObjectPropertyScopeGlobal, 0 };
-        err = AudioObjectRemovePropertyListener(p_sys->i_stream_id, &physicalFormatsAddress, HardwareListener, (void *)p_aout);
-        if (err != noErr)
-            msg_Err(p_aout, "failed to remove audio device property streams callback: [%4.4s]", (char *)&err);
-    }
-
     if (p_sys->au_unit) {
         verify_noerr(AudioOutputUnitStop(p_sys->au_unit));
         verify_noerr(AudioUnitUninitialize(p_sys->au_unit));
@@ -1047,7 +1054,7 @@ static void RebuildDeviceList(audio_output_t * p_aout)
     /* Find the ID of the default Device */
     AudioObjectPropertyAddress defaultDeviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
     propertySize = sizeof(AudioObjectID);
-    err= AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultDeviceAddress, 0, NULL, &propertySize, &defaultDeviceID);
+    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;
@@ -1101,17 +1108,16 @@ static void RebuildDeviceList(audio_output_t * p_aout)
             free(psz_encoded_name);
         }
 
+        // TODO: only register once for each device
+        RegisterAudioStreamsCallback(p_aout, deviceIDs[i]);
+
         CFRelease(device_name_ref);
         free(psz_name);
     }
 
+    // TODO: fix default audio device
     add_device_to_list(p_aout, 0, _("System Sound Output Device"));
 
-    /* Attach a Listener so that we are notified of a change in the Device setup */
-    err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &audioDevicesAddress, HardwareListener, (void *)p_aout);
-    if (err != noErr)
-        msg_Warn(p_aout, "failed to add listener for audio device configuration (%i)", err);
-
     free(deviceIDs);
 }
 
@@ -1427,6 +1433,52 @@ static OSStatus StreamListener(AudioObjectID inObjectID,  UInt32 inNumberAddress
 #pragma mark -
 #pragma mark helpers
 
+static int RegisterAudioStreamsCallback(audio_output_t *p_aout, AudioDeviceID i_dev_id)
+{
+    OSStatus                    err = noErr;
+    UInt32                      i_param_size = 0;
+    AudioStreamID               *p_streams = NULL;
+    int                         i_streams = 0;
+
+    /* Retrieve all the output streams */
+    AudioObjectPropertyAddress streamsAddress = { kAudioDevicePropertyStreams, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
+    err = AudioObjectGetPropertyDataSize(i_dev_id, &streamsAddress, 0, NULL, &i_param_size);
+    if (err != noErr) {
+        msg_Err(p_aout, "could not get number of streams: [%s] (%i)", (char *)&err, (int32_t)err);
+        return VLC_EGENERIC;
+    }
+
+    i_streams = i_param_size / sizeof(AudioStreamID);
+    p_streams = (AudioStreamID *)malloc(i_param_size);
+    if (p_streams == NULL)
+        return VLC_ENOMEM;
+
+    err = AudioObjectGetPropertyData(i_dev_id, &streamsAddress, 0, NULL, &i_param_size, p_streams);
+    if (err != noErr) {
+        msg_Err(p_aout, "could not get list of streams: [%s]", (char *)&err);
+        return VLC_EGENERIC;
+    }
+
+    for (int i = 0; i < i_streams; i++) {
+        /* get notified when physical formats change */
+        AudioObjectPropertyAddress physicalFormatsAddress = { kAudioStreamPropertyAvailablePhysicalFormats, kAudioObjectPropertyScopeGlobal, 0 };
+        err = AudioObjectAddPropertyListener(p_streams[i], &physicalFormatsAddress, HardwareListener, (void *)p_aout);
+        if (err != noErr) {
+            // nope just means that we already have a callback
+            if (err == kAudioHardwareIllegalOperationError) {
+                msg_Dbg(p_aout, "could not set audio stream formats property callback on stream id %i, already have callback: %4.4s", p_streams[i],
+                         (char *)&err);
+            } else {
+            msg_Warn(p_aout, "could not set audio stream formats property callback on stream id %i: %4.4s", p_streams[i],
+                     (char *)&err);
+            }
+        }
+    }
+
+    free(p_streams);
+    return VLC_SUCCESS;
+}
+
 /*
  * AudioDeviceHasOutput: Checks if the device is actually an output device
  */
@@ -1503,7 +1555,7 @@ static int AudioStreamSupportsDigital(audio_output_t *p_aout, AudioStreamID i_st
     }
 
     i_formats = i_param_size / sizeof(AudioStreamRangedDescription);
-    msg_Dbg(p_aout, "found %i stream formats", i_formats);
+    msg_Dbg(p_aout, "found %i stream formats for stream id %i", i_formats, i_stream_id);
 
     p_format_list = (AudioStreamRangedDescription *)malloc(i_param_size);
     if (p_format_list == NULL)



More information about the vlc-commits mailing list