osxaudio: Clean up a GstCoreAudio -> GstOsxAudioSrc/Sink reference
authorArun Raghavan <git@arunraghavan.net>
Fri, 28 Nov 2014 16:53:17 +0000 (22:23 +0530)
committerArun Raghavan <git@arunraghavan.net>
Mon, 15 Dec 2014 05:49:51 +0000 (11:19 +0530)
Now that device selection has no sink/source-specific bits, we can have
generic device selection for this path. We do need to now track state
changes so we can look up the final device_id once the device is open,
though.

https://bugzilla.gnome.org/show_bug.cgi?id=740987

sys/osxaudio/gstosxaudioringbuffer.c
sys/osxaudio/gstosxaudioringbuffer.h
sys/osxaudio/gstosxaudiosink.c
sys/osxaudio/gstosxaudiosrc.c
sys/osxaudio/gstosxcoreaudio.c
sys/osxaudio/gstosxcoreaudio.h
sys/osxaudio/gstosxcoreaudiohal.c
sys/osxaudio/gstosxcoreaudioremoteio.c

index 0476651511baa5c3e34ddc40ab7605b57bf5da3f..7f9b86fa479d53d415bfb8234c3eb778a5a7f659 100644 (file)
@@ -149,9 +149,8 @@ static gboolean
 gst_osx_audio_ring_buffer_open_device (GstAudioRingBuffer * buf)
 {
   GstOsxAudioRingBuffer *osxbuf = GST_OSX_AUDIO_RING_BUFFER (buf);;
-  GstElement *parent = GST_ELEMENT_CAST (GST_OBJECT_PARENT (buf));
 
-  if (!osxbuf->select_device (parent, osxbuf))
+  if (!gst_core_audio_select_device (osxbuf->core_audio))
     return FALSE;
 
   return gst_core_audio_open (osxbuf->core_audio);
index dbc2e122567213be637e998fa1a8a1b02f3eaa4d..5054fd38533a2cf4cfcfb87a26d910abf47de45c 100644 (file)
@@ -81,9 +81,6 @@ struct _GstOsxAudioRingBuffer
 
   GstCoreAudio *core_audio;
 
-  /* Set by the parent to select the required device */
-  gboolean (*select_device) (GstElement * element, GstOsxAudioRingBuffer * buf);
-
   guint buffer_len;
   guint segoffset;
 };
index 10f5b24bad19eb8bda0519182abcbd2ea6ac7b60..51b87bf0eaeacac93b7bec3bcad847ed939d0a39 100644 (file)
@@ -116,6 +116,10 @@ static void gst_osx_audio_sink_set_property (GObject * object, guint prop_id,
 static void gst_osx_audio_sink_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
+static GstStateChangeReturn
+gst_osx_audio_sink_change_state (GstElement * element,
+    GstStateChange transition);
+
 static gboolean gst_osx_audio_sink_query (GstBaseSink * base, GstQuery * query);
 
 static gboolean gst_osx_audio_sink_stop (GstBaseSink * base);
@@ -130,8 +134,6 @@ static GstAudioRingBuffer
     * gst_osx_audio_sink_create_ringbuffer (GstAudioBaseSink * sink);
 static void gst_osx_audio_sink_osxelement_init (gpointer g_iface,
     gpointer iface_data);
-static gboolean gst_osx_audio_sink_select_device (GstElement * sink,
-    GstOsxAudioRingBuffer * ringbuffer);
 static void gst_osx_audio_sink_probe_caps (GstOsxAudioSink * sink);
 static void gst_osx_audio_sink_set_volume (GstOsxAudioSink * sink);
 
@@ -179,6 +181,9 @@ gst_osx_audio_sink_class_init (GstOsxAudioSinkClass * klass)
   gobject_class->set_property = gst_osx_audio_sink_set_property;
   gobject_class->get_property = gst_osx_audio_sink_get_property;
 
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_osx_audio_sink_change_state);
+
 #ifndef HAVE_IOS
   g_object_class_install_property (gobject_class, ARG_DEVICE,
       g_param_spec_int ("device", "Device ID", "Device ID of output device",
@@ -248,6 +253,44 @@ gst_osx_audio_sink_set_property (GObject * object, guint prop_id,
   }
 }
 
+static GstStateChangeReturn
+gst_osx_audio_sink_change_state (GstElement * element,
+    GstStateChange transition)
+{
+  GstOsxAudioSink *osxsink = GST_OSX_AUDIO_SINK (element);
+  GstOsxAudioRingBuffer *ringbuffer;
+  GstStateChangeReturn ret;
+
+  switch (transition) {
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    goto out;
+
+  switch (transition) {
+    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;
+      break;
+
+    default:
+      break;
+  }
+
+out:
+  return ret;
+}
+
 static void
 gst_osx_audio_sink_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
@@ -452,13 +495,15 @@ gst_osx_audio_sink_create_ringbuffer (GstAudioBaseSink * sink)
       GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink),
       (void *) gst_osx_audio_sink_io_proc);
 
