From ffcb1577fa267ade69ba83e0b62d9ebacb8ef7ed Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Fri, 28 Nov 2014 22:23:17 +0530 Subject: [PATCH] osxaudio: Clean up a GstCoreAudio -> GstOsxAudioSrc/Sink reference 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 | 3 +- sys/osxaudio/gstosxaudioringbuffer.h | 3 -- sys/osxaudio/gstosxaudiosink.c | 71 ++++++++++++++++++-------- sys/osxaudio/gstosxaudiosrc.c | 63 ++++++++++++++++------- sys/osxaudio/gstosxcoreaudio.c | 4 +- sys/osxaudio/gstosxcoreaudio.h | 2 +- sys/osxaudio/gstosxcoreaudiohal.c | 17 ++++-- sys/osxaudio/gstosxcoreaudioremoteio.c | 2 +- 8 files changed, 112 insertions(+), 53 deletions(-) diff --git a/sys/osxaudio/gstosxaudioringbuffer.c b/sys/osxaudio/gstosxaudioringbuffer.c index 0476651511..7f9b86fa47 100644 --- a/sys/osxaudio/gstosxaudioringbuffer.c +++ b/sys/osxaudio/gstosxaudioringbuffer.c @@ -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); diff --git a/sys/osxaudio/gstosxaudioringbuffer.h b/sys/osxaudio/gstosxaudioringbuffer.h index dbc2e12256..5054fd3853 100644 --- a/sys/osxaudio/gstosxaudioringbuffer.h +++ b/sys/osxaudio/gstosxaudioringbuffer.h @@ -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; }; diff --git a/sys/osxaudio/gstosxaudiosink.c b/sys/osxaudio/gstosxaudiosink.c index 10f5b24bad..51b87bf0ea 100644 --- a/sys/osxaudio/gstosxaudiosink.c +++ b/sys/osxaudio/gstosxaudiosink.c @@ -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; -} diff --git a/sys/osxaudio/gstosxaudiosrc.c b/sys/osxaudio/gstosxaudiosrc.c index 6698714ffe..c47b861862 100644 --- a/sys/osxaudio/gstosxaudiosrc.c +++ b/sys/osxaudio/gstosxaudiosrc.c @@ -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; -} diff --git a/sys/osxaudio/gstosxcoreaudio.c b/sys/osxaudio/gstosxcoreaudio.c index d7129f13ba..03763eb3ff 100644 --- a/sys/osxaudio/gstosxcoreaudio.c +++ b/sys/osxaudio/gstosxcoreaudio.c @@ -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 diff --git a/sys/osxaudio/gstosxcoreaudio.h b/sys/osxaudio/gstosxcoreaudio.h index ff97f509b0..b1f7a285b0 100644 --- a/sys/osxaudio/gstosxcoreaudio.h +++ b/sys/osxaudio/gstosxcoreaudio.h @@ -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); diff --git a/sys/osxaudio/gstosxcoreaudiohal.c b/sys/osxaudio/gstosxcoreaudiohal.c index 92e4046d00..4c2eb490f3 100644 --- a/sys/osxaudio/gstosxcoreaudiohal.c +++ b/sys/osxaudio/gstosxcoreaudiohal.c @@ -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; diff --git a/sys/osxaudio/gstosxcoreaudioremoteio.c b/sys/osxaudio/gstosxcoreaudioremoteio.c index 58ad5d036b..238617b4a3 100644 --- a/sys/osxaudio/gstosxcoreaudioremoteio.c +++ b/sys/osxaudio/gstosxcoreaudioremoteio.c @@ -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;