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