-  ringbuffer->select_device =
-      GST_DEBUG_FUNCPTR (gst_osx_audio_sink_select_device);
-
   ringbuffer->core_audio->element =
       GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink);
   ringbuffer->core_audio->is_src = FALSE;
 
+  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);
 }
 
@@ -648,19 +693,3 @@ gst_osx_audio_sink_probe_caps (GstOsxAudioSink * osxsink)
   osxsink->cached_caps = caps;
   osxsink->channels = channels;
 }
-
-static gboolean
-gst_osx_audio_sink_select_device (GstElement * sink,
-    GstOsxAudioRingBuffer * ringbuffer)
-{
-  GstOsxAudioSink *osxsink = GST_OSX_AUDIO_SINK (sink);
-
-  if (!gst_core_audio_select_device (&osxsink->device_id, TRUE))
-    return FALSE;
-
-  ringbuffer->core_audio->device_id = osxsink->device_id;
-
-  gst_osx_audio_sink_set_volume (osxsink);
-
-  return TRUE;
-}
index 6698714ffe49da71df55d6ebb707b7c75e1fd2e0..c47b861862e2308d0712dfa6a5d1f1d5594f3cfb 100644 (file)
@@ -99,6 +99,10 @@ static void gst_osx_audio_src_set_property (GObject * object, guint prop_id,
 static void gst_osx_audio_src_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
+static GstStateChangeReturn
+gst_osx_audio_src_change_state (GstElement * element,
+    GstStateChange transition);
+
 static GstCaps *gst_osx_audio_src_get_caps (GstBaseSrc * src, GstCaps * filter);
 
 static GstAudioRingBuffer *gst_osx_audio_src_create_ringbuffer (GstAudioBaseSrc
@@ -109,8 +113,6 @@ static OSStatus gst_osx_audio_src_io_proc (GstOsxAudioRingBuffer * buf,
     AudioUnitRenderActionFlags * ioActionFlags,
     const AudioTimeStamp * inTimeStamp, UInt32 inBusNumber,
     UInt32 inNumberFrames, AudioBufferList * bufferList);
-static gboolean gst_osx_audio_src_select_device (GstElement * src,
-    GstOsxAudioRingBuffer * ringbuffer);
 
 static void
 gst_osx_audio_src_do_init (GType type)
@@ -127,6 +129,7 @@ gst_osx_audio_src_do_init (GType type)
       &osxelement_info);
 }
 
+#define gst_osx_audio_src_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstOsxAudioSrc, gst_osx_audio_src,
     GST_TYPE_AUDIO_BASE_SRC, gst_osx_audio_src_do_init (g_define_type_id));
 
@@ -146,6 +149,9 @@ gst_osx_audio_src_class_init (GstOsxAudioSrcClass * klass)
   gobject_class->set_property = gst_osx_audio_src_set_property;
   gobject_class->get_property = gst_osx_audio_src_get_property;
 
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_osx_audio_src_change_state);
+
   gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_osx_audio_src_get_caps);
 
   g_object_class_install_property (gobject_class, ARG_DEVICE,
@@ -205,6 +211,38 @@ gst_osx_audio_src_get_property (GObject * object, guint prop_id,
   }
 }
 
+static GstStateChangeReturn
+gst_osx_audio_src_change_state (GstElement * element, GstStateChange transition)
+{
+  GstOsxAudioSrc *osxsrc = GST_OSX_AUDIO_SRC (element);
+  GstOsxAudioRingBuffer *ringbuffer;
+  GstStateChangeReturn ret;
+
+  switch (transition) {
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    goto out;
+
+  switch (transition) {
+    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_SRC (osxsrc)->ringbuffer);
+      osxsrc->device_id = ringbuffer->core_audio->device_id;
+      break;
+
+    default:
+      break;
+  }
+
+out:
+  return ret;
+}
+
 static GstCaps *
 gst_osx_audio_src_get_caps (GstBaseSrc * src, GstCaps * filter)
 {
@@ -258,13 +296,15 @@ gst_osx_audio_src_create_ringbuffer (GstAudioBaseSrc * src)
       GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc),
       (void *) gst_osx_audio_src_io_proc);
 
-  ringbuffer->select_device =
-      GST_DEBUG_FUNCPTR (gst_osx_audio_src_select_device);
-
   ringbuffer->core_audio->element =
       GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc);
   ringbuffer->core_audio->is_src = TRUE;
 
+  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);
 }
 
