osxaudio: Fix deadlock and property change notification in device selection code
authorSebastian Dröge <sebastian@centricular.com>
Mon, 22 Dec 2014 09:23:01 +0000 (10:23 +0100)
committerSebastian Dröge <sebastian@centricular.com>
Mon, 22 Dec 2014 09:29:01 +0000 (10:29 +0100)
After creating the ringbuffer we have to set the device on the ringbuffer as
it defaults to kAudioDeviceUnknown. At this point it can't have changed to
anything else yet and we don't have to notify about changes to the sink/src
"device" property. It's also not a good idea because GstAudioBaseSrc has the
object lock taken while the ringbuffer is created, which might cause a
deadlock if something calls back into the element from "notify::device".

Once the base class is done with the NULL_TO_READY state change, it has opened
the device via the ringbuffer and this might have chosen a different device.
Especially if we initially used kAudioDeviceUnknown. Also notify about this
property change as initially intended by this code.

sys/osxaudio/gstosxaudiosink.c
sys/osxaudio/gstosxaudiosrc.c

index 3b1e5a4..53d4c29 100644 (file)
@@ -274,13 +274,14 @@ gst_osx_audio_sink_change_state (GstElement * element,
     case GST_STATE_CHANGE_NULL_TO_READY:
       /* Device has been selected, AudioUnit set up, so initialize volume */
       gst_osx_audio_sink_set_volume (osxsink);
-      break;
 
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
       /* The device is open now, so fix our device_id if it changed */
       ringbuffer =
           GST_OSX_AUDIO_RING_BUFFER (GST_AUDIO_BASE_SINK (osxsink)->ringbuffer);
-      osxsink->device_id = ringbuffer->core_audio->device_id;
+      if (ringbuffer->core_audio->device_id != osxsink->device_id) {
+        osxsink->device_id = ringbuffer->core_audio->device_id;
+        g_object_notify (G_OBJECT (osxsink), "device");
+      }
       break;
 
     default:
@@ -520,10 +521,12 @@ gst_osx_audio_sink_create_ringbuffer (GstAudioBaseSink * sink)
       GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink);
   ringbuffer->core_audio->is_src = FALSE;
 
-  if (ringbuffer->core_audio->device_id != osxsink->device_id) {
+  /* By default the coreaudio instance created by the ringbuffer
+   * has device_id==kAudioDeviceUnknown. The user might have
+   * selected a different one here
+   */
+  if (ringbuffer->core_audio->device_id != osxsink->device_id)
     ringbuffer->core_audio->device_id = osxsink->device_id;
-    g_object_notify (G_OBJECT (osxsink), "device");
-  }
 
   return GST_AUDIO_RING_BUFFER (ringbuffer);
 }
index 8592b7c..266be57 100644 (file)
@@ -229,11 +229,14 @@ gst_osx_audio_src_change_state (GstElement * element, GstStateChange transition)
     goto out;
 
   switch (transition) {
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
+    case GST_STATE_CHANGE_NULL_TO_READY:
       /* The device is open now, so fix our device_id if it changed */
       ringbuffer =
           GST_OSX_AUDIO_RING_BUFFER (GST_AUDIO_BASE_SRC (osxsrc)->ringbuffer);
-      osxsrc->device_id = ringbuffer->core_audio->device_id;
+      if (ringbuffer->core_audio->device_id != osxsrc->device_id) {
+        osxsrc->device_id = ringbuffer->core_audio->device_id;
+        g_object_notify (G_OBJECT (osxsrc), "device");
+      }
       break;
 
     default:
@@ -369,10 +372,12 @@ gst_osx_audio_src_create_ringbuffer (GstAudioBaseSrc * src)
       GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc);
   ringbuffer->core_audio->is_src = TRUE;
 
-  if (ringbuffer->core_audio->device_id != osxsrc->device_id) {
+  /* By default the coreaudio instance created by the ringbuffer
+   * has device_id==kAudioDeviceUnknown. The user might have
+   * selected a different one here
+   */
+  if (ringbuffer->core_audio->device_id != osxsrc->device_id)
     ringbuffer->core_audio->device_id = osxsrc->device_id;
-    g_object_notify (G_OBJECT (osxsrc), "device");
-  }
 
   return GST_AUDIO_RING_BUFFER (ringbuffer);
 }