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