#include "gstalsasrc.h"
#include "gstalsadeviceprobe.h"
+#include "gst/glib-compat-private.h"
#include <gst/gst-i18n-plugin.h>
-/* elementfactory information */
-static const GstElementDetails gst_alsasrc_details =
-GST_ELEMENT_DETAILS ("Audio source (ALSA)",
- "Source/Audio",
- "Read from a sound card via ALSA",
- "Wim Taymans <wim@fluendo.com>");
-
#define DEFAULT_PROP_DEVICE "default"
#define DEFAULT_PROP_DEVICE_NAME ""
+#define DEFAULT_PROP_CARD_NAME ""
enum
{
PROP_0,
PROP_DEVICE,
PROP_DEVICE_NAME,
+ PROP_CARD_NAME,
+ PROP_LAST
};
static void gst_alsasrc_init_interfaces (GType type);
-
-GST_BOILERPLATE_FULL (GstAlsaSrc, gst_alsasrc, GstAudioSrc,
- GST_TYPE_AUDIO_SRC, gst_alsasrc_init_interfaces);
+#define gst_alsasrc_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstAlsaSrc, gst_alsasrc,
+ GST_TYPE_AUDIO_SRC, gst_alsasrc_init_interfaces (g_define_type_id));
GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaSrc, gst_alsasrc_mixer);
static void gst_alsasrc_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec);
-static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc);
+static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
static gboolean gst_alsasrc_open (GstAudioSrc * asrc);
static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc,
- GstRingBufferSpec * spec);
+ GstAudioRingBufferSpec * spec);
static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc);
static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
#endif
static GstStaticPadTemplate alsasrc_src_factory =
- GST_STATIC_PAD_TEMPLATE ("src",
+GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 32, "
- "depth = (int) 32, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 32, "
- "depth = (int) 24, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 24, "
- "depth = (int) 24, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 16, "
- "depth = (int) 16, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 8, "
- "depth = (int) 8, "
+ GST_STATIC_CAPS ("audio/x-raw, "
+ "format = (string) " GST_AUDIO_FORMATS_ALL ", "
"rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
);
G_OBJECT_CLASS (parent_class)->finalize (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)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &gst_alsasrc_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&alsasrc_src_factory));
-}
-
-static void
gst_alsasrc_class_init (GstAlsaSrcClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSrcClass *gstbasesrc_class;
- GstBaseAudioSrcClass *gstbaseaudiosrc_class;
GstAudioSrcClass *gstaudiosrc_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass;
- gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
gstaudiosrc_class = (GstAudioSrcClass *) klass;
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasrc_finalize);
- gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasrc_get_property);
- gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasrc_set_property);
+ gobject_class->finalize = gst_alsasrc_finalize;
+ gobject_class->get_property = gst_alsasrc_get_property;
+ gobject_class->set_property = gst_alsasrc_set_property;
+
+ gst_element_class_set_details_simple (gstelement_class,
+ "Audio source (ALSA)", "Source/Audio",
+ "Read from a sound card via ALSA", "Wim Taymans <wim@fluendo.com>");
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&alsasrc_src_factory));
gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
g_param_spec_string ("device-name", "Device name",
"Human-readable name of the sound device",
DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_CARD_NAME,
+ g_param_spec_string ("card-name", "Card name",
+ "Human-readable name of the sound card",
+ DEFAULT_PROP_CARD_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
}
static void
gst_alsa_find_device_name (GST_OBJECT_CAST (src),
src->device, src->handle, SND_PCM_STREAM_CAPTURE));
break;
+ case PROP_CARD_NAME:
+ g_value_take_string (value,
+ gst_alsa_find_card_name (GST_OBJECT_CAST (src),
+ src->device, SND_PCM_STREAM_CAPTURE));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
static void
-gst_alsasrc_init (GstAlsaSrc * alsasrc, GstAlsaSrcClass * g_class)
+gst_alsasrc_init (GstAlsaSrc * alsasrc)
{
GST_DEBUG_OBJECT (alsasrc, "initializing");
static GstCaps *
-gst_alsasrc_getcaps (GstBaseSrc * bsrc)
+gst_alsasrc_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
{
GstElementClass *element_class;
GstPadTemplate *pad_template;
GstAlsaSrc *src;
- GstCaps *caps;
+ GstCaps *caps, *templ_caps;
src = GST_ALSA_SRC (bsrc);
if (src->handle == NULL) {
GST_DEBUG_OBJECT (src, "device not open, using template caps");
- return NULL; /* base class will get template caps for us */
+ return GST_BASE_SRC_CLASS (parent_class)->get_caps (bsrc, filter);
}
if (src->cached_caps) {
GST_LOG_OBJECT (src, "Returning cached caps");
- return gst_caps_ref (src->cached_caps);
+ if (filter)
+ return gst_caps_intersect_full (filter, src->cached_caps,
+ GST_CAPS_INTERSECT_FIRST);
+ else
+ return gst_caps_ref (src->cached_caps);
}
element_class = GST_ELEMENT_GET_CLASS (src);
pad_template = gst_element_class_get_pad_template (element_class, "src");
g_return_val_if_fail (pad_template != NULL, NULL);
+ templ_caps = gst_pad_template_get_caps (pad_template);
+ GST_INFO_OBJECT (src, "template caps %" GST_PTR_FORMAT, templ_caps);
+
caps = gst_alsa_probe_supported_formats (GST_OBJECT (src), src->handle,
- gst_pad_template_get_caps (pad_template));
+ templ_caps);
+ gst_caps_unref (templ_caps);
if (caps) {
src->cached_caps = gst_caps_ref (caps);
GST_INFO_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
- return caps;
+ if (filter) {
+ GstCaps *intersection;
+
+ intersection =
+ gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (caps);
+ return intersection;
+ } else {
+ return caps;
+ }
}
static int
set_hwparams (GstAlsaSrc * alsa)
{
guint rrate;
- gint err, dir;
+ gint err;
snd_pcm_hw_params_t *params;
snd_pcm_hw_params_malloc (¶ms);
if (alsa->buffer_time != -1) {
/* set the buffer time */
CHECK (snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
- &alsa->buffer_time, &dir), buffer_time);
+ &alsa->buffer_time, NULL), buffer_time);
}
if (alsa->period_time != -1) {
/* set the period time */
CHECK (snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
- &alsa->period_time, &dir), period_time);
+ &alsa->period_time, NULL), period_time);
}
/* write the parameters to device */
CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
buffer_size);
- CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
+ CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, NULL),
period_size);
snd_pcm_hw_params_free (params);
g_strdup_printf (_
("Could not open device for recording in %d-channel mode"),
alsa->channels);
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, ("%s", msg),
+ ("%s", snd_strerror (err)));
g_free (msg);
snd_pcm_hw_params_free (params);
return err;
}
static gboolean
-alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * spec)
+alsasrc_parse_spec (GstAlsaSrc * alsa, GstAudioRingBufferSpec * spec)
{
switch (spec->type) {
- case GST_BUFTYPE_LINEAR:
- alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
- spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
- break;
- case GST_BUFTYPE_FLOAT:
- switch (spec->format) {
- case GST_FLOAT32_LE:
+ case GST_BUFTYPE_RAW:
+ switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
+ case GST_AUDIO_FORMAT_U8:
+ alsa->format = SND_PCM_FORMAT_U8;
+ break;
+ case GST_AUDIO_FORMAT_S8:
+ alsa->format = SND_PCM_FORMAT_S8;
+ break;
+ case GST_AUDIO_FORMAT_S16LE:
+ alsa->format = SND_PCM_FORMAT_S16_LE;
+ break;
+ case GST_AUDIO_FORMAT_S16BE:
+ alsa->format = SND_PCM_FORMAT_S16_BE;
+ break;
+ case GST_AUDIO_FORMAT_U16LE:
+ alsa->format = SND_PCM_FORMAT_U16_LE;
+ break;
+ case GST_AUDIO_FORMAT_U16BE:
+ alsa->format = SND_PCM_FORMAT_U16_BE;
+ break;
+ case GST_AUDIO_FORMAT_S24_32LE:
+ alsa->format = SND_PCM_FORMAT_S24_LE;
+ break;
+ case GST_AUDIO_FORMAT_S24_32BE:
+ alsa->format = SND_PCM_FORMAT_S24_BE;
+ break;
+ case GST_AUDIO_FORMAT_U24_32LE:
+ alsa->format = SND_PCM_FORMAT_U24_LE;
+ break;
+ case GST_AUDIO_FORMAT_U24_32BE:
+ alsa->format = SND_PCM_FORMAT_U24_BE;
+ break;
+ case GST_AUDIO_FORMAT_S32LE:
+ alsa->format = SND_PCM_FORMAT_S32_LE;
+ break;
+ case GST_AUDIO_FORMAT_S32BE:
+ alsa->format = SND_PCM_FORMAT_S32_BE;
+ break;
+ case GST_AUDIO_FORMAT_U32LE:
+ alsa->format = SND_PCM_FORMAT_U32_LE;
+ break;
+ case GST_AUDIO_FORMAT_U32BE:
+ alsa->format = SND_PCM_FORMAT_U32_BE;
+ break;
+ case GST_AUDIO_FORMAT_S24LE:
+ alsa->format = SND_PCM_FORMAT_S24_3LE;
+ break;
+ case GST_AUDIO_FORMAT_S24BE:
+ alsa->format = SND_PCM_FORMAT_S24_3BE;
+ break;
+ case GST_AUDIO_FORMAT_U24LE:
+ alsa->format = SND_PCM_FORMAT_U24_3LE;
+ break;
+ case GST_AUDIO_FORMAT_U24BE:
+ alsa->format = SND_PCM_FORMAT_U24_3BE;
+ break;
+ case GST_AUDIO_FORMAT_S20LE:
+ alsa->format = SND_PCM_FORMAT_S20_3LE;
+ break;
+ case GST_AUDIO_FORMAT_S20BE:
+ alsa->format = SND_PCM_FORMAT_S20_3BE;
+ break;
+ case GST_AUDIO_FORMAT_U20LE:
+ alsa->format = SND_PCM_FORMAT_U20_3LE;
+ break;
+ case GST_AUDIO_FORMAT_U20BE:
+ alsa->format = SND_PCM_FORMAT_U20_3BE;
+ break;
+ case GST_AUDIO_FORMAT_S18LE:
+ alsa->format = SND_PCM_FORMAT_S18_3LE;
+ break;
+ case GST_AUDIO_FORMAT_S18BE:
+ alsa->format = SND_PCM_FORMAT_S18_3BE;
+ break;
+ case GST_AUDIO_FORMAT_U18LE:
+ alsa->format = SND_PCM_FORMAT_U18_3LE;
+ break;
+ case GST_AUDIO_FORMAT_U18BE:
+ alsa->format = SND_PCM_FORMAT_U18_3BE;
+ break;
+ case GST_AUDIO_FORMAT_F32LE:
alsa->format = SND_PCM_FORMAT_FLOAT_LE;
break;
- case GST_FLOAT32_BE:
+ case GST_AUDIO_FORMAT_F32BE:
alsa->format = SND_PCM_FORMAT_FLOAT_BE;
break;
- case GST_FLOAT64_LE:
+ case GST_AUDIO_FORMAT_F64LE:
alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
break;
- case GST_FLOAT64_BE:
+ case GST_AUDIO_FORMAT_F64BE:
alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
break;
default:
goto error;
}
- alsa->rate = spec->rate;
- alsa->channels = spec->channels;
+ alsa->rate = GST_AUDIO_INFO_RATE (&spec->info);
+ alsa->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
alsa->buffer_time = spec->buffer_time;
alsa->period_time = spec->latency_time;
alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
}
static gboolean
-gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
+gst_alsasrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
{
GstAlsaSrc *alsa;
gint err;
CHECK (set_swparams (alsa), sw_params_failed);
CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);
- alsa->bytes_per_sample = spec->bytes_per_sample;
- spec->segsize = alsa->period_size * spec->bytes_per_sample;
+ alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info);
+ spec->segsize = alsa->period_size * alsa->bpf;
spec->segtotal = alsa->buffer_size / alsa->period_size;
- spec->silence_sample[0] = 0;
- spec->silence_sample[1] = 0;
- spec->silence_sample[2] = 0;
- spec->silence_sample[3] = 0;
return TRUE;
gst_alsasrc_unprepare (GstAudioSrc * asrc)
{
GstAlsaSrc *alsa;
- gint err;
alsa = GST_ALSA_SRC (asrc);
- CHECK (snd_pcm_drop (alsa->handle), drop);
-
- CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
-
- CHECK (snd_pcm_nonblock (alsa->handle, 1), non_block);
+ snd_pcm_drop (alsa->handle);
+ snd_pcm_hw_free (alsa->handle);
+ snd_pcm_nonblock (alsa->handle, 1);
return TRUE;
-
- /* ERRORS */
-drop:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not drop samples: %s", snd_strerror (err)));
- return FALSE;
- }
-hw_free:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not free hw params: %s", snd_strerror (err)));
- return FALSE;
- }
-non_block:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not set device to nonblocking: %s", snd_strerror (err)));
- return FALSE;
- }
}
static gboolean
alsa = GST_ALSA_SRC (asrc);
- cptr = length / alsa->bytes_per_sample;
+ cptr = length / alsa->bpf;
ptr = data;
GST_ALSA_SRC_LOCK (asrc);
}
GST_ALSA_SRC_UNLOCK (asrc);
- return length - cptr;
+ return length - (cptr * alsa->bpf);
read_error:
{