Initialize Tizen 2.3
[framework/multimedia/gst-plugins-base0.10.git] / wearable / ext / alsa / gstalsasrc.c
1 /* GStreamer
2  * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
3  *
4  * gstalsasrc.c:
5  *
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.
10  *
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.
15  *
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.
20  */
21
22 /**
23  * SECTION:element-alsasrc
24  * @see_also: alsasink, alsamixer
25  *
26  * This element reads data from an audio card using the ALSA API.
27  *
28  * <refsect2>
29  * <title>Example pipelines</title>
30  * |[
31  * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
32  * ]| Record from a sound card using ALSA and encode to Ogg/Vorbis.
33  * </refsect2>
34  *
35  * Last reviewed on 2006-03-01 (0.10.4)
36  */
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41 #include <sys/ioctl.h>
42 #include <fcntl.h>
43 #include <errno.h>
44 #include <unistd.h>
45 #include <string.h>
46 #include <getopt.h>
47 #include <alsa/asoundlib.h>
48
49 #include "gstalsasrc.h"
50 #include "gstalsadeviceprobe.h"
51 #include "gst/glib-compat-private.h"
52
53 #include <gst/gst-i18n-plugin.h>
54
55 #define DEFAULT_PROP_DEVICE             "default"
56 #define DEFAULT_PROP_DEVICE_NAME        ""
57 #define DEFAULT_PROP_CARD_NAME          ""
58
59 enum
60 {
61   PROP_0,
62   PROP_DEVICE,
63   PROP_DEVICE_NAME,
64   PROP_CARD_NAME,
65   PROP_LAST
66 };
67
68 static void gst_alsasrc_init_interfaces (GType type);
69
70 GST_BOILERPLATE_FULL (GstAlsaSrc, gst_alsasrc, GstAudioSrc,
71     GST_TYPE_AUDIO_SRC, gst_alsasrc_init_interfaces);
72
73 GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaSrc, gst_alsasrc_mixer);
74
75 static void gst_alsasrc_finalize (GObject * object);
76 static void gst_alsasrc_set_property (GObject * object,
77     guint prop_id, const GValue * value, GParamSpec * pspec);
78 static void gst_alsasrc_get_property (GObject * object,
79     guint prop_id, GValue * value, GParamSpec * pspec);
80
81 static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc);
82
83 static gboolean gst_alsasrc_open (GstAudioSrc * asrc);
84 static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc,
85     GstRingBufferSpec * spec);
86 static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc);
87 static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
88 static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
89 static guint gst_alsasrc_delay (GstAudioSrc * asrc);
90 static void gst_alsasrc_reset (GstAudioSrc * asrc);
91
92 /* AlsaSrc signals and args */
93 enum
94 {
95   LAST_SIGNAL
96 };
97
98 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
99 # define ALSA_SRC_FACTORY_ENDIANNESS   "LITTLE_ENDIAN, BIG_ENDIAN"
100 #else
101 # define ALSA_SRC_FACTORY_ENDIANNESS   "BIG_ENDIAN, LITTLE_ENDIAN"
102 #endif
103
104 static GstStaticPadTemplate alsasrc_src_factory =
105     GST_STATIC_PAD_TEMPLATE ("src",
106     GST_PAD_SRC,
107     GST_PAD_ALWAYS,
108     GST_STATIC_CAPS ("audio/x-lpcm, "
109         "endianness = (int) { 1234, 4321 }, "
110         "signed = (boolean) { TRUE, FALSE }, "
111         "width = (int) 16, "
112         "depth = (int) 16, "
113         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ];"
114         "audio/x-raw-int, "
115         "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
116         "signed = (boolean) { TRUE, FALSE }, "
117         "width = (int) 32, "
118         "depth = (int) 32, "
119         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
120         "audio/x-raw-int, "
121         "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
122         "signed = (boolean) { TRUE, FALSE }, "
123         "width = (int) 32, "
124         "depth = (int) 24, "
125         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
126         "audio/x-raw-int, "
127         "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
128         "signed = (boolean) { TRUE, FALSE }, "
129         "width = (int) 24, "
130         "depth = (int) 24, "
131         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
132         "audio/x-raw-int, "
133         "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
134         "signed = (boolean) { TRUE, FALSE }, "
135         "width = (int) 16, "
136         "depth = (int) 16, "
137         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
138         "audio/x-raw-int, "
139         "signed = (boolean) { TRUE, FALSE }, "
140         "width = (int) 8, "
141         "depth = (int) 8, "
142         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
143     );
144
145 static void
146 gst_alsasrc_finalize (GObject * object)
147 {
148   GstAlsaSrc *src = GST_ALSA_SRC (object);
149
150   g_free (src->device);
151   g_mutex_free (src->alsa_lock);
152
153   G_OBJECT_CLASS (parent_class)->finalize (object);
154 }
155
156 static gboolean
157 gst_alsasrc_interface_supported (GstAlsaSrc * this, GType interface_type)
158 {
159   /* only support this one interface (wrapped by GstImplementsInterface) */
160   g_assert (interface_type == GST_TYPE_MIXER);
161
162   return gst_alsasrc_mixer_supported (this, interface_type);
163 }
164
165 static void
166 gst_implements_interface_init (GstImplementsInterfaceClass * klass)
167 {
168   klass->supported = (gpointer) gst_alsasrc_interface_supported;
169 }
170
171 static void
172 gst_alsasrc_init_interfaces (GType type)
173 {
174   static const GInterfaceInfo implements_iface_info = {
175     (GInterfaceInitFunc) gst_implements_interface_init,
176     NULL,
177     NULL,
178   };
179   static const GInterfaceInfo mixer_iface_info = {
180     (GInterfaceInitFunc) gst_alsasrc_mixer_interface_init,
181     NULL,
182     NULL,
183   };
184
185   g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
186       &implements_iface_info);
187   g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
188
189   gst_alsa_type_add_device_property_probe_interface (type);
190 }
191
192 static void
193 gst_alsasrc_base_init (gpointer g_class)
194 {
195   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
196
197   gst_element_class_set_details_simple (element_class,
198       "Audio source (ALSA)", "Source/Audio",
199       "Read from a sound card via ALSA", "Wim Taymans <wim@fluendo.com>");
200
201   gst_element_class_add_static_pad_template (element_class,
202       &alsasrc_src_factory);
203 }
204
205 static void
206 gst_alsasrc_class_init (GstAlsaSrcClass * klass)
207 {
208   GObjectClass *gobject_class;
209   GstBaseSrcClass *gstbasesrc_class;
210   GstAudioSrcClass *gstaudiosrc_class;
211
212   gobject_class = (GObjectClass *) klass;
213   gstbasesrc_class = (GstBaseSrcClass *) klass;
214   gstaudiosrc_class = (GstAudioSrcClass *) klass;
215
216   gobject_class->finalize = gst_alsasrc_finalize;
217   gobject_class->get_property = gst_alsasrc_get_property;
218   gobject_class->set_property = gst_alsasrc_set_property;
219
220   gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
221
222   gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open);
223   gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasrc_prepare);
224   gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasrc_unprepare);
225   gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_alsasrc_close);
226   gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
227   gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay);
228   gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_alsasrc_reset);
229
230   g_object_class_install_property (gobject_class, PROP_DEVICE,
231       g_param_spec_string ("device", "Device",
232           "ALSA device, as defined in an asound configuration file",
233           DEFAULT_PROP_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
234
235   g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
236       g_param_spec_string ("device-name", "Device name",
237           "Human-readable name of the sound device",
238           DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
239
240   g_object_class_install_property (gobject_class, PROP_CARD_NAME,
241       g_param_spec_string ("card-name", "Card name",
242           "Human-readable name of the sound card",
243           DEFAULT_PROP_CARD_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
244 }
245
246 static void
247 gst_alsasrc_set_property (GObject * object, guint prop_id,
248     const GValue * value, GParamSpec * pspec)
249 {
250   GstAlsaSrc *src;
251
252   src = GST_ALSA_SRC (object);
253
254   switch (prop_id) {
255     case PROP_DEVICE:
256       g_free (src->device);
257       src->device = g_value_dup_string (value);
258       if (src->device == NULL) {
259         src->device = g_strdup (DEFAULT_PROP_DEVICE);
260       }
261       break;
262     default:
263       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
264       break;
265   }
266 }
267
268 static void
269 gst_alsasrc_get_property (GObject * object, guint prop_id,
270     GValue * value, GParamSpec * pspec)
271 {
272   GstAlsaSrc *src;
273
274   src = GST_ALSA_SRC (object);
275
276   switch (prop_id) {
277     case PROP_DEVICE:
278       g_value_set_string (value, src->device);
279       break;
280     case PROP_DEVICE_NAME:
281       g_value_take_string (value,
282           gst_alsa_find_device_name (GST_OBJECT_CAST (src),
283               src->device, src->handle, SND_PCM_STREAM_CAPTURE));
284       break;
285     case PROP_CARD_NAME:
286       g_value_take_string (value,
287           gst_alsa_find_card_name (GST_OBJECT_CAST (src),
288               src->device, SND_PCM_STREAM_CAPTURE));
289       break;
290     default:
291       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
292       break;
293   }
294 }
295
296 static void
297 gst_alsasrc_init (GstAlsaSrc * alsasrc, GstAlsaSrcClass * g_class)
298 {
299   GST_DEBUG_OBJECT (alsasrc, "initializing");
300
301   alsasrc->device = g_strdup (DEFAULT_PROP_DEVICE);
302   alsasrc->cached_caps = NULL;
303
304   alsasrc->alsa_lock = g_mutex_new ();
305 }
306
307 #define CHECK(call, error) \
308 G_STMT_START {                  \
309 if ((err = call) < 0)           \
310   goto error;                   \
311 } G_STMT_END;
312
313
314 static GstCaps *
315 gst_alsasrc_getcaps (GstBaseSrc * bsrc)
316 {
317   GstElementClass *element_class;
318   GstPadTemplate *pad_template;
319   GstAlsaSrc *src;
320   GstCaps *caps;
321
322   src = GST_ALSA_SRC (bsrc);
323
324   if (src->handle == NULL) {
325     GST_DEBUG_OBJECT (src, "device not open, using template caps");
326     return NULL;                /* base class will get template caps for us */
327   }
328
329   if (src->cached_caps) {
330     GST_LOG_OBJECT (src, "Returning cached caps");
331     return gst_caps_ref (src->cached_caps);
332   }
333
334   element_class = GST_ELEMENT_GET_CLASS (src);
335   pad_template = gst_element_class_get_pad_template (element_class, "src");
336   g_return_val_if_fail (pad_template != NULL, NULL);
337
338   caps = gst_alsa_probe_supported_formats (GST_OBJECT (src), src->handle,
339       gst_pad_template_get_caps (pad_template));
340
341   if (caps) {
342     src->cached_caps = gst_caps_ref (caps);
343   }
344
345   GST_INFO_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
346
347   return caps;
348 }
349
350 static int
351 set_hwparams (GstAlsaSrc * alsa)
352 {
353   guint rrate;
354   gint err;
355   snd_pcm_hw_params_t *params;
356
357   snd_pcm_hw_params_malloc (&params);
358
359   /* choose all parameters */
360   CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
361   /* set the interleaved read/write format */
362   CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
363       wrong_access);
364   /* set the sample format */
365   CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
366       no_sample_format);
367   /* set the count of channels */
368   CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
369       no_channels);
370   /* set the stream rate */
371   rrate = alsa->rate;
372   CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
373       no_rate);
374   if (rrate != alsa->rate)
375     goto rate_match;
376
377   if (alsa->buffer_time != -1) {
378     /* set the buffer time */
379     CHECK (snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
380             &alsa->buffer_time, NULL), buffer_time);
381   }
382   if (alsa->period_time != -1) {
383     /* set the period time */
384     CHECK (snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
385             &alsa->period_time, NULL), period_time);
386   }
387
388   /* write the parameters to device */
389   CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
390
391   CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
392       buffer_size);
393
394   CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, NULL),
395       period_size);
396
397   snd_pcm_hw_params_free (params);
398   return 0;
399
400   /* ERRORS */
401 no_config:
402   {
403     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
404         ("Broken configuration for recording: no configurations available: %s",
405             snd_strerror (err)));
406     snd_pcm_hw_params_free (params);
407     return err;
408   }
409 wrong_access:
410   {
411     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
412         ("Access type not available for recording: %s", snd_strerror (err)));
413     snd_pcm_hw_params_free (params);
414     return err;
415   }
416 no_sample_format:
417   {
418     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
419         ("Sample format not available for recording: %s", snd_strerror (err)));
420     snd_pcm_hw_params_free (params);
421     return err;
422   }
423 no_channels:
424   {
425     gchar *msg = NULL;
426
427     if ((alsa->channels) == 1)
428       msg = g_strdup (_("Could not open device for recording in mono mode."));
429     if ((alsa->channels) == 2)
430       msg = g_strdup (_("Could not open device for recording in stereo mode."));
431     if ((alsa->channels) > 2)
432       msg =
433           g_strdup_printf (_
434           ("Could not open device for recording in %d-channel mode"),
435           alsa->channels);
436     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, ("%s", msg),
437         ("%s", snd_strerror (err)));
438     g_free (msg);
439     snd_pcm_hw_params_free (params);
440     return err;
441   }
442 no_rate:
443   {
444     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
445         ("Rate %iHz not available for recording: %s",
446             alsa->rate, snd_strerror (err)));
447     snd_pcm_hw_params_free (params);
448     return err;
449   }
450 rate_match:
451   {
452     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
453         ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
454     snd_pcm_hw_params_free (params);
455     return -EINVAL;
456   }
457 buffer_time:
458   {
459     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
460         ("Unable to set buffer time %i for recording: %s",
461             alsa->buffer_time, snd_strerror (err)));
462     snd_pcm_hw_params_free (params);
463     return err;
464   }
465 buffer_size:
466   {
467     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
468         ("Unable to get buffer size for recording: %s", snd_strerror (err)));
469     snd_pcm_hw_params_free (params);
470     return err;
471   }
472 period_time:
473   {
474     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
475         ("Unable to set period time %i for recording: %s", alsa->period_time,
476             snd_strerror (err)));
477     snd_pcm_hw_params_free (params);
478     return err;
479   }
480 period_size:
481   {
482     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
483         ("Unable to get period size for recording: %s", snd_strerror (err)));
484     snd_pcm_hw_params_free (params);
485     return err;
486   }
487 set_hw_params:
488   {
489     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
490         ("Unable to set hw params for recording: %s", snd_strerror (err)));
491     snd_pcm_hw_params_free (params);
492     return err;
493   }
494 }
495
496 static int
497 set_swparams (GstAlsaSrc * alsa)
498 {
499   int err;
500   snd_pcm_sw_params_t *params;
501
502   snd_pcm_sw_params_malloc (&params);
503
504   /* get the current swparams */
505   CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
506   /* allow the transfer when at least period_size samples can be processed */
507   CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
508           alsa->period_size), set_avail);
509   /* start the transfer on first read */
510   CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
511           0), start_threshold);
512
513 #if GST_CHECK_ALSA_VERSION(1,0,16)
514   /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
515 #else
516   /* align all transfers to 1 sample */
517   CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
518 #endif
519
520   /* write the parameters to the recording device */
521   CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
522
523   snd_pcm_sw_params_free (params);
524   return 0;
525
526   /* ERRORS */
527 no_config:
528   {
529     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
530         ("Unable to determine current swparams for playback: %s",
531             snd_strerror (err)));
532     snd_pcm_sw_params_free (params);
533     return err;
534   }
535 start_threshold:
536   {
537     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
538         ("Unable to set start threshold mode for playback: %s",
539             snd_strerror (err)));
540     snd_pcm_sw_params_free (params);
541     return err;
542   }
543 set_avail:
544   {
545     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
546         ("Unable to set avail min for playback: %s", snd_strerror (err)));
547     snd_pcm_sw_params_free (params);
548     return err;
549   }
550 #if !GST_CHECK_ALSA_VERSION(1,0,16)
551 set_align:
552   {
553     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
554         ("Unable to set transfer align for playback: %s", snd_strerror (err)));
555     snd_pcm_sw_params_free (params);
556     return err;
557   }
558 #endif
559 set_sw_params:
560   {
561     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
562         ("Unable to set sw params for playback: %s", snd_strerror (err)));
563     snd_pcm_sw_params_free (params);
564     return err;
565   }
566 }
567
568 static gboolean
569 alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * spec)
570 {
571   switch (spec->type) {
572     case GST_BUFTYPE_LINEAR:
573       alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
574           spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
575       break;
576     case GST_BUFTYPE_FLOAT:
577       switch (spec->format) {
578         case GST_FLOAT32_LE:
579           alsa->format = SND_PCM_FORMAT_FLOAT_LE;
580           break;
581         case GST_FLOAT32_BE:
582           alsa->format = SND_PCM_FORMAT_FLOAT_BE;
583           break;
584         case GST_FLOAT64_LE:
585           alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
586           break;
587         case GST_FLOAT64_BE:
588           alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
589           break;
590         default:
591           goto error;
592       }
593       break;
594     case GST_BUFTYPE_A_LAW:
595       alsa->format = SND_PCM_FORMAT_A_LAW;
596       break;
597     case GST_BUFTYPE_MU_LAW:
598       alsa->format = SND_PCM_FORMAT_MU_LAW;
599       break;
600     default:
601       goto error;
602
603   }
604   alsa->rate = spec->rate;
605   alsa->channels = spec->channels;
606   alsa->buffer_time = spec->buffer_time;
607   alsa->period_time = spec->latency_time;
608   alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
609
610   return TRUE;
611
612   /* ERRORS */
613 error:
614   {
615     return FALSE;
616   }
617 }
618
619 static gboolean
620 gst_alsasrc_open (GstAudioSrc * asrc)
621 {
622   GstAlsaSrc *alsa;
623   gint err;
624
625   alsa = GST_ALSA_SRC (asrc);
626
627   CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_CAPTURE,
628           SND_PCM_NONBLOCK), open_error);
629
630   if (!alsa->mixer)
631     alsa->mixer = gst_alsa_mixer_new (alsa->device, GST_ALSA_MIXER_CAPTURE);
632
633   return TRUE;
634
635   /* ERRORS */
636 open_error:
637   {
638     if (err == -EBUSY) {
639       GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
640           (_("Could not open audio device for recording. "
641                   "Device is being used by another application.")),
642           ("Device '%s' is busy", alsa->device));
643     } else {
644       GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
645           (_("Could not open audio device for recording.")),
646           ("Recording open error on device '%s': %s", alsa->device,
647               snd_strerror (err)));
648     }
649     return FALSE;
650   }
651 }
652
653 static gboolean
654 gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
655 {
656   GstAlsaSrc *alsa;
657   gint err;
658
659   alsa = GST_ALSA_SRC (asrc);
660
661   if (!alsasrc_parse_spec (alsa, spec))
662     goto spec_parse;
663
664   CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);
665
666   CHECK (set_hwparams (alsa), hw_params_failed);
667   CHECK (set_swparams (alsa), sw_params_failed);
668   CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);
669
670   alsa->bytes_per_sample = spec->bytes_per_sample;
671   spec->segsize = alsa->period_size * spec->bytes_per_sample;
672   spec->segtotal = alsa->buffer_size / alsa->period_size;
673   spec->silence_sample[0] = 0;
674   spec->silence_sample[1] = 0;
675   spec->silence_sample[2] = 0;
676   spec->silence_sample[3] = 0;
677
678   return TRUE;
679
680   /* ERRORS */
681 spec_parse:
682   {
683     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
684         ("Error parsing spec"));
685     return FALSE;
686   }
687 non_block:
688   {
689     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
690         ("Could not set device to blocking: %s", snd_strerror (err)));
691     return FALSE;
692   }
693 hw_params_failed:
694   {
695     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
696         ("Setting of hwparams failed: %s", snd_strerror (err)));
697     return FALSE;
698   }
699 sw_params_failed:
700   {
701     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
702         ("Setting of swparams failed: %s", snd_strerror (err)));
703     return FALSE;
704   }
705 prepare_failed:
706   {
707     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
708         ("Prepare failed: %s", snd_strerror (err)));
709     return FALSE;
710   }
711 }
712
713 static gboolean
714 gst_alsasrc_unprepare (GstAudioSrc * asrc)
715 {
716   GstAlsaSrc *alsa;
717
718   alsa = GST_ALSA_SRC (asrc);
719
720   snd_pcm_drop (alsa->handle);
721   snd_pcm_hw_free (alsa->handle);
722   snd_pcm_nonblock (alsa->handle, 1);
723
724   return TRUE;
725 }
726
727 static gboolean
728 gst_alsasrc_close (GstAudioSrc * asrc)
729 {
730   GstAlsaSrc *alsa = GST_ALSA_SRC (asrc);
731
732   snd_pcm_close (alsa->handle);
733   alsa->handle = NULL;
734
735   if (alsa->mixer) {
736     gst_alsa_mixer_free (alsa->mixer);
737     alsa->mixer = NULL;
738   }
739
740   gst_caps_replace (&alsa->cached_caps, NULL);
741
742   return TRUE;
743 }
744
745 /*
746  *   Underrun and suspend recovery
747  */
748 static gint
749 xrun_recovery (GstAlsaSrc * alsa, snd_pcm_t * handle, gint err)
750 {
751   GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
752
753   if (err == -EPIPE) {          /* under-run */
754     err = snd_pcm_prepare (handle);
755     if (err < 0)
756       GST_WARNING_OBJECT (alsa,
757           "Can't recovery from underrun, prepare failed: %s",
758           snd_strerror (err));
759     return 0;
760   } else if (err == -ESTRPIPE) {
761     while ((err = snd_pcm_resume (handle)) == -EAGAIN)
762       g_usleep (100);           /* wait until the suspend flag is released */
763
764     if (err < 0) {
765       err = snd_pcm_prepare (handle);
766       if (err < 0)
767         GST_WARNING_OBJECT (alsa,
768             "Can't recovery from suspend, prepare failed: %s",
769             snd_strerror (err));
770     }
771     return 0;
772   }
773   return err;
774 }
775
776 static guint
777 gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length)
778 {
779   GstAlsaSrc *alsa;
780   gint err;
781   gint cptr;
782   gint16 *ptr;
783
784   alsa = GST_ALSA_SRC (asrc);
785
786   cptr = length / alsa->bytes_per_sample;
787   ptr = data;
788
789   GST_ALSA_SRC_LOCK (asrc);
790   while (cptr > 0) {
791     if ((err = snd_pcm_readi (alsa->handle, ptr, cptr)) < 0) {
792       if (err == -EAGAIN) {
793         GST_DEBUG_OBJECT (asrc, "Read error: %s", snd_strerror (err));
794         continue;
795       } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
796         goto read_error;
797       }
798       continue;
799     }
800
801     ptr += err * alsa->channels;
802     cptr -= err;
803   }
804   GST_ALSA_SRC_UNLOCK (asrc);
805
806   return length - (cptr * alsa->bytes_per_sample);
807
808 read_error:
809   {
810     GST_ALSA_SRC_UNLOCK (asrc);
811     return length;              /* skip one period */
812   }
813 }
814
815 static guint
816 gst_alsasrc_delay (GstAudioSrc * asrc)
817 {
818   GstAlsaSrc *alsa;
819   snd_pcm_sframes_t delay;
820   int res;
821
822   alsa = GST_ALSA_SRC (asrc);
823
824   res = snd_pcm_delay (alsa->handle, &delay);
825   if (G_UNLIKELY (res < 0)) {
826     GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
827     delay = 0;
828   }
829
830   return CLAMP (delay, 0, alsa->buffer_size);
831 }
832
833 static void
834 gst_alsasrc_reset (GstAudioSrc * asrc)
835 {
836   GstAlsaSrc *alsa;
837   gint err;
838
839   alsa = GST_ALSA_SRC (asrc);
840
841   GST_ALSA_SRC_LOCK (asrc);
842   GST_DEBUG_OBJECT (alsa, "drop");
843   CHECK (snd_pcm_drop (alsa->handle), drop_error);
844   GST_DEBUG_OBJECT (alsa, "prepare");
845   CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
846   GST_DEBUG_OBJECT (alsa, "reset done");
847   GST_ALSA_SRC_UNLOCK (asrc);
848
849   return;
850
851   /* ERRORS */
852 drop_error:
853   {
854     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
855         snd_strerror (err));
856     GST_ALSA_SRC_UNLOCK (asrc);
857     return;
858   }
859 prepare_error:
860   {
861     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
862         snd_strerror (err));
863     GST_ALSA_SRC_UNLOCK (asrc);
864     return;
865   }
866 }