From f0f9f5ac7f2b7fd9ffd74a962b37d3a65d260fea Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Thu, 18 May 2006 17:19:39 +0000 Subject: [PATCH] ext/alsa/: Clean up and simplify alsa device probing. Make it actually work for multiple classes. Don't cache results... Original commit message from CVS: * ext/alsa/gstalsadeviceprobe.c: (gst_alsa_get_device_list), (gst_alsa_device_property_probe_probe_property), (gst_alsa_device_property_probe_needs_probe), (gst_alsa_device_property_probe_get_values), (gst_alsa_type_add_device_property_probe_interface): * ext/alsa/gstalsadeviceprobe.h: * ext/alsa/gstalsamixerelement.c: (gst_alsa_mixer_element_init_interfaces): * ext/alsa/gstalsamixerelement.h: Clean up and simplify alsa device probing. Make it actually work for multiple classes. Don't cache results any longer. * ext/alsa/gstalsasink.c: (gst_alsasink_init_interfaces), (gst_alsasink_init): * ext/alsa/gstalsasrc.c: (gst_alsasrc_dispose), (gst_alsasrc_interface_supported), (gst_implements_interface_init), (gst_alsasrc_init_interfaces), (gst_alsasrc_set_property): Make alsasink and alsasrc implement the GstPropertyProbe interface for device probing (#342181). Patch by: Martin Szulecki --- ChangeLog | 23 ++++ common | 2 +- ext/alsa/gstalsadeviceprobe.c | 190 +++++++++------------------------ ext/alsa/gstalsadeviceprobe.h | 12 +-- ext/alsa/gstalsamixerelement.c | 4 +- ext/alsa/gstalsamixerelement.h | 3 - ext/alsa/gstalsasink.c | 45 +++----- ext/alsa/gstalsasrc.c | 53 ++++++++- 8 files changed, 139 insertions(+), 193 deletions(-) diff --git a/ChangeLog b/ChangeLog index 293371ad3c..0b1c785968 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2006-05-18 Tim-Philipp Müller + + * ext/alsa/gstalsadeviceprobe.c: (gst_alsa_get_device_list), + (gst_alsa_device_property_probe_probe_property), + (gst_alsa_device_property_probe_needs_probe), + (gst_alsa_device_property_probe_get_values), + (gst_alsa_type_add_device_property_probe_interface): + * ext/alsa/gstalsadeviceprobe.h: + * ext/alsa/gstalsamixerelement.c: + (gst_alsa_mixer_element_init_interfaces): + * ext/alsa/gstalsamixerelement.h: + Clean up and simplify alsa device probing. Make it actually work + for multiple classes. Don't cache results any longer. + + * ext/alsa/gstalsasink.c: (gst_alsasink_init_interfaces), + (gst_alsasink_init): + * ext/alsa/gstalsasrc.c: (gst_alsasrc_dispose), + (gst_alsasrc_interface_supported), (gst_implements_interface_init), + (gst_alsasrc_init_interfaces), (gst_alsasrc_set_property): + Make alsasink and alsasrc implement the GstPropertyProbe interface + for device probing (#342181). + Patch by: Martin Szulecki + 2006-05-18 Tim-Philipp Müller * gst/subparse/samiparse.c: (handle_start_font): diff --git a/common b/common index 8eb9ea4613..a5b66304e7 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 8eb9ea46137c34191bdbeca946ca4419ba573b51 +Subproject commit a5b66304e7abe1440a0f8b0ed232ffbc56e8f3de diff --git a/ext/alsa/gstalsadeviceprobe.c b/ext/alsa/gstalsadeviceprobe.c index 606918c5b4..d34cc99c65 100644 --- a/ext/alsa/gstalsadeviceprobe.c +++ b/ext/alsa/gstalsadeviceprobe.c @@ -26,12 +26,6 @@ #include "gstalsadeviceprobe.h" #include "gst/interfaces/propertyprobe.h" -#define DATA_OFFSET_QUARK \ - g_quark_from_static_string ("alsa-device-probe-data-offset-quark") - -#define DEVICE_PROPID_QUARK \ - g_quark_from_static_string ("alsa-device-probe-device-propid-quark") - static const GList * gst_alsa_device_property_probe_get_properties (GstPropertyProbe * probe) { @@ -54,48 +48,15 @@ gst_alsa_device_property_probe_get_properties (GstPropertyProbe * probe) return list; } -/* yes, this is evil, but hey, it works */ - -static gboolean -gst_alsa_device_probe_get_data (GObject * obj, GstAlsaDeviceProbeData ** p_data, - guint * p_device_propid) -{ - gpointer klass; - guint devpropid; - guint offset; - GType type; - - type = G_TYPE_FROM_INSTANCE (obj); - - /* in case this is a derived class ... */ - while (g_type_get_qdata (type, DATA_OFFSET_QUARK) == NULL) { - type = g_type_parent (type); - g_return_val_if_fail (G_TYPE_IS_FUNDAMENTAL (type) == FALSE, FALSE); - } - - offset = GPOINTER_TO_UINT (g_type_get_qdata (type, DATA_OFFSET_QUARK)); - devpropid = GPOINTER_TO_UINT (g_type_get_qdata (type, DEVICE_PROPID_QUARK)); - - g_return_val_if_fail (offset != 0, FALSE); - g_return_val_if_fail (devpropid != 0, FALSE); - - klass = G_OBJECT_GET_CLASS (obj); - - *p_data = (GstAlsaDeviceProbeData *) G_STRUCT_MEMBER_P (klass, offset); - *p_device_propid = devpropid; - - return TRUE; -} - -static void -gst_alsa_add_device_list (GstAlsaDeviceProbeData * probe_data, - snd_pcm_stream_t stream) +static GList * +gst_alsa_get_device_list (snd_pcm_stream_t stream) { snd_ctl_t *handle; int card, err, dev; snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; gboolean mixer = (stream == -1); + GList *list = NULL; if (stream == -1) stream = 0; @@ -106,8 +67,9 @@ gst_alsa_add_device_list (GstAlsaDeviceProbeData * probe_data, if (snd_card_next (&card) < 0 || card < 0) { /* no soundcard found */ - return; + return NULL; } + while (card >= 0) { gchar name[32]; @@ -121,8 +83,7 @@ gst_alsa_add_device_list (GstAlsaDeviceProbeData * probe_data, } if (mixer) { - probe_data->devices = g_list_append (probe_data->devices, - g_strdup (name)); + list = g_list_append (list, g_strdup (name)); } else { dev = -1; while (1) { @@ -140,7 +101,7 @@ gst_alsa_add_device_list (GstAlsaDeviceProbeData * probe_data, } gst_device = g_strdup_printf ("hw:%d,%d", card, dev); - probe_data->devices = g_list_append (probe_data->devices, gst_device); + list = g_list_append (list, gst_device); } } snd_ctl_close (handle); @@ -149,52 +110,15 @@ gst_alsa_add_device_list (GstAlsaDeviceProbeData * probe_data, break; } } -} -static gboolean -gst_alsa_probe_devices (GstElementClass * klass, - GstAlsaDeviceProbeData * probe_data, gboolean check) -{ - static gboolean init = FALSE; - - /* I'm pretty sure ALSA has a good way to do this. However, their cool - * auto-generated documentation is pretty much useless if you try to - * do function-wise look-ups. */ - - if (!init && !check) { - snd_pcm_stream_t mode = -1; - const GList *templates; - - /* we assume one pad template at max [zero=mixer] */ - templates = gst_element_class_get_pad_template_list (klass); - if (templates) { - if (GST_PAD_TEMPLATE_DIRECTION (templates->data) == GST_PAD_SRC) - mode = SND_PCM_STREAM_CAPTURE; - else - mode = SND_PCM_STREAM_PLAYBACK; - } - - gst_alsa_add_device_list (probe_data, mode); - - init = TRUE; - } - - return init; + return list; } static void gst_alsa_device_property_probe_probe_property (GstPropertyProbe * probe, guint prop_id, const GParamSpec * pspec) { - GstAlsaDeviceProbeData *probe_data; - guint devid; - - if (!gst_alsa_device_probe_get_data (G_OBJECT (probe), &probe_data, &devid)) - g_return_if_reached (); - - if (prop_id == devid) { - gst_alsa_probe_devices (GST_ELEMENT_GET_CLASS (probe), probe_data, FALSE); - } else { + if (!g_str_equal (pspec->name, "device")) { G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); } } @@ -203,59 +127,59 @@ static gboolean gst_alsa_device_property_probe_needs_probe (GstPropertyProbe * probe, guint prop_id, const GParamSpec * pspec) { - GstAlsaDeviceProbeData *probe_data; - GstElementClass *klass; - guint devid; - - if (!gst_alsa_device_probe_get_data (G_OBJECT (probe), &probe_data, &devid)) - g_return_val_if_reached (FALSE); - - if (prop_id != devid) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); - return FALSE; - } - - klass = GST_ELEMENT_GET_CLASS (probe); - return !gst_alsa_probe_devices (klass, probe_data, TRUE); -} - -static GValueArray * -gst_alsa_device_probe_list_devices (GstAlsaDeviceProbeData * probe_data) -{ - GValueArray *array; - GValue value = { 0 }; - GList *item; - - if (!probe_data->devices) - return NULL; - - array = g_value_array_new (g_list_length (probe_data->devices)); - g_value_init (&value, G_TYPE_STRING); - for (item = probe_data->devices; item != NULL; item = item->next) { - g_value_set_string (&value, (const gchar *) item->data); - g_value_array_append (array, &value); - } - g_value_unset (&value); - - return array; + /* don't cache probed data */ + return TRUE; } static GValueArray * gst_alsa_device_property_probe_get_values (GstPropertyProbe * probe, guint prop_id, const GParamSpec * pspec) { - GstAlsaDeviceProbeData *probe_data; - guint devid; + GstElementClass *klass; + const GList *templates; + snd_pcm_stream_t mode = -1; + GValueArray *array; + GValue value = { 0, }; + GList *l, *list; - if (!gst_alsa_device_probe_get_data (G_OBJECT (probe), &probe_data, &devid)) - g_return_val_if_reached (NULL); - - if (prop_id != devid) { + if (!g_str_equal (pspec->name, "device")) { G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); return NULL; } - return gst_alsa_device_probe_list_devices (probe_data); + klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe)); + + /* I'm pretty sure ALSA has a good way to do this. However, their cool + * auto-generated documentation is pretty much useless if you try to + * do function-wise look-ups. */ + /* we assume one pad template at max [zero=mixer] */ + templates = gst_element_class_get_pad_template_list (klass); + if (templates) { + if (GST_PAD_TEMPLATE_DIRECTION (templates->data) == GST_PAD_SRC) + mode = SND_PCM_STREAM_CAPTURE; + else + mode = SND_PCM_STREAM_PLAYBACK; + } + + list = gst_alsa_get_device_list (mode); + + if (list == NULL) { + GST_LOG_OBJECT (probe, "No devices found"); + return NULL; + } + + array = g_value_array_new (g_list_length (list)); + g_value_init (&value, G_TYPE_STRING); + for (l = list; l != NULL; l = l->next) { + GST_LOG_OBJECT (probe, "Found device: %s", l->data); + g_value_take_string (&value, (gchar *) l->data); + l->data = NULL; + g_value_array_append (array, &value); + } + g_value_unset (&value); + g_list_free (list); + + return array; } static void @@ -268,8 +192,7 @@ gst_alsa_property_probe_interface_init (GstPropertyProbeInterface * iface) } void -gst_alsa_type_add_device_property_probe_interface (GType type, - guint probe_data_klass_offset, guint device_prop_id) +gst_alsa_type_add_device_property_probe_interface (GType type) { static const GInterfaceInfo probe_iface_info = { (GInterfaceInitFunc) gst_alsa_property_probe_interface_init, @@ -277,15 +200,6 @@ gst_alsa_type_add_device_property_probe_interface (GType type, NULL, }; - g_assert (probe_data_klass_offset != 0); - g_assert (device_prop_id != 0); - - g_type_set_qdata (type, DATA_OFFSET_QUARK, - GUINT_TO_POINTER (probe_data_klass_offset)); - - g_type_set_qdata (type, DEVICE_PROPID_QUARK, - GUINT_TO_POINTER (device_prop_id)); - g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE, &probe_iface_info); } diff --git a/ext/alsa/gstalsadeviceprobe.h b/ext/alsa/gstalsadeviceprobe.h index 3ad2076582..b60b0fef9e 100644 --- a/ext/alsa/gstalsadeviceprobe.h +++ b/ext/alsa/gstalsadeviceprobe.h @@ -25,17 +25,7 @@ G_BEGIN_DECLS -typedef struct _GstAlsaDeviceProbeData GstAlsaDeviceProbeData; - -struct _GstAlsaDeviceProbeData { - /* autodetected devices available */ - GList *devices; -}; - -/* offset is the offset of the device probe data struct in the klass struct */ -void gst_alsa_type_add_device_property_probe_interface (GType type, - guint probe_data_offset, - guint device_prop_id); +void gst_alsa_type_add_device_property_probe_interface (GType type); G_END_DECLS diff --git a/ext/alsa/gstalsamixerelement.c b/ext/alsa/gstalsamixerelement.c index 36fe2b6558..2fa5bec713 100644 --- a/ext/alsa/gstalsamixerelement.c +++ b/ext/alsa/gstalsamixerelement.c @@ -94,9 +94,7 @@ gst_alsa_mixer_element_init_interfaces (GType type) &implements_iface_info); g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info); - gst_alsa_type_add_device_property_probe_interface (type, - G_STRUCT_OFFSET (GstAlsaMixerElementClass, device_probe_data), - PROP_DEVICE); + gst_alsa_type_add_device_property_probe_interface (type); } static void diff --git a/ext/alsa/gstalsamixerelement.h b/ext/alsa/gstalsamixerelement.h index 3b85afb297..67cb391812 100644 --- a/ext/alsa/gstalsamixerelement.h +++ b/ext/alsa/gstalsamixerelement.h @@ -23,7 +23,6 @@ #include "gstalsa.h" #include "gstalsamixer.h" -#include "gstalsadeviceprobe.h" G_BEGIN_DECLS @@ -50,8 +49,6 @@ struct _GstAlsaMixerElement { struct _GstAlsaMixerElementClass { GstElementClass parent; - - GstAlsaDeviceProbeData device_probe_data; }; diff --git a/ext/alsa/gstalsasink.c b/ext/alsa/gstalsasink.c index c0112c112b..17f5768dbf 100644 --- a/ext/alsa/gstalsasink.c +++ b/ext/alsa/gstalsasink.c @@ -54,6 +54,7 @@ #include "gstalsa.h" #include "gstalsasink.h" +#include "gstalsadeviceprobe.h" #include @@ -74,9 +75,11 @@ enum PROP_DEVICE_NAME }; -static void gst_alsasink_base_init (gpointer g_class); -static void gst_alsasink_class_init (GstAlsaSinkClass * klass); -static void gst_alsasink_init (GstAlsaSink * alsasink); +static void gst_alsasink_init_interfaces (GType type); + +GST_BOILERPLATE_FULL (GstAlsaSink, gst_alsasink, GstAudioSink, + GST_TYPE_AUDIO_SINK, gst_alsasink_init_interfaces); + static void gst_alsasink_dispose (GObject * object); static void gst_alsasink_finalise (GObject * object); static void gst_alsasink_set_property (GObject * object, @@ -130,34 +133,6 @@ static GstStaticPadTemplate alsasink_sink_factory = "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 8 ]") ); -static GstElementClass *parent_class = NULL; - -GType -gst_alsasink_get_type (void) -{ - static GType alsasink_type = 0; - - if (!alsasink_type) { - static const GTypeInfo alsasink_info = { - sizeof (GstAlsaSinkClass), - gst_alsasink_base_init, - NULL, - (GClassInitFunc) gst_alsasink_class_init, - NULL, - NULL, - sizeof (GstAlsaSink), - 0, - (GInstanceInitFunc) gst_alsasink_init, - }; - - alsasink_type = - g_type_register_static (GST_TYPE_AUDIO_SINK, "GstAlsaSink", - &alsasink_info, 0); - } - - return alsasink_type; -} - static void gst_alsasink_dispose (GObject * object) { @@ -183,6 +158,12 @@ gst_alsasink_finalise (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +gst_alsasink_init_interfaces (GType type) +{ + gst_alsa_type_add_device_property_probe_interface (type); +} + static void gst_alsasink_base_init (gpointer g_class) { @@ -287,7 +268,7 @@ gst_alsasink_get_property (GObject * object, guint prop_id, } static void -gst_alsasink_init (GstAlsaSink * alsasink) +gst_alsasink_init (GstAlsaSink * alsasink, GstAlsaSinkClass * g_class) { GST_DEBUG_OBJECT (alsasink, "initializing alsasink"); diff --git a/ext/alsa/gstalsasrc.c b/ext/alsa/gstalsasrc.c index 3970fffbb9..89ba5825de 100644 --- a/ext/alsa/gstalsasrc.c +++ b/ext/alsa/gstalsasrc.c @@ -52,6 +52,7 @@ #include #include "gstalsasrc.h" +#include "gstalsadeviceprobe.h" #include @@ -72,8 +73,10 @@ enum PROP_DEVICE_NAME, }; -GST_BOILERPLATE_WITH_INTERFACE (GstAlsaSrc, gst_alsasrc, GstAudioSrc, - GST_TYPE_AUDIO_SRC, GstMixer, GST_TYPE_MIXER, gst_alsasrc_mixer); +static void gst_alsasrc_init_interfaces (GType type); + +GST_BOILERPLATE_FULL (GstAlsaSrc, gst_alsasrc, GstAudioSrc, + GST_TYPE_AUDIO_SRC, gst_alsasrc_init_interfaces); GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaSrc, gst_alsasrc_mixer); @@ -126,9 +129,50 @@ static GstStaticPadTemplate alsasrc_src_factory = static void gst_alsasrc_dispose (GObject * object) { + GstAlsaSrc *src = GST_ALSA_SRC (object); + + g_free (src->device); + src->device = NULL; + G_OBJECT_CLASS (parent_class)->dispose (object); } +static gboolean +gst_alsasrc_interface_supported (GstAlsaSrc * this, GType interface_type) +{ + /* only support this one interface (wrapped by GstImplementsInterface) */ + g_assert (interface_type == GST_TYPE_MIXER); + + return gst_alsasrc_mixer_supported (this, interface_type); +} + +static void +gst_implements_interface_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = (gpointer) gst_alsasrc_interface_supported; +} + +static void +gst_alsasrc_init_interfaces (GType type) +{ + static const GInterfaceInfo implements_iface_info = { + (GInterfaceInitFunc) gst_implements_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo mixer_iface_info = { + (GInterfaceInitFunc) gst_alsasrc_mixer_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, + &implements_iface_info); + g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info); + + gst_alsa_type_add_device_property_probe_interface (type); +} + static void gst_alsasrc_base_init (gpointer g_class) { @@ -190,9 +234,8 @@ gst_alsasrc_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_DEVICE: - if (src->device) - g_free (src->device); - src->device = g_strdup (g_value_get_string (value)); + g_free (src->device); + src->device = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);