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