2 * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
25 #include <sys/ioctl.h>
31 #include <alsa/asoundlib.h>
34 #include "gstalsasrc.h"
36 /* elementfactory information */
37 static GstElementDetails gst_alsasrc_details =
38 GST_ELEMENT_DETAILS ("Audio Src (ALSA)",
40 "Output to a sound card via ALSA",
41 "Wim Taymans <wim@fluendo.com>");
50 GST_BOILERPLATE_WITH_INTERFACE (GstAlsaSrc, gst_alsasrc, GstAudioSrc,
51 GST_TYPE_AUDIO_SRC, GstMixer, GST_TYPE_MIXER, gst_alsasrc_mixer);
53 GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaSrc, gst_alsasrc_mixer);
55 static void gst_alsasrc_dispose (GObject * object);
56 static void gst_alsasrc_set_property (GObject * object,
57 guint prop_id, const GValue * value, GParamSpec * pspec);
58 static void gst_alsasrc_get_property (GObject * object,
59 guint prop_id, GValue * value, GParamSpec * pspec);
61 static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc);
63 static gboolean gst_alsasrc_open (GstAudioSrc * asrc);
64 static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc,
65 GstRingBufferSpec * spec);
66 static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc);
67 static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
68 static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
69 static guint gst_alsasrc_delay (GstAudioSrc * asrc);
70 static void gst_alsasrc_reset (GstAudioSrc * asrc);
72 /* AlsaSrc signals and args */
78 static GstStaticPadTemplate alsasrc_src_factory =
79 GST_STATIC_PAD_TEMPLATE ("src",
82 GST_STATIC_CAPS ("audio/x-raw-int, "
83 "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
84 "signed = (boolean) { TRUE, FALSE }, "
87 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
89 "signed = (boolean) { TRUE, FALSE }, "
92 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
96 gst_alsasrc_dispose (GObject * object)
98 G_OBJECT_CLASS (parent_class)->dispose (object);
102 gst_alsasrc_base_init (gpointer g_class)
104 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
106 gst_element_class_set_details (element_class, &gst_alsasrc_details);
108 gst_element_class_add_pad_template (element_class,
109 gst_static_pad_template_get (&alsasrc_src_factory));
113 gst_alsasrc_class_init (GstAlsaSrcClass * klass)
115 GObjectClass *gobject_class;
116 GstElementClass *gstelement_class;
117 GstBaseSrcClass *gstbasesrc_class;
118 GstBaseAudioSrcClass *gstbaseaudiosrc_class;
119 GstAudioSrcClass *gstaudiosrc_class;
121 gobject_class = (GObjectClass *) klass;
122 gstelement_class = (GstElementClass *) klass;
123 gstbasesrc_class = (GstBaseSrcClass *) klass;
124 gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
125 gstaudiosrc_class = (GstAudioSrcClass *) klass;
127 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_alsasrc_dispose);
128 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasrc_get_property);
129 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasrc_set_property);
131 gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
133 gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open);
134 gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasrc_prepare);
135 gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasrc_unprepare);
136 gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_alsasrc_close);
137 gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
138 gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay);
139 gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_alsasrc_reset);
141 g_object_class_install_property (gobject_class, PROP_DEVICE,
142 g_param_spec_string ("device", "Device",
143 "ALSA device, as defined in an asound configuration file",
144 "default", G_PARAM_READWRITE));
146 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
147 g_param_spec_string ("device-name", "Device name",
148 "Human-readable name of the sound device", "", G_PARAM_READABLE));
152 gst_alsasrc_set_property (GObject * object, guint prop_id,
153 const GValue * value, GParamSpec * pspec)
157 src = GST_ALSA_SRC (object);
162 g_free (src->device);
163 src->device = g_strdup (g_value_get_string (value));
166 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
172 gst_alsasrc_get_property (GObject * object, guint prop_id,
173 GValue * value, GParamSpec * pspec)
177 src = GST_ALSA_SRC (object);
181 g_value_set_string (value, src->device);
183 case PROP_DEVICE_NAME:
185 snd_pcm_info_t *info;
187 snd_pcm_info_malloc (&info);
188 snd_pcm_info (src->handle, info);
189 g_value_set_string (value, snd_pcm_info_get_name (info));
190 snd_pcm_info_free (info);
192 g_value_set_string (value, NULL);
196 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
202 gst_alsasrc_init (GstAlsaSrc * alsasrc, GstAlsaSrcClass * g_class)
204 GST_DEBUG ("initializing alsasrc");
206 alsasrc->device = g_strdup ("default");
210 gst_alsasrc_getcaps (GstBaseSrc * bsrc)
215 #define CHECK(call, error) \
217 if ((err = call) < 0) \
222 set_hwparams (GstAlsaSrc * alsa)
226 snd_pcm_hw_params_t *params;
228 snd_pcm_hw_params_alloca (¶ms);
230 /* choose all parameters */
231 CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
232 /* set the interleaved read/write format */
233 CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
235 /* set the sample format */
236 CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
238 /* set the count of channels */
239 CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
241 /* set the stream rate */
243 CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, 0),
245 if (rrate != alsa->rate)
248 if (alsa->buffer_time != -1) {
249 /* set the buffer time */
250 CHECK (snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
251 &alsa->buffer_time, &dir), buffer_time);
253 if (alsa->period_time != -1) {
254 /* set the period time */
255 CHECK (snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
256 &alsa->period_time, &dir), period_time);
259 /* write the parameters to device */
260 CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
262 CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
265 CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
273 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
274 ("Broken configuration for recording: no configurations available: %s",
275 snd_strerror (err)), (NULL));
280 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
281 ("Access type not available for recording: %s", snd_strerror (err)),
287 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
288 ("Sample format not available for recording: %s", snd_strerror (err)),
294 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
295 ("Channels count (%i) not available for recording: %s",
296 alsa->channels, snd_strerror (err)), (NULL));
301 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
302 ("Rate %iHz not available for recording: %s",
303 alsa->rate, snd_strerror (err)), (NULL));
308 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
309 ("Rate doesn't match (requested %iHz, get %iHz)",
310 alsa->rate, err), (NULL));
315 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
316 ("Unable to set buffer time %i for recording: %s",
317 alsa->buffer_time, snd_strerror (err)), (NULL));
322 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
323 ("Unable to get buffer size for recording: %s", snd_strerror (err)),
329 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
330 ("Unable to set period time %i for recording: %s", alsa->period_time,
331 snd_strerror (err)), (NULL));
336 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
337 ("Unable to get period size for recording: %s", snd_strerror (err)),
343 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
344 ("Unable to set hw params for recording: %s", snd_strerror (err)),
351 set_swparams (GstAlsaSrc * alsa)
354 snd_pcm_sw_params_t *params;
356 snd_pcm_sw_params_alloca (¶ms);
358 /* get the current swparams */
359 CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
360 /* start the transfer when the buffer is almost full: */
361 /* (buffer_size / avail_min) * avail_min */
363 CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
364 (alsa->buffer_size / alsa->period_size) * alsa->period_size),
367 /* allow the transfer when at least period_size samples can be processed */
368 CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
369 alsa->period_size), set_avail);
371 /* align all transfers to 1 sample */
372 CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
374 /* write the parameters to the recording device */
375 CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
382 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
383 ("Unable to determine current swparams for recording: %s",
384 snd_strerror (err)), (NULL));
390 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
391 ("Unable to set start threshold mode for recording: %s",
392 snd_strerror (err)), (NULL));
397 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
398 ("Unable to set avail min for recording: %s", snd_strerror (err)),
405 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
406 ("Unable to set transfer align for recording: %s", snd_strerror (err)),
412 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
413 ("Unable to set sw params for recording: %s", snd_strerror (err)),
420 alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * spec)
422 switch (spec->type) {
423 case GST_BUFTYPE_LINEAR:
424 alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
425 spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
427 case GST_BUFTYPE_FLOAT:
428 switch (spec->format) {
430 alsa->format = SND_PCM_FORMAT_FLOAT_LE;
433 alsa->format = SND_PCM_FORMAT_FLOAT_BE;
436 alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
439 alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
445 case GST_BUFTYPE_A_LAW:
446 alsa->format = SND_PCM_FORMAT_A_LAW;
448 case GST_BUFTYPE_MU_LAW:
449 alsa->format = SND_PCM_FORMAT_MU_LAW;
455 alsa->rate = spec->rate;
456 alsa->channels = spec->channels;
457 alsa->buffer_time = spec->buffer_time;
458 alsa->period_time = spec->latency_time;
459 alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
471 gst_alsasrc_open (GstAudioSrc * asrc)
476 alsa = GST_ALSA_SRC (asrc);
478 CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_CAPTURE,
479 SND_PCM_NONBLOCK), open_error);
482 alsa->mixer = gst_alsa_mixer_new (alsa->device, GST_ALSA_MIXER_CAPTURE);
489 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
490 ("Capture open error: %s", snd_strerror (err)), (NULL));
496 gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
501 alsa = GST_ALSA_SRC (asrc);
503 if (!alsasrc_parse_spec (alsa, spec))
506 CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);
508 CHECK (set_hwparams (alsa), hw_params_failed);
509 CHECK (set_swparams (alsa), sw_params_failed);
510 CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);
512 alsa->bytes_per_sample = spec->bytes_per_sample;
513 spec->segsize = alsa->period_size * spec->bytes_per_sample;
514 spec->segtotal = alsa->buffer_size / alsa->period_size;
515 spec->silence_sample[0] = 0;
516 spec->silence_sample[1] = 0;
517 spec->silence_sample[2] = 0;
518 spec->silence_sample[3] = 0;
525 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
526 ("Error parsing spec"), (NULL));
531 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
532 ("Could not set device to blocking: %s", snd_strerror (err)), (NULL));
537 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
538 ("Setting of hwparams failed: %s", snd_strerror (err)), (NULL));
543 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
544 ("Setting of swparams failed: %s", snd_strerror (err)), (NULL));
549 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
550 ("Prepare failed: %s", snd_strerror (err)), (NULL));
556 gst_alsasrc_unprepare (GstAudioSrc * asrc)
561 alsa = GST_ALSA_SRC (asrc);
563 CHECK (snd_pcm_drop (alsa->handle), drop);
565 CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
567 CHECK (snd_pcm_nonblock (alsa->handle, 1), non_block);
574 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
575 ("Could not drop samples: %s", snd_strerror (err)), (NULL));
580 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
581 ("Could not free hw params: %s", snd_strerror (err)), (NULL));
586 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
587 ("Could not set device to nonblocking: %s", snd_strerror (err)),
594 gst_alsasrc_close (GstAudioSrc * asrc)
596 GstAlsaSrc *alsa = GST_ALSA_SRC (asrc);
598 snd_pcm_close (alsa->handle);
601 gst_alsa_mixer_free (alsa->mixer);
609 * Underrun and suspend recovery
612 xrun_recovery (snd_pcm_t * handle, gint err)
614 GST_DEBUG ("xrun recovery %d", err);
616 if (err == -EPIPE) { /* under-run */
617 err = snd_pcm_prepare (handle);
619 GST_WARNING ("Can't recovery from underrun, prepare failed: %s",
622 } else if (err == -ESTRPIPE) {
623 while ((err = snd_pcm_resume (handle)) == -EAGAIN)
624 g_usleep (100); /* wait until the suspend flag is released */
627 err = snd_pcm_prepare (handle);
629 GST_WARNING ("Can't recovery from suspend, prepare failed: %s",
638 gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length)
645 alsa = GST_ALSA_SRC (asrc);
647 cptr = length / alsa->bytes_per_sample;
651 if ((err = snd_pcm_readi (alsa->handle, ptr, cptr)) < 0) {
652 if (err == -EAGAIN) {
653 GST_DEBUG ("Read error: %s", snd_strerror (err));
655 } else if (xrun_recovery (alsa->handle, err) < 0) {
661 ptr += err * alsa->channels;
664 return length - cptr;
668 return length; /* skip one period */
673 gst_alsasrc_delay (GstAudioSrc * asrc)
676 snd_pcm_sframes_t delay;
678 alsa = GST_ALSA_SRC (asrc);
680 snd_pcm_delay (alsa->handle, &delay);
686 gst_alsasrc_reset (GstAudioSrc * asrc)
693 alsa = GST_ALSA_SRC (asrc);
695 CHECK (snd_pcm_drop (alsa->handle), drop_error);
696 CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
703 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
704 ("alsa-reset: pcm drop error: %s", snd_strerror (err)), (NULL));
709 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
710 ("alsa-reset: pcm prepare error: %s", snd_strerror (err)), (NULL));