@@ -326,16 +366,3 @@ gst_osx_audio_src_osxelement_init (gpointer g_iface, gpointer iface_data)
 
   iface->io_proc = (AURenderCallback) gst_osx_audio_src_io_proc;
 }
-
-static gboolean
-gst_osx_audio_src_select_device (GstOsxAudioSrc * osxsrc)
-{
-  GstOsxAudioSrc *osxsrc = GST_OSX_AUDIO_SRC (element);
-
-  if (!gst_core_audio_select_device (&osxsrc->device_id, FALSE))
-    return FALSE;
-
-  ringbuffer->core_audio->device_id = osxsrc->device_id;
-
-  return TRUE;
-}
index d7129f13ba0c200b30c715bc2dda1b0303bbf3f9..03763eb3ffeb22bd7ebd0a78b5d3ae529192b018 100644 (file)
@@ -196,9 +196,9 @@ gst_core_audio_set_volume (GstCoreAudio * core_audio, gfloat volume)
 }
 
 gboolean
-gst_core_audio_select_device (AudioDeviceID * device_id, gboolean output)
+gst_core_audio_select_device (GstCoreAudio * core_audio)
 {
-  return gst_core_audio_select_device_impl (device_id, output);
+  return gst_core_audio_select_device_impl (core_audio);
 }
 
 void
index ff97f509b08859f77cb6b31ffc01eeb5242f5612..b1f7a285b09719bcfc1468a110bdaf09c090e6ab 100644 (file)
@@ -139,7 +139,7 @@ void  gst_core_audio_set_volume                              (GstCoreAudio *core
 gboolean gst_core_audio_audio_device_is_spdif_avail          (AudioDeviceID device_id);
 
 
-gboolean gst_core_audio_select_device                        (AudioDeviceID *device_id, gboolean output);
+gboolean gst_core_audio_select_device                        (GstCoreAudio * core_audio);
 
 AudioChannelLayout * gst_core_audio_audio_device_get_channel_layout (AudioDeviceID device_id, gboolean output);
 
index 92e4046d00dddb4863a3e3951ffc8de3346137d3..4c2eb490f30bb105af9816f15785622c7290a1ca 100644 (file)
@@ -71,6 +71,8 @@ _audio_system_get_default_device (gboolean output)
     GST_ERROR ("failed getting default output device: %d", (int) status);
   }
 
+  GST_DEBUG ("Default device id: %u", (unsigned) device_id);
+
   return device_id;
 }
 
@@ -1148,11 +1150,13 @@ done:
 }
 
 static gboolean
-gst_core_audio_select_device_impl (AudioDeviceID * device_id, gboolean output)
+gst_core_audio_select_device_impl (GstCoreAudio * core_audio)
 {
   AudioDeviceID *devices = NULL;
+  AudioDeviceID device_id = core_audio->device_id;
   AudioDeviceID default_device_id = 0;
   gint i, ndevices = 0;
+  gboolean output = !core_audio->is_src;
   gboolean res = FALSE;
 #ifdef GST_CORE_AUDIO_DEBUG
   AudioChannelLayout *channel_layout;
@@ -1197,9 +1201,9 @@ gst_core_audio_select_device_impl (AudioDeviceID * device_id, gboolean output)
 
   /* Here we decide if selected device is valid or autoselect
    * the default one when required */
-  if (*device_id == kAudioDeviceUnknown) {
+  if (device_id == kAudioDeviceUnknown) {
     if (default_device_id != kAudioDeviceUnknown) {
-      *device_id = default_device_id;
+      device_id = default_device_id;
       res = TRUE;
     } else {
       /* No device of required type available */
@@ -1207,18 +1211,21 @@ gst_core_audio_select_device_impl (AudioDeviceID * device_id, gboolean output)
     }
   } else {
     for (i = 0; i < ndevices; i++) {
-      if (*device_id == devices[i]) {
+      if (device_id == devices[i]) {
         res = TRUE;
       }
     }
 
-    if (res && !_audio_device_is_alive (*device_id, output)) {
+    if (res && !_audio_device_is_alive (device_id, output)) {
       GST_ERROR ("Requested device not usable");
       res = FALSE;
       goto done;
     }
   }
 
+  if (res)
+    core_audio->device_id = device_id;
+
 done:
   g_free (devices);
   return res;
index 58ad5d036bdd66564a25fc0331cdb85a130e70d8..238617b4a3a5c472c91406cb7c0eee814cdb8afb 100644 (file)
@@ -106,7 +106,7 @@ gst_core_audio_audio_device_get_channel_layout (AudioDeviceID device_id)
 }
 
 static gboolean
-gst_core_audio_select_device_impl (AudioDeviceID * device_id, gboolean output)
+gst_core_audio_select_device_impl (GstCoreAudio * core_audio)
 {
   /* No device selection in iOS */
   return TRUE;