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., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 /**
24 * SECTION:element-alsasink
25 * @title: alsasink
26 * @see_also: alsasrc
27 *
28 * This element renders audio samples using the ALSA audio API.
29 *
30 * ## Example pipelines
31 * |[
32 * gst-launch-1.0 -v uridecodebin uri=file:///path/to/audio.ogg ! audioconvert ! audioresample ! autoaudiosink
33 * ]|
34 *
35 * Play an Ogg/Vorbis file and output audio via ALSA.
36 *
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/audio/gstaudioiec61937.h>
55 #include <gst/gst-i18n-plugin.h>
56
57 #ifndef ESTRPIPE
58 #define ESTRPIPE EPIPE
59 #endif
60
61 #define DEFAULT_DEVICE "default"
62 #define DEFAULT_DEVICE_NAME ""
63 #define DEFAULT_CARD_NAME ""
64 #define SPDIF_PERIOD_SIZE 1536
65 #define SPDIF_BUFFER_SIZE 15360
66
67 enum
68 {
69 PROP_0,
70 PROP_DEVICE,
71 PROP_DEVICE_NAME,
72 PROP_CARD_NAME,
73 PROP_LAST
74 };
75
76 static void gst_alsasink_init_interfaces (GType type);
77 #define gst_alsasink_parent_class parent_class
78 G_DEFINE_TYPE_WITH_CODE (GstAlsaSink, gst_alsasink,
79 GST_TYPE_AUDIO_SINK, gst_alsasink_init_interfaces (g_define_type_id));
80
81 static void gst_alsasink_finalise (GObject * object);
82 static void gst_alsasink_set_property (GObject * object,
83 guint prop_id, const GValue * value, GParamSpec * pspec);
84 static void gst_alsasink_get_property (GObject * object,
85 guint prop_id, GValue * value, GParamSpec * pspec);
86
87 static GstCaps *gst_alsasink_getcaps (GstBaseSink * bsink, GstCaps * filter);
88 static gboolean gst_alsasink_query (GstBaseSink * bsink, GstQuery * query);
89
90 static gboolean gst_alsasink_open (GstAudioSink * asink);
91 static gboolean gst_alsasink_prepare (GstAudioSink * asink,
92 GstAudioRingBufferSpec * spec);
93 static gboolean gst_alsasink_unprepare (GstAudioSink * asink);
94 static gboolean gst_alsasink_close (GstAudioSink * asink);
95 static gint gst_alsasink_write (GstAudioSink * asink, gpointer data,
96 guint length);
97 static guint gst_alsasink_delay (GstAudioSink * asink);
98 static void gst_alsasink_reset (GstAudioSink * asink);
99 static gboolean gst_alsasink_acceptcaps (GstAlsaSink * alsa, GstCaps * caps);
100 static GstBuffer *gst_alsasink_payload (GstAudioBaseSink * sink,
101 GstBuffer * buf);
102
103 static gint output_ref; /* 0 */
104 static snd_output_t *output; /* NULL */
105 static GMutex output_mutex;
106
107 static GstStaticPadTemplate alsasink_sink_factory =
108 GST_STATIC_PAD_TEMPLATE ("sink",
109 GST_PAD_SINK,
110 GST_PAD_ALWAYS,
111 GST_STATIC_CAPS ("audio/x-raw, "
112 "format = (string) " GST_AUDIO_FORMATS_ALL ", "
113 "layout = (string) interleaved, "
114 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
115 PASSTHROUGH_CAPS)
116 );
117
118 static void
gst_alsasink_finalise(GObject * object)119 gst_alsasink_finalise (GObject * object)
120 {
121 GstAlsaSink *sink = GST_ALSA_SINK (object);
122
123 g_free (sink->device);
124 g_mutex_clear (&sink->alsa_lock);
125 g_mutex_clear (&sink->delay_lock);
126
127 g_mutex_lock (&output_mutex);
128 --output_ref;
129 if (output_ref == 0) {
130 snd_output_close (output);
131 output = NULL;
132 }
133 g_mutex_unlock (&output_mutex);
134
135 G_OBJECT_CLASS (parent_class)->finalize (object);
136 }
137
138 static void
gst_alsasink_init_interfaces(GType type)139 gst_alsasink_init_interfaces (GType type)
140 {
141 #if 0
142 gst_alsa_type_add_device_property_probe_interface (type);
143 #endif
144 }
145
146 static void
gst_alsasink_class_init(GstAlsaSinkClass * klass)147 gst_alsasink_class_init (GstAlsaSinkClass * klass)
148 {
149 GObjectClass *gobject_class;
150 GstElementClass *gstelement_class;
151 GstBaseSinkClass *gstbasesink_class;
152 GstAudioBaseSinkClass *gstbaseaudiosink_class;
153 GstAudioSinkClass *gstaudiosink_class;
154
155 gobject_class = (GObjectClass *) klass;
156 gstelement_class = (GstElementClass *) klass;
157 gstbasesink_class = (GstBaseSinkClass *) klass;
158 gstbaseaudiosink_class = (GstAudioBaseSinkClass *) klass;
159 gstaudiosink_class = (GstAudioSinkClass *) klass;
160
161 parent_class = g_type_class_peek_parent (klass);
162
163 gobject_class->finalize = gst_alsasink_finalise;
164 gobject_class->get_property = gst_alsasink_get_property;
165 gobject_class->set_property = gst_alsasink_set_property;
166
167 gst_element_class_set_static_metadata (gstelement_class,
168 "Audio sink (ALSA)", "Sink/Audio",
169 "Output to a sound card via ALSA", "Wim Taymans <wim@fluendo.com>");
170
171 gst_element_class_add_static_pad_template (gstelement_class,
172 &alsasink_sink_factory);
173
174 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink_getcaps);
175 gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_alsasink_query);
176
177 gstbaseaudiosink_class->payload = GST_DEBUG_FUNCPTR (gst_alsasink_payload);
178
179 gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink_open);
180 gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasink_prepare);
181 gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasink_unprepare);
182 gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_alsasink_close);
183 gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_alsasink_write);
184 gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_alsasink_delay);
185 gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_alsasink_reset);
186
187 g_object_class_install_property (gobject_class, PROP_DEVICE,
188 g_param_spec_string ("device", "Device",
189 "ALSA device, as defined in an asound configuration file",
190 DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
191
192 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
193 g_param_spec_string ("device-name", "Device name",
194 "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
195 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
196
197 g_object_class_install_property (gobject_class, PROP_CARD_NAME,
198 g_param_spec_string ("card-name", "Card name",
199 "Human-readable name of the sound card", DEFAULT_CARD_NAME,
200 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
201 }
202
203 static void
gst_alsasink_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)204 gst_alsasink_set_property (GObject * object, guint prop_id,
205 const GValue * value, GParamSpec * pspec)
206 {
207 GstAlsaSink *sink;
208
209 sink = GST_ALSA_SINK (object);
210
211 switch (prop_id) {
212 case PROP_DEVICE:
213 g_free (sink->device);
214 sink->device = g_value_dup_string (value);
215 /* setting NULL restores the default device */
216 if (sink->device == NULL) {
217 sink->device = g_strdup (DEFAULT_DEVICE);
218 }
219 break;
220 default:
221 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
222 break;
223 }
224 }
225
226 static void
gst_alsasink_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)227 gst_alsasink_get_property (GObject * object, guint prop_id,
228 GValue * value, GParamSpec * pspec)
229 {
230 GstAlsaSink *sink;
231
232 sink = GST_ALSA_SINK (object);
233
234 switch (prop_id) {
235 case PROP_DEVICE:
236 g_value_set_string (value, sink->device);
237 break;
238 case PROP_DEVICE_NAME:
239 g_value_take_string (value,
240 gst_alsa_find_device_name (GST_OBJECT_CAST (sink),
241 sink->device, sink->handle, SND_PCM_STREAM_PLAYBACK));
242 break;
243 case PROP_CARD_NAME:
244 g_value_take_string (value,
245 gst_alsa_find_card_name (GST_OBJECT_CAST (sink),
246 sink->device, SND_PCM_STREAM_PLAYBACK));
247 break;
248 default:
249 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
250 break;
251 }
252 }
253
254 static void
gst_alsasink_init(GstAlsaSink * alsasink)255 gst_alsasink_init (GstAlsaSink * alsasink)
256 {
257 GST_DEBUG_OBJECT (alsasink, "initializing alsasink");
258
259 alsasink->device = g_strdup (DEFAULT_DEVICE);
260 alsasink->handle = NULL;
261 alsasink->cached_caps = NULL;
262 g_mutex_init (&alsasink->alsa_lock);
263 g_mutex_init (&alsasink->delay_lock);
264
265 g_mutex_lock (&output_mutex);
266 if (output_ref == 0) {
267 snd_output_stdio_attach (&output, stdout, 0);
268 ++output_ref;
269 }
270 g_mutex_unlock (&output_mutex);
271 }
272
273 #define CHECK(call, error) \
274 G_STMT_START { \
275 if ((err = call) < 0) { \
276 GST_WARNING_OBJECT (alsa, "Error %d (%s) calling " #call, err, snd_strerror (err)); \
277 goto error; \
278 } \
279 } G_STMT_END;
280
281 static GstCaps *
gst_alsasink_getcaps(GstBaseSink * bsink,GstCaps * filter)282 gst_alsasink_getcaps (GstBaseSink * bsink, GstCaps * filter)
283 {
284 GstElementClass *element_class;
285 GstPadTemplate *pad_template;
286 GstAlsaSink *sink = GST_ALSA_SINK (bsink);
287 GstCaps *caps, *templ_caps;
288
289 GST_OBJECT_LOCK (sink);
290 if (sink->handle == NULL) {
291 GST_OBJECT_UNLOCK (sink);
292 GST_DEBUG_OBJECT (sink, "device not open, using template caps");
293 return NULL; /* base class will get template caps for us */
294 }
295
296 if (sink->cached_caps) {
297 if (filter) {
298 caps = gst_caps_intersect_full (filter, sink->cached_caps,
299 GST_CAPS_INTERSECT_FIRST);
300 GST_OBJECT_UNLOCK (sink);
301 GST_LOG_OBJECT (sink, "Returning cached caps %" GST_PTR_FORMAT " with "
302 "filter %" GST_PTR_FORMAT " applied: %" GST_PTR_FORMAT,
303 sink->cached_caps, filter, caps);
304 return caps;
305 } else {
306 caps = gst_caps_ref (sink->cached_caps);
307 GST_OBJECT_UNLOCK (sink);
308 GST_LOG_OBJECT (sink, "Returning cached caps %" GST_PTR_FORMAT, caps);
309 return caps;
310 }
311 }
312
313 element_class = GST_ELEMENT_GET_CLASS (sink);
314 pad_template = gst_element_class_get_pad_template (element_class, "sink");
315 if (pad_template == NULL) {
316 GST_OBJECT_UNLOCK (sink);
317 g_assert_not_reached ();
318 return NULL;
319 }
320
321 templ_caps = gst_pad_template_get_caps (pad_template);
322 caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->device,
323 sink->handle, templ_caps);
324 gst_caps_unref (templ_caps);
325
326 if (caps) {
327 sink->cached_caps = gst_caps_ref (caps);
328 }
329
330 GST_OBJECT_UNLOCK (sink);
331
332 GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
333
334 if (filter) {
335 GstCaps *intersection;
336
337 intersection =
338 gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
339 gst_caps_unref (caps);
340 return intersection;
341 } else {
342 return caps;
343 }
344 }
345
346 static gboolean
gst_alsasink_acceptcaps(GstAlsaSink * alsa,GstCaps * caps)347 gst_alsasink_acceptcaps (GstAlsaSink * alsa, GstCaps * caps)
348 {
349 GstPad *pad = GST_BASE_SINK (alsa)->sinkpad;
350 GstCaps *pad_caps;
351 GstStructure *st;
352 gboolean ret = FALSE;
353 GstAudioRingBufferSpec spec = { 0 };
354
355 pad_caps = gst_pad_query_caps (pad, caps);
356 if (!pad_caps || gst_caps_is_empty (pad_caps)) {
357 if (pad_caps)
358 gst_caps_unref (pad_caps);
359 ret = FALSE;
360 goto done;
361 }
362 gst_caps_unref (pad_caps);
363
364 /* If we've not got fixed caps, creating a stream might fail, so let's just
365 * return from here with default acceptcaps behaviour */
366 if (!gst_caps_is_fixed (caps))
367 goto done;
368
369 /* parse helper expects this set, so avoid nasty warning
370 * will be set properly later on anyway */
371 spec.latency_time = GST_SECOND;
372 if (!gst_audio_ring_buffer_parse_caps (&spec, caps))
373 goto done;
374
375 /* Make sure input is framed (one frame per buffer) and can be payloaded */
376 switch (spec.type) {
377 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3:
378 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3:
379 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS:
380 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG:
381 {
382 gboolean framed = FALSE, parsed = FALSE;
383 st = gst_caps_get_structure (caps, 0);
384
385 gst_structure_get_boolean (st, "framed", &framed);
386 gst_structure_get_boolean (st, "parsed", &parsed);
387 if ((!framed && !parsed) || gst_audio_iec61937_frame_size (&spec) <= 0)
388 goto done;
389 }
390 default:{
391 }
392 }
393 ret = TRUE;
394
395 done:
396 gst_caps_replace (&spec.caps, NULL);
397 return ret;
398 }
399
400 static gboolean
gst_alsasink_query(GstBaseSink * sink,GstQuery * query)401 gst_alsasink_query (GstBaseSink * sink, GstQuery * query)
402 {
403 GstAlsaSink *alsa = GST_ALSA_SINK (sink);
404 gboolean ret;
405
406 switch (GST_QUERY_TYPE (query)) {
407 case GST_QUERY_ACCEPT_CAPS:
408 {
409 GstCaps *caps;
410
411 gst_query_parse_accept_caps (query, &caps);
412 ret = gst_alsasink_acceptcaps (alsa, caps);
413 gst_query_set_accept_caps_result (query, ret);
414 ret = TRUE;
415 break;
416 }
417 default:
418 ret = GST_BASE_SINK_CLASS (parent_class)->query (sink, query);
419 break;
420 }
421 return ret;
422 }
423
424 static int
set_hwparams(GstAlsaSink * alsa)425 set_hwparams (GstAlsaSink * alsa)
426 {
427 guint rrate;
428 gint err;
429 snd_pcm_hw_params_t *params;
430 guint period_time, buffer_time;
431
432 snd_pcm_hw_params_malloc (¶ms);
433
434 GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
435 "SPDIF (%d)", alsa->channels, alsa->rate,
436 snd_pcm_format_name (alsa->format), alsa->iec958);
437
438 /* start with requested values, if we cannot configure alsa for those values,
439 * we set these values to -1, which will leave the default alsa values */
440 buffer_time = alsa->buffer_time;
441 period_time = alsa->period_time;
442
443 retry:
444 /* choose all parameters */
445 CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
446 /* set the interleaved read/write format */
447 CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
448 wrong_access);
449 /* set the sample format */
450 if (alsa->iec958) {
451 /* Try to use big endian first else fallback to le and swap bytes */
452 if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
453 alsa->format = SND_PCM_FORMAT_S16_LE;
454 alsa->need_swap = TRUE;
455 GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
456 } else {
457 alsa->need_swap = FALSE;
458 }
459 }
460 CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
461 no_sample_format);
462 /* set the count of channels */
463 CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
464 no_channels);
465 /* set the stream rate */
466 rrate = alsa->rate;
467 CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
468 no_rate);
469
470 #ifndef GST_DISABLE_GST_DEBUG
471 /* get and dump some limits */
472 {
473 guint min, max;
474
475 snd_pcm_hw_params_get_buffer_time_min (params, &min, NULL);
476 snd_pcm_hw_params_get_buffer_time_max (params, &max, NULL);
477
478 GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
479 alsa->buffer_time, min, max);
480
481 snd_pcm_hw_params_get_period_time_min (params, &min, NULL);
482 snd_pcm_hw_params_get_period_time_max (params, &max, NULL);
483
484 GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
485 alsa->period_time, min, max);
486
487 snd_pcm_hw_params_get_periods_min (params, &min, NULL);
488 snd_pcm_hw_params_get_periods_max (params, &max, NULL);
489
490 GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
491 }
492 #endif
493
494 /* now try to configure the buffer time and period time, if one
495 * of those fail, we fall back to the defaults and emit a warning. */
496 if (buffer_time != -1 && !alsa->iec958) {
497 /* set the buffer time */
498 if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
499 &buffer_time, NULL)) < 0) {
500 GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
501 ("Unable to set buffer time %i for playback: %s",
502 buffer_time, snd_strerror (err)));
503 /* disable buffer_time the next round */
504 buffer_time = -1;
505 goto retry;
506 }
507 GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
508 alsa->buffer_time = buffer_time;
509 }
510 if (period_time != -1 && !alsa->iec958) {
511 /* set the period time */
512 if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
513 &period_time, NULL)) < 0) {
514 GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
515 ("Unable to set period time %i for playback: %s",
516 period_time, snd_strerror (err)));
517 /* disable period_time the next round */
518 period_time = -1;
519 goto retry;
520 }
521 GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
522 alsa->period_time = period_time;
523 }
524
525 /* Set buffer size and period size manually for SPDIF */
526 if (G_UNLIKELY (alsa->iec958)) {
527 snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
528 snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;
529
530 CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
531 &buffer_size), buffer_size);
532 CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
533 &period_size, NULL), period_size);
534 }
535
536 /* write the parameters to device */
537 CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
538
539 /* now get the configured values */
540 CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
541 buffer_size);
542 CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, NULL),
543 period_size);
544
545 GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
546 alsa->period_size);
547
548 snd_pcm_hw_params_free (params);
549 return 0;
550
551 /* ERRORS */
552 no_config:
553 {
554 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
555 ("Broken configuration for playback: no configurations available: %s",
556 snd_strerror (err)));
557 snd_pcm_hw_params_free (params);
558 return err;
559 }
560 wrong_access:
561 {
562 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
563 ("Access type not available for playback: %s", snd_strerror (err)));
564 snd_pcm_hw_params_free (params);
565 return err;
566 }
567 no_sample_format:
568 {
569 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
570 ("Sample format not available for playback: %s", snd_strerror (err)));
571 snd_pcm_hw_params_free (params);
572 return err;
573 }
574 no_channels:
575 {
576 gchar *msg = NULL;
577
578 if ((alsa->channels) == 1)
579 msg = g_strdup (_("Could not open device for playback in mono mode."));
580 if ((alsa->channels) == 2)
581 msg = g_strdup (_("Could not open device for playback in stereo mode."));
582 if ((alsa->channels) > 2)
583 msg =
584 g_strdup_printf (_
585 ("Could not open device for playback in %d-channel mode."),
586 alsa->channels);
587 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, ("%s", msg),
588 ("%s", snd_strerror (err)));
589 g_free (msg);
590 snd_pcm_hw_params_free (params);
591 return err;
592 }
593 no_rate:
594 {
595 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
596 ("Rate %iHz not available for playback: %s",
597 alsa->rate, snd_strerror (err)));
598 return err;
599 }
600 buffer_size:
601 {
602 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
603 ("Unable to get buffer size for playback: %s", snd_strerror (err)));
604 snd_pcm_hw_params_free (params);
605 return err;
606 }
607 period_size:
608 {
609 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
610 ("Unable to get period size for playback: %s", snd_strerror (err)));
611 snd_pcm_hw_params_free (params);
612 return err;
613 }
614 set_hw_params:
615 {
616 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
617 ("Unable to set hw params for playback: %s", snd_strerror (err)));
618 snd_pcm_hw_params_free (params);
619 return err;
620 }
621 }
622
623 static int
set_swparams(GstAlsaSink * alsa)624 set_swparams (GstAlsaSink * alsa)
625 {
626 int err;
627 snd_pcm_sw_params_t *params;
628
629 snd_pcm_sw_params_malloc (¶ms);
630
631 /* get the current swparams */
632 CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
633 /* start the transfer when the buffer is almost full: */
634 /* (buffer_size / avail_min) * avail_min */
635 CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
636 (alsa->buffer_size / alsa->period_size) * alsa->period_size),
637 start_threshold);
638
639 /* allow the transfer when at least period_size samples can be processed */
640 CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
641 alsa->period_size), set_avail);
642
643 #if GST_CHECK_ALSA_VERSION(1,0,16)
644 /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
645 #else
646 /* align all transfers to 1 sample */
647 CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
648 #endif
649
650 /* write the parameters to the playback device */
651 CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
652
653 snd_pcm_sw_params_free (params);
654 return 0;
655
656 /* ERRORS */
657 no_config:
658 {
659 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
660 ("Unable to determine current swparams for playback: %s",
661 snd_strerror (err)));
662 snd_pcm_sw_params_free (params);
663 return err;
664 }
665 start_threshold:
666 {
667 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
668 ("Unable to set start threshold mode for playback: %s",
669 snd_strerror (err)));
670 snd_pcm_sw_params_free (params);
671 return err;
672 }
673 set_avail:
674 {
675 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
676 ("Unable to set avail min for playback: %s", snd_strerror (err)));
677 snd_pcm_sw_params_free (params);
678 return err;
679 }
680 #if !GST_CHECK_ALSA_VERSION(1,0,16)
681 set_align:
682 {
683 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
684 ("Unable to set transfer align for playback: %s", snd_strerror (err)));
685 snd_pcm_sw_params_free (params);
686 return err;
687 }
688 #endif
689 set_sw_params:
690 {
691 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
692 ("Unable to set sw params for playback: %s", snd_strerror (err)));
693 snd_pcm_sw_params_free (params);
694 return err;
695 }
696 }
697
698 static gboolean
alsasink_parse_spec(GstAlsaSink * alsa,GstAudioRingBufferSpec * spec)699 alsasink_parse_spec (GstAlsaSink * alsa, GstAudioRingBufferSpec * spec)
700 {
701 /* Initialize our boolean */
702 alsa->iec958 = FALSE;
703
704 switch (spec->type) {
705 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW:
706 switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
707 case GST_AUDIO_FORMAT_U8:
708 alsa->format = SND_PCM_FORMAT_U8;
709 break;
710 case GST_AUDIO_FORMAT_S8:
711 alsa->format = SND_PCM_FORMAT_S8;
712 break;
713 case GST_AUDIO_FORMAT_S16LE:
714 alsa->format = SND_PCM_FORMAT_S16_LE;
715 break;
716 case GST_AUDIO_FORMAT_S16BE:
717 alsa->format = SND_PCM_FORMAT_S16_BE;
718 break;
719 case GST_AUDIO_FORMAT_U16LE:
720 alsa->format = SND_PCM_FORMAT_U16_LE;
721 break;
722 case GST_AUDIO_FORMAT_U16BE:
723 alsa->format = SND_PCM_FORMAT_U16_BE;
724 break;
725 case GST_AUDIO_FORMAT_S24_32LE:
726 alsa->format = SND_PCM_FORMAT_S24_LE;
727 break;
728 case GST_AUDIO_FORMAT_S24_32BE:
729 alsa->format = SND_PCM_FORMAT_S24_BE;
730 break;
731 case GST_AUDIO_FORMAT_U24_32LE:
732 alsa->format = SND_PCM_FORMAT_U24_LE;
733 break;
734 case GST_AUDIO_FORMAT_U24_32BE:
735 alsa->format = SND_PCM_FORMAT_U24_BE;
736 break;
737 case GST_AUDIO_FORMAT_S32LE:
738 alsa->format = SND_PCM_FORMAT_S32_LE;
739 break;
740 case GST_AUDIO_FORMAT_S32BE:
741 alsa->format = SND_PCM_FORMAT_S32_BE;
742 break;
743 case GST_AUDIO_FORMAT_U32LE:
744 alsa->format = SND_PCM_FORMAT_U32_LE;
745 break;
746 case GST_AUDIO_FORMAT_U32BE:
747 alsa->format = SND_PCM_FORMAT_U32_BE;
748 break;
749 case GST_AUDIO_FORMAT_S24LE:
750 alsa->format = SND_PCM_FORMAT_S24_3LE;
751 break;
752 case GST_AUDIO_FORMAT_S24BE:
753 alsa->format = SND_PCM_FORMAT_S24_3BE;
754 break;
755 case GST_AUDIO_FORMAT_U24LE:
756 alsa->format = SND_PCM_FORMAT_U24_3LE;
757 break;
758 case GST_AUDIO_FORMAT_U24BE:
759 alsa->format = SND_PCM_FORMAT_U24_3BE;
760 break;
761 case GST_AUDIO_FORMAT_S20LE:
762 alsa->format = SND_PCM_FORMAT_S20_3LE;
763 break;
764 case GST_AUDIO_FORMAT_S20BE:
765 alsa->format = SND_PCM_FORMAT_S20_3BE;
766 break;
767 case GST_AUDIO_FORMAT_U20LE:
768 alsa->format = SND_PCM_FORMAT_U20_3LE;
769 break;
770 case GST_AUDIO_FORMAT_U20BE:
771 alsa->format = SND_PCM_FORMAT_U20_3BE;
772 break;
773 case GST_AUDIO_FORMAT_S18LE:
774 alsa->format = SND_PCM_FORMAT_S18_3LE;
775 break;
776 case GST_AUDIO_FORMAT_S18BE:
777 alsa->format = SND_PCM_FORMAT_S18_3BE;
778 break;
779 case GST_AUDIO_FORMAT_U18LE:
780 alsa->format = SND_PCM_FORMAT_U18_3LE;
781 break;
782 case GST_AUDIO_FORMAT_U18BE:
783 alsa->format = SND_PCM_FORMAT_U18_3BE;
784 break;
785 case GST_AUDIO_FORMAT_F32LE:
786 alsa->format = SND_PCM_FORMAT_FLOAT_LE;
787 break;
788 case GST_AUDIO_FORMAT_F32BE:
789 alsa->format = SND_PCM_FORMAT_FLOAT_BE;
790 break;
791 case GST_AUDIO_FORMAT_F64LE:
792 alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
793 break;
794 case GST_AUDIO_FORMAT_F64BE:
795 alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
796 break;
797 default:
798 goto error;
799 }
800 break;
801 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW:
802 alsa->format = SND_PCM_FORMAT_A_LAW;
803 break;
804 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW:
805 alsa->format = SND_PCM_FORMAT_MU_LAW;
806 break;
807 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3:
808 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3:
809 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS:
810 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG:
811 alsa->format = SND_PCM_FORMAT_S16_BE;
812 alsa->iec958 = TRUE;
813 break;
814 default:
815 goto error;
816
817 }
818 alsa->rate = GST_AUDIO_INFO_RATE (&spec->info);
819 alsa->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
820 alsa->buffer_time = spec->buffer_time;
821 alsa->period_time = spec->latency_time;
822 alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
823
824 if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9)
825 gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SINK
826 (alsa)->ringbuffer, alsa_position[alsa->channels - 1]);
827
828 return TRUE;
829
830 /* ERRORS */
831 error:
832 {
833 return FALSE;
834 }
835 }
836
837 static gboolean
gst_alsasink_open(GstAudioSink * asink)838 gst_alsasink_open (GstAudioSink * asink)
839 {
840 GstAlsaSink *alsa;
841 gint err;
842
843 alsa = GST_ALSA_SINK (asink);
844
845 /* open in non-blocking mode, we'll use snd_pcm_wait() for space to become
846 * available. */
847 CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_PLAYBACK,
848 SND_PCM_NONBLOCK), open_error);
849 GST_LOG_OBJECT (alsa, "Opened device %s", alsa->device);
850
851 return TRUE;
852
853 /* ERRORS */
854 open_error:
855 {
856 if (err == -EBUSY) {
857 GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
858 (_("Could not open audio device for playback. "
859 "Device is being used by another application.")),
860 ("Device '%s' is busy", alsa->device));
861 } else {
862 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE,
863 (_("Could not open audio device for playback.")),
864 ("Playback open error on device '%s': %s", alsa->device,
865 snd_strerror (err)));
866 }
867 return FALSE;
868 }
869 }
870
871 static gboolean
gst_alsasink_prepare(GstAudioSink * asink,GstAudioRingBufferSpec * spec)872 gst_alsasink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec)
873 {
874 GstAlsaSink *alsa;
875 gint err;
876
877 alsa = GST_ALSA_SINK (asink);
878
879 if (alsa->iec958) {
880 snd_pcm_close (alsa->handle);
881 alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa), alsa->device);
882 if (G_UNLIKELY (!alsa->handle)) {
883 goto no_iec958;
884 }
885 }
886
887 if (!alsasink_parse_spec (alsa, spec))
888 goto spec_parse;
889
890 CHECK (set_hwparams (alsa), hw_params_failed);
891 CHECK (set_swparams (alsa), sw_params_failed);
892
893 alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info);
894 spec->segsize = alsa->period_size * alsa->bpf;
895 spec->segtotal = alsa->buffer_size / alsa->period_size;
896
897 {
898 snd_output_t *out_buf = NULL;
899 char *msg = NULL;
900
901 snd_output_buffer_open (&out_buf);
902 snd_pcm_dump_hw_setup (alsa->handle, out_buf);
903 snd_output_buffer_string (out_buf, &msg);
904 GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
905 snd_output_close (out_buf);
906 snd_output_buffer_open (&out_buf);
907 snd_pcm_dump_sw_setup (alsa->handle, out_buf);
908 snd_output_buffer_string (out_buf, &msg);
909 GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
910 snd_output_close (out_buf);
911 }
912
913 #ifdef SND_CHMAP_API_VERSION
914 alsa_detect_channels_mapping (GST_OBJECT (alsa), alsa->handle, spec,
915 alsa->channels, GST_AUDIO_BASE_SINK (alsa)->ringbuffer);
916 #endif /* SND_CHMAP_API_VERSION */
917
918 return TRUE;
919
920 /* ERRORS */
921 no_iec958:
922 {
923 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL),
924 ("Could not open IEC958 (SPDIF) device for playback"));
925 return FALSE;
926 }
927 spec_parse:
928 {
929 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
930 ("Error parsing spec"));
931 return FALSE;
932 }
933 hw_params_failed:
934 {
935 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
936 ("Setting of hwparams failed: %s", snd_strerror (err)));
937 return FALSE;
938 }
939 sw_params_failed:
940 {
941 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
942 ("Setting of swparams failed: %s", snd_strerror (err)));
943 return FALSE;
944 }
945 }
946
947 static gboolean
gst_alsasink_unprepare(GstAudioSink * asink)948 gst_alsasink_unprepare (GstAudioSink * asink)
949 {
950 GstAlsaSink *alsa;
951
952 alsa = GST_ALSA_SINK (asink);
953
954 snd_pcm_drop (alsa->handle);
955 snd_pcm_hw_free (alsa->handle);
956
957 return TRUE;
958 }
959
960 static gboolean
gst_alsasink_close(GstAudioSink * asink)961 gst_alsasink_close (GstAudioSink * asink)
962 {
963 GstAlsaSink *alsa = GST_ALSA_SINK (asink);
964
965 GST_OBJECT_LOCK (asink);
966 if (alsa->handle) {
967 snd_pcm_close (alsa->handle);
968 alsa->handle = NULL;
969 }
970 gst_caps_replace (&alsa->cached_caps, NULL);
971 GST_OBJECT_UNLOCK (asink);
972
973 return TRUE;
974 }
975
976
977 /*
978 * Underrun and suspend recovery
979 */
980 static gint
xrun_recovery(GstAlsaSink * alsa,snd_pcm_t * handle,gint err)981 xrun_recovery (GstAlsaSink * alsa, snd_pcm_t * handle, gint err)
982 {
983 GST_WARNING_OBJECT (alsa, "xrun recovery %d: %s", err, g_strerror (-err));
984
985 if (err == -EPIPE) { /* under-run */
986 err = snd_pcm_prepare (handle);
987 if (err < 0)
988 GST_WARNING_OBJECT (alsa,
989 "Can't recover from underrun, prepare failed: %s",
990 snd_strerror (err));
991 gst_audio_base_sink_report_device_failure (GST_AUDIO_BASE_SINK (alsa));
992 return 0;
993 } else if (err == -ESTRPIPE) {
994 while ((err = snd_pcm_resume (handle)) == -EAGAIN)
995 g_usleep (100); /* wait until the suspend flag is released */
996
997 if (err < 0) {
998 err = snd_pcm_prepare (handle);
999 if (err < 0)
1000 GST_WARNING_OBJECT (alsa,
1001 "Can't recover from suspend, prepare failed: %s",
1002 snd_strerror (err));
1003 }
1004 if (err == 0)
1005 gst_audio_base_sink_report_device_failure (GST_AUDIO_BASE_SINK (alsa));
1006 return 0;
1007 }
1008 return err;
1009 }
1010
1011 static gint
gst_alsasink_write(GstAudioSink * asink,gpointer data,guint length)1012 gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
1013 {
1014 GstAlsaSink *alsa;
1015 gint err;
1016 gint cptr;
1017 guint8 *ptr = data;
1018
1019 alsa = GST_ALSA_SINK (asink);
1020
1021 if (alsa->iec958 && alsa->need_swap) {
1022 guint i;
1023 guint16 *ptr_tmp = (guint16 *) ptr;
1024
1025 GST_DEBUG_OBJECT (asink, "swapping bytes");
1026 for (i = 0; i < length / 2; i++) {
1027 ptr_tmp[i] = GUINT16_SWAP_LE_BE (ptr_tmp[i]);
1028 }
1029 }
1030
1031 GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
1032
1033 cptr = length / alsa->bpf;
1034
1035 GST_ALSA_SINK_LOCK (asink);
1036 while (cptr > 0) {
1037 /* start by doing a blocking wait for free space. Set the timeout
1038 * to 4 times the period time */
1039 err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
1040 if (err < 0) {
1041 GST_DEBUG_OBJECT (asink, "wait error, %d", err);
1042 } else {
1043 GST_DELAY_SINK_LOCK (asink);
1044 err = snd_pcm_writei (alsa->handle, ptr, cptr);
1045 GST_DELAY_SINK_UNLOCK (asink);
1046 }
1047
1048 GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
1049 if (err < 0) {
1050 GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
1051 if (err == -EAGAIN) {
1052 continue;
1053 } else if (err == -ENODEV) {
1054 goto device_disappeared;
1055 } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
1056 goto write_error;
1057 }
1058 continue;
1059 }
1060
1061 ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
1062 cptr -= err;
1063 }
1064 GST_ALSA_SINK_UNLOCK (asink);
1065
1066 return length - (cptr * alsa->bpf);
1067
1068 write_error:
1069 {
1070 GST_ALSA_SINK_UNLOCK (asink);
1071 return length; /* skip one period */
1072 }
1073 device_disappeared:
1074 {
1075 GST_ELEMENT_ERROR (asink, RESOURCE, WRITE,
1076 (_("Error outputting to audio device. "
1077 "The device has been disconnected.")), (NULL));
1078 goto write_error;
1079 }
1080 }
1081
1082 static guint
gst_alsasink_delay(GstAudioSink * asink)1083 gst_alsasink_delay (GstAudioSink * asink)
1084 {
1085 GstAlsaSink *alsa;
1086 snd_pcm_sframes_t delay;
1087 int res;
1088
1089 alsa = GST_ALSA_SINK (asink);
1090
1091 GST_DELAY_SINK_LOCK (asink);
1092 res = snd_pcm_delay (alsa->handle, &delay);
1093 GST_DELAY_SINK_UNLOCK (asink);
1094 if (G_UNLIKELY (res < 0)) {
1095 /* on errors, report 0 delay */
1096 GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
1097 delay = 0;
1098 }
1099 if (G_UNLIKELY (delay < 0)) {
1100 /* make sure we never return a negative delay */
1101 GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay");
1102 delay = 0;
1103 }
1104
1105 return delay;
1106 }
1107
1108 static void
gst_alsasink_reset(GstAudioSink * asink)1109 gst_alsasink_reset (GstAudioSink * asink)
1110 {
1111 GstAlsaSink *alsa;
1112 gint err;
1113
1114 alsa = GST_ALSA_SINK (asink);
1115
1116 GST_ALSA_SINK_LOCK (asink);
1117 GST_DEBUG_OBJECT (alsa, "drop");
1118 CHECK (snd_pcm_drop (alsa->handle), drop_error);
1119 GST_DEBUG_OBJECT (alsa, "prepare");
1120 CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
1121 GST_DEBUG_OBJECT (alsa, "reset done");
1122 GST_ALSA_SINK_UNLOCK (asink);
1123
1124 return;
1125
1126 /* ERRORS */
1127 drop_error:
1128 {
1129 GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
1130 snd_strerror (err));
1131 GST_ALSA_SINK_UNLOCK (asink);
1132 return;
1133 }
1134 prepare_error:
1135 {
1136 GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
1137 snd_strerror (err));
1138 GST_ALSA_SINK_UNLOCK (asink);
1139 return;
1140 }
1141 }
1142
1143 static GstBuffer *
gst_alsasink_payload(GstAudioBaseSink * sink,GstBuffer * buf)1144 gst_alsasink_payload (GstAudioBaseSink * sink, GstBuffer * buf)
1145 {
1146 GstAlsaSink *alsa;
1147
1148 alsa = GST_ALSA_SINK (sink);
1149
1150 if (alsa->iec958) {
1151 GstBuffer *out;
1152 gint framesize;
1153 GstMapInfo iinfo, oinfo;
1154
1155 framesize = gst_audio_iec61937_frame_size (&sink->ringbuffer->spec);
1156 if (framesize <= 0)
1157 return NULL;
1158
1159 out = gst_buffer_new_and_alloc (framesize);
1160
1161 gst_buffer_map (buf, &iinfo, GST_MAP_READ);
1162 gst_buffer_map (out, &oinfo, GST_MAP_WRITE);
1163
1164 if (!gst_audio_iec61937_payload (iinfo.data, iinfo.size,
1165 oinfo.data, oinfo.size, &sink->ringbuffer->spec, G_BIG_ENDIAN)) {
1166 gst_buffer_unmap (buf, &iinfo);
1167 gst_buffer_unmap (out, &oinfo);
1168 gst_buffer_unref (out);
1169 return NULL;
1170 }
1171
1172 gst_buffer_unmap (buf, &iinfo);
1173 gst_buffer_unmap (out, &oinfo);
1174
1175 gst_buffer_copy_into (out, buf, GST_BUFFER_COPY_METADATA, 0, -1);
1176 return out;
1177 }
1178
1179 return gst_buffer_ref (buf);
1180 }
1181