tizen 2.3 release
[framework/multimedia/gst-plugins-base0.10.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 #include "gst/glib-compat-private.h"
56
57 #define DEFAULT_DEVICE          "default"
58 #define DEFAULT_DEVICE_NAME     ""
59 #define DEFAULT_CARD_NAME       ""
60 #define SPDIF_PERIOD_SIZE 1536
61 #define SPDIF_BUFFER_SIZE 15360
62
63 enum
64 {
65   PROP_0,
66   PROP_DEVICE,
67   PROP_DEVICE_NAME,
68   PROP_CARD_NAME,
69   PROP_LAST
70 };
71
72 static void gst_alsasink_init_interfaces (GType type);
73
74 GST_BOILERPLATE_FULL (GstAlsaSink, gst_alsasink, GstAudioSink,
75     GST_TYPE_AUDIO_SINK, gst_alsasink_init_interfaces);
76
77 static void gst_alsasink_finalise (GObject * object);
78 static void gst_alsasink_set_property (GObject * object,
79     guint prop_id, const GValue * value, GParamSpec * pspec);
80 static void gst_alsasink_get_property (GObject * object,
81     guint prop_id, GValue * value, GParamSpec * pspec);
82
83 static GstCaps *gst_alsasink_getcaps (GstBaseSink * bsink);
84
85 static gboolean gst_alsasink_open (GstAudioSink * asink);
86 static gboolean gst_alsasink_prepare (GstAudioSink * asink,
87     GstRingBufferSpec * spec);
88 static gboolean gst_alsasink_unprepare (GstAudioSink * asink);
89 static gboolean gst_alsasink_close (GstAudioSink * asink);
90 static guint gst_alsasink_write (GstAudioSink * asink, gpointer data,
91     guint length);
92 static guint gst_alsasink_delay (GstAudioSink * asink);
93 static void gst_alsasink_reset (GstAudioSink * asink);
94
95 static gint output_ref;         /* 0    */
96 static snd_output_t *output;    /* NULL */
97 static GStaticMutex output_mutex = G_STATIC_MUTEX_INIT;
98
99
100 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
101 # define ALSA_SINK_FACTORY_ENDIANNESS   "LITTLE_ENDIAN, BIG_ENDIAN"
102 #else
103 # define ALSA_SINK_FACTORY_ENDIANNESS   "BIG_ENDIAN, LITTLE_ENDIAN"
104 #endif
105
106 static GstStaticPadTemplate alsasink_sink_factory =
107     GST_STATIC_PAD_TEMPLATE ("sink",
108     GST_PAD_SINK,
109     GST_PAD_ALWAYS,
110     GST_STATIC_CAPS ("audio/x-raw-int, "
111         "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
112         "signed = (boolean) { TRUE, FALSE }, "
113         "width = (int) 32, "
114         "depth = (int) 32, "
115         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
116         "audio/x-raw-int, "
117         "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
118         "signed = (boolean) { TRUE, FALSE }, "
119         "width = (int) 24, "
120         "depth = (int) 24, "
121         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
122         "audio/x-raw-int, "
123         "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
124         "signed = (boolean) { TRUE, FALSE }, "
125         "width = (int) 32, "
126         "depth = (int) 24, "
127         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
128         "audio/x-raw-int, "
129         "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
130         "signed = (boolean) { TRUE, FALSE }, "
131         "width = (int) 16, "
132         "depth = (int) 16, "
133         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
134         "audio/x-raw-int, "
135         "signed = (boolean) { TRUE, FALSE }, "
136         "width = (int) 8, "
137         "depth = (int) 8, "
138         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ];"
139         "audio/x-iec958")
140     );
141
142 static void
143 gst_alsasink_finalise (GObject * object)
144 {
145   GstAlsaSink *sink = GST_ALSA_SINK (object);
146
147   g_free (sink->device);
148   g_mutex_free (sink->alsa_lock);
149
150   g_static_mutex_lock (&output_mutex);
151   --output_ref;
152   if (output_ref == 0) {
153     snd_output_close (output);
154     output = NULL;
155   }
156   g_static_mutex_unlock (&output_mutex);
157
158   G_OBJECT_CLASS (parent_class)->finalize (object);
159 }
160
161 static void
162 gst_alsasink_init_interfaces (GType type)
163 {
164   gst_alsa_type_add_device_property_probe_interface (type);
165 }
166
167 static void
168 gst_alsasink_base_init (gpointer g_class)
169 {
170   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
171
172   gst_element_class_set_details_simple (element_class,
173       "Audio sink (ALSA)", "Sink/Audio",
174       "Output to a sound card via ALSA", "Wim Taymans <wim@fluendo.com>");
175
176   gst_element_class_add_static_pad_template (element_class,
177       &alsasink_sink_factory);
178 }
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_alsasink_finalise;
194   gobject_class->get_property = gst_alsasink_get_property;
195   gobject_class->set_property = 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   g_object_class_install_property (gobject_class, PROP_CARD_NAME,
218       g_param_spec_string ("card-name", "Card name",
219           "Human-readable name of the sound card", DEFAULT_CARD_NAME,
220           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
221 }
222
223 static void
224 gst_alsasink_set_property (GObject * object, guint prop_id,
225     const GValue * value, GParamSpec * pspec)
226 {
227   GstAlsaSink *sink;
228
229   sink = GST_ALSA_SINK (object);
230
231   switch (prop_id) {
232     case PROP_DEVICE:
233       g_free (sink->device);
234       sink->device = g_value_dup_string (value);
235       /* setting NULL restores the default device */
236       if (sink->device == NULL) {
237         sink->device = g_strdup (DEFAULT_DEVICE);
238       }
239       break;
240     default:
241       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
242       break;
243   }
244 }
245
246 static void
247 gst_alsasink_get_property (GObject * object, guint prop_id,
248     GValue * value, GParamSpec * pspec)
249 {
250   GstAlsaSink *sink;
251
252   sink = GST_ALSA_SINK (object);
253
254   switch (prop_id) {
255     case PROP_DEVICE:
256       g_value_set_string (value, sink->device);
257       break;
258     case PROP_DEVICE_NAME:
259       g_value_take_string (value,
260           gst_alsa_find_device_name (GST_OBJECT_CAST (sink),
261               sink->device, sink->handle, SND_PCM_STREAM_PLAYBACK));
262       break;
263     case PROP_CARD_NAME:
264       g_value_take_string (value,
265           gst_alsa_find_card_name (GST_OBJECT_CAST (sink),
266               sink->device, SND_PCM_STREAM_PLAYBACK));
267       break;
268     default:
269       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
270       break;
271   }
272 }
273
274 static void
275 gst_alsasink_init (GstAlsaSink * alsasink, GstAlsaSinkClass * g_class)
276 {
277   GST_DEBUG_OBJECT (alsasink, "initializing alsasink");
278
279   alsasink->device = g_strdup (DEFAULT_DEVICE);
280   alsasink->handle = NULL;
281   alsasink->cached_caps = NULL;
282   alsasink->alsa_lock = g_mutex_new ();
283
284   g_static_mutex_lock (&output_mutex);
285   if (output_ref == 0) {
286     snd_output_stdio_attach (&output, stdout, 0);
287     ++output_ref;
288   }
289   g_static_mutex_unlock (&output_mutex);
290 }
291
292 #define CHECK(call, error) \
293 G_STMT_START {                  \
294 if ((err = call) < 0)           \
295   goto error;                   \
296 } G_STMT_END;
297
298 static GstCaps *
299 gst_alsasink_getcaps (GstBaseSink * bsink)
300 {
301   GstElementClass *element_class;
302   GstPadTemplate *pad_template;
303   GstAlsaSink *sink = GST_ALSA_SINK (bsink);
304   GstCaps *caps;
305
306   if (sink->handle == NULL) {
307     GST_DEBUG_OBJECT (sink, "device not open, using template caps");
308     return NULL;                /* base class will get template caps for us */
309   }
310
311   if (sink->cached_caps) {
312     GST_LOG_OBJECT (sink, "Returning cached caps");
313     return gst_caps_ref (sink->cached_caps);
314   }
315
316   element_class = GST_ELEMENT_GET_CLASS (sink);
317   pad_template = gst_element_class_get_pad_template (element_class, "sink");
318   g_return_val_if_fail (pad_template != NULL, NULL);
319
320   caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->handle,
321       gst_pad_template_get_caps (pad_template));
322
323   if (caps) {
324     sink->cached_caps = gst_caps_ref (caps);
325   }
326
327   GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
328
329   return caps;
330 }
331
332 static int
333 set_hwparams (GstAlsaSink * alsa)
334 {
335   guint rrate;
336   gint err;
337   snd_pcm_hw_params_t *params;
338   guint period_time, buffer_time;
339
340   snd_pcm_hw_params_malloc (&params);
341
342   GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
343       "SPDIF (%d)", alsa->channels, alsa->rate,
344       snd_pcm_format_name (alsa->format), alsa->iec958);
345
346   /* start with requested values, if we cannot configure alsa for those values,
347    * we set these values to -1, which will leave the default alsa values */
348   buffer_time = alsa->buffer_time;
349   period_time = alsa->period_time;
350
351 retry:
352   /* choose all parameters */
353   CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
354   /* set the interleaved read/write format */
355   CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
356       wrong_access);
357   /* set the sample format */
358   if (alsa->iec958) {
359     /* Try to use big endian first else fallback to le and swap bytes */
360     if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
361       alsa->format = SND_PCM_FORMAT_S16_LE;
362       alsa->need_swap = TRUE;
363       GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
364     } else {
365       alsa->need_swap = FALSE;
366     }
367   }
368   CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
369       no_sample_format);
370   /* set the count of channels */
371   CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
372       no_channels);
373   /* set the stream rate */
374   rrate = alsa->rate;
375   CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
376       no_rate);
377
378 #ifndef GST_DISABLE_GST_DEBUG
379   /* get and dump some limits */
380   {
381     guint min, max;
382
383     snd_pcm_hw_params_get_buffer_time_min (params, &min, NULL);
384     snd_pcm_hw_params_get_buffer_time_max (params, &max, NULL);
385
386     GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
387         alsa->buffer_time, min, max);
388
389     snd_pcm_hw_params_get_period_time_min (params, &min, NULL);
390     snd_pcm_hw_params_get_period_time_max (params, &max, NULL);
391
392     GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
393         alsa->period_time, min, max);
394
395     snd_pcm_hw_params_get_periods_min (params, &min, NULL);
396     snd_pcm_hw_params_get_periods_max (params, &max, NULL);
397
398     GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
399   }
400 #endif
401
402   /* now try to configure the buffer time and period time, if one
403    * of those fail, we fall back to the defaults and emit a warning. */
404   if (buffer_time != -1 && !alsa->iec958) {
405     /* set the buffer time */
406     if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
407                 &buffer_time, NULL)) < 0) {
408       GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
409           ("Unable to set buffer time %i for playback: %s",
410               buffer_time, snd_strerror (err)));
411       /* disable buffer_time the next round */
412       buffer_time = -1;
413       goto retry;
414     }
415     GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
416   }
417   if (period_time != -1 && !alsa->iec958) {
418     /* set the period time */
419     if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
420                 &period_time, NULL)) < 0) {
421       GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
422           ("Unable to set period time %i for playback: %s",
423               period_time, snd_strerror (err)));
424       /* disable period_time the next round */
425       period_time = -1;
426       goto retry;
427     }
428     GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
429   }
430
431   /* Set buffer size and period size manually for SPDIF */
432   if (G_UNLIKELY (alsa->iec958)) {
433     snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
434     snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;
435
436     CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
437             &buffer_size), buffer_size);
438     CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
439             &period_size, NULL), period_size);
440   }
441
442   /* write the parameters to device */
443   CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
444
445   /* now get the configured values */
446   CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
447       buffer_size);
448   CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, NULL),
449       period_size);
450
451   GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
452       alsa->period_size);
453
454   snd_pcm_hw_params_free (params);
455   return 0;
456
457   /* ERRORS */
458 no_config:
459   {
460     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
461         ("Broken configuration for playback: no configurations available: %s",
462             snd_strerror (err)));
463     snd_pcm_hw_params_free (params);
464     return err;
465   }
466 wrong_access:
467   {
468     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
469         ("Access type not available for playback: %s", snd_strerror (err)));
470     snd_pcm_hw_params_free (params);
471     return err;
472   }
473 no_sample_format:
474   {
475     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
476         ("Sample format not available for playback: %s", snd_strerror (err)));
477     snd_pcm_hw_params_free (params);
478     return err;
479   }
480 no_channels:
481   {
482     gchar *msg = NULL;
483
484     if ((alsa->channels) == 1)
485       msg = g_strdup (_("Could not open device for playback in mono mode."));
486     if ((alsa->channels) == 2)
487       msg = g_strdup (_("Could not open device for playback in stereo mode."));
488     if ((alsa->channels) > 2)
489       msg =
490           g_strdup_printf (_
491           ("Could not open device for playback in %d-channel mode."),
492           alsa->channels);
493     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, ("%s", msg),
494         ("%s", snd_strerror (err)));
495     g_free (msg);
496     snd_pcm_hw_params_free (params);
497     return err;
498   }
499 no_rate:
500   {
501     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
502         ("Rate %iHz not available for playback: %s",
503             alsa->rate, snd_strerror (err)));
504     return err;
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
776   alsa = GST_ALSA_SINK (asink);
777
778   snd_pcm_drop (alsa->handle);
779   snd_pcm_hw_free (alsa->handle);
780
781   return TRUE;
782 }
783
784 static gboolean
785 gst_alsasink_close (GstAudioSink * asink)
786 {
787   GstAlsaSink *alsa = GST_ALSA_SINK (asink);
788
789   if (alsa->handle) {
790     snd_pcm_close (alsa->handle);
791     alsa->handle = NULL;
792   }
793   gst_caps_replace (&alsa->cached_caps, NULL);
794
795   return TRUE;
796 }
797
798
799 /*
800  *   Underrun and suspend recovery
801  */
802 static gint
803 xrun_recovery (GstAlsaSink * alsa, snd_pcm_t * handle, gint err)
804 {
805   GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
806
807   if (err == -EPIPE) {          /* under-run */
808     err = snd_pcm_prepare (handle);
809     if (err < 0)
810       GST_WARNING_OBJECT (alsa,
811           "Can't recovery from underrun, prepare failed: %s",
812           snd_strerror (err));
813     return 0;
814   } else if (err == -ESTRPIPE) {
815     while ((err = snd_pcm_resume (handle)) == -EAGAIN)
816       g_usleep (100);           /* wait until the suspend flag is released */
817
818     if (err < 0) {
819       err = snd_pcm_prepare (handle);
820       if (err < 0)
821         GST_WARNING_OBJECT (alsa,
822             "Can't recovery from suspend, prepare failed: %s",
823             snd_strerror (err));
824     }
825     return 0;
826   }
827   return err;
828 }
829
830 static guint
831 gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
832 {
833   GstAlsaSink *alsa;
834   gint err;
835   gint cptr;
836   gint16 *ptr = data;
837
838   alsa = GST_ALSA_SINK (asink);
839
840   if (alsa->iec958 && alsa->need_swap) {
841     guint i;
842
843     GST_DEBUG_OBJECT (asink, "swapping bytes");
844     for (i = 0; i < length / 2; i++) {
845       ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
846     }
847   }
848
849   GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
850
851   cptr = length / alsa->bytes_per_sample;
852
853   GST_ALSA_SINK_LOCK (asink);
854   while (cptr > 0) {
855     /* start by doing a blocking wait for free space. Set the timeout
856      * to 4 times the period time */
857     err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
858     if (err < 0) {
859       GST_DEBUG_OBJECT (asink, "wait error, %d", err);
860     } else {
861       err = snd_pcm_writei (alsa->handle, ptr, cptr);
862     }
863
864     GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
865     if (err < 0) {
866       GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
867       if (err == -EAGAIN) {
868         continue;
869       } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
870         goto write_error;
871       }
872       continue;
873     }
874
875     ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
876     cptr -= err;
877   }
878   GST_ALSA_SINK_UNLOCK (asink);
879
880   return length - (cptr * alsa->bytes_per_sample);
881
882 write_error:
883   {
884     GST_ALSA_SINK_UNLOCK (asink);
885     return length;              /* skip one period */
886   }
887 }
888
889 static guint
890 gst_alsasink_delay (GstAudioSink * asink)
891 {
892   GstAlsaSink *alsa;
893   snd_pcm_sframes_t delay;
894   int res;
895
896   alsa = GST_ALSA_SINK (asink);
897
898   res = snd_pcm_delay (alsa->handle, &delay);
899   if (G_UNLIKELY (res < 0)) {
900     /* on errors, report 0 delay */
901     GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
902     delay = 0;
903   }
904   if (G_UNLIKELY (delay < 0)) {
905     /* make sure we never return a negative delay */
906     GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay");
907     delay = 0;
908   }
909
910   return delay;
911 }
912
913 static void
914 gst_alsasink_reset (GstAudioSink * asink)
915 {
916   GstAlsaSink *alsa;
917   gint err;
918
919   alsa = GST_ALSA_SINK (asink);
920
921   GST_ALSA_SINK_LOCK (asink);
922   GST_DEBUG_OBJECT (alsa, "drop");
923   CHECK (snd_pcm_drop (alsa->handle), drop_error);
924   GST_DEBUG_OBJECT (alsa, "prepare");
925   CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
926   GST_DEBUG_OBJECT (alsa, "reset done");
927   GST_ALSA_SINK_UNLOCK (asink);
928
929   return;
930
931   /* ERRORS */
932 drop_error:
933   {
934     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
935         snd_strerror (err));
936     GST_ALSA_SINK_UNLOCK (asink);
937     return;
938   }
939 prepare_error:
940   {
941     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
942         snd_strerror (err));
943     GST_ALSA_SINK_UNLOCK (asink);
944     return;
945   }
946 }