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