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