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