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