9172f496e865b0d02c9ec05fec2ff50ede37386d
[platform/upstream/gstreamer.git] / ext / alsa / gstalsasink.c
1 /* GStreamer
2  * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
3  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
4  *
5  * gstalsasink.c:
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:element-alsasink
25  * @see_also: alsasrc, alsamixer
26  *
27  * This element renders raw audio samples using the ALSA api.
28  *
29  * <refsect2>
30  * <title>Example pipelines</title>
31  * |[
32  * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! alsasink
33  * ]| Play an Ogg/Vorbis file.
34  * </refsect2>
35  *
36  * Last reviewed on 2006-03-01 (0.10.4)
37  */
38
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42 #include <sys/ioctl.h>
43 #include <fcntl.h>
44 #include <errno.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include <getopt.h>
48 #include <alsa/asoundlib.h>
49
50 #include "gstalsa.h"
51 #include "gstalsasink.h"
52 #include "gstalsadeviceprobe.h"
53
54 #include <gst/gst-i18n-plugin.h>
55
56 /* elementfactory information */
57 static const GstElementDetails gst_alsasink_details =
58 GST_ELEMENT_DETAILS ("Audio sink (ALSA)",
59     "Sink/Audio",
60     "Output to a sound card via ALSA",
61     "Wim Taymans <wim@fluendo.com>");
62
63 #define DEFAULT_DEVICE          "default"
64 #define DEFAULT_DEVICE_NAME     ""
65 #define SPDIF_PERIOD_SIZE 1536
66 #define SPDIF_BUFFER_SIZE 15360
67
68 enum
69 {
70   PROP_0,
71   PROP_DEVICE,
72   PROP_DEVICE_NAME
73 };
74
75 static void gst_alsasink_init_interfaces (GType type);
76
77 GST_BOILERPLATE_FULL (GstAlsaSink, gst_alsasink, GstAudioSink,
78     GST_TYPE_AUDIO_SINK, gst_alsasink_init_interfaces);
79
80 static void gst_alsasink_finalise (GObject * object);
81 static void gst_alsasink_set_property (GObject * object,
82     guint prop_id, const GValue * value, GParamSpec * pspec);
83 static void gst_alsasink_get_property (GObject * object,
84     guint prop_id, GValue * value, GParamSpec * pspec);
85
86 static GstCaps *gst_alsasink_getcaps (GstBaseSink * bsink);
87
88 static gboolean gst_alsasink_open (GstAudioSink * asink);
89 static gboolean gst_alsasink_prepare (GstAudioSink * asink,
90     GstRingBufferSpec * spec);
91 static gboolean gst_alsasink_unprepare (GstAudioSink * asink);
92 static gboolean gst_alsasink_close (GstAudioSink * asink);
93 static guint gst_alsasink_write (GstAudioSink * asink, gpointer data,
94     guint length);
95 static guint gst_alsasink_delay (GstAudioSink * asink);
96 static void gst_alsasink_reset (GstAudioSink * asink);
97
98 static gint output_ref;         /* 0    */
99 static snd_output_t *output;    /* NULL */
100 static GStaticMutex output_mutex = G_STATIC_MUTEX_INIT;
101
102
103 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
104 # define ALSA_SINK_FACTORY_ENDIANNESS   "LITTLE_ENDIAN, BIG_ENDIAN"
105 #else
106 # define ALSA_SINK_FACTORY_ENDIANNESS   "BIG_ENDIAN, LITTLE_ENDIAN"
107 #endif
108
109 static GstStaticPadTemplate alsasink_sink_factory =
110     GST_STATIC_PAD_TEMPLATE ("sink",
111     GST_PAD_SINK,
112     GST_PAD_ALWAYS,
113     GST_STATIC_CAPS ("audio/x-raw-int, "
114         "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
115         "signed = (boolean) { TRUE, FALSE }, "
116         "width = (int) 32, "
117         "depth = (int) 32, "
118         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
119         "audio/x-raw-int, "
120         "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
121         "signed = (boolean) { TRUE, FALSE }, "
122         "width = (int) 24, "
123         "depth = (int) 24, "
124         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
125         "audio/x-raw-int, "
126         "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
127         "signed = (boolean) { TRUE, FALSE }, "
128         "width = (int) 32, "
129         "depth = (int) 24, "
130         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
131         "audio/x-raw-int, "
132         "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
133         "signed = (boolean) { TRUE, FALSE }, "
134         "width = (int) 16, "
135         "depth = (int) 16, "
136         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
137         "audio/x-raw-int, "
138         "signed = (boolean) { TRUE, FALSE }, "
139         "width = (int) 8, "
140         "depth = (int) 8, "
141         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ];"
142         "audio/x-iec958")
143     );
144
145 static void
146 gst_alsasink_finalise (GObject * object)
147 {
148   GstAlsaSink *sink = GST_ALSA_SINK (object);
149
150   g_free (sink->device);
151   g_mutex_free (sink->alsa_lock);
152
153   g_static_mutex_lock (&output_mutex);
154   --output_ref;
155   if (output_ref == 0) {
156     snd_output_close (output);
157     output = NULL;
158   }
159   g_static_mutex_unlock (&output_mutex);
160
161   G_OBJECT_CLASS (parent_class)->finalize (object);
162 }
163
164 static void
165 gst_alsasink_init_interfaces (GType type)
166 {
167   gst_alsa_type_add_device_property_probe_interface (type);
168 }
169
170 static void
171 gst_alsasink_base_init (gpointer g_class)
172 {
173   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
174
175   gst_element_class_set_details (element_class, &gst_alsasink_details);
176
177   gst_element_class_add_pad_template (element_class,
178       gst_static_pad_template_get (&alsasink_sink_factory));
179 }
180 static void
181 gst_alsasink_class_init (GstAlsaSinkClass * klass)
182 {
183   GObjectClass *gobject_class;
184   GstElementClass *gstelement_class;
185   GstBaseSinkClass *gstbasesink_class;
186   GstBaseAudioSinkClass *gstbaseaudiosink_class;
187   GstAudioSinkClass *gstaudiosink_class;
188
189   gobject_class = (GObjectClass *) klass;
190   gstelement_class = (GstElementClass *) klass;
191   gstbasesink_class = (GstBaseSinkClass *) klass;
192   gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
193   gstaudiosink_class = (GstAudioSinkClass *) klass;
194
195   parent_class = g_type_class_peek_parent (klass);
196
197   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasink_finalise);
198   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasink_get_property);
199   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasink_set_property);
200
201   gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink_getcaps);
202
203   gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink_open);
204   gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasink_prepare);
205   gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasink_unprepare);
206   gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_alsasink_close);
207   gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_alsasink_write);
208   gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_alsasink_delay);
209   gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_alsasink_reset);
210
211   g_object_class_install_property (gobject_class, PROP_DEVICE,
212       g_param_spec_string ("device", "Device",
213           "ALSA device, as defined in an asound configuration file",
214           DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
215
216   g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
217       g_param_spec_string ("device-name", "Device name",
218           "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
219           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
220 }
221
222 static void
223 gst_alsasink_set_property (GObject * object, guint prop_id,
224     const GValue * value, GParamSpec * pspec)
225 {
226   GstAlsaSink *sink;
227
228   sink = GST_ALSA_SINK (object);
229
230   switch (prop_id) {
231     case PROP_DEVICE:
232       g_free (sink->device);
233       sink->device = g_value_dup_string (value);
234       /* setting NULL restores the default device */
235       if (sink->device == NULL) {
236         sink->device = g_strdup (DEFAULT_DEVICE);
237       }
238       break;
239     default:
240       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
241       break;
242   }
243 }
244
245 static void
246 gst_alsasink_get_property (GObject * object, guint prop_id,
247     GValue * value, GParamSpec * pspec)
248 {
249   GstAlsaSink *sink;
250
251   sink = GST_ALSA_SINK (object);
252
253   switch (prop_id) {
254     case PROP_DEVICE:
255       g_value_set_string (value, sink->device);
256       break;
257     case PROP_DEVICE_NAME:
258       g_value_take_string (value,
259           gst_alsa_find_device_name (GST_OBJECT_CAST (sink),
260               sink->device, sink->handle, SND_PCM_STREAM_PLAYBACK));
261       break;
262     default:
263       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
264       break;
265   }
266 }
267
268 static void
269 gst_alsasink_init (GstAlsaSink * alsasink, GstAlsaSinkClass * g_class)
270 {
271   GST_DEBUG_OBJECT (alsasink, "initializing alsasink");
272
273   alsasink->device = g_strdup (DEFAULT_DEVICE);
274   alsasink->handle = NULL;
275   alsasink->cached_caps = NULL;
276   alsasink->alsa_lock = g_mutex_new ();
277
278   g_static_mutex_lock (&output_mutex);
279   if (output_ref == 0) {
280     snd_output_stdio_attach (&output, stdout, 0);
281     ++output_ref;
282   }
283   g_static_mutex_unlock (&output_mutex);
284 }
285
286 #define CHECK(call, error) \
287 G_STMT_START {                  \
288 if ((err = call) < 0)           \
289   goto error;                   \
290 } G_STMT_END;
291
292 static GstCaps *
293 gst_alsasink_getcaps (GstBaseSink * bsink)
294 {
295   GstElementClass *element_class;
296   GstPadTemplate *pad_template;
297   GstAlsaSink *sink = GST_ALSA_SINK (bsink);
298   GstCaps *caps;
299
300   if (sink->handle == NULL) {
301     GST_DEBUG_OBJECT (sink, "device not open, using template caps");
302     return NULL;                /* base class will get template caps for us */
303   }
304
305   if (sink->cached_caps) {
306     GST_LOG_OBJECT (sink, "Returning cached caps");
307     return gst_caps_ref (sink->cached_caps);
308   }
309
310   element_class = GST_ELEMENT_GET_CLASS (sink);
311   pad_template = gst_element_class_get_pad_template (element_class, "sink");
312   g_return_val_if_fail (pad_template != NULL, NULL);
313
314   caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->handle,
315       gst_pad_template_get_caps (pad_template));
316
317   if (caps) {
318     sink->cached_caps = gst_caps_ref (caps);
319   }
320
321   GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
322
323   return caps;
324 }
325
326 static int
327 set_hwparams (GstAlsaSink * alsa)
328 {
329   guint rrate;
330   gint err, dir;
331   snd_pcm_hw_params_t *params;
332   guint period_time, buffer_time;
333
334   snd_pcm_hw_params_malloc (&params);
335
336   GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
337       "SPDIF (%d)", alsa->channels, alsa->rate,
338       snd_pcm_format_name (alsa->format), alsa->iec958);
339
340   /* start with requested values, if we cannot configure alsa for those values,
341    * we set these values to -1, which will leave the default alsa values */
342   buffer_time = alsa->buffer_time;
343   period_time = alsa->period_time;
344
345 retry:
346   /* choose all parameters */
347   CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
348   /* set the interleaved read/write format */
349   CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
350       wrong_access);
351   /* set the sample format */
352   if (alsa->iec958) {
353     /* Try to use big endian first else fallback to le and swap bytes */
354     if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
355       alsa->format = SND_PCM_FORMAT_S16_LE;
356       alsa->need_swap = TRUE;
357       GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
358     } else {
359       alsa->need_swap = FALSE;
360     }
361   }
362   CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
363       no_sample_format);
364   /* set the count of channels */
365   CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
366       no_channels);
367   /* set the stream rate */
368   rrate = alsa->rate;
369   CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
370       no_rate);
371   if (rrate != alsa->rate)
372     goto rate_match;
373
374   /* get and dump some limits */
375   {
376     guint min, max;
377
378     snd_pcm_hw_params_get_buffer_time_min (params, &min, &dir);
379     snd_pcm_hw_params_get_buffer_time_max (params, &max, &dir);
380
381     GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
382         alsa->buffer_time, min, max);
383
384     snd_pcm_hw_params_get_period_time_min (params, &min, &dir);
385     snd_pcm_hw_params_get_period_time_max (params, &max, &dir);
386
387     GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
388         alsa->period_time, min, max);
389
390     snd_pcm_hw_params_get_periods_min (params, &min, &dir);
391     snd_pcm_hw_params_get_periods_max (params, &max, &dir);
392
393     GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
394   }
395
396   /* now try to configure the buffer time and period time, if one
397    * of those fail, we fall back to the defaults and emit a warning. */
398   if (buffer_time != -1 && !alsa->iec958) {
399     /* set the buffer time */
400     if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
401                 &buffer_time, &dir)) < 0) {
402       GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
403           ("Unable to set buffer time %i for playback: %s",
404               buffer_time, snd_strerror (err)));
405       /* disable buffer_time the next round */
406       buffer_time = -1;
407       goto retry;
408     }
409     GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
410   }
411   if (period_time != -1 && !alsa->iec958) {
412     /* set the period time */
413     if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
414                 &period_time, &dir)) < 0) {
415       GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
416           ("Unable to set period time %i for playback: %s",
417               period_time, snd_strerror (err)));
418       /* disable period_time the next round */
419       period_time = -1;
420       goto retry;
421     }
422     GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
423   }
424
425   /* Set buffer size and period size manually for SPDIF */
426   if (G_UNLIKELY (alsa->iec958)) {
427     snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
428     snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;
429
430     CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
431             &buffer_size), buffer_size);
432     CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
433             &period_size, NULL), period_size);
434   }
435
436   /* write the parameters to device */
437   CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
438
439   /* now get the configured values */
440   CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
441       buffer_size);
442   CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
443       period_size);
444
445   GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
446       alsa->period_size);
447
448   snd_pcm_hw_params_free (params);
449   return 0;
450
451   /* ERRORS */
452 no_config:
453   {
454     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
455         ("Broken configuration for playback: no configurations available: %s",
456             snd_strerror (err)));
457     snd_pcm_hw_params_free (params);
458     return err;
459   }
460 wrong_access:
461   {
462     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
463         ("Access type not available for playback: %s", snd_strerror (err)));
464     snd_pcm_hw_params_free (params);
465     return err;
466   }
467 no_sample_format:
468   {
469     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
470         ("Sample format not available for playback: %s", snd_strerror (err)));
471     snd_pcm_hw_params_free (params);
472     return err;
473   }
474 no_channels:
475   {
476     gchar *msg = NULL;
477
478     if ((alsa->channels) == 1)
479       msg = g_strdup (_("Could not open device for playback in mono mode."));
480     if ((alsa->channels) == 2)
481       msg = g_strdup (_("Could not open device for playback in stereo mode."));
482     if ((alsa->channels) > 2)
483       msg =
484           g_strdup_printf (_
485           ("Could not open device for playback in %d-channel mode."),
486           alsa->channels);
487     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
488     g_free (msg);
489     snd_pcm_hw_params_free (params);
490     return err;
491   }
492 no_rate:
493   {
494     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
495         ("Rate %iHz not available for playback: %s",
496             alsa->rate, snd_strerror (err)));
497     return err;
498   }
499 rate_match:
500   {
501     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
502         ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
503     snd_pcm_hw_params_free (params);
504     return -EINVAL;
505   }
506 buffer_size:
507   {
508     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
509         ("Unable to get buffer size for playback: %s", snd_strerror (err)));
510     snd_pcm_hw_params_free (params);
511     return err;
512   }
513 period_size:
514   {
515     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
516         ("Unable to get period size for playback: %s", snd_strerror (err)));
517     snd_pcm_hw_params_free (params);
518     return err;
519   }
520 set_hw_params:
521   {
522     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
523         ("Unable to set hw params for playback: %s", snd_strerror (err)));
524     snd_pcm_hw_params_free (params);
525     return err;
526   }
527 }
528
529 static int
530 set_swparams (GstAlsaSink * alsa)
531 {
532   int err;
533   snd_pcm_sw_params_t *params;
534
535   snd_pcm_sw_params_malloc (&params);
536
537   /* get the current swparams */
538   CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
539   /* start the transfer when the buffer is almost full: */
540   /* (buffer_size / avail_min) * avail_min */
541   CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
542           (alsa->buffer_size / alsa->period_size) * alsa->period_size),
543       start_threshold);
544
545   /* allow the transfer when at least period_size samples can be processed */
546   CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
547           alsa->period_size), set_avail);
548
549 #if GST_CHECK_ALSA_VERSION(1,0,16)
550   /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
551 #else
552   /* align all transfers to 1 sample */
553   CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
554 #endif
555
556   /* write the parameters to the playback device */
557   CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
558
559   snd_pcm_sw_params_free (params);
560   return 0;
561
562   /* ERRORS */
563 no_config:
564   {
565     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
566         ("Unable to determine current swparams for playback: %s",
567             snd_strerror (err)));
568     snd_pcm_sw_params_free (params);
569     return err;
570   }
571 start_threshold:
572   {
573     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
574         ("Unable to set start threshold mode for playback: %s",
575             snd_strerror (err)));
576     snd_pcm_sw_params_free (params);
577     return err;
578   }
579 set_avail:
580   {
581     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
582         ("Unable to set avail min for playback: %s", snd_strerror (err)));
583     snd_pcm_sw_params_free (params);
584     return err;
585   }
586 #if !GST_CHECK_ALSA_VERSION(1,0,16)
587 set_align:
588   {
589     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
590         ("Unable to set transfer align for playback: %s", snd_strerror (err)));
591     snd_pcm_sw_params_free (params);
592     return err;
593   }
594 #endif
595 set_sw_params:
596   {
597     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
598         ("Unable to set sw params for playback: %s", snd_strerror (err)));
599     snd_pcm_sw_params_free (params);
600     return err;
601   }
602 }
603
604 static gboolean
605 alsasink_parse_spec (GstAlsaSink * alsa, GstRingBufferSpec * spec)
606 {
607   /* Initialize our boolean */
608   alsa->iec958 = FALSE;
609
610   switch (spec->type) {
611     case GST_BUFTYPE_LINEAR:
612       GST_DEBUG_OBJECT (alsa,
613           "Linear format : depth=%d, width=%d, sign=%d, bigend=%d", spec->depth,
614           spec->width, spec->sign, spec->bigend);
615
616       alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
617           spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
618       break;
619     case GST_BUFTYPE_FLOAT:
620       switch (spec->format) {
621         case GST_FLOAT32_LE:
622           alsa->format = SND_PCM_FORMAT_FLOAT_LE;
623           break;
624         case GST_FLOAT32_BE:
625           alsa->format = SND_PCM_FORMAT_FLOAT_BE;
626           break;
627         case GST_FLOAT64_LE:
628           alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
629           break;
630         case GST_FLOAT64_BE:
631           alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
632           break;
633         default:
634           goto error;
635       }
636       break;
637     case GST_BUFTYPE_A_LAW:
638       alsa->format = SND_PCM_FORMAT_A_LAW;
639       break;
640     case GST_BUFTYPE_MU_LAW:
641       alsa->format = SND_PCM_FORMAT_MU_LAW;
642       break;
643     case GST_BUFTYPE_IEC958:
644       alsa->format = SND_PCM_FORMAT_S16_BE;
645       alsa->iec958 = TRUE;
646       break;
647     default:
648       goto error;
649
650   }
651   alsa->rate = spec->rate;
652   alsa->channels = spec->channels;
653   alsa->buffer_time = spec->buffer_time;
654   alsa->period_time = spec->latency_time;
655   alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
656
657   return TRUE;
658
659   /* ERRORS */
660 error:
661   {
662     return FALSE;
663   }
664 }
665
666 static gboolean
667 gst_alsasink_open (GstAudioSink * asink)
668 {
669   GstAlsaSink *alsa;
670   gint err;
671
672   alsa = GST_ALSA_SINK (asink);
673
674   /* open in non-blocking mode, we'll use snd_pcm_wait() for space to become
675    * available. */
676   CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_PLAYBACK,
677           SND_PCM_NONBLOCK), open_error);
678   GST_LOG_OBJECT (alsa, "Opened device %s", alsa->device);
679
680   return TRUE;
681
682   /* ERRORS */
683 open_error:
684   {
685     if (err == -EBUSY) {
686       GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
687           (_("Could not open audio device for playback. "
688                   "Device is being used by another application.")),
689           ("Device '%s' is busy", alsa->device));
690     } else {
691       GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE,
692           (_("Could not open audio device for playback.")),
693           ("Playback open error on device '%s': %s", alsa->device,
694               snd_strerror (err)));
695     }
696     return FALSE;
697   }
698 }
699
700 static gboolean
701 gst_alsasink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
702 {
703   GstAlsaSink *alsa;
704   gint err;
705
706   alsa = GST_ALSA_SINK (asink);
707
708   if (spec->format == GST_IEC958) {
709     snd_pcm_close (alsa->handle);
710     alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa));
711     if (G_UNLIKELY (!alsa->handle)) {
712       goto no_iec958;
713     }
714   }
715
716   if (!alsasink_parse_spec (alsa, spec))
717     goto spec_parse;
718
719   CHECK (set_hwparams (alsa), hw_params_failed);
720   CHECK (set_swparams (alsa), sw_params_failed);
721
722   alsa->bytes_per_sample = spec->bytes_per_sample;
723   spec->segsize = alsa->period_size * spec->bytes_per_sample;
724   spec->segtotal = alsa->buffer_size / alsa->period_size;
725
726   {
727     snd_output_t *out_buf = NULL;
728     char *msg = NULL;
729
730     snd_output_buffer_open (&out_buf);
731     snd_pcm_dump_hw_setup (alsa->handle, out_buf);
732     snd_output_buffer_string (out_buf, &msg);
733     GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
734     snd_output_close (out_buf);
735     snd_output_buffer_open (&out_buf);
736     snd_pcm_dump_sw_setup (alsa->handle, out_buf);
737     snd_output_buffer_string (out_buf, &msg);
738     GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
739     snd_output_close (out_buf);
740   }
741
742   return TRUE;
743
744   /* ERRORS */
745 no_iec958:
746   {
747     GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL),
748         ("Could not open IEC958 (SPDIF) device for playback"));
749     return FALSE;
750   }
751 spec_parse:
752   {
753     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
754         ("Error parsing spec"));
755     return FALSE;
756   }
757 hw_params_failed:
758   {
759     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
760         ("Setting of hwparams failed: %s", snd_strerror (err)));
761     return FALSE;
762   }
763 sw_params_failed:
764   {
765     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
766         ("Setting of swparams failed: %s", snd_strerror (err)));
767     return FALSE;
768   }
769 }
770
771 static gboolean
772 gst_alsasink_unprepare (GstAudioSink * asink)
773 {
774   GstAlsaSink *alsa;
775   gint err;
776
777   alsa = GST_ALSA_SINK (asink);
778
779   CHECK (snd_pcm_drop (alsa->handle), drop);
780
781   CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
782
783   return TRUE;
784
785   /* ERRORS */
786 drop:
787   {
788     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
789         ("Could not drop samples: %s", snd_strerror (err)));
790     return FALSE;
791   }
792 hw_free:
793   {
794     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
795         ("Could not free hw params: %s", snd_strerror (err)));
796     return FALSE;
797   }
798 }
799
800 static gboolean
801 gst_alsasink_close (GstAudioSink * asink)
802 {
803   GstAlsaSink *alsa = GST_ALSA_SINK (asink);
804   gint err;
805
806   if (alsa->handle) {
807     CHECK (snd_pcm_close (alsa->handle), close_error);
808     alsa->handle = NULL;
809   }
810   gst_caps_replace (&alsa->cached_caps, NULL);
811
812   return TRUE;
813
814   /* ERRORS */
815 close_error:
816   {
817     GST_ELEMENT_ERROR (alsa, RESOURCE, CLOSE, (NULL),
818         ("Playback close error: %s", snd_strerror (err)));
819     return FALSE;
820   }
821 }
822
823
824 /*
825  *   Underrun and suspend recovery
826  */
827 static gint
828 xrun_recovery (GstAlsaSink * alsa, snd_pcm_t * handle, gint err)
829 {
830   GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
831
832   if (err == -EPIPE) {          /* under-run */
833     err = snd_pcm_prepare (handle);
834     if (err < 0)
835       GST_WARNING_OBJECT (alsa,
836           "Can't recovery from underrun, prepare failed: %s",
837           snd_strerror (err));
838     return 0;
839   } else if (err == -ESTRPIPE) {
840     while ((err = snd_pcm_resume (handle)) == -EAGAIN)
841       g_usleep (100);           /* wait until the suspend flag is released */
842
843     if (err < 0) {
844       err = snd_pcm_prepare (handle);
845       if (err < 0)
846         GST_WARNING_OBJECT (alsa,
847             "Can't recovery from suspend, prepare failed: %s",
848             snd_strerror (err));
849     }
850     return 0;
851   }
852   return err;
853 }
854
855 static guint
856 gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
857 {
858   GstAlsaSink *alsa;
859   gint err;
860   gint cptr;
861   gint16 *ptr = data;
862
863   alsa = GST_ALSA_SINK (asink);
864
865   if (alsa->iec958 && alsa->need_swap) {
866     guint i;
867
868     GST_DEBUG_OBJECT (asink, "swapping bytes");
869     for (i = 0; i < length / 2; i++) {
870       ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
871     }
872   }
873
874   GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
875
876   cptr = length / alsa->bytes_per_sample;
877
878   GST_ALSA_SINK_LOCK (asink);
879   while (cptr > 0) {
880     /* start by doing a blocking wait for free space. Set the timeout
881      * to 4 times the period time */
882     err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
883     if (err < 0) {
884       GST_DEBUG_OBJECT (asink, "wait error, %d", err);
885     }
886     else {
887       err = snd_pcm_writei (alsa->handle, ptr, cptr);
888     }
889
890     GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
891     if (err < 0) {
892       GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
893       if (err == -EAGAIN) {
894         continue;
895       } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
896         goto write_error;
897       }
898       continue;
899     }
900
901     ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
902     cptr -= err;
903   }
904   GST_ALSA_SINK_UNLOCK (asink);
905
906   return length - (cptr * alsa->bytes_per_sample);
907
908 write_error:
909   {
910     GST_ALSA_SINK_UNLOCK (asink);
911     return length;              /* skip one period */
912   }
913 }
914
915 static guint
916 gst_alsasink_delay (GstAudioSink * asink)
917 {
918   GstAlsaSink *alsa;
919   snd_pcm_sframes_t delay;
920   int res;
921
922   alsa = GST_ALSA_SINK (asink);
923
924   res = snd_pcm_delay (alsa->handle, &delay);
925   if (G_UNLIKELY (res < 0)) {
926     /* on errors, report 0 delay */
927     GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
928     delay = 0;
929   }
930   if (G_UNLIKELY (delay < 0)) {
931     /* make sure we never return a negative delay */
932     GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay");
933     delay = 0;
934   }
935
936   return delay;
937 }
938
939 static void
940 gst_alsasink_reset (GstAudioSink * asink)
941 {
942   GstAlsaSink *alsa;
943   gint err;
944
945   alsa = GST_ALSA_SINK (asink);
946
947   GST_ALSA_SINK_LOCK (asink);
948   GST_DEBUG_OBJECT (alsa, "drop");
949   CHECK (snd_pcm_drop (alsa->handle), drop_error);
950   GST_DEBUG_OBJECT (alsa, "prepare");
951   CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
952   GST_DEBUG_OBJECT (alsa, "reset done");
953   GST_ALSA_SINK_UNLOCK (asink);
954
955   return;
956
957   /* ERRORS */
958 drop_error:
959   {
960     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
961         snd_strerror (err));
962     GST_ALSA_SINK_UNLOCK (asink);
963     return;
964   }
965 prepare_error:
966   {
967     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
968         snd_strerror (err));
969     GST_ALSA_SINK_UNLOCK (asink);
970     return;
971   }
972 }