d665f6e3ac6193f068419d38d25916e2548d36a2
[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., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 /**
23  * SECTION:element-alsasrc
24  * @title: alsasrc
25  * @see_also: alsasink
26  *
27  * This element reads data from an audio card using the ALSA API.
28  *
29  * ## Example pipelines
30  * |[
31  * gst-launch-1.0 -v alsasrc ! queue ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
32  * ]|
33  *  Record from a sound card using ALSA and encode to Ogg/Vorbis.
34  *
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40 #include <sys/ioctl.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #include <unistd.h>
44 #include <string.h>
45 #include <getopt.h>
46 #include <alsa/asoundlib.h>
47
48 #include "gstalsasrc.h"
49 #include "gstalsadeviceprobe.h"
50
51 #include <gst/gst-i18n-plugin.h>
52
53 #ifndef ESTRPIPE
54 #define ESTRPIPE EPIPE
55 #endif
56
57 #define DEFAULT_PROP_DEVICE             "default"
58 #define DEFAULT_PROP_DEVICE_NAME        ""
59 #define DEFAULT_PROP_CARD_NAME          ""
60
61 enum
62 {
63   PROP_0,
64   PROP_DEVICE,
65   PROP_DEVICE_NAME,
66   PROP_CARD_NAME,
67   PROP_LAST
68 };
69
70 #define gst_alsasrc_parent_class parent_class
71 G_DEFINE_TYPE (GstAlsaSrc, gst_alsasrc, GST_TYPE_AUDIO_SRC);
72
73 static void gst_alsasrc_finalize (GObject * object);
74 static void gst_alsasrc_set_property (GObject * object,
75     guint prop_id, const GValue * value, GParamSpec * pspec);
76 static void gst_alsasrc_get_property (GObject * object,
77     guint prop_id, GValue * value, GParamSpec * pspec);
78 static GstStateChangeReturn gst_alsasrc_change_state (GstElement * element,
79     GstStateChange transition);
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
88     (GstAudioSrc * asrc, gpointer data, guint length, GstClockTime * timestamp);
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-raw, "
109         "format = (string) " GST_AUDIO_FORMATS_ALL ", "
110         "layout = (string) interleaved, "
111         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
112     );
113
114 static void
115 gst_alsasrc_finalize (GObject * object)
116 {
117   GstAlsaSrc *src = GST_ALSA_SRC (object);
118
119   g_free (src->device);
120   g_mutex_clear (&src->alsa_lock);
121   g_mutex_clear (&src->delay_lock);
122
123   G_OBJECT_CLASS (parent_class)->finalize (object);
124 }
125
126 static void
127 gst_alsasrc_class_init (GstAlsaSrcClass * klass)
128 {
129   GObjectClass *gobject_class;
130   GstElementClass *gstelement_class;
131   GstBaseSrcClass *gstbasesrc_class;
132   GstAudioSrcClass *gstaudiosrc_class;
133
134   gobject_class = (GObjectClass *) klass;
135   gstelement_class = (GstElementClass *) klass;
136   gstbasesrc_class = (GstBaseSrcClass *) klass;
137   gstaudiosrc_class = (GstAudioSrcClass *) klass;
138
139   gobject_class->finalize = gst_alsasrc_finalize;
140   gobject_class->get_property = gst_alsasrc_get_property;
141   gobject_class->set_property = gst_alsasrc_set_property;
142
143   gst_element_class_set_static_metadata (gstelement_class,
144       "Audio source (ALSA)", "Source/Audio",
145       "Read from a sound card via ALSA", "Wim Taymans <wim@fluendo.com>");
146
147   gst_element_class_add_static_pad_template (gstelement_class,
148       &alsasrc_src_factory);
149
150   gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
151
152   gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open);
153   gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasrc_prepare);
154   gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasrc_unprepare);
155   gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_alsasrc_close);
156   gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
157   gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay);
158   gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_alsasrc_reset);
159   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_alsasrc_change_state);
160
161   g_object_class_install_property (gobject_class, PROP_DEVICE,
162       g_param_spec_string ("device", "Device",
163           "ALSA device, as defined in an asound configuration file",
164           DEFAULT_PROP_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
165
166   g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
167       g_param_spec_string ("device-name", "Device name",
168           "Human-readable name of the sound device",
169           DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
170
171   g_object_class_install_property (gobject_class, PROP_CARD_NAME,
172       g_param_spec_string ("card-name", "Card name",
173           "Human-readable name of the sound card",
174           DEFAULT_PROP_CARD_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
175 }
176
177 static void
178 gst_alsasrc_set_property (GObject * object, guint prop_id,
179     const GValue * value, GParamSpec * pspec)
180 {
181   GstAlsaSrc *src;
182
183   src = GST_ALSA_SRC (object);
184
185   switch (prop_id) {
186     case PROP_DEVICE:
187       g_free (src->device);
188       src->device = g_value_dup_string (value);
189       if (src->device == NULL) {
190         src->device = g_strdup (DEFAULT_PROP_DEVICE);
191       }
192       break;
193     default:
194       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
195       break;
196   }
197 }
198
199 static void
200 gst_alsasrc_get_property (GObject * object, guint prop_id,
201     GValue * value, GParamSpec * pspec)
202 {
203   GstAlsaSrc *src;
204
205   src = GST_ALSA_SRC (object);
206
207   switch (prop_id) {
208     case PROP_DEVICE:
209       g_value_set_string (value, src->device);
210       break;
211     case PROP_DEVICE_NAME:
212       g_value_take_string (value,
213           gst_alsa_find_device_name (GST_OBJECT_CAST (src),
214               src->device, src->handle, SND_PCM_STREAM_CAPTURE));
215       break;
216     case PROP_CARD_NAME:
217       g_value_take_string (value,
218           gst_alsa_find_card_name (GST_OBJECT_CAST (src),
219               src->device, SND_PCM_STREAM_CAPTURE));
220       break;
221     default:
222       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
223       break;
224   }
225 }
226
227 static GstStateChangeReturn
228 gst_alsasrc_change_state (GstElement * element, GstStateChange transition)
229 {
230   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
231   GstAlsaSrc *alsa = GST_ALSA_SRC (element);
232   GstClock *clk;
233
234   switch (transition) {
235       /* show the compiler that we care */
236     case GST_STATE_CHANGE_NULL_TO_READY:
237     case GST_STATE_CHANGE_READY_TO_PAUSED:
238     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
239     case GST_STATE_CHANGE_PAUSED_TO_READY:
240     case GST_STATE_CHANGE_READY_TO_NULL:
241     case GST_STATE_CHANGE_NULL_TO_NULL:
242     case GST_STATE_CHANGE_READY_TO_READY:
243     case GST_STATE_CHANGE_PAUSED_TO_PAUSED:
244     case GST_STATE_CHANGE_PLAYING_TO_PLAYING:
245       break;
246     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
247       alsa->driver_timestamps = FALSE;
248
249       clk = gst_element_get_clock (element);
250       if (clk != NULL) {
251         if (GST_IS_SYSTEM_CLOCK (clk)) {
252           gint clocktype;
253           g_object_get (clk, "clock-type", &clocktype, NULL);
254           if (clocktype == GST_CLOCK_TYPE_MONOTONIC) {
255             GST_INFO ("Using driver timestamps !");
256             alsa->driver_timestamps = TRUE;
257           }
258         }
259
260         gst_object_unref (clk);
261       }
262       break;
263   }
264   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
265
266   return ret;
267 }
268
269 static void
270 gst_alsasrc_init (GstAlsaSrc * alsasrc)
271 {
272   GST_DEBUG_OBJECT (alsasrc, "initializing");
273
274   alsasrc->device = g_strdup (DEFAULT_PROP_DEVICE);
275   alsasrc->cached_caps = NULL;
276   alsasrc->driver_timestamps = FALSE;
277
278   g_mutex_init (&alsasrc->alsa_lock);
279   g_mutex_init (&alsasrc->delay_lock);
280 }
281
282 #define CHECK(call, error) \
283 G_STMT_START {                  \
284 if ((err = call) < 0)           \
285   goto error;                   \
286 } G_STMT_END;
287
288
289 static GstCaps *
290 gst_alsasrc_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
291 {
292   GstElementClass *element_class;
293   GstPadTemplate *pad_template;
294   GstAlsaSrc *src;
295   GstCaps *caps, *templ_caps;
296
297   src = GST_ALSA_SRC (bsrc);
298
299   if (src->handle == NULL) {
300     GST_DEBUG_OBJECT (src, "device not open, using template caps");
301     return GST_BASE_SRC_CLASS (parent_class)->get_caps (bsrc, filter);
302   }
303
304   if (src->cached_caps) {
305     GST_LOG_OBJECT (src, "Returning cached caps");
306     if (filter)
307       return gst_caps_intersect_full (filter, src->cached_caps,
308           GST_CAPS_INTERSECT_FIRST);
309     else
310       return gst_caps_ref (src->cached_caps);
311   }
312
313   element_class = GST_ELEMENT_GET_CLASS (src);
314   pad_template = gst_element_class_get_pad_template (element_class, "src");
315   g_return_val_if_fail (pad_template != NULL, NULL);
316
317   templ_caps = gst_pad_template_get_caps (pad_template);
318   GST_INFO_OBJECT (src, "template caps %" GST_PTR_FORMAT, templ_caps);
319
320   caps = gst_alsa_probe_supported_formats (GST_OBJECT (src),
321       src->device, src->handle, templ_caps);
322   gst_caps_unref (templ_caps);
323
324   if (caps) {
325     src->cached_caps = gst_caps_ref (caps);
326   }
327
328   GST_INFO_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
329
330   if (filter) {
331     GstCaps *intersection;
332
333     intersection =
334         gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
335     gst_caps_unref (caps);
336     return intersection;
337   } else {
338     return caps;
339   }
340 }
341
342 static int
343 set_hwparams (GstAlsaSrc * alsa)
344 {
345   guint rrate;
346   gint err;
347   snd_pcm_hw_params_t *params;
348
349   snd_pcm_hw_params_malloc (&params);
350
351   /* choose all parameters */
352   CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
353   /* set the interleaved read/write format */
354   CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
355       wrong_access);
356   /* set the sample format */
357   CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
358       no_sample_format);
359   /* set the count of channels */
360   CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
361       no_channels);
362   /* set the stream rate */
363   rrate = alsa->rate;
364   CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
365       no_rate);
366   if (rrate != alsa->rate)
367     goto rate_match;
368
369 #ifndef GST_DISABLE_GST_DEBUG
370   /* get and dump some limits */
371   {
372     guint min, max;
373
374     snd_pcm_hw_params_get_buffer_time_min (params, &min, NULL);
375     snd_pcm_hw_params_get_buffer_time_max (params, &max, NULL);
376
377     GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
378         alsa->buffer_time, min, max);
379
380     snd_pcm_hw_params_get_period_time_min (params, &min, NULL);
381     snd_pcm_hw_params_get_period_time_max (params, &max, NULL);
382
383     GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
384         alsa->period_time, min, max);
385
386     snd_pcm_hw_params_get_periods_min (params, &min, NULL);
387     snd_pcm_hw_params_get_periods_max (params, &max, NULL);
388
389     GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
390   }
391 #endif
392
393   if (alsa->buffer_time != -1) {
394     /* set the buffer time */
395     CHECK (snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
396             &alsa->buffer_time, NULL), buffer_time);
397     GST_DEBUG_OBJECT (alsa, "buffer time %u", alsa->buffer_time);
398   }
399   if (alsa->period_time != -1) {
400     /* set the period time */
401     CHECK (snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
402             &alsa->period_time, NULL), period_time);
403     GST_DEBUG_OBJECT (alsa, "period time %u", alsa->period_time);
404   }
405
406   /* write the parameters to device */
407   CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
408
409   CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
410       buffer_size);
411
412   CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, NULL),
413       period_size);
414
415   snd_pcm_hw_params_free (params);
416   return 0;
417
418   /* ERRORS */
419 no_config:
420   {
421     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
422         ("Broken configuration for recording: no configurations available: %s",
423             snd_strerror (err)));
424     snd_pcm_hw_params_free (params);
425     return err;
426   }
427 wrong_access:
428   {
429     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
430         ("Access type not available for recording: %s", snd_strerror (err)));
431     snd_pcm_hw_params_free (params);
432     return err;
433   }
434 no_sample_format:
435   {
436     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
437         ("Sample format not available for recording: %s", snd_strerror (err)));
438     snd_pcm_hw_params_free (params);
439     return err;
440   }
441 no_channels:
442   {
443     gchar *msg = NULL;
444
445     if ((alsa->channels) == 1)
446       msg = g_strdup (_("Could not open device for recording in mono mode."));
447     if ((alsa->channels) == 2)
448       msg = g_strdup (_("Could not open device for recording in stereo mode."));
449     if ((alsa->channels) > 2)
450       msg =
451           g_strdup_printf (_
452           ("Could not open device for recording in %d-channel mode"),
453           alsa->channels);
454     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, ("%s", msg),
455         ("%s", snd_strerror (err)));
456     g_free (msg);
457     snd_pcm_hw_params_free (params);
458     return err;
459   }
460 no_rate:
461   {
462     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
463         ("Rate %iHz not available for recording: %s",
464             alsa->rate, snd_strerror (err)));
465     snd_pcm_hw_params_free (params);
466     return err;
467   }
468 rate_match:
469   {
470     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
471         ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
472     snd_pcm_hw_params_free (params);
473     return -EINVAL;
474   }
475 buffer_time:
476   {
477     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
478         ("Unable to set buffer time %i for recording: %s",
479             alsa->buffer_time, snd_strerror (err)));
480     snd_pcm_hw_params_free (params);
481     return err;
482   }
483 buffer_size:
484   {
485     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
486         ("Unable to get buffer size for recording: %s", snd_strerror (err)));
487     snd_pcm_hw_params_free (params);
488     return err;
489   }
490 period_time:
491   {
492     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
493         ("Unable to set period time %i for recording: %s", alsa->period_time,
494             snd_strerror (err)));
495     snd_pcm_hw_params_free (params);
496     return err;
497   }
498 period_size:
499   {
500     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
501         ("Unable to get period size for recording: %s", snd_strerror (err)));
502     snd_pcm_hw_params_free (params);
503     return err;
504   }
505 set_hw_params:
506   {
507     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
508         ("Unable to set hw params for recording: %s", snd_strerror (err)));
509     snd_pcm_hw_params_free (params);
510     return err;
511   }
512 }
513
514 static int
515 set_swparams (GstAlsaSrc * alsa)
516 {
517   int err;
518   snd_pcm_sw_params_t *params;
519
520   snd_pcm_sw_params_malloc (&params);
521
522   /* get the current swparams */
523   CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
524   /* allow the transfer when at least period_size samples can be processed */
525   CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
526           alsa->period_size), set_avail);
527   /* start the transfer on first read */
528   CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
529           0), start_threshold);
530   /* use monotonic timestamping */
531   CHECK (snd_pcm_sw_params_set_tstamp_mode (alsa->handle, params,
532           SND_PCM_TSTAMP_MMAP), tstamp_mode);
533
534 #if GST_CHECK_ALSA_VERSION(1,0,16)
535   /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
536 #else
537   /* align all transfers to 1 sample */
538   CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
539 #endif
540
541   /* write the parameters to the recording device */
542   CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
543
544   snd_pcm_sw_params_free (params);
545   return 0;
546
547   /* ERRORS */
548 no_config:
549   {
550     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
551         ("Unable to determine current swparams for playback: %s",
552             snd_strerror (err)));
553     snd_pcm_sw_params_free (params);
554     return err;
555   }
556 start_threshold:
557   {
558     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
559         ("Unable to set start threshold mode for playback: %s",
560             snd_strerror (err)));
561     snd_pcm_sw_params_free (params);
562     return err;
563   }
564 set_avail:
565   {
566     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
567         ("Unable to set avail min for playback: %s", snd_strerror (err)));
568     snd_pcm_sw_params_free (params);
569     return err;
570   }
571 tstamp_mode:
572   {
573     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
574         ("Unable to set tstamp mode for playback: %s", snd_strerror (err)));
575     snd_pcm_sw_params_free (params);
576     return err;
577   }
578 #if !GST_CHECK_ALSA_VERSION(1,0,16)
579 set_align:
580   {
581     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
582         ("Unable to set transfer align for playback: %s", snd_strerror (err)));
583     snd_pcm_sw_params_free (params);
584     return err;
585   }
586 #endif
587 set_sw_params:
588   {
589     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
590         ("Unable to set sw params for playback: %s", snd_strerror (err)));
591     snd_pcm_sw_params_free (params);
592     return err;
593   }
594 }
595
596 static gboolean
597 alsasrc_parse_spec (GstAlsaSrc * alsa, GstAudioRingBufferSpec * spec)
598 {
599   switch (spec->type) {
600     case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW:
601       switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
602         case GST_AUDIO_FORMAT_U8:
603           alsa->format = SND_PCM_FORMAT_U8;
604           break;
605         case GST_AUDIO_FORMAT_S8:
606           alsa->format = SND_PCM_FORMAT_S8;
607           break;
608         case GST_AUDIO_FORMAT_S16LE:
609           alsa->format = SND_PCM_FORMAT_S16_LE;
610           break;
611         case GST_AUDIO_FORMAT_S16BE:
612           alsa->format = SND_PCM_FORMAT_S16_BE;
613           break;
614         case GST_AUDIO_FORMAT_U16LE:
615           alsa->format = SND_PCM_FORMAT_U16_LE;
616           break;
617         case GST_AUDIO_FORMAT_U16BE:
618           alsa->format = SND_PCM_FORMAT_U16_BE;
619           break;
620         case GST_AUDIO_FORMAT_S24_32LE:
621           alsa->format = SND_PCM_FORMAT_S24_LE;
622           break;
623         case GST_AUDIO_FORMAT_S24_32BE:
624           alsa->format = SND_PCM_FORMAT_S24_BE;
625           break;
626         case GST_AUDIO_FORMAT_U24_32LE:
627           alsa->format = SND_PCM_FORMAT_U24_LE;
628           break;
629         case GST_AUDIO_FORMAT_U24_32BE:
630           alsa->format = SND_PCM_FORMAT_U24_BE;
631           break;
632         case GST_AUDIO_FORMAT_S32LE:
633           alsa->format = SND_PCM_FORMAT_S32_LE;
634           break;
635         case GST_AUDIO_FORMAT_S32BE:
636           alsa->format = SND_PCM_FORMAT_S32_BE;
637           break;
638         case GST_AUDIO_FORMAT_U32LE:
639           alsa->format = SND_PCM_FORMAT_U32_LE;
640           break;
641         case GST_AUDIO_FORMAT_U32BE:
642           alsa->format = SND_PCM_FORMAT_U32_BE;
643           break;
644         case GST_AUDIO_FORMAT_S24LE:
645           alsa->format = SND_PCM_FORMAT_S24_3LE;
646           break;
647         case GST_AUDIO_FORMAT_S24BE:
648           alsa->format = SND_PCM_FORMAT_S24_3BE;
649           break;
650         case GST_AUDIO_FORMAT_U24LE:
651           alsa->format = SND_PCM_FORMAT_U24_3LE;
652           break;
653         case GST_AUDIO_FORMAT_U24BE:
654           alsa->format = SND_PCM_FORMAT_U24_3BE;
655           break;
656         case GST_AUDIO_FORMAT_S20LE:
657           alsa->format = SND_PCM_FORMAT_S20_3LE;
658           break;
659         case GST_AUDIO_FORMAT_S20BE:
660           alsa->format = SND_PCM_FORMAT_S20_3BE;
661           break;
662         case GST_AUDIO_FORMAT_U20LE:
663           alsa->format = SND_PCM_FORMAT_U20_3LE;
664           break;
665         case GST_AUDIO_FORMAT_U20BE:
666           alsa->format = SND_PCM_FORMAT_U20_3BE;
667           break;
668         case GST_AUDIO_FORMAT_S18LE:
669           alsa->format = SND_PCM_FORMAT_S18_3LE;
670           break;
671         case GST_AUDIO_FORMAT_S18BE:
672           alsa->format = SND_PCM_FORMAT_S18_3BE;
673           break;
674         case GST_AUDIO_FORMAT_U18LE:
675           alsa->format = SND_PCM_FORMAT_U18_3LE;
676           break;
677         case GST_AUDIO_FORMAT_U18BE:
678           alsa->format = SND_PCM_FORMAT_U18_3BE;
679           break;
680         case GST_AUDIO_FORMAT_F32LE:
681           alsa->format = SND_PCM_FORMAT_FLOAT_LE;
682           break;
683         case GST_AUDIO_FORMAT_F32BE:
684           alsa->format = SND_PCM_FORMAT_FLOAT_BE;
685           break;
686         case GST_AUDIO_FORMAT_F64LE:
687           alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
688           break;
689         case GST_AUDIO_FORMAT_F64BE:
690           alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
691           break;
692         default:
693           goto error;
694       }
695       break;
696     case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW:
697       alsa->format = SND_PCM_FORMAT_A_LAW;
698       break;
699     case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW:
700       alsa->format = SND_PCM_FORMAT_MU_LAW;
701       break;
702     default:
703       goto error;
704
705   }
706   alsa->rate = GST_AUDIO_INFO_RATE (&spec->info);
707   alsa->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
708   alsa->buffer_time = spec->buffer_time;
709   alsa->period_time = spec->latency_time;
710   alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
711
712   if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9)
713     gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
714         (alsa)->ringbuffer, alsa_position[alsa->channels - 1]);
715
716   return TRUE;
717
718   /* ERRORS */
719 error:
720   {
721     return FALSE;
722   }
723 }
724
725 static gboolean
726 gst_alsasrc_open (GstAudioSrc * asrc)
727 {
728   GstAlsaSrc *alsa;
729   gint err;
730
731   alsa = GST_ALSA_SRC (asrc);
732
733   CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_CAPTURE,
734           (alsa->driver_timestamps) ? 0 : SND_PCM_NONBLOCK), open_error);
735
736   return TRUE;
737
738   /* ERRORS */
739 open_error:
740   {
741     if (err == -EBUSY) {
742       GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
743           (_("Could not open audio device for recording. "
744                   "Device is being used by another application.")),
745           ("Device '%s' is busy", alsa->device));
746     } else {
747       GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
748           (_("Could not open audio device for recording.")),
749           ("Recording open error on device '%s': %s", alsa->device,
750               snd_strerror (err)));
751     }
752     return FALSE;
753   }
754 }
755
756 static gboolean
757 gst_alsasrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
758 {
759   GstAlsaSrc *alsa;
760   gint err;
761
762   alsa = GST_ALSA_SRC (asrc);
763
764   if (!alsasrc_parse_spec (alsa, spec))
765     goto spec_parse;
766
767   CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);
768
769   CHECK (set_hwparams (alsa), hw_params_failed);
770   CHECK (set_swparams (alsa), sw_params_failed);
771   CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);
772
773   alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info);
774   spec->segsize = alsa->period_size * alsa->bpf;
775   spec->segtotal = alsa->buffer_size / alsa->period_size;
776
777   {
778     snd_output_t *out_buf = NULL;
779     char *msg = NULL;
780
781     snd_output_buffer_open (&out_buf);
782     snd_pcm_dump_hw_setup (alsa->handle, out_buf);
783     snd_output_buffer_string (out_buf, &msg);
784     GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
785     snd_output_close (out_buf);
786     snd_output_buffer_open (&out_buf);
787     snd_pcm_dump_sw_setup (alsa->handle, out_buf);
788     snd_output_buffer_string (out_buf, &msg);
789     GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
790     snd_output_close (out_buf);
791   }
792
793 #ifdef SND_CHMAP_API_VERSION
794   alsa_detect_channels_mapping (GST_OBJECT (alsa), alsa->handle, spec,
795       alsa->channels, GST_AUDIO_BASE_SRC (alsa)->ringbuffer);
796 #endif /* SND_CHMAP_API_VERSION */
797
798   return TRUE;
799
800   /* ERRORS */
801 spec_parse:
802   {
803     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
804         ("Error parsing spec"));
805     return FALSE;
806   }
807 non_block:
808   {
809     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
810         ("Could not set device to blocking: %s", snd_strerror (err)));
811     return FALSE;
812   }
813 hw_params_failed:
814   {
815     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
816         ("Setting of hwparams failed: %s", snd_strerror (err)));
817     return FALSE;
818   }
819 sw_params_failed:
820   {
821     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
822         ("Setting of swparams failed: %s", snd_strerror (err)));
823     return FALSE;
824   }
825 prepare_failed:
826   {
827     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
828         ("Prepare failed: %s", snd_strerror (err)));
829     return FALSE;
830   }
831 }
832
833 static gboolean
834 gst_alsasrc_unprepare (GstAudioSrc * asrc)
835 {
836   GstAlsaSrc *alsa;
837
838   alsa = GST_ALSA_SRC (asrc);
839
840   snd_pcm_drop (alsa->handle);
841   snd_pcm_hw_free (alsa->handle);
842   snd_pcm_nonblock (alsa->handle, 1);
843
844   return TRUE;
845 }
846
847 static gboolean
848 gst_alsasrc_close (GstAudioSrc * asrc)
849 {
850   GstAlsaSrc *alsa = GST_ALSA_SRC (asrc);
851
852   snd_pcm_close (alsa->handle);
853   alsa->handle = NULL;
854
855   gst_caps_replace (&alsa->cached_caps, NULL);
856
857   return TRUE;
858 }
859
860 /*
861  *   Underrun and suspend recovery
862  */
863 static gint
864 xrun_recovery (GstAlsaSrc * alsa, snd_pcm_t * handle, gint err)
865 {
866   GST_WARNING_OBJECT (alsa, "xrun recovery %d: %s", err, g_strerror (-err));
867
868   if (err == -EPIPE) {          /* under-run */
869     err = snd_pcm_prepare (handle);
870     if (err < 0)
871       GST_WARNING_OBJECT (alsa,
872           "Can't recover from underrun, prepare failed: %s",
873           snd_strerror (err));
874     return 0;
875   } else if (err == -ESTRPIPE) {
876     while ((err = snd_pcm_resume (handle)) == -EAGAIN)
877       g_usleep (100);           /* wait until the suspend flag is released */
878
879     if (err < 0) {
880       err = snd_pcm_prepare (handle);
881       if (err < 0)
882         GST_WARNING_OBJECT (alsa,
883             "Can't recover from suspend, prepare failed: %s",
884             snd_strerror (err));
885     }
886     return 0;
887   }
888   return err;
889 }
890
891 static GstClockTime
892 gst_alsasrc_get_timestamp (GstAlsaSrc * asrc)
893 {
894   snd_pcm_status_t *status;
895   snd_htimestamp_t tstamp;
896   GstClockTime timestamp;
897   snd_pcm_uframes_t avail;
898   gint err = -EPIPE;
899
900   if (G_UNLIKELY (!asrc)) {
901     GST_ERROR_OBJECT (asrc, "No alsa handle created yet !");
902     return GST_CLOCK_TIME_NONE;
903   }
904
905   if (G_UNLIKELY (snd_pcm_status_malloc (&status) != 0)) {
906     GST_ERROR_OBJECT (asrc, "snd_pcm_status_malloc failed");
907     return GST_CLOCK_TIME_NONE;
908   }
909
910   if (G_UNLIKELY (snd_pcm_status (asrc->handle, status) != 0)) {
911     GST_ERROR_OBJECT (asrc, "snd_pcm_status failed");
912     return GST_CLOCK_TIME_NONE;
913   }
914
915   /* in case an xrun condition has occured we need to handle this */
916   if (snd_pcm_status_get_state (status) != SND_PCM_STATE_RUNNING) {
917     if (xrun_recovery (asrc, asrc->handle, err) < 0) {
918       GST_WARNING_OBJECT (asrc, "Could not recover from xrun condition !");
919     }
920     /* reload the status alsa status object, since recovery made it invalid */
921     if (G_UNLIKELY (snd_pcm_status (asrc->handle, status) != 0)) {
922       GST_ERROR_OBJECT (asrc, "snd_pcm_status failed");
923     }
924   }
925
926   /* get high resolution time stamp from driver */
927   snd_pcm_status_get_htstamp (status, &tstamp);
928   timestamp = GST_TIMESPEC_TO_TIME (tstamp);
929
930   /* max available frames sets the depth of the buffer */
931   avail = snd_pcm_status_get_avail (status);
932
933   /* calculate the timestamp of the next sample to be read */
934   timestamp -= gst_util_uint64_scale_int (avail, GST_SECOND, asrc->rate);
935
936   /* compensate for the fact that we really need the timestamp of the
937    * previously read data segment */
938   timestamp -= asrc->period_time * 1000;
939
940   snd_pcm_status_free (status);
941
942   GST_LOG_OBJECT (asrc, "ALSA timestamp : %" GST_TIME_FORMAT
943       ", delay %lu", GST_TIME_ARGS (timestamp), avail);
944
945   return timestamp;
946 }
947
948 static guint
949 gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length,
950     GstClockTime * timestamp)
951 {
952   GstAlsaSrc *alsa;
953   gint err;
954   gint cptr;
955   guint8 *ptr = data;
956
957   alsa = GST_ALSA_SRC (asrc);
958
959   cptr = length / alsa->bpf;
960
961   GST_ALSA_SRC_LOCK (asrc);
962   while (cptr > 0) {
963     GST_DELAY_SRC_LOCK (asrc);
964     err = snd_pcm_readi (alsa->handle, ptr, cptr);
965     GST_DELAY_SRC_UNLOCK (asrc);
966
967     if (err < 0) {
968       if (err == -EAGAIN) {
969         GST_DEBUG_OBJECT (asrc, "Read error: %s", snd_strerror (err));
970         continue;
971       } else if (err == -ENODEV) {
972         goto device_disappeared;
973       } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
974         goto read_error;
975       }
976       continue;
977     }
978
979     ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
980     cptr -= err;
981   }
982   GST_ALSA_SRC_UNLOCK (asrc);
983
984   /* if driver timestamps are enabled we need to return this here */
985   if (alsa->driver_timestamps && timestamp)
986     *timestamp = gst_alsasrc_get_timestamp (alsa);
987
988   return length - (cptr * alsa->bpf);
989
990 read_error:
991   {
992     GST_ALSA_SRC_UNLOCK (asrc);
993     return length;              /* skip one period */
994   }
995 device_disappeared:
996   {
997     GST_ELEMENT_ERROR (asrc, RESOURCE, READ,
998         (_("Error recording from audio device. "
999                 "The device has been disconnected.")), (NULL));
1000     GST_ALSA_SRC_UNLOCK (asrc);
1001     return (guint) - 1;
1002   }
1003 }
1004
1005 static guint
1006 gst_alsasrc_delay (GstAudioSrc * asrc)
1007 {
1008   GstAlsaSrc *alsa;
1009   snd_pcm_sframes_t delay;
1010   int res;
1011
1012   alsa = GST_ALSA_SRC (asrc);
1013
1014   GST_DELAY_SRC_LOCK (asrc);
1015   res = snd_pcm_delay (alsa->handle, &delay);
1016   GST_DELAY_SRC_UNLOCK (asrc);
1017   if (G_UNLIKELY (res < 0)) {
1018     GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
1019     delay = 0;
1020   }
1021
1022   return CLAMP (delay, 0, alsa->buffer_size);
1023 }
1024
1025 static void
1026 gst_alsasrc_reset (GstAudioSrc * asrc)
1027 {
1028   GstAlsaSrc *alsa;
1029   gint err;
1030
1031   alsa = GST_ALSA_SRC (asrc);
1032
1033   GST_ALSA_SRC_LOCK (asrc);
1034   GST_DEBUG_OBJECT (alsa, "drop");
1035   CHECK (snd_pcm_drop (alsa->handle), drop_error);
1036   GST_DEBUG_OBJECT (alsa, "prepare");
1037   CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
1038   GST_DEBUG_OBJECT (alsa, "reset done");
1039   GST_ALSA_SRC_UNLOCK (asrc);
1040
1041   return;
1042
1043   /* ERRORS */
1044 drop_error:
1045   {
1046     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
1047         snd_strerror (err));
1048     GST_ALSA_SRC_UNLOCK (asrc);
1049     return;
1050   }
1051 prepare_error:
1052   {
1053     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
1054         snd_strerror (err));
1055     GST_ALSA_SRC_UNLOCK (asrc);
1056     return;
1057   }
1058 }