ext: Remove dead assignments and resulting unused variables.
[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   GstBaseSinkClass *gstbasesink_class;
185   GstAudioSinkClass *gstaudiosink_class;
186
187   gobject_class = (GObjectClass *) klass;
188   gstbasesink_class = (GstBaseSinkClass *) klass;
189   gstaudiosink_class = (GstAudioSinkClass *) klass;
190
191   parent_class = g_type_class_peek_parent (klass);
192
193   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasink_finalise);
194   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasink_get_property);
195   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasink_set_property);
196
197   gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink_getcaps);
198
199   gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink_open);
200   gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasink_prepare);
201   gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasink_unprepare);
202   gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_alsasink_close);
203   gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_alsasink_write);
204   gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_alsasink_delay);
205   gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_alsasink_reset);
206
207   g_object_class_install_property (gobject_class, PROP_DEVICE,
208       g_param_spec_string ("device", "Device",
209           "ALSA device, as defined in an asound configuration file",
210           DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
211
212   g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
213       g_param_spec_string ("device-name", "Device name",
214           "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
215           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
216 }
217
218 static void
219 gst_alsasink_set_property (GObject * object, guint prop_id,
220     const GValue * value, GParamSpec * pspec)
221 {
222   GstAlsaSink *sink;
223
224   sink = GST_ALSA_SINK (object);
225
226   switch (prop_id) {
227     case PROP_DEVICE:
228       g_free (sink->device);
229       sink->device = g_value_dup_string (value);
230       /* setting NULL restores the default device */
231       if (sink->device == NULL) {
232         sink->device = g_strdup (DEFAULT_DEVICE);
233       }
234       break;
235     default:
236       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
237       break;
238   }
239 }
240
241 static void
242 gst_alsasink_get_property (GObject * object, guint prop_id,
243     GValue * value, GParamSpec * pspec)
244 {
245   GstAlsaSink *sink;
246
247   sink = GST_ALSA_SINK (object);
248
249   switch (prop_id) {
250     case PROP_DEVICE:
251       g_value_set_string (value, sink->device);
252       break;
253     case PROP_DEVICE_NAME:
254       g_value_take_string (value,
255           gst_alsa_find_device_name (GST_OBJECT_CAST (sink),
256               sink->device, sink->handle, SND_PCM_STREAM_PLAYBACK));
257       break;
258     default:
259       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
260       break;
261   }
262 }
263
264 static void
265 gst_alsasink_init (GstAlsaSink * alsasink, GstAlsaSinkClass * g_class)
266 {
267   GST_DEBUG_OBJECT (alsasink, "initializing alsasink");
268
269   alsasink->device = g_strdup (DEFAULT_DEVICE);
270   alsasink->handle = NULL;
271   alsasink->cached_caps = NULL;
272   alsasink->alsa_lock = g_mutex_new ();
273
274   g_static_mutex_lock (&output_mutex);
275   if (output_ref == 0) {
276     snd_output_stdio_attach (&output, stdout, 0);
277     ++output_ref;
278   }
279   g_static_mutex_unlock (&output_mutex);
280 }
281
282 #define CHECK(call, error) \
283 G_STMT_START {                  \
284 if ((err = call) < 0)           \
285   goto error;                   \
286 } G_STMT_END;
287
288 static GstCaps *
289 gst_alsasink_getcaps (GstBaseSink * bsink)
290 {
291   GstElementClass *element_class;
292   GstPadTemplate *pad_template;
293   GstAlsaSink *sink = GST_ALSA_SINK (bsink);
294   GstCaps *caps;
295
296   if (sink->handle == NULL) {
297     GST_DEBUG_OBJECT (sink, "device not open, using template caps");
298     return NULL;                /* base class will get template caps for us */
299   }
300
301   if (sink->cached_caps) {
302     GST_LOG_OBJECT (sink, "Returning cached caps");
303     return gst_caps_ref (sink->cached_caps);
304   }
305
306   element_class = GST_ELEMENT_GET_CLASS (sink);
307   pad_template = gst_element_class_get_pad_template (element_class, "sink");
308   g_return_val_if_fail (pad_template != NULL, NULL);
309
310   caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->handle,
311       gst_pad_template_get_caps (pad_template));
312
313   if (caps) {
314     sink->cached_caps = gst_caps_ref (caps);
315   }
316
317   GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
318
319   return caps;
320 }
321
322 static int
323 set_hwparams (GstAlsaSink * alsa)
324 {
325   guint rrate;
326   gint err, dir;
327   snd_pcm_hw_params_t *params;
328   guint period_time, buffer_time;
329
330   snd_pcm_hw_params_malloc (&params);
331
332   GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
333       "SPDIF (%d)", alsa->channels, alsa->rate,
334       snd_pcm_format_name (alsa->format), alsa->iec958);
335
336   /* start with requested values, if we cannot configure alsa for those values,
337    * we set these values to -1, which will leave the default alsa values */
338   buffer_time = alsa->buffer_time;
339   period_time = alsa->period_time;
340
341 retry:
342   /* choose all parameters */
343   CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
344   /* set the interleaved read/write format */
345   CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
346       wrong_access);
347   /* set the sample format */
348   if (alsa->iec958) {
349     /* Try to use big endian first else fallback to le and swap bytes */
350     if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
351       alsa->format = SND_PCM_FORMAT_S16_LE;
352       alsa->need_swap = TRUE;
353       GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
354     } else {
355       alsa->need_swap = FALSE;
356     }
357   }
358   CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
359       no_sample_format);
360   /* set the count of channels */
361   CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
362       no_channels);
363   /* set the stream rate */
364   rrate = alsa->rate;
365   CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
366       no_rate);
367   if (rrate != alsa->rate)
368     goto rate_match;
369
370   /* get and dump some limits */
371   {
372     guint min, max;
373
374     snd_pcm_hw_params_get_buffer_time_min (params, &min, &dir);
375     snd_pcm_hw_params_get_buffer_time_max (params, &max, &dir);
376
377     GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
378         alsa->buffer_time, min, max);
379
380     snd_pcm_hw_params_get_period_time_min (params, &min, &dir);
381     snd_pcm_hw_params_get_period_time_max (params, &max, &dir);
382
383     GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
384         alsa->period_time, min, max);
385
386     snd_pcm_hw_params_get_periods_min (params, &min, &dir);
387     snd_pcm_hw_params_get_periods_max (params, &max, &dir);
388
389     GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
390   }
391
392   /* now try to configure the buffer time and period time, if one
393    * of those fail, we fall back to the defaults and emit a warning. */
394   if (buffer_time != -1 && !alsa->iec958) {
395     /* set the buffer time */
396     if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
397                 &buffer_time, &dir)) < 0) {
398       GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
399           ("Unable to set buffer time %i for playback: %s",
400               buffer_time, snd_strerror (err)));
401       /* disable buffer_time the next round */
402       buffer_time = -1;
403       goto retry;
404     }
405     GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
406   }
407   if (period_time != -1 && !alsa->iec958) {
408     /* set the period time */
409     if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
410                 &period_time, &dir)) < 0) {
411       GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
412           ("Unable to set period time %i for playback: %s",
413               period_time, snd_strerror (err)));
414       /* disable period_time the next round */
415       period_time = -1;
416       goto retry;
417     }
418     GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
419   }
420
421   /* Set buffer size and period size manually for SPDIF */
422   if (G_UNLIKELY (alsa->iec958)) {
423     snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
424     snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;
425
426     CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
427             &buffer_size), buffer_size);
428     CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
429             &period_size, NULL), period_size);
430   }
431
432   /* write the parameters to device */
433   CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
434
435   /* now get the configured values */
436   CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
437       buffer_size);
438   CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
439       period_size);
440
441   GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
442       alsa->period_size);
443
444   snd_pcm_hw_params_free (params);
445   return 0;
446
447   /* ERRORS */
448 no_config:
449   {
450     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
451         ("Broken configuration for playback: no configurations available: %s",
452             snd_strerror (err)));
453     snd_pcm_hw_params_free (params);
454     return err;
455   }
456 wrong_access:
457   {
458     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
459         ("Access type not available for playback: %s", snd_strerror (err)));
460     snd_pcm_hw_params_free (params);
461     return err;
462   }
463 no_sample_format:
464   {
465     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
466         ("Sample format not available for playback: %s", snd_strerror (err)));
467     snd_pcm_hw_params_free (params);
468     return err;
469   }
470 no_channels:
471   {
472     gchar *msg = NULL;
473
474     if ((alsa->channels) == 1)
475       msg = g_strdup (_("Could not open device for playback in mono mode."));
476     if ((alsa->channels) == 2)
477       msg = g_strdup (_("Could not open device for playback in stereo mode."));
478     if ((alsa->channels) > 2)
479       msg =
480           g_strdup_printf (_
481           ("Could not open device for playback in %d-channel mode."),
482           alsa->channels);
483     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
484     g_free (msg);
485     snd_pcm_hw_params_free (params);
486     return err;
487   }
488 no_rate:
489   {
490     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
491         ("Rate %iHz not available for playback: %s",
492             alsa->rate, snd_strerror (err)));
493     return err;
494   }
495 rate_match:
496   {
497     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
498         ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
499     snd_pcm_hw_params_free (params);
500     return -EINVAL;
501   }
502 buffer_size:
503   {
504     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
505         ("Unable to get buffer size for playback: %s", snd_strerror (err)));
506     snd_pcm_hw_params_free (params);
507     return err;
508   }
509 period_size:
510   {
511     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
512         ("Unable to get period size for playback: %s", snd_strerror (err)));
513     snd_pcm_hw_params_free (params);
514     return err;
515   }
516 set_hw_params:
517   {
518     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
519         ("Unable to set hw params for playback: %s", snd_strerror (err)));
520     snd_pcm_hw_params_free (params);
521     return err;
522   }
523 }
524
525 static int
526 set_swparams (GstAlsaSink * alsa)
527 {
528   int err;
529   snd_pcm_sw_params_t *params;
530
531   snd_pcm_sw_params_malloc (&params);
532
533   /* get the current swparams */
534   CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
535   /* start the transfer when the buffer is almost full: */
536   /* (buffer_size / avail_min) * avail_min */
537   CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
538           (alsa->buffer_size / alsa->period_size) * alsa->period_size),
539       start_threshold);
540
541   /* allow the transfer when at least period_size samples can be processed */
542   CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
543           alsa->period_size), set_avail);
544
545 #if GST_CHECK_ALSA_VERSION(1,0,16)
546   /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
547 #else
548   /* align all transfers to 1 sample */
549   CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
550 #endif
551
552   /* write the parameters to the playback device */
553   CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
554
555   snd_pcm_sw_params_free (params);
556   return 0;
557
558   /* ERRORS */
559 no_config:
560   {
561     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
562         ("Unable to determine current swparams for playback: %s",
563             snd_strerror (err)));
564     snd_pcm_sw_params_free (params);
565     return err;
566   }
567 start_threshold:
568   {
569     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
570         ("Unable to set start threshold mode for playback: %s",
571             snd_strerror (err)));
572     snd_pcm_sw_params_free (params);
573     return err;
574   }
575 set_avail:
576   {
577     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
578         ("Unable to set avail min for playback: %s", snd_strerror (err)));
579     snd_pcm_sw_params_free (params);
580     return err;
581   }
582 #if !GST_CHECK_ALSA_VERSION(1,0,16)
583 set_align:
584   {
585     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
586         ("Unable to set transfer align for playback: %s", snd_strerror (err)));
587     snd_pcm_sw_params_free (params);
588     return err;
589   }
590 #endif
591 set_sw_params:
592   {
593     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
594         ("Unable to set sw params for playback: %s", snd_strerror (err)));
595     snd_pcm_sw_params_free (params);
596     return err;
597   }
598 }
599
600 static gboolean
601 alsasink_parse_spec (GstAlsaSink * alsa, GstRingBufferSpec * spec)
602 {
603   /* Initialize our boolean */
604   alsa->iec958 = FALSE;
605
606   switch (spec->type) {
607     case GST_BUFTYPE_LINEAR:
608       GST_DEBUG_OBJECT (alsa,
609           "Linear format : depth=%d, width=%d, sign=%d, bigend=%d", spec->depth,
610           spec->width, spec->sign, spec->bigend);
611
612       alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
613           spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
614       break;
615     case GST_BUFTYPE_FLOAT:
616       switch (spec->format) {
617         case GST_FLOAT32_LE:
618           alsa->format = SND_PCM_FORMAT_FLOAT_LE;
619           break;
620         case GST_FLOAT32_BE:
621           alsa->format = SND_PCM_FORMAT_FLOAT_BE;
622           break;
623         case GST_FLOAT64_LE:
624           alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
625           break;
626         case GST_FLOAT64_BE:
627           alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
628           break;
629         default:
630           goto error;
631       }
632       break;
633     case GST_BUFTYPE_A_LAW:
634       alsa->format = SND_PCM_FORMAT_A_LAW;
635       break;
636     case GST_BUFTYPE_MU_LAW:
637       alsa->format = SND_PCM_FORMAT_MU_LAW;
638       break;
639     case GST_BUFTYPE_IEC958:
640       alsa->format = SND_PCM_FORMAT_S16_BE;
641       alsa->iec958 = TRUE;
642       break;
643     default:
644       goto error;
645
646   }
647   alsa->rate = spec->rate;
648   alsa->channels = spec->channels;
649   alsa->buffer_time = spec->buffer_time;
650   alsa->period_time = spec->latency_time;
651   alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
652
653   return TRUE;
654
655   /* ERRORS */
656 error:
657   {
658     return FALSE;
659   }
660 }
661
662 static gboolean
663 gst_alsasink_open (GstAudioSink * asink)
664 {
665   GstAlsaSink *alsa;
666   gint err;
667
668   alsa = GST_ALSA_SINK (asink);
669
670   /* open in non-blocking mode, we'll use snd_pcm_wait() for space to become
671    * available. */
672   CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_PLAYBACK,
673           SND_PCM_NONBLOCK), open_error);
674   GST_LOG_OBJECT (alsa, "Opened device %s", alsa->device);
675
676   return TRUE;
677
678   /* ERRORS */
679 open_error:
680   {
681     if (err == -EBUSY) {
682       GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
683           (_("Could not open audio device for playback. "
684                   "Device is being used by another application.")),
685           ("Device '%s' is busy", alsa->device));
686     } else {
687       GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE,
688           (_("Could not open audio device for playback.")),
689           ("Playback open error on device '%s': %s", alsa->device,
690               snd_strerror (err)));
691     }
692     return FALSE;
693   }
694 }
695
696 static gboolean
697 gst_alsasink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
698 {
699   GstAlsaSink *alsa;
700   gint err;
701
702   alsa = GST_ALSA_SINK (asink);
703
704   if (spec->format == GST_IEC958) {
705     snd_pcm_close (alsa->handle);
706     alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa));
707     if (G_UNLIKELY (!alsa->handle)) {
708       goto no_iec958;
709     }
710   }
711
712   if (!alsasink_parse_spec (alsa, spec))
713     goto spec_parse;
714
715   CHECK (set_hwparams (alsa), hw_params_failed);
716   CHECK (set_swparams (alsa), sw_params_failed);
717
718   alsa->bytes_per_sample = spec->bytes_per_sample;
719   spec->segsize = alsa->period_size * spec->bytes_per_sample;
720   spec->segtotal = alsa->buffer_size / alsa->period_size;
721
722   {
723     snd_output_t *out_buf = NULL;
724     char *msg = NULL;
725
726     snd_output_buffer_open (&out_buf);
727     snd_pcm_dump_hw_setup (alsa->handle, out_buf);
728     snd_output_buffer_string (out_buf, &msg);
729     GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
730     snd_output_close (out_buf);
731     snd_output_buffer_open (&out_buf);
732     snd_pcm_dump_sw_setup (alsa->handle, out_buf);
733     snd_output_buffer_string (out_buf, &msg);
734     GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
735     snd_output_close (out_buf);
736   }
737
738   return TRUE;
739
740   /* ERRORS */
741 no_iec958:
742   {
743     GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL),
744         ("Could not open IEC958 (SPDIF) device for playback"));
745     return FALSE;
746   }
747 spec_parse:
748   {
749     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
750         ("Error parsing spec"));
751     return FALSE;
752   }
753 hw_params_failed:
754   {
755     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
756         ("Setting of hwparams failed: %s", snd_strerror (err)));
757     return FALSE;
758   }
759 sw_params_failed:
760   {
761     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
762         ("Setting of swparams failed: %s", snd_strerror (err)));
763     return FALSE;
764   }
765 }
766
767 static gboolean
768 gst_alsasink_unprepare (GstAudioSink * asink)
769 {
770   GstAlsaSink *alsa;
771   gint err;
772
773   alsa = GST_ALSA_SINK (asink);
774
775   CHECK (snd_pcm_drop (alsa->handle), drop);
776
777   CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
778
779   return TRUE;
780
781   /* ERRORS */
782 drop:
783   {
784     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
785         ("Could not drop samples: %s", snd_strerror (err)));
786     return FALSE;
787   }
788 hw_free:
789   {
790     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
791         ("Could not free hw params: %s", snd_strerror (err)));
792     return FALSE;
793   }
794 }
795
796 static gboolean
797 gst_alsasink_close (GstAudioSink * asink)
798 {
799   GstAlsaSink *alsa = GST_ALSA_SINK (asink);
800   gint err;
801
802   if (alsa->handle) {
803     CHECK (snd_pcm_close (alsa->handle), close_error);
804     alsa->handle = NULL;
805   }
806   gst_caps_replace (&alsa->cached_caps, NULL);
807
808   return TRUE;
809
810   /* ERRORS */
811 close_error:
812   {
813     GST_ELEMENT_ERROR (alsa, RESOURCE, CLOSE, (NULL),
814         ("Playback close error: %s", snd_strerror (err)));
815     return FALSE;
816   }
817 }
818
819
820 /*
821  *   Underrun and suspend recovery
822  */
823 static gint
824 xrun_recovery (GstAlsaSink * alsa, snd_pcm_t * handle, gint err)
825 {
826   GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
827
828   if (err == -EPIPE) {          /* under-run */
829     err = snd_pcm_prepare (handle);
830     if (err < 0)
831       GST_WARNING_OBJECT (alsa,
832           "Can't recovery from underrun, prepare failed: %s",
833           snd_strerror (err));
834     return 0;
835   } else if (err == -ESTRPIPE) {
836     while ((err = snd_pcm_resume (handle)) == -EAGAIN)
837       g_usleep (100);           /* wait until the suspend flag is released */
838
839     if (err < 0) {
840       err = snd_pcm_prepare (handle);
841       if (err < 0)
842         GST_WARNING_OBJECT (alsa,
843             "Can't recovery from suspend, prepare failed: %s",
844             snd_strerror (err));
845     }
846     return 0;
847   }
848   return err;
849 }
850
851 static guint
852 gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
853 {
854   GstAlsaSink *alsa;
855   gint err;
856   gint cptr;
857   gint16 *ptr = data;
858
859   alsa = GST_ALSA_SINK (asink);
860
861   if (alsa->iec958 && alsa->need_swap) {
862     guint i;
863
864     GST_DEBUG_OBJECT (asink, "swapping bytes");
865     for (i = 0; i < length / 2; i++) {
866       ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
867     }
868   }
869
870   GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
871
872   cptr = length / alsa->bytes_per_sample;
873
874   GST_ALSA_SINK_LOCK (asink);
875   while (cptr > 0) {
876     /* start by doing a blocking wait for free space. Set the timeout
877      * to 4 times the period time */
878     err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
879     if (err < 0) {
880       GST_DEBUG_OBJECT (asink, "wait error, %d", err);
881     } else {
882       err = snd_pcm_writei (alsa->handle, ptr, cptr);
883     }
884
885     GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
886     if (err < 0) {
887       GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
888       if (err == -EAGAIN) {
889         continue;
890       } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
891         goto write_error;
892       }
893       continue;
894     }
895
896     ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
897     cptr -= err;
898   }
899   GST_ALSA_SINK_UNLOCK (asink);
900
901   return length - (cptr * alsa->bytes_per_sample);
902
903 write_error:
904   {
905     GST_ALSA_SINK_UNLOCK (asink);
906     return length;              /* skip one period */
907   }
908 }
909
910 static guint
911 gst_alsasink_delay (GstAudioSink * asink)
912 {
913   GstAlsaSink *alsa;
914   snd_pcm_sframes_t delay;
915   int res;
916
917   alsa = GST_ALSA_SINK (asink);
918
919   res = snd_pcm_delay (alsa->handle, &delay);
920   if (G_UNLIKELY (res < 0)) {
921     /* on errors, report 0 delay */
922     GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
923     delay = 0;
924   }
925   if (G_UNLIKELY (delay < 0)) {
926     /* make sure we never return a negative delay */
927     GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay");
928     delay = 0;
929   }
930
931   return delay;
932 }
933
934 static void
935 gst_alsasink_reset (GstAudioSink * asink)
936 {
937   GstAlsaSink *alsa;
938   gint err;
939
940   alsa = GST_ALSA_SINK (asink);
941
942   GST_ALSA_SINK_LOCK (asink);
943   GST_DEBUG_OBJECT (alsa, "drop");
944   CHECK (snd_pcm_drop (alsa->handle), drop_error);
945   GST_DEBUG_OBJECT (alsa, "prepare");
946   CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
947   GST_DEBUG_OBJECT (alsa, "reset done");
948   GST_ALSA_SINK_UNLOCK (asink);
949
950   return;
951
952   /* ERRORS */
953 drop_error:
954   {
955     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
956         snd_strerror (err));
957     GST_ALSA_SINK_UNLOCK (asink);
958     return;
959   }
960 prepare_error:
961   {
962     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
963         snd_strerror (err));
964     GST_ALSA_SINK_UNLOCK (asink);
965     return;
966   }
967 }