source: trunk/src/3rdparty/phonon/gstreamer/alsasink2.c@ 846

Last change on this file since 846 was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 49.3 KB
Line 
1/* GStreamer
2 * Copyright (C) 2001 CodeFactory AB
3 * Copyright (C) 2001 Thomas Nyberg <[email protected]>
4 * Copyright (C) 2001-2002 Andy Wingo <[email protected]>
5 * Copyright (C) 2003 Benjamin Otte <[email protected]>
6 * Copyright (C) 2005 Wim Taymans <[email protected]>
7 * Copyright (C) 2005, 2006 Tim-Philipp MÃŒller <tim centricular net>
8 * Copyright (C) 2008 Matthias Kretz <[email protected]>
9 *
10 * gstalsasink2.c:
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26/**
27 * SECTION:element-alsasink2
28 * @short_description: play audio to an ALSA device
29 * @see_also: alsasrc, alsamixer
30 *
31 * <refsect2>
32 * <para>
33 * This element renders raw audio samples using the ALSA api.
34 * </para>
35 * <title>Example pipelines</title>
36 * <para>
37 * Play an Ogg/Vorbis file.
38 * </para>
39 * <programlisting>
40 * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! alsasink2
41 * </programlisting>
42 * </refsect2>
43 *
44 * Last reviewed on 2006-03-01 (0.10.4)
45 */
46
47#define _XOPEN_SOURCE 600
48
49#include <sys/ioctl.h>
50#include <fcntl.h>
51#include <errno.h>
52#include <unistd.h>
53#include <string.h>
54#include <getopt.h>
55#include <alsa/asoundlib.h>
56
57#include "alsasink2.h"
58
59#include <gst/interfaces/propertyprobe.h>
60#include <gst/audio/multichannel.h>
61
62#define _(text) (text)
63
64#define GST_CHECK_ALSA_VERSION(major,minor,micro) \
65 (SND_LIB_MAJOR > (major) || \
66 (SND_LIB_MAJOR == (major) && SND_LIB_MINOR > (minor)) || \
67 (SND_LIB_MAJOR == (major) && SND_LIB_MINOR == (minor) && \
68 SND_LIB_SUBMINOR >= (micro)))
69
70static const GList *
71gst_alsa_device_property_probe_get_properties (GstPropertyProbe * probe)
72{
73 GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
74 static GList *list = NULL;
75
76 /* well, not perfect, but better than no locking at all.
77 * In the worst case we leak a list node, so who cares? */
78 GST_CLASS_LOCK (GST_OBJECT_CLASS (klass));
79
80 if (!list) {
81 GParamSpec *pspec;
82
83 pspec = g_object_class_find_property (klass, "device");
84 list = g_list_append (NULL, pspec);
85 }
86
87 GST_CLASS_UNLOCK (GST_OBJECT_CLASS (klass));
88
89 return list;
90}
91
92static GList *
93gst_alsa_get_device_list (snd_pcm_stream_t stream)
94{
95 snd_ctl_t *handle;
96 int card, err, dev;
97 snd_ctl_card_info_t *info;
98 snd_pcm_info_t *pcminfo;
99 gboolean mixer = (stream == ~0u);
100 GList *list = NULL;
101
102 if (stream == ~0u)
103 stream = 0;
104
105 snd_ctl_card_info_malloc (&info);
106 snd_pcm_info_malloc (&pcminfo);
107 card = -1;
108
109 if (snd_card_next (&card) < 0 || card < 0) {
110 /* no soundcard found */
111 return NULL;
112 }
113
114 while (card >= 0) {
115 gchar name[32];
116
117 g_snprintf (name, sizeof (name), "hw:%d", card);
118 if ((err = snd_ctl_open (&handle, name, 0)) < 0) {
119 goto next_card;
120 }
121 if ((err = snd_ctl_card_info (handle, info)) < 0) {
122 snd_ctl_close (handle);
123 goto next_card;
124 }
125
126 if (mixer) {
127 list = g_list_append (list, g_strdup (name));
128 } else {
129 g_snprintf (name, sizeof (name), "default:CARD=%d", card);
130 list = g_list_append (list, g_strdup (name));
131 dev = -1;
132 while (1) {
133 gchar *gst_device;
134
135 snd_ctl_pcm_next_device (handle, &dev);
136
137 if (dev < 0)
138 break;
139 snd_pcm_info_set_device (pcminfo, dev);
140 snd_pcm_info_set_subdevice (pcminfo, 0);
141 snd_pcm_info_set_stream (pcminfo, stream);
142 if ((err = snd_ctl_pcm_info (handle, pcminfo)) < 0) {
143 continue;
144 }
145
146 gst_device = g_strdup_printf ("hw:%d,%d", card, dev);
147 list = g_list_append (list, gst_device);
148 }
149 }
150 snd_ctl_close (handle);
151 next_card:
152 if (snd_card_next (&card) < 0) {
153 break;
154 }
155 }
156
157 snd_ctl_card_info_free (info);
158 snd_pcm_info_free (pcminfo);
159
160 return list;
161}
162
163static void
164gst_alsa_device_property_probe_probe_property (GstPropertyProbe * probe,
165 guint prop_id, const GParamSpec * pspec)
166{
167 if (!g_str_equal (pspec->name, "device")) {
168 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
169 }
170}
171
172static gboolean
173gst_alsa_device_property_probe_needs_probe (GstPropertyProbe * probe,
174 guint prop_id, const GParamSpec * pspec)
175{
176 /* don't cache probed data */
177 return TRUE;
178}
179
180static GValueArray *
181gst_alsa_device_property_probe_get_values (GstPropertyProbe * probe,
182 guint prop_id, const GParamSpec * pspec)
183{
184 GstElementClass *klass;
185 const GList *templates;
186 snd_pcm_stream_t mode = -1;
187 GValueArray *array;
188 GValue value = { 0, };
189 GList *l, *list;
190
191 if (!g_str_equal (pspec->name, "device")) {
192 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
193 return NULL;
194 }
195
196 klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe));
197
198 /* I'm pretty sure ALSA has a good way to do this. However, their cool
199 * auto-generated documentation is pretty much useless if you try to
200 * do function-wise look-ups. */
201 /* we assume one pad template at max [zero=mixer] */
202 templates = gst_element_class_get_pad_template_list (klass);
203 if (templates) {
204 if (GST_PAD_TEMPLATE_DIRECTION (templates->data) == GST_PAD_SRC)
205 mode = SND_PCM_STREAM_CAPTURE;
206 else
207 mode = SND_PCM_STREAM_PLAYBACK;
208 }
209
210 list = gst_alsa_get_device_list (mode);
211
212 if (list == NULL) {
213 GST_LOG_OBJECT (probe, "No devices found");
214 return NULL;
215 }
216
217 array = g_value_array_new (g_list_length (list));
218 g_value_init (&value, G_TYPE_STRING);
219 for (l = list; l != NULL; l = l->next) {
220 GST_LOG_OBJECT (probe, "Found device: %s", (gchar *) l->data);
221 g_value_take_string (&value, (gchar *) l->data);
222 l->data = NULL;
223 g_value_array_append (array, &value);
224 }
225 g_value_unset (&value);
226 g_list_free (list);
227
228 return array;
229}
230
231static void
232gst_alsa_property_probe_interface_init (GstPropertyProbeInterface * iface)
233{
234 iface->get_properties = gst_alsa_device_property_probe_get_properties;
235 iface->probe_property = gst_alsa_device_property_probe_probe_property;
236 iface->needs_probe = gst_alsa_device_property_probe_needs_probe;
237 iface->get_values = gst_alsa_device_property_probe_get_values;
238}
239
240static void
241gst_alsa_type_add_device_property_probe_interface (GType type)
242{
243 static const GInterfaceInfo probe_iface_info = {
244 (GInterfaceInitFunc) gst_alsa_property_probe_interface_init,
245 NULL,
246 NULL,
247 };
248
249 g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
250 &probe_iface_info);
251}
252
253static GstCaps *
254gst_alsa_detect_rates (GstObject * obj, snd_pcm_hw_params_t * hw_params,
255 GstCaps * in_caps)
256{
257 GstCaps *caps;
258 guint min, max;
259 gint err, dir, min_rate, max_rate;
260 guint i;
261
262 GST_LOG_OBJECT (obj, "probing sample rates ...");
263
264 if ((err = snd_pcm_hw_params_get_rate_min (hw_params, &min, &dir)) < 0)
265 goto min_rate_err;
266
267 if ((err = snd_pcm_hw_params_get_rate_max (hw_params, &max, &dir)) < 0)
268 goto max_rate_err;
269
270 min_rate = min;
271 max_rate = max;
272
273 if (min_rate < 4000)
274 min_rate = 4000; /* random 'sensible minimum' */
275
276 if (max_rate <= 0)
277 max_rate = G_MAXINT; /* or maybe just use 192400 or so? */
278 else if (max_rate > 0 && max_rate < 4000)
279 max_rate = MAX (4000, min_rate);
280
281 GST_DEBUG_OBJECT (obj, "Min. rate = %u (%d)", min_rate, min);
282 GST_DEBUG_OBJECT (obj, "Max. rate = %u (%d)", max_rate, max);
283
284 caps = gst_caps_make_writable (in_caps);
285
286 for (i = 0; i < gst_caps_get_size (caps); ++i) {
287 GstStructure *s;
288
289 s = gst_caps_get_structure (caps, i);
290 if (min_rate == max_rate) {
291 gst_structure_set (s, "rate", G_TYPE_INT, min_rate, NULL);
292 } else {
293 gst_structure_set (s, "rate", GST_TYPE_INT_RANGE,
294 min_rate, max_rate, NULL);
295 }
296 }
297
298 return caps;
299
300 /* ERRORS */
301min_rate_err:
302 {
303 GST_ERROR_OBJECT (obj, "failed to query minimum sample rate: %s",
304 snd_strerror (err));
305 gst_caps_unref (in_caps);
306 return NULL;
307 }
308max_rate_err:
309 {
310 GST_ERROR_OBJECT (obj, "failed to query maximum sample rate: %s",
311 snd_strerror (err));
312 gst_caps_unref (in_caps);
313 return NULL;
314 }
315}
316
317static const struct
318{
319 const int width;
320 const int depth;
321 const int sformat;
322 const int uformat;
323} pcmformats[] = {
324 {
325 8, 8, SND_PCM_FORMAT_S8, SND_PCM_FORMAT_U8}, {
326 16, 16, SND_PCM_FORMAT_S16, SND_PCM_FORMAT_U16}, {
327 32, 24, SND_PCM_FORMAT_S24, SND_PCM_FORMAT_U24}, {
328#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) /* no endian-unspecific enum available */
329 24, 24, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_U24_3LE}, {
330#else
331 24, 24, SND_PCM_FORMAT_S24_3BE, SND_PCM_FORMAT_U24_3BE}, {
332#endif
333 32, 32, SND_PCM_FORMAT_S32, SND_PCM_FORMAT_U32}
334};
335
336static GstCaps *
337gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params,
338 GstCaps * in_caps)
339{
340 snd_pcm_format_mask_t *mask;
341 GstStructure *s;
342 GstCaps *caps;
343 guint i;
344
345 snd_pcm_format_mask_malloc (&mask);
346 snd_pcm_hw_params_get_format_mask (hw_params, mask);
347
348 caps = gst_caps_new_empty ();
349
350 for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
351 GstStructure *scopy;
352 guint w;
353 gint width = 0, depth = 0;
354
355 s = gst_caps_get_structure (in_caps, i);
356 if (!gst_structure_has_name (s, "audio/x-raw-int")) {
357 GST_WARNING_OBJECT (obj, "skipping non-int format");
358 continue;
359 }
360 if (!gst_structure_get_int (s, "width", &width) ||
361 !gst_structure_get_int (s, "depth", &depth))
362 continue;
363 if (width == 0 || (width % 8) != 0)
364 continue; /* Only full byte widths are valid */
365 for (w = 0; w < G_N_ELEMENTS (pcmformats); w++)
366 if (pcmformats[w].width == width && pcmformats[w].depth == depth)
367 break;
368 if (w == G_N_ELEMENTS (pcmformats))
369 continue; /* Unknown format */
370
371 if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat) &&
372 snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
373 /* template contains { true, false } or just one, leave it as it is */
374 scopy = gst_structure_copy (s);
375 } else if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat)) {
376 scopy = gst_structure_copy (s);
377 gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
378 } else if (snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
379 scopy = gst_structure_copy (s);
380 gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
381 } else {
382 scopy = NULL;
383 }
384 if (scopy) {
385 if (width > 8) {
386 /* TODO: proper endianness detection, for now it's CPU endianness only */
387 gst_structure_set (scopy, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
388 }
389 gst_caps_append_structure (caps, scopy);
390 }
391 }
392
393 snd_pcm_format_mask_free (mask);
394 gst_caps_unref (in_caps);
395 return caps;
396}
397
398/* we don't have channel mappings for more than this many channels */
399#define GST_ALSA_MAX_CHANNELS 8
400
401static GstStructure *
402get_channel_free_structure (const GstStructure * in_structure)
403{
404 GstStructure *s = gst_structure_copy (in_structure);
405
406 gst_structure_remove_field (s, "channels");
407 return s;
408}
409
410static void
411caps_add_channel_configuration (GstCaps * caps,
412 const GstStructure * in_structure, gint min_chans, gint max_chans)
413{
414 GstAudioChannelPosition pos[8] = {
415 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
416 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
417 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
418 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
419 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
420 GST_AUDIO_CHANNEL_POSITION_LFE,
421 GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
422 GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT
423 };
424 GstStructure *s = NULL;
425 gint c;
426
427 if (min_chans == max_chans && max_chans <= 2) {
428 s = get_channel_free_structure (in_structure);
429 gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL);
430 gst_caps_append_structure (caps, s);
431 return;
432 }
433
434 g_assert (min_chans >= 1);
435
436 /* mono and stereo don't need channel configurations */
437 if (min_chans == 2) {
438 s = get_channel_free_structure (in_structure);
439 gst_structure_set (s, "channels", G_TYPE_INT, 2, NULL);
440 gst_caps_append_structure (caps, s);
441 } else if (min_chans == 1 && max_chans >= 2) {
442 s = get_channel_free_structure (in_structure);
443 gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
444 gst_caps_append_structure (caps, s);
445 }
446
447 /* don't know whether to use 2.1 or 3.0 here - but I suspect
448 * alsa might work around that/fix it somehow. Can we tell alsa
449 * what our channel layout is like? */
450 if (max_chans >= 3 && min_chans <= 3) {
451 GstAudioChannelPosition pos_21[3] = {
452 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
453 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
454 GST_AUDIO_CHANNEL_POSITION_LFE
455 };
456
457 s = get_channel_free_structure (in_structure);
458 gst_structure_set (s, "channels", G_TYPE_INT, 3, NULL);
459 gst_audio_set_channel_positions (s, pos_21);
460 gst_caps_append_structure (caps, s);
461 }
462
463 /* everything else (4, 6, 8 channels) needs a channel layout */
464 for (c = MAX (4, min_chans); c <= 8; c += 2) {
465 if (max_chans >= c) {
466 s = get_channel_free_structure (in_structure);
467 gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
468 gst_audio_set_channel_positions (s, pos);
469 gst_caps_append_structure (caps, s);
470 }
471 }
472
473 for (c = MAX (9, min_chans); c <= max_chans; ++c) {
474 GstAudioChannelPosition *ch_layout;
475 gint i;
476
477 ch_layout = g_new (GstAudioChannelPosition, c);
478 for (i = 0; i < c; ++i) {
479 ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
480 }
481 s = get_channel_free_structure (in_structure);
482 gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
483 gst_audio_set_channel_positions (s, ch_layout);
484 gst_caps_append_structure (caps, s);
485 g_free (ch_layout);
486 }
487}
488
489static GstCaps *
490gst_alsa_detect_channels (GstObject * obj, snd_pcm_hw_params_t * hw_params,
491 GstCaps * in_caps)
492{
493 GstCaps *caps;
494 guint min, max;
495 gint min_chans, max_chans;
496 gint err;
497 guint i;
498
499 GST_LOG_OBJECT (obj, "probing channels ...");
500
501 if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &min)) < 0)
502 goto min_chan_error;
503
504 if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &max)) < 0)
505 goto max_chan_error;
506
507 /* note: the above functions may return (guint) -1 */
508 min_chans = min;
509 max_chans = max;
510
511 if (min_chans < 0) {
512 min_chans = 1;
513 max_chans = GST_ALSA_MAX_CHANNELS;
514 } else if (max_chans < 0) {
515 max_chans = GST_ALSA_MAX_CHANNELS;
516 }
517
518 if (min_chans > max_chans) {
519 gint temp;
520
521 GST_WARNING_OBJECT (obj, "minimum channels > maximum channels (%d > %d), "
522 "please fix your soundcard drivers", min, max);
523 temp = min_chans;
524 min_chans = max_chans;
525 max_chans = temp;
526 }
527
528 /* pro cards seem to return large numbers for min_channels */
529 if (min_chans > GST_ALSA_MAX_CHANNELS) {
530 GST_DEBUG_OBJECT (obj, "min_chans = %u, looks like a pro card", min_chans);
531 if (max_chans < min_chans) {
532 max_chans = min_chans;
533 } else {
534 /* only support [max_chans; max_chans] for these cards for now
535 * to avoid inflating the source caps with loads of structures ... */
536 min_chans = max_chans;
537 }
538 } else {
539 min_chans = MAX (min_chans, 1);
540 max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans);
541 }
542
543 GST_DEBUG_OBJECT (obj, "Min. channels = %d (%d)", min_chans, min);
544 GST_DEBUG_OBJECT (obj, "Max. channels = %d (%d)", max_chans, max);
545
546 caps = gst_caps_new_empty ();
547
548 for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
549 GstStructure *s;
550 GType field_type;
551 gint c_min = min_chans;
552 gint c_max = max_chans;
553
554 s = gst_caps_get_structure (in_caps, i);
555 /* the template caps might limit the number of channels (like alsasrc),
556 * in which case we don't want to return a superset, so hack around this
557 * for the two common cases where the channels are either a fixed number
558 * or a min/max range). Example: alsasrc template has channels = [1,2] and
559 * the detection will claim to support 8 channels for device 'plughw:0' */
560 field_type = gst_structure_get_field_type (s, "channels");
561 if (field_type == G_TYPE_INT) {
562 gst_structure_get_int (s, "channels", &c_min);
563 gst_structure_get_int (s, "channels", &c_max);
564 } else if (field_type == GST_TYPE_INT_RANGE) {
565 const GValue *val;
566
567 val = gst_structure_get_value (s, "channels");
568 c_min = CLAMP (gst_value_get_int_range_min (val), min_chans, max_chans);
569 c_max = CLAMP (gst_value_get_int_range_max (val), min_chans, max_chans);
570 } else {
571 c_min = min_chans;
572 c_max = max_chans;
573 }
574
575 caps_add_channel_configuration (caps, s, c_min, c_max);
576 }
577
578 gst_caps_unref (in_caps);
579
580 return caps;
581
582 /* ERRORS */
583min_chan_error:
584 {
585 GST_ERROR_OBJECT (obj, "failed to query minimum channel count: %s",
586 snd_strerror (err));
587 return NULL;
588 }
589max_chan_error:
590 {
591 GST_ERROR_OBJECT (obj, "failed to query maximum channel count: %s",
592 snd_strerror (err));
593 return NULL;
594 }
595}
596
597#ifndef GST_CHECK_VERSION
598#define GST_CHECK_VERSION(major,minor,micro) \
599 (GST_VERSION_MAJOR > (major) || \
600 (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR > (minor)) || \
601 (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR == (minor) && GST_VERSION_MICRO >= (micro)))
602#endif
603
604#if GST_CHECK_VERSION(0, 10, 18)
605snd_pcm_t *
606gst_alsa_open_iec958_pcm (GstObject * obj)
607{
608 char *iec958_pcm_name = NULL;
609 snd_pcm_t *pcm = NULL;
610 int res;
611 char devstr[256]; /* Storage for local 'default' device string */
612
613 /*
614 * Try and open our default iec958 device. Fall back to searching on card x
615 * if this fails, which should only happen on older alsa setups
616 */
617
618 /* The string will be one of these:
619 * SPDIF_CON: Non-audio flag not set:
620 * spdif:{AES0 0x0 AES1 0x82 AES2 0x0 AES3 0x2}
621 * SPDIF_CON: Non-audio flag set:
622 * spdif:{AES0 0x2 AES1 0x82 AES2 0x0 AES3 0x2}
623 */
624 sprintf (devstr,
625 "iec958:{AES0 0x%02x AES1 0x%02x AES2 0x%02x AES3 0x%02x}",
626 IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
627 IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
628 0, IEC958_AES3_CON_FS_48000);
629
630 GST_DEBUG_OBJECT (obj, "Generated device string \"%s\"", devstr);
631 iec958_pcm_name = devstr;
632
633 res = snd_pcm_open (&pcm, iec958_pcm_name, SND_PCM_STREAM_PLAYBACK, 0);
634 if (G_UNLIKELY (res < 0)) {
635 GST_DEBUG_OBJECT (obj, "failed opening IEC958 device: %s",
636 snd_strerror (res));
637 pcm = NULL;
638 }
639
640 return pcm;
641}
642#endif
643
644
645/*
646 * gst_alsa_probe_supported_formats:
647 *
648 * Takes the template caps and returns the subset which is actually
649 * supported by this device.
650 *
651 */
652
653GstCaps *
654gst_alsa_probe_supported_formats (GstObject * obj, snd_pcm_t * handle,
655 const GstCaps * template_caps)
656{
657 snd_pcm_hw_params_t *hw_params;
658 snd_pcm_stream_t stream_type;
659 GstCaps *caps;
660 gint err;
661
662 snd_pcm_hw_params_malloc (&hw_params);
663 if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0)
664 goto error;
665
666 stream_type = snd_pcm_stream (handle);
667
668 caps = gst_caps_copy (template_caps);
669
670 if (!(caps = gst_alsa_detect_formats (obj, hw_params, caps)))
671 goto subroutine_error;
672
673 if (!(caps = gst_alsa_detect_rates (obj, hw_params, caps)))
674 goto subroutine_error;
675
676 if (!(caps = gst_alsa_detect_channels (obj, hw_params, caps)))
677 goto subroutine_error;
678
679#if GST_CHECK_VERSION(0, 10, 18)
680 /* Try opening IEC958 device to see if we can support that format (playback
681 * only for now but we could add SPDIF capture later) */
682 if (stream_type == SND_PCM_STREAM_PLAYBACK) {
683 snd_pcm_t *pcm = gst_alsa_open_iec958_pcm (obj);
684
685 if (G_LIKELY (pcm)) {
686 gst_caps_append (caps, gst_caps_new_simple ("audio/x-iec958", NULL));
687 snd_pcm_close (pcm);
688 }
689 }
690#endif
691
692 snd_pcm_hw_params_free (hw_params);
693 return caps;
694
695 /* ERRORS */
696error:
697 {
698 GST_ERROR_OBJECT (obj, "failed to query formats: %s", snd_strerror (err));
699 snd_pcm_hw_params_free (hw_params);
700 return NULL;
701 }
702subroutine_error:
703 {
704 GST_ERROR_OBJECT (obj, "failed to query formats");
705 snd_pcm_hw_params_free (hw_params);
706 return NULL;
707 }
708}
709
710static gchar *
711gst_alsa_find_device_name_no_handle (GstObject * obj, const gchar * devcard,
712 gint device_num, snd_pcm_stream_t stream)
713{
714 snd_ctl_card_info_t *info = NULL;
715 snd_ctl_t *ctl = NULL;
716 gchar *ret = NULL;
717 gint dev = -1;
718
719 GST_LOG_OBJECT (obj, "[%s] device=%d", devcard, device_num);
720
721 if (snd_ctl_open (&ctl, devcard, 0) < 0)
722 return NULL;
723
724 snd_ctl_card_info_malloc (&info);
725 if (snd_ctl_card_info (ctl, info) < 0)
726 goto done;
727
728 while (snd_ctl_pcm_next_device (ctl, &dev) == 0 && dev >= 0) {
729 if (dev == device_num) {
730 snd_pcm_info_t *pcminfo;
731
732 snd_pcm_info_malloc (&pcminfo);
733 snd_pcm_info_set_device (pcminfo, dev);
734 snd_pcm_info_set_subdevice (pcminfo, 0);
735 snd_pcm_info_set_stream (pcminfo, stream);
736 if (snd_ctl_pcm_info (ctl, pcminfo) < 0) {
737 snd_pcm_info_free (pcminfo);
738 break;
739 }
740
741 ret = g_strdup (snd_pcm_info_get_name (pcminfo));
742 snd_pcm_info_free (pcminfo);
743 GST_LOG_OBJECT (obj, "name from pcminfo: %s", GST_STR_NULL (ret));
744 }
745 }
746
747 if (ret == NULL) {
748 char *name = NULL;
749 gint card;
750
751 GST_LOG_OBJECT (obj, "no luck so far, trying backup");
752 card = snd_ctl_card_info_get_card (info);
753 snd_card_get_name (card, &name);
754 ret = g_strdup (name);
755 free (name);
756 }
757
758done:
759 snd_ctl_card_info_free (info);
760 snd_ctl_close (ctl);
761
762 return ret;
763}
764
765gchar *
766gst_alsa_find_device_name (GstObject * obj, const gchar * device,
767 snd_pcm_t * handle, snd_pcm_stream_t stream)
768{
769 gchar *ret = NULL;
770
771 if (device != NULL) {
772 gchar *dev, *comma;
773 gint devnum;
774
775 GST_LOG_OBJECT (obj, "Trying to get device name from string '%s'", device);
776
777 /* only want name:card bit, but not devices and subdevices */
778 dev = g_strdup (device);
779 if ((comma = strchr (dev, ','))) {
780 *comma = '\0';
781 devnum = atoi (comma + 1);
782 ret = gst_alsa_find_device_name_no_handle (obj, dev, devnum, stream);
783 }
784 g_free (dev);
785 }
786
787 if (ret == NULL && handle != NULL) {
788 snd_pcm_info_t *info;
789
790 GST_LOG_OBJECT (obj, "Trying to get device name from open handle");
791 snd_pcm_info_malloc (&info);
792 snd_pcm_info (handle, info);
793 ret = g_strdup (snd_pcm_info_get_name (info));
794 snd_pcm_info_free (info);
795 }
796
797 GST_LOG_OBJECT (obj, "Device name for device '%s': %s",
798 GST_STR_NULL (device), GST_STR_NULL (ret));
799
800 return ret;
801}
802
803/* elementfactory information */
804static const GstElementDetails gst_alsasink2_details =
805GST_ELEMENT_DETAILS ("Audio sink (ALSA)",
806 "Sink/Audio",
807 "Output to a sound card via ALSA",
808 "Wim Taymans <[email protected]>");
809
810#define DEFAULT_DEVICE "default"
811#define DEFAULT_DEVICE_NAME ""
812#define SPDIF_PERIOD_SIZE 1536
813#define SPDIF_BUFFER_SIZE 15360
814
815enum
816{
817 PROP_0,
818 PROP_DEVICE,
819 PROP_DEVICE_NAME
820};
821
822static void gst_alsasink2_init_interfaces (GType type);
823
824GST_BOILERPLATE_FULL (_k_GstAlsaSink, gst_alsasink2, GstAudioSink,
825 GST_TYPE_AUDIO_SINK, gst_alsasink2_init_interfaces);
826
827static void gst_alsasink2_finalise (GObject * object);
828static void gst_alsasink2_set_property (GObject * object,
829 guint prop_id, const GValue * value, GParamSpec * pspec);
830static void gst_alsasink2_get_property (GObject * object,
831 guint prop_id, GValue * value, GParamSpec * pspec);
832
833static GstCaps *gst_alsasink2_getcaps (GstBaseSink * bsink);
834
835static gboolean gst_alsasink2_open (GstAudioSink * asink);
836static gboolean gst_alsasink2_prepare (GstAudioSink * asink,
837 GstRingBufferSpec * spec);
838static gboolean gst_alsasink2_unprepare (GstAudioSink * asink);
839static gboolean gst_alsasink2_close (GstAudioSink * asink);
840static guint gst_alsasink2_write (GstAudioSink * asink, gpointer data,
841 guint length);
842static guint gst_alsasink2_delay (GstAudioSink * asink);
843static void gst_alsasink2_reset (GstAudioSink * asink);
844
845static gint output_ref; /* 0 */
846static snd_output_t *output; /* NULL */
847static GStaticMutex output_mutex = G_STATIC_MUTEX_INIT;
848
849
850#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
851# define ALSA_SINK2_FACTORY_ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN"
852#else
853# define ALSA_SINK2_FACTORY_ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN"
854#endif
855
856static GstStaticPadTemplate alsasink2_sink_factory =
857 GST_STATIC_PAD_TEMPLATE ("sink",
858 GST_PAD_SINK,
859 GST_PAD_ALWAYS,
860 GST_STATIC_CAPS ("audio/x-raw-int, "
861 "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
862 "signed = (boolean) { TRUE, FALSE }, "
863 "width = (int) 32, "
864 "depth = (int) 32, "
865 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
866 "audio/x-raw-int, "
867 "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
868 "signed = (boolean) { TRUE, FALSE }, "
869 "width = (int) 24, "
870 "depth = (int) 24, "
871 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
872 "audio/x-raw-int, "
873 "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
874 "signed = (boolean) { TRUE, FALSE }, "
875 "width = (int) 32, "
876 "depth = (int) 24, "
877 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
878 "audio/x-raw-int, "
879 "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
880 "signed = (boolean) { TRUE, FALSE }, "
881 "width = (int) 16, "
882 "depth = (int) 16, "
883 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
884 "audio/x-raw-int, "
885 "signed = (boolean) { TRUE, FALSE }, "
886 "width = (int) 8, "
887 "depth = (int) 8, "
888 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ];"
889 "audio/x-iec958")
890 );
891
892static void
893gst_alsasink2_finalise (GObject * object)
894{
895 _k_GstAlsaSink *sink = GST_ALSA_SINK2 (object);
896
897 g_free (sink->device);
898 g_mutex_free (sink->alsa_lock);
899
900 g_static_mutex_lock (&output_mutex);
901 --output_ref;
902 if (output_ref == 0) {
903 snd_output_close (output);
904 output = NULL;
905 }
906 g_static_mutex_unlock (&output_mutex);
907
908 G_OBJECT_CLASS (parent_class)->finalize (object);
909}
910
911static void
912gst_alsasink2_init_interfaces (GType type)
913{
914 gst_alsa_type_add_device_property_probe_interface (type);
915}
916
917static void
918gst_alsasink2_base_init (gpointer g_class)
919{
920 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
921
922 gst_element_class_set_details (element_class, &gst_alsasink2_details);
923
924 gst_element_class_add_pad_template (element_class,
925 gst_static_pad_template_get (&alsasink2_sink_factory));
926}
927static void
928gst_alsasink2_class_init (_k_GstAlsaSinkClass * klass)
929{
930 GObjectClass *gobject_class;
931 GstElementClass *gstelement_class;
932 GstBaseSinkClass *gstbasesink_class;
933 GstBaseAudioSinkClass *gstbaseaudiosink_class;
934 GstAudioSinkClass *gstaudiosink_class;
935
936 gobject_class = (GObjectClass *) klass;
937 gstelement_class = (GstElementClass *) klass;
938 gstbasesink_class = (GstBaseSinkClass *) klass;
939 gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
940 gstaudiosink_class = (GstAudioSinkClass *) klass;
941
942 parent_class = g_type_class_peek_parent (klass);
943
944 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasink2_finalise);
945 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasink2_get_property);
946 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasink2_set_property);
947
948 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink2_getcaps);
949
950 gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink2_open);
951 gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasink2_prepare);
952 gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasink2_unprepare);
953 gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_alsasink2_close);
954 gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_alsasink2_write);
955 gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_alsasink2_delay);
956 gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_alsasink2_reset);
957
958 g_object_class_install_property (gobject_class, PROP_DEVICE,
959 g_param_spec_string ("device", "Device",
960 "ALSA device, as defined in an asound configuration file",
961 DEFAULT_DEVICE, G_PARAM_READWRITE));
962
963 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
964 g_param_spec_string ("device-name", "Device name",
965 "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
966 G_PARAM_READABLE));
967}
968
969static void
970gst_alsasink2_set_property (GObject * object, guint prop_id,
971 const GValue * value, GParamSpec * pspec)
972{
973 _k_GstAlsaSink *sink;
974
975 sink = GST_ALSA_SINK2 (object);
976
977 switch (prop_id) {
978 case PROP_DEVICE:
979 g_free (sink->device);
980 sink->device = g_value_dup_string (value);
981 /* setting NULL restores the default device */
982 if (sink->device == NULL) {
983 sink->device = g_strdup (DEFAULT_DEVICE);
984 }
985 break;
986 default:
987 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
988 break;
989 }
990}
991
992static void
993gst_alsasink2_get_property (GObject * object, guint prop_id,
994 GValue * value, GParamSpec * pspec)
995{
996 _k_GstAlsaSink *sink;
997
998 sink = GST_ALSA_SINK2 (object);
999
1000 switch (prop_id) {
1001 case PROP_DEVICE:
1002 g_value_set_string (value, sink->device);
1003 break;
1004 case PROP_DEVICE_NAME:
1005 g_value_take_string (value,
1006 gst_alsa_find_device_name (GST_OBJECT_CAST (sink),
1007 sink->device, sink->handle, SND_PCM_STREAM_PLAYBACK));
1008 break;
1009 default:
1010 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1011 break;
1012 }
1013}
1014
1015static void
1016gst_alsasink2_init (_k_GstAlsaSink * alsasink2, _k_GstAlsaSinkClass * g_class)
1017{
1018 GST_DEBUG_OBJECT (alsasink2, "initializing alsasink2");
1019
1020 alsasink2->device = g_strdup (DEFAULT_DEVICE);
1021 alsasink2->handle = NULL;
1022 alsasink2->cached_caps = NULL;
1023 alsasink2->alsa_lock = g_mutex_new ();
1024
1025 g_static_mutex_lock (&output_mutex);
1026 if (output_ref == 0) {
1027 snd_output_stdio_attach (&output, stdout, 0);
1028 ++output_ref;
1029 }
1030 g_static_mutex_unlock (&output_mutex);
1031}
1032
1033#define CHECK(call, error) \
1034G_STMT_START { \
1035if ((err = call) < 0) \
1036 goto error; \
1037} G_STMT_END;
1038
1039static GstCaps *
1040gst_alsasink2_getcaps (GstBaseSink * bsink)
1041{
1042 GstElementClass *element_class;
1043 GstPadTemplate *pad_template;
1044 _k_GstAlsaSink *sink = GST_ALSA_SINK2 (bsink);
1045 GstCaps *caps;
1046
1047 if (sink->handle == NULL) {
1048 GST_DEBUG_OBJECT (sink, "device not open, using template caps");
1049 return NULL; /* base class will get template caps for us */
1050 }
1051
1052 if (sink->cached_caps) {
1053 GST_LOG_OBJECT (sink, "Returning cached caps");
1054 return gst_caps_ref (sink->cached_caps);
1055 }
1056
1057 element_class = GST_ELEMENT_GET_CLASS (sink);
1058 pad_template = gst_element_class_get_pad_template (element_class, "sink");
1059 g_return_val_if_fail (pad_template != NULL, NULL);
1060
1061 caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->handle,
1062 gst_pad_template_get_caps (pad_template));
1063
1064 if (caps) {
1065 sink->cached_caps = gst_caps_ref (caps);
1066 }
1067
1068 GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
1069
1070 return caps;
1071}
1072
1073static int
1074set_hwparams (_k_GstAlsaSink * alsa)
1075{
1076 guint rrate;
1077 gint err, dir;
1078 snd_pcm_hw_params_t *params;
1079 guint period_time, buffer_time;
1080
1081 snd_pcm_hw_params_malloc (&params);
1082
1083 GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
1084 "SPDIF (%d)", alsa->channels, alsa->rate,
1085 snd_pcm_format_name (alsa->format), alsa->iec958);
1086
1087 /* start with requested values, if we cannot configure alsa for those values,
1088 * we set these values to -1, which will leave the default alsa values */
1089 buffer_time = alsa->buffer_time;
1090 period_time = alsa->period_time;
1091
1092retry:
1093 /* choose all parameters */
1094 CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
1095 /* set the interleaved read/write format */
1096 CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
1097 wrong_access);
1098 /* set the sample format */
1099#if GST_CHECK_VERSION(0, 10, 18)
1100 if (alsa->iec958) {
1101 /* Try to use big endian first else fallback to le and swap bytes */
1102 if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
1103 alsa->format = SND_PCM_FORMAT_S16_LE;
1104 alsa->need_swap = TRUE;
1105 GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
1106 } else {
1107 alsa->need_swap = FALSE;
1108 }
1109 }
1110#endif
1111 CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
1112 no_sample_format);
1113 /* set the count of channels */
1114 CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
1115 no_channels);
1116 /* set the stream rate */
1117 rrate = alsa->rate;
1118 CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
1119 no_rate);
1120 if (rrate != alsa->rate)
1121 goto rate_match;
1122
1123 /* get and dump some limits */
1124 {
1125 guint min, max;
1126
1127 snd_pcm_hw_params_get_buffer_time_min (params, &min, &dir);
1128 snd_pcm_hw_params_get_buffer_time_max (params, &max, &dir);
1129
1130 GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
1131 alsa->buffer_time, min, max);
1132
1133 snd_pcm_hw_params_get_period_time_min (params, &min, &dir);
1134 snd_pcm_hw_params_get_period_time_max (params, &max, &dir);
1135
1136 GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
1137 alsa->period_time, min, max);
1138
1139 snd_pcm_hw_params_get_periods_min (params, &min, &dir);
1140 snd_pcm_hw_params_get_periods_max (params, &max, &dir);
1141
1142 GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
1143 }
1144
1145 /* now try to configure the buffer time and period time, if one
1146 * of those fail, we fall back to the defaults and emit a warning. */
1147 if (buffer_time != ~0u && !alsa->iec958) {
1148 /* set the buffer time */
1149 if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
1150 &buffer_time, &dir)) < 0) {
1151 GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
1152 ("Unable to set buffer time %i for playback: %s",
1153 buffer_time, snd_strerror (err)));
1154 /* disable buffer_time the next round */
1155 buffer_time = -1;
1156 goto retry;
1157 }
1158 GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
1159 }
1160 if (period_time != ~0u && !alsa->iec958) {
1161 /* set the period time */
1162 if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
1163 &period_time, &dir)) < 0) {
1164 GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
1165 ("Unable to set period time %i for playback: %s",
1166 period_time, snd_strerror (err)));
1167 /* disable period_time the next round */
1168 period_time = -1;
1169 goto retry;
1170 }
1171 GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
1172 }
1173
1174 /* Set buffer size and period size manually for SPDIF */
1175 if (G_UNLIKELY (alsa->iec958)) {
1176 snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
1177 snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;
1178
1179 CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
1180 &buffer_size), buffer_size);
1181 CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
1182 &period_size, NULL), period_size);
1183 }
1184
1185 /* write the parameters to device */
1186 CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
1187
1188 /* now get the configured values */
1189 CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
1190 buffer_size);
1191 CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
1192 period_size);
1193
1194 GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
1195 alsa->period_size);
1196
1197 snd_pcm_hw_params_free (params);
1198 return 0;
1199
1200 /* ERRORS */
1201no_config:
1202 {
1203 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1204 ("Broken configuration for playback: no configurations available: %s",
1205 snd_strerror (err)));
1206 snd_pcm_hw_params_free (params);
1207 return err;
1208 }
1209wrong_access:
1210 {
1211 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1212 ("Access type not available for playback: %s", snd_strerror (err)));
1213 snd_pcm_hw_params_free (params);
1214 return err;
1215 }
1216no_sample_format:
1217 {
1218 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1219 ("Sample format not available for playback: %s", snd_strerror (err)));
1220 snd_pcm_hw_params_free (params);
1221 return err;
1222 }
1223no_channels:
1224 {
1225 gchar *msg = NULL;
1226
1227 if ((alsa->channels) == 1)
1228 msg = g_strdup (_("Could not open device for playback in mono mode."));
1229 if ((alsa->channels) == 2)
1230 msg = g_strdup (_("Could not open device for playback in stereo mode."));
1231 if ((alsa->channels) > 2)
1232 msg =
1233 g_strdup_printf (_
1234 ("Could not open device for playback in %d-channel mode."),
1235 alsa->channels);
1236 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
1237 g_free (msg);
1238 snd_pcm_hw_params_free (params);
1239 return err;
1240 }
1241no_rate:
1242 {
1243 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1244 ("Rate %iHz not available for playback: %s",
1245 alsa->rate, snd_strerror (err)));
1246 return err;
1247 }
1248rate_match:
1249 {
1250 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1251 ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
1252 snd_pcm_hw_params_free (params);
1253 return -EINVAL;
1254 }
1255buffer_size:
1256 {
1257 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1258 ("Unable to get buffer size for playback: %s", snd_strerror (err)));
1259 snd_pcm_hw_params_free (params);
1260 return err;
1261 }
1262period_size:
1263 {
1264 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1265 ("Unable to get period size for playback: %s", snd_strerror (err)));
1266 snd_pcm_hw_params_free (params);
1267 return err;
1268 }
1269set_hw_params:
1270 {
1271 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1272 ("Unable to set hw params for playback: %s", snd_strerror (err)));
1273 snd_pcm_hw_params_free (params);
1274 return err;
1275 }
1276}
1277
1278static int
1279set_swparams (_k_GstAlsaSink * alsa)
1280{
1281 int err;
1282 snd_pcm_sw_params_t *params;
1283
1284 snd_pcm_sw_params_malloc (&params);
1285
1286 /* get the current swparams */
1287 CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
1288 /* start the transfer when the buffer is almost full: */
1289 /* (buffer_size / avail_min) * avail_min */
1290 CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
1291 (alsa->buffer_size / alsa->period_size) * alsa->period_size),
1292 start_threshold);
1293
1294 /* allow the transfer when at least period_size samples can be processed */
1295 CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
1296 alsa->period_size), set_avail);
1297
1298#if GST_CHECK_ALSA_VERSION(1,0,16)
1299 /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
1300#else
1301 /* align all transfers to 1 sample */
1302 CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
1303#endif
1304
1305 /* write the parameters to the playback device */
1306 CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
1307
1308 snd_pcm_sw_params_free (params);
1309 return 0;
1310
1311 /* ERRORS */
1312no_config:
1313 {
1314 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1315 ("Unable to determine current swparams for playback: %s",
1316 snd_strerror (err)));
1317 snd_pcm_sw_params_free (params);
1318 return err;
1319 }
1320start_threshold:
1321 {
1322 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1323 ("Unable to set start threshold mode for playback: %s",
1324 snd_strerror (err)));
1325 snd_pcm_sw_params_free (params);
1326 return err;
1327 }
1328set_avail:
1329 {
1330 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1331 ("Unable to set avail min for playback: %s", snd_strerror (err)));
1332 snd_pcm_sw_params_free (params);
1333 return err;
1334 }
1335#if !GST_CHECK_ALSA_VERSION(1,0,16)
1336set_align:
1337 {
1338 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1339 ("Unable to set transfer align for playback: %s", snd_strerror (err)));
1340 snd_pcm_sw_params_free (params);
1341 return err;
1342 }
1343#endif
1344set_sw_params:
1345 {
1346 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1347 ("Unable to set sw params for playback: %s", snd_strerror (err)));
1348 snd_pcm_sw_params_free (params);
1349 return err;
1350 }
1351}
1352
1353static gboolean
1354alsasink2_parse_spec (_k_GstAlsaSink * alsa, GstRingBufferSpec * spec)
1355{
1356 /* Initialize our boolean */
1357 alsa->iec958 = FALSE;
1358
1359 switch (spec->type) {
1360 case GST_BUFTYPE_LINEAR:
1361 GST_DEBUG_OBJECT (alsa,
1362 "Linear format : depth=%d, width=%d, sign=%d, bigend=%d", spec->depth,
1363 spec->width, spec->sign, spec->bigend);
1364
1365 alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
1366 spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
1367 break;
1368 case GST_BUFTYPE_FLOAT:
1369 switch (spec->format) {
1370 case GST_FLOAT32_LE:
1371 alsa->format = SND_PCM_FORMAT_FLOAT_LE;
1372 break;
1373 case GST_FLOAT32_BE:
1374 alsa->format = SND_PCM_FORMAT_FLOAT_BE;
1375 break;
1376 case GST_FLOAT64_LE:
1377 alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
1378 break;
1379 case GST_FLOAT64_BE:
1380 alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
1381 break;
1382 default:
1383 goto error;
1384 }
1385 break;
1386 case GST_BUFTYPE_A_LAW:
1387 alsa->format = SND_PCM_FORMAT_A_LAW;
1388 break;
1389 case GST_BUFTYPE_MU_LAW:
1390 alsa->format = SND_PCM_FORMAT_MU_LAW;
1391 break;
1392#if GST_CHECK_VERSION(0, 10, 18)
1393 case GST_BUFTYPE_IEC958:
1394 alsa->format = SND_PCM_FORMAT_S16_BE;
1395 alsa->iec958 = TRUE;
1396 break;
1397#endif
1398 default:
1399 goto error;
1400
1401 }
1402 alsa->rate = spec->rate;
1403 alsa->channels = spec->channels;
1404 alsa->buffer_time = spec->buffer_time;
1405 alsa->period_time = spec->latency_time;
1406 alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
1407
1408 return TRUE;
1409
1410 /* ERRORS */
1411error:
1412 {
1413 return FALSE;
1414 }
1415}
1416
1417static gboolean
1418gst_alsasink2_open (GstAudioSink * asink)
1419{
1420 _k_GstAlsaSink *alsa;
1421 gint err;
1422
1423 alsa = GST_ALSA_SINK2 (asink);
1424
1425 CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_PLAYBACK,
1426 SND_PCM_NONBLOCK), open_error);
1427 GST_LOG_OBJECT (alsa, "Opened device %s", alsa->device);
1428
1429 return TRUE;
1430
1431 /* ERRORS */
1432open_error:
1433 {
1434 if (err == -EBUSY) {
1435 GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
1436 (_("Could not open audio device for playback. "
1437 "Device is being used by another application.")),
1438 ("Device '%s' is busy", alsa->device));
1439 } else {
1440 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE,
1441 (_("Could not open audio device for playback.")),
1442 ("Playback open error on device '%s': %s", alsa->device,
1443 snd_strerror (err)));
1444 }
1445 return FALSE;
1446 }
1447}
1448
1449static gboolean
1450gst_alsasink2_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
1451{
1452 _k_GstAlsaSink *alsa;
1453 gint err;
1454
1455 alsa = GST_ALSA_SINK2 (asink);
1456
1457#if GST_CHECK_VERSION(0, 10, 18)
1458 if (spec->format == GST_IEC958) {
1459 snd_pcm_close (alsa->handle);
1460 alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa));
1461 if (G_UNLIKELY (!alsa->handle)) {
1462 goto no_iec958;
1463 }
1464 }
1465#endif
1466
1467 if (!alsasink2_parse_spec (alsa, spec))
1468 goto spec_parse;
1469
1470 CHECK (set_hwparams (alsa), hw_params_failed);
1471 CHECK (set_swparams (alsa), sw_params_failed);
1472
1473 alsa->bytes_per_sample = spec->bytes_per_sample;
1474 spec->segsize = alsa->period_size * spec->bytes_per_sample;
1475 spec->segtotal = alsa->buffer_size / alsa->period_size;
1476
1477 {
1478 snd_output_t *out_buf = NULL;
1479 char *msg = NULL;
1480
1481 snd_output_buffer_open (&out_buf);
1482 snd_pcm_dump_hw_setup (alsa->handle, out_buf);
1483 snd_output_buffer_string (out_buf, &msg);
1484 GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
1485 snd_output_close (out_buf);
1486 snd_output_buffer_open (&out_buf);
1487 snd_pcm_dump_sw_setup (alsa->handle, out_buf);
1488 snd_output_buffer_string (out_buf, &msg);
1489 GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
1490 snd_output_close (out_buf);
1491 }
1492
1493 return TRUE;
1494
1495 /* ERRORS */
1496#if GST_CHECK_VERSION(0, 10, 18)
1497no_iec958:
1498 {
1499 GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL),
1500 ("Could not open IEC958 (SPDIF) device for playback"));
1501 return FALSE;
1502 }
1503#endif
1504spec_parse:
1505 {
1506 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1507 ("Error parsing spec"));
1508 return FALSE;
1509 }
1510hw_params_failed:
1511 {
1512 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1513 ("Setting of hwparams failed: %s", snd_strerror (err)));
1514 return FALSE;
1515 }
1516sw_params_failed:
1517 {
1518 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1519 ("Setting of swparams failed: %s", snd_strerror (err)));
1520 return FALSE;
1521 }
1522}
1523
1524static gboolean
1525gst_alsasink2_unprepare (GstAudioSink * asink)
1526{
1527 _k_GstAlsaSink *alsa;
1528 gint err;
1529
1530 alsa = GST_ALSA_SINK2 (asink);
1531
1532 CHECK (snd_pcm_drop (alsa->handle), drop);
1533
1534 CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
1535
1536 return TRUE;
1537
1538 /* ERRORS */
1539drop:
1540 {
1541 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1542 ("Could not drop samples: %s", snd_strerror (err)));
1543 return FALSE;
1544 }
1545hw_free:
1546 {
1547 GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
1548 ("Could not free hw params: %s", snd_strerror (err)));
1549 return FALSE;
1550 }
1551}
1552
1553static gboolean
1554gst_alsasink2_close (GstAudioSink * asink)
1555{
1556 _k_GstAlsaSink *alsa = GST_ALSA_SINK2 (asink);
1557 gint err;
1558
1559 if (alsa->handle) {
1560 CHECK (snd_pcm_close (alsa->handle), close_error);
1561 alsa->handle = NULL;
1562 }
1563 gst_caps_replace (&alsa->cached_caps, NULL);
1564
1565 return TRUE;
1566
1567 /* ERRORS */
1568close_error:
1569 {
1570 GST_ELEMENT_ERROR (alsa, RESOURCE, CLOSE, (NULL),
1571 ("Playback close error: %s", snd_strerror (err)));
1572 return FALSE;
1573 }
1574}
1575
1576
1577/*
1578 * Underrun and suspend recovery
1579 */
1580static gint
1581xrun_recovery (_k_GstAlsaSink * alsa, snd_pcm_t * handle, gint err)
1582{
1583 GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
1584
1585 if (err == -EPIPE) { /* under-run */
1586 err = snd_pcm_prepare (handle);
1587 if (err < 0) {
1588 GST_WARNING_OBJECT (alsa,
1589 "Can't recovery from underrun, prepare failed: %s",
1590 snd_strerror (err));
1591 }
1592 return 0;
1593 } else if (err == -ESTRPIPE) {
1594 while ((err = snd_pcm_resume (handle)) == -EAGAIN)
1595 g_usleep (100); /* wait until the suspend flag is released */
1596
1597 if (err < 0) {
1598 err = snd_pcm_prepare (handle);
1599 if (err < 0) {
1600 GST_WARNING_OBJECT (alsa,
1601 "Can't recovery from suspend, prepare failed: %s",
1602 snd_strerror (err));
1603 }
1604 }
1605 return 0;
1606 }
1607 return err;
1608}
1609
1610static guint
1611gst_alsasink2_write (GstAudioSink * asink, gpointer data, guint length)
1612{
1613 _k_GstAlsaSink *alsa;
1614 gint err;
1615 gint cptr;
1616 gint16 *ptr = data;
1617
1618 alsa = GST_ALSA_SINK2 (asink);
1619
1620 if (alsa->iec958 && alsa->need_swap) {
1621 guint i;
1622
1623 GST_DEBUG_OBJECT (asink, "swapping bytes");
1624 for (i = 0; i < length / 2; i++) {
1625 ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
1626 }
1627 }
1628
1629 GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
1630
1631 cptr = length / alsa->bytes_per_sample;
1632
1633 GST_ALSA_SINK2_LOCK (asink);
1634 while (cptr > 0) {
1635 /* start by doing a blocking wait for free space. Set the timeout
1636 * to 4 times the period time */
1637 err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
1638 if (err < 0) {
1639 GST_DEBUG_OBJECT (asink, "wait timeout, %d", err);
1640 } else {
1641 err = snd_pcm_writei (alsa->handle, ptr, cptr);
1642 }
1643
1644 GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
1645 if (err < 0) {
1646 GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
1647 if (err == -EAGAIN) {
1648 continue;
1649 } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
1650 goto write_error;
1651 }
1652 continue;
1653 }
1654
1655 ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
1656 cptr -= err;
1657 }
1658 GST_ALSA_SINK2_UNLOCK (asink);
1659
1660 return length - (cptr * alsa->bytes_per_sample);
1661
1662write_error:
1663 {
1664 GST_ALSA_SINK2_UNLOCK (asink);
1665 return length; /* skip one period */
1666 }
1667}
1668
1669static guint
1670gst_alsasink2_delay (GstAudioSink * asink)
1671{
1672 _k_GstAlsaSink *alsa;
1673 snd_pcm_sframes_t delay;
1674 int res;
1675
1676 alsa = GST_ALSA_SINK2 (asink);
1677
1678 res = snd_pcm_delay (alsa->handle, &delay);
1679 if (G_UNLIKELY (res < 0)) {
1680 /* on errors, report 0 delay */
1681 GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
1682 delay = 0;
1683 }
1684 if (G_UNLIKELY (delay < 0)) {
1685 /* make sure we never return a negative delay */
1686 GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay");
1687 delay = 0;
1688 }
1689
1690 return delay;
1691}
1692
1693static void
1694gst_alsasink2_reset (GstAudioSink * asink)
1695{
1696 _k_GstAlsaSink *alsa;
1697 gint err;
1698
1699 alsa = GST_ALSA_SINK2 (asink);
1700
1701 GST_ALSA_SINK2_LOCK (asink);
1702 GST_DEBUG_OBJECT (alsa, "drop");
1703 CHECK (snd_pcm_drop (alsa->handle), drop_error);
1704 GST_DEBUG_OBJECT (alsa, "prepare");
1705 CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
1706 GST_DEBUG_OBJECT (alsa, "reset done");
1707 GST_ALSA_SINK2_UNLOCK (asink);
1708
1709 return;
1710
1711 /* ERRORS */
1712drop_error:
1713 {
1714 GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
1715 snd_strerror (err));
1716 GST_ALSA_SINK2_UNLOCK (asink);
1717 return;
1718 }
1719prepare_error:
1720 {
1721 GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
1722 snd_strerror (err));
1723 GST_ALSA_SINK2_UNLOCK (asink);
1724 return;
1725 }
1726}
1727
1728static void
1729gst_alsa_error_wrapper (const char *file, int line, const char *function,
1730 int err, const char *fmt, ...)
1731{
1732}
1733
1734static gboolean
1735plugin_init (GstPlugin * plugin)
1736{
1737 int err;
1738
1739 if (!gst_element_register (plugin, "_k_alsasink", GST_RANK_PRIMARY,
1740 GST_TYPE_ALSA_SINK2))
1741 return FALSE;
1742
1743 err = snd_lib_error_set_handler (gst_alsa_error_wrapper);
1744 if (err != 0)
1745 GST_WARNING ("failed to set alsa error handler");
1746
1747 return TRUE;
1748}
1749
1750#define PACKAGE ""
1751GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR,
1752 GST_VERSION_MINOR,
1753 "_k_alsa",
1754 "ALSA plugin library (hotfixed)",
1755 plugin_init, "0.1", "LGPL", "Phonon-GStreamer", "")
1756#undef PACKAGE
Note: See TracBrowser for help on using the repository browser.