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  <gnomebugzilla at sukimashita com>
This commit is contained in:
Martin Szulecki 2006-05-18 17:19:39 +00:00 committed by Tim-Philipp Müller
parent 320a2f974a
commit f0f9f5ac7f
8 changed files with 139 additions and 193 deletions

View file

@ -1,3 +1,26 @@
2006-05-18 Tim-Philipp Müller <tim at centricular dot net>
* 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 <gnomebugzilla at sukimashita com>
2006-05-18 Tim-Philipp Müller <tim at centricular dot net>
* gst/subparse/samiparse.c: (handle_start_font):

2
common

@ -1 +1 @@
Subproject commit 8eb9ea46137c34191bdbeca946ca4419ba573b51
Subproject commit a5b66304e7abe1440a0f8b0ed232ffbc56e8f3de

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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;
};

View file

@ -54,6 +54,7 @@
#include "gstalsa.h"
#include "gstalsasink.h"
#include "gstalsadeviceprobe.h"
#include <gst/gst-i18n-plugin.h>
@ -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");

View file

@ -52,6 +52,7 @@
#include <alsa/asoundlib.h>
#include "gstalsasrc.h"
#include "gstalsadeviceprobe.h"
#include <gst/gst-i18n-plugin.h>
@ -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);