1 /* Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Library General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Library General Public License for more details.
12 *
13 * You should have received a copy of the GNU Library General Public
14 * License along with this library; if not, write to the Free
15 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
16 */
17
18 #include "gstalsa.h"
19
20 #include <gst/audio/audio.h>
21
22 static GstCaps *
gst_alsa_detect_rates(GstObject * obj,snd_pcm_hw_params_t * hw_params,GstCaps * in_caps)23 gst_alsa_detect_rates (GstObject * obj, snd_pcm_hw_params_t * hw_params,
24 GstCaps * in_caps)
25 {
26 GstCaps *caps;
27 guint min, max;
28 gint err, dir, min_rate, max_rate, i;
29
30 GST_LOG_OBJECT (obj, "probing sample rates ...");
31
32 if ((err = snd_pcm_hw_params_get_rate_min (hw_params, &min, &dir)) < 0)
33 goto min_rate_err;
34
35 if ((err = snd_pcm_hw_params_get_rate_max (hw_params, &max, &dir)) < 0)
36 goto max_rate_err;
37
38 min_rate = min;
39 max_rate = max;
40
41 if (min_rate < 4000)
42 min_rate = 4000; /* random 'sensible minimum' */
43
44 if (max_rate <= 0)
45 max_rate = G_MAXINT; /* or maybe just use 192400 or so? */
46 else if (max_rate > 0 && max_rate < 4000)
47 max_rate = MAX (4000, min_rate);
48
49 GST_DEBUG_OBJECT (obj, "Min. rate = %u (%d)", min_rate, min);
50 GST_DEBUG_OBJECT (obj, "Max. rate = %u (%d)", max_rate, max);
51
52 caps = gst_caps_make_writable (in_caps);
53
54 for (i = 0; i < gst_caps_get_size (caps); ++i) {
55 GstStructure *s;
56
57 s = gst_caps_get_structure (caps, i);
58 if (min_rate == max_rate) {
59 gst_structure_set (s, "rate", G_TYPE_INT, min_rate, NULL);
60 } else {
61 gst_structure_set (s, "rate", GST_TYPE_INT_RANGE,
62 min_rate, max_rate, NULL);
63 }
64 }
65
66 return caps;
67
68 /* ERRORS */
69 min_rate_err:
70 {
71 GST_ERROR_OBJECT (obj, "failed to query minimum sample rate: %s",
72 snd_strerror (err));
73 gst_caps_unref (in_caps);
74 return NULL;
75 }
76 max_rate_err:
77 {
78 GST_ERROR_OBJECT (obj, "failed to query maximum sample rate: %s",
79 snd_strerror (err));
80 gst_caps_unref (in_caps);
81 return NULL;
82 }
83 }
84
85 static snd_pcm_format_t
gst_alsa_get_pcm_format(GstAudioFormat fmt)86 gst_alsa_get_pcm_format (GstAudioFormat fmt)
87 {
88 switch (fmt) {
89 case GST_AUDIO_FORMAT_S8:
90 return SND_PCM_FORMAT_S8;
91 case GST_AUDIO_FORMAT_U8:
92 return SND_PCM_FORMAT_U8;
93 /* 16 bit */
94 case GST_AUDIO_FORMAT_S16LE:
95 return SND_PCM_FORMAT_S16_LE;
96 case GST_AUDIO_FORMAT_S16BE:
97 return SND_PCM_FORMAT_S16_BE;
98 case GST_AUDIO_FORMAT_U16LE:
99 return SND_PCM_FORMAT_U16_LE;
100 case GST_AUDIO_FORMAT_U16BE:
101 return SND_PCM_FORMAT_U16_BE;
102 /* 24 bit in low 3 bytes of 32 bits */
103 case GST_AUDIO_FORMAT_S24_32LE:
104 return SND_PCM_FORMAT_S24_LE;
105 case GST_AUDIO_FORMAT_S24_32BE:
106 return SND_PCM_FORMAT_S24_BE;
107 case GST_AUDIO_FORMAT_U24_32LE:
108 return SND_PCM_FORMAT_U24_LE;
109 case GST_AUDIO_FORMAT_U24_32BE:
110 return SND_PCM_FORMAT_U24_BE;
111 /* 24 bit in 3 bytes */
112 case GST_AUDIO_FORMAT_S24LE:
113 return SND_PCM_FORMAT_S24_3LE;
114 case GST_AUDIO_FORMAT_S24BE:
115 return SND_PCM_FORMAT_S24_3BE;
116 case GST_AUDIO_FORMAT_U24LE:
117 return SND_PCM_FORMAT_U24_3LE;
118 case GST_AUDIO_FORMAT_U24BE:
119 return SND_PCM_FORMAT_U24_3BE;
120 /* 32 bit */
121 case GST_AUDIO_FORMAT_S32LE:
122 return SND_PCM_FORMAT_S32_LE;
123 case GST_AUDIO_FORMAT_S32BE:
124 return SND_PCM_FORMAT_S32_BE;
125 case GST_AUDIO_FORMAT_U32LE:
126 return SND_PCM_FORMAT_U32_LE;
127 case GST_AUDIO_FORMAT_U32BE:
128 return SND_PCM_FORMAT_U32_BE;
129 case GST_AUDIO_FORMAT_F32LE:
130 return SND_PCM_FORMAT_FLOAT_LE;
131 case GST_AUDIO_FORMAT_F32BE:
132 return SND_PCM_FORMAT_FLOAT_BE;
133 case GST_AUDIO_FORMAT_F64LE:
134 return SND_PCM_FORMAT_FLOAT64_LE;
135 case GST_AUDIO_FORMAT_F64BE:
136 return SND_PCM_FORMAT_FLOAT64_BE;
137 default:
138 break;
139 }
140 return SND_PCM_FORMAT_UNKNOWN;
141 }
142
143 static gboolean
format_supported(const GValue * format_val,snd_pcm_format_mask_t * mask,int endianness)144 format_supported (const GValue * format_val, snd_pcm_format_mask_t * mask,
145 int endianness)
146 {
147 const GstAudioFormatInfo *finfo;
148 snd_pcm_format_t pcm_format;
149 GstAudioFormat format;
150
151 if (!G_VALUE_HOLDS_STRING (format_val))
152 return FALSE;
153
154 format = gst_audio_format_from_string (g_value_get_string (format_val));
155 if (format == GST_AUDIO_FORMAT_UNKNOWN)
156 return FALSE;
157
158 finfo = gst_audio_format_get_info (format);
159
160 if (GST_AUDIO_FORMAT_INFO_ENDIANNESS (finfo) != endianness
161 && GST_AUDIO_FORMAT_INFO_ENDIANNESS (finfo) != 0)
162 return FALSE;
163
164 pcm_format = gst_alsa_get_pcm_format (format);
165 if (pcm_format == SND_PCM_FORMAT_UNKNOWN)
166 return FALSE;
167
168 return snd_pcm_format_mask_test (mask, pcm_format);
169 }
170
171 static GstCaps *
gst_alsa_detect_formats(GstObject * obj,snd_pcm_hw_params_t * hw_params,GstCaps * in_caps,int endianness)172 gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params,
173 GstCaps * in_caps, int endianness)
174 {
175 snd_pcm_format_mask_t *mask;
176 GstStructure *s;
177 GstCaps *caps;
178 gint i;
179
180 snd_pcm_format_mask_malloc (&mask);
181 snd_pcm_hw_params_get_format_mask (hw_params, mask);
182
183 caps = NULL;
184
185 for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
186 const GValue *format;
187 GValue list = G_VALUE_INIT;
188
189 s = gst_caps_get_structure (in_caps, i);
190 if (!gst_structure_has_name (s, "audio/x-raw")) {
191 GST_DEBUG_OBJECT (obj, "skipping non-raw format");
192 continue;
193 }
194
195 format = gst_structure_get_value (s, "format");
196 if (format == NULL)
197 continue;
198
199 g_value_init (&list, GST_TYPE_LIST);
200
201 if (GST_VALUE_HOLDS_LIST (format)) {
202 gint i, len;
203
204 len = gst_value_list_get_size (format);
205 for (i = 0; i < len; i++) {
206 const GValue *val;
207
208 val = gst_value_list_get_value (format, i);
209 if (format_supported (val, mask, endianness))
210 gst_value_list_append_value (&list, val);
211 }
212 } else if (G_VALUE_HOLDS_STRING (format)) {
213 if (format_supported (format, mask, endianness))
214 gst_value_list_append_value (&list, format);
215 }
216
217 if (gst_value_list_get_size (&list) > 1) {
218 if (caps == NULL)
219 caps = gst_caps_new_empty ();
220 s = gst_structure_copy (s);
221 gst_structure_take_value (s, "format", &list);
222 gst_caps_append_structure (caps, s);
223 } else if (gst_value_list_get_size (&list) == 1) {
224 if (caps == NULL)
225 caps = gst_caps_new_empty ();
226 format = gst_value_list_get_value (&list, 0);
227 s = gst_structure_copy (s);
228 gst_structure_set_value (s, "format", format);
229 gst_caps_append_structure (caps, s);
230 g_value_unset (&list);
231 } else {
232 g_value_unset (&list);
233 }
234 }
235
236 snd_pcm_format_mask_free (mask);
237 gst_caps_unref (in_caps);
238 return caps;
239 }
240
241 /* we don't have channel mappings for more than this many channels */
242 #define GST_ALSA_MAX_CHANNELS 8
243
244 static GstStructure *
get_channel_free_structure(const GstStructure * in_structure)245 get_channel_free_structure (const GstStructure * in_structure)
246 {
247 GstStructure *s = gst_structure_copy (in_structure);
248
249 gst_structure_remove_field (s, "channels");
250 return s;
251 }
252
253 #define ONE_64 G_GUINT64_CONSTANT (1)
254 #define CHANNEL_MASK_STEREO ((ONE_64<<GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT))
255 #define CHANNEL_MASK_2_1 (CHANNEL_MASK_STEREO | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_LFE1))
256 #define CHANNEL_MASK_4_0 (CHANNEL_MASK_STEREO | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_REAR_LEFT) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT))
257 #define CHANNEL_MASK_5_1 (CHANNEL_MASK_4_0 | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_LFE1))
258 #define CHANNEL_MASK_7_1 (CHANNEL_MASK_5_1 | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT))
259
260 static GstCaps *
caps_add_channel_configuration(GstCaps * caps,const GstStructure * in_structure,gint min_chans,gint max_chans)261 caps_add_channel_configuration (GstCaps * caps,
262 const GstStructure * in_structure, gint min_chans, gint max_chans)
263 {
264 GstStructure *s = NULL;
265 gint c;
266
267 if (min_chans == max_chans && max_chans == 1) {
268 s = get_channel_free_structure (in_structure);
269 gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
270 caps = gst_caps_merge_structure (caps, s);
271 return caps;
272 }
273
274 g_assert (min_chans >= 1);
275
276 /* mono and stereo don't need channel configurations */
277 if (min_chans == 2) {
278 s = get_channel_free_structure (in_structure);
279 gst_structure_set (s, "channels", G_TYPE_INT, 2, "channel-mask",
280 GST_TYPE_BITMASK, CHANNEL_MASK_STEREO, NULL);
281 caps = gst_caps_merge_structure (caps, s);
282 } else if (min_chans == 1 && max_chans >= 2) {
283 s = get_channel_free_structure (in_structure);
284 gst_structure_set (s, "channels", G_TYPE_INT, 2, "channel-mask",
285 GST_TYPE_BITMASK, CHANNEL_MASK_STEREO, NULL);
286 caps = gst_caps_merge_structure (caps, s);
287 s = get_channel_free_structure (in_structure);
288 gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
289 caps = gst_caps_merge_structure (caps, s);
290 }
291
292 /* don't know whether to use 2.1 or 3.0 here - but I suspect
293 * alsa might work around that/fix it somehow. Can we tell alsa
294 * what our channel layout is like? */
295 if (max_chans >= 3 && min_chans <= 3) {
296 s = get_channel_free_structure (in_structure);
297 gst_structure_set (s, "channels", G_TYPE_INT, 3, "channel-mask",
298 GST_TYPE_BITMASK, CHANNEL_MASK_2_1, NULL);
299 caps = gst_caps_merge_structure (caps, s);
300 }
301
302 /* everything else (4, 6, 8 channels) needs a channel layout */
303 for (c = MAX (4, min_chans); c <= 8; c += 2) {
304 if (max_chans >= c) {
305 guint64 channel_mask;
306
307 s = get_channel_free_structure (in_structure);
308 switch (c) {
309 case 4:
310 channel_mask = CHANNEL_MASK_4_0;
311 break;
312 case 6:
313 channel_mask = CHANNEL_MASK_5_1;
314 break;
315 case 8:
316 channel_mask = CHANNEL_MASK_7_1;
317 break;
318 default:
319 channel_mask = 0;
320 g_assert_not_reached ();
321 break;
322 }
323 gst_structure_set (s, "channels", G_TYPE_INT, c, "channel-mask",
324 GST_TYPE_BITMASK, channel_mask, NULL);
325 caps = gst_caps_merge_structure (caps, s);
326 }
327 }
328
329 /* NONE layouts for everything else */
330 for (c = MAX (9, min_chans); c <= max_chans; ++c) {
331 s = get_channel_free_structure (in_structure);
332 gst_structure_set (s, "channels", G_TYPE_INT, c, "channel-mask",
333 GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
334 caps = gst_caps_merge_structure (caps, s);
335 }
336 return caps;
337 }
338
339 static GstCaps *
gst_alsa_detect_channels(GstObject * obj,snd_pcm_hw_params_t * hw_params,GstCaps * in_caps)340 gst_alsa_detect_channels (GstObject * obj, snd_pcm_hw_params_t * hw_params,
341 GstCaps * in_caps)
342 {
343 GstCaps *caps;
344 guint min, max;
345 gint min_chans, max_chans;
346 gint err, i;
347
348 GST_LOG_OBJECT (obj, "probing channels ...");
349
350 if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &min)) < 0)
351 goto min_chan_error;
352
353 if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &max)) < 0)
354 goto max_chan_error;
355
356 /* note: the above functions may return (guint) -1 */
357 min_chans = min;
358 max_chans = max;
359
360 if (min_chans < 0) {
361 min_chans = 1;
362 max_chans = GST_ALSA_MAX_CHANNELS;
363 } else if (max_chans < 0) {
364 max_chans = GST_ALSA_MAX_CHANNELS;
365 }
366
367 if (min_chans > max_chans) {
368 gint temp;
369
370 GST_WARNING_OBJECT (obj, "minimum channels > maximum channels (%d > %d), "
371 "please fix your soundcard drivers", min, max);
372 temp = min_chans;
373 min_chans = max_chans;
374 max_chans = temp;
375 }
376
377 /* pro cards seem to return large numbers for min_channels */
378 if (min_chans > GST_ALSA_MAX_CHANNELS) {
379 GST_DEBUG_OBJECT (obj, "min_chans = %u, looks like a pro card", min_chans);
380 if (max_chans < min_chans) {
381 max_chans = min_chans;
382 } else {
383 /* only support [max_chans; max_chans] for these cards for now
384 * to avoid inflating the source caps with loads of structures ... */
385 min_chans = max_chans;
386 }
387 } else {
388 min_chans = MAX (min_chans, 1);
389 max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans);
390 }
391
392 GST_DEBUG_OBJECT (obj, "Min. channels = %d (%d)", min_chans, min);
393 GST_DEBUG_OBJECT (obj, "Max. channels = %d (%d)", max_chans, max);
394
395 caps = gst_caps_new_empty ();
396
397 for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
398 GstStructure *s;
399 GType field_type;
400 gint c_min = min_chans;
401 gint c_max = max_chans;
402
403 s = gst_caps_get_structure (in_caps, i);
404 /* the template caps might limit the number of channels (like alsasrc),
405 * in which case we don't want to return a superset, so hack around this
406 * for the two common cases where the channels are either a fixed number
407 * or a min/max range). Example: alsasrc template has channels = [1,2] and
408 * the detection will claim to support 8 channels for device 'plughw:0' */
409 field_type = gst_structure_get_field_type (s, "channels");
410 if (field_type == G_TYPE_INT) {
411 gst_structure_get_int (s, "channels", &c_min);
412 gst_structure_get_int (s, "channels", &c_max);
413 } else if (field_type == GST_TYPE_INT_RANGE) {
414 const GValue *val;
415
416 val = gst_structure_get_value (s, "channels");
417 c_min = CLAMP (gst_value_get_int_range_min (val), min_chans, max_chans);
418 c_max = CLAMP (gst_value_get_int_range_max (val), min_chans, max_chans);
419 } else {
420 c_min = min_chans;
421 c_max = max_chans;
422 }
423
424 caps = caps_add_channel_configuration (caps, s, c_min, c_max);
425 }
426
427 gst_caps_unref (in_caps);
428
429 return caps;
430
431 /* ERRORS */
432 min_chan_error:
433 {
434 GST_ERROR_OBJECT (obj, "failed to query minimum channel count: %s",
435 snd_strerror (err));
436 return NULL;
437 }
438 max_chan_error:
439 {
440 GST_ERROR_OBJECT (obj, "failed to query maximum channel count: %s",
441 snd_strerror (err));
442 return NULL;
443 }
444 }
445
446 snd_pcm_t *
gst_alsa_open_iec958_pcm(GstObject * obj,gchar * device)447 gst_alsa_open_iec958_pcm (GstObject * obj, gchar * device)
448 {
449 char *iec958_pcm_name = NULL;
450 snd_pcm_t *pcm = NULL;
451 int res;
452 char devstr[256]; /* Storage for local 'default' device string */
453
454 /*
455 * Try and open our default iec958 device. Fall back to searching on card x
456 * if this fails, which should only happen on older alsa setups
457 */
458
459 /* The string will be one of these:
460 * SPDIF_CON: Non-audio flag not set:
461 * spdif:{AES0 0x0 AES1 0x82 AES2 0x0 AES3 0x2}
462 * SPDIF_CON: Non-audio flag set:
463 * spdif:{AES0 0x2 AES1 0x82 AES2 0x0 AES3 0x2}
464 */
465 sprintf (devstr,
466 "%s:{AES0 0x%02x AES1 0x%02x AES2 0x%02x AES3 0x%02x}",
467 device,
468 IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
469 IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
470 0, IEC958_AES3_CON_FS_48000);
471
472 GST_DEBUG_OBJECT (obj, "Generated device string \"%s\"", devstr);
473 iec958_pcm_name = devstr;
474
475 res = snd_pcm_open (&pcm, iec958_pcm_name, SND_PCM_STREAM_PLAYBACK, 0);
476 if (G_UNLIKELY (res < 0)) {
477 GST_DEBUG_OBJECT (obj, "failed opening IEC958 device: %s",
478 snd_strerror (res));
479 pcm = NULL;
480 }
481
482 return pcm;
483 }
484
485
486 /*
487 * gst_alsa_probe_supported_formats:
488 *
489 * Takes the template caps and returns the subset which is actually
490 * supported by this device.
491 *
492 */
493
494 GstCaps *
gst_alsa_probe_supported_formats(GstObject * obj,gchar * device,snd_pcm_t * handle,const GstCaps * template_caps)495 gst_alsa_probe_supported_formats (GstObject * obj, gchar * device,
496 snd_pcm_t * handle, const GstCaps * template_caps)
497 {
498 snd_pcm_hw_params_t *hw_params;
499 snd_pcm_stream_t stream_type;
500 GstCaps *caps;
501 gint err;
502
503 snd_pcm_hw_params_malloc (&hw_params);
504 if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0)
505 goto error;
506
507 stream_type = snd_pcm_stream (handle);
508
509 caps = gst_alsa_detect_formats (obj, hw_params,
510 gst_caps_copy (template_caps), G_BYTE_ORDER);
511
512 /* if there are no formats in native endianness, try non-native as well */
513 if (caps == NULL) {
514 GST_INFO_OBJECT (obj, "no formats in native endianness detected");
515
516 caps = gst_alsa_detect_formats (obj, hw_params,
517 gst_caps_copy (template_caps),
518 (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? G_BIG_ENDIAN : G_LITTLE_ENDIAN);
519
520 if (caps == NULL)
521 goto subroutine_error;
522 }
523
524 if (!(caps = gst_alsa_detect_rates (obj, hw_params, caps)))
525 goto subroutine_error;
526
527 if (!(caps = gst_alsa_detect_channels (obj, hw_params, caps)))
528 goto subroutine_error;
529
530 /* Try opening IEC958 device to see if we can support that format (playback
531 * only for now but we could add SPDIF capture later) */
532 if (stream_type == SND_PCM_STREAM_PLAYBACK) {
533 snd_pcm_t *pcm = gst_alsa_open_iec958_pcm (obj, device);
534
535 if (G_LIKELY (pcm)) {
536 gst_caps_append (caps, gst_caps_from_string (PASSTHROUGH_CAPS));
537 snd_pcm_close (pcm);
538 }
539 }
540
541 snd_pcm_hw_params_free (hw_params);
542 return caps;
543
544 /* ERRORS */
545 error:
546 {
547 GST_ERROR_OBJECT (obj, "failed to query formats: %s", snd_strerror (err));
548 snd_pcm_hw_params_free (hw_params);
549 return NULL;
550 }
551 subroutine_error:
552 {
553 GST_ERROR_OBJECT (obj, "failed to query formats");
554 snd_pcm_hw_params_free (hw_params);
555 gst_caps_replace (&caps, NULL);
556 return NULL;
557 }
558 }
559
560 /* returns the card name when the device number is unknown or -1 */
561 static gchar *
gst_alsa_find_device_name_no_handle(GstObject * obj,const gchar * devcard,gint device_num,snd_pcm_stream_t stream)562 gst_alsa_find_device_name_no_handle (GstObject * obj, const gchar * devcard,
563 gint device_num, snd_pcm_stream_t stream)
564 {
565 snd_ctl_card_info_t *info = NULL;
566 snd_ctl_t *ctl = NULL;
567 gchar *ret = NULL;
568 gint dev = -1;
569
570 GST_LOG_OBJECT (obj, "[%s] device=%d", devcard, device_num);
571
572 if (snd_ctl_open (&ctl, devcard, 0) < 0)
573 return NULL;
574
575 snd_ctl_card_info_malloc (&info);
576 if (snd_ctl_card_info (ctl, info) < 0)
577 goto done;
578
579 if (device_num != -1) {
580 while (snd_ctl_pcm_next_device (ctl, &dev) == 0 && dev >= 0) {
581 if (dev == device_num) {
582 snd_pcm_info_t *pcminfo;
583
584 snd_pcm_info_malloc (&pcminfo);
585 snd_pcm_info_set_device (pcminfo, dev);
586 snd_pcm_info_set_subdevice (pcminfo, 0);
587 snd_pcm_info_set_stream (pcminfo, stream);
588 if (snd_ctl_pcm_info (ctl, pcminfo) < 0) {
589 snd_pcm_info_free (pcminfo);
590 break;
591 }
592
593 ret = (gchar *) snd_pcm_info_get_name (pcminfo);
594 if (ret) {
595 ret = g_strdup (ret);
596 GST_LOG_OBJECT (obj, "name from pcminfo: %s", ret);
597 }
598 snd_pcm_info_free (pcminfo);
599 if (ret)
600 break;
601 }
602 }
603 }
604
605 if (ret == NULL) {
606 char *name = NULL;
607 gint card;
608
609 GST_LOG_OBJECT (obj, "trying card name");
610 card = snd_ctl_card_info_get_card (info);
611 snd_card_get_name (card, &name);
612 ret = g_strdup (name);
613 free (name);
614 }
615
616 done:
617 snd_ctl_card_info_free (info);
618 snd_ctl_close (ctl);
619
620 return ret;
621 }
622
623 gchar *
gst_alsa_find_card_name(GstObject * obj,const gchar * devcard,snd_pcm_stream_t stream)624 gst_alsa_find_card_name (GstObject * obj, const gchar * devcard,
625 snd_pcm_stream_t stream)
626 {
627 return gst_alsa_find_device_name_no_handle (obj, devcard, -1, stream);
628 }
629
630 gchar *
gst_alsa_find_device_name(GstObject * obj,const gchar * device,snd_pcm_t * handle,snd_pcm_stream_t stream)631 gst_alsa_find_device_name (GstObject * obj, const gchar * device,
632 snd_pcm_t * handle, snd_pcm_stream_t stream)
633 {
634 gchar *ret = NULL;
635
636 if (device != NULL) {
637 gchar *dev, *comma;
638 gint devnum;
639
640 GST_LOG_OBJECT (obj, "Trying to get device name from string '%s'", device);
641
642 /* only want name:card bit, but not devices and subdevices */
643 dev = g_strdup (device);
644 if ((comma = strchr (dev, ','))) {
645 *comma = '\0';
646 devnum = atoi (comma + 1);
647 ret = gst_alsa_find_device_name_no_handle (obj, dev, devnum, stream);
648 }
649 g_free (dev);
650 }
651
652 if (ret == NULL && handle != NULL) {
653 snd_pcm_info_t *info;
654
655 GST_LOG_OBJECT (obj, "Trying to get device name from open handle");
656 snd_pcm_info_malloc (&info);
657 snd_pcm_info (handle, info);
658 ret = g_strdup (snd_pcm_info_get_name (info));
659 snd_pcm_info_free (info);
660 }
661
662 GST_LOG_OBJECT (obj, "Device name for device '%s': %s",
663 GST_STR_NULL (device), GST_STR_NULL (ret));
664
665 return ret;
666 }
667
668 /* ALSA channel positions */
669 const GstAudioChannelPosition alsa_position[][8] = {
670 {
671 GST_AUDIO_CHANNEL_POSITION_MONO},
672 {
673 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
674 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
675 {
676 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
677 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
678 GST_AUDIO_CHANNEL_POSITION_LFE1},
679 {
680 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
681 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
682 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
683 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
684 {
685 GST_AUDIO_CHANNEL_POSITION_INVALID,
686 GST_AUDIO_CHANNEL_POSITION_INVALID,
687 GST_AUDIO_CHANNEL_POSITION_INVALID,
688 GST_AUDIO_CHANNEL_POSITION_INVALID,
689 GST_AUDIO_CHANNEL_POSITION_INVALID,
690 GST_AUDIO_CHANNEL_POSITION_INVALID,
691 GST_AUDIO_CHANNEL_POSITION_INVALID,
692 GST_AUDIO_CHANNEL_POSITION_INVALID},
693 {
694 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
695 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
696 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
697 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
698 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
699 GST_AUDIO_CHANNEL_POSITION_LFE1},
700 {
701 GST_AUDIO_CHANNEL_POSITION_INVALID,
702 GST_AUDIO_CHANNEL_POSITION_INVALID,
703 GST_AUDIO_CHANNEL_POSITION_INVALID,
704 GST_AUDIO_CHANNEL_POSITION_INVALID,
705 GST_AUDIO_CHANNEL_POSITION_INVALID,
706 GST_AUDIO_CHANNEL_POSITION_INVALID,
707 GST_AUDIO_CHANNEL_POSITION_INVALID,
708 GST_AUDIO_CHANNEL_POSITION_INVALID},
709 {
710 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
711 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
712 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
713 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
714 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
715 GST_AUDIO_CHANNEL_POSITION_LFE1,
716 GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
717 GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
718 };
719
720 #ifdef SND_CHMAP_API_VERSION
721 /* +1 is to make zero as holes */
722 #define ITEM(x, y) \
723 [SND_CHMAP_ ## x] = GST_AUDIO_CHANNEL_POSITION_ ## y + 1
724
725 static const GstAudioChannelPosition gst_pos[SND_CHMAP_LAST + 1] = {
726 ITEM (MONO, MONO),
727 ITEM (FL, FRONT_LEFT),
728 ITEM (FR, FRONT_RIGHT),
729 ITEM (FC, FRONT_CENTER),
730 ITEM (RL, REAR_LEFT),
731 ITEM (RR, REAR_RIGHT),
732 ITEM (RC, REAR_CENTER),
733 ITEM (LFE, LFE1),
734 ITEM (SL, SIDE_LEFT),
735 ITEM (SR, SIDE_RIGHT),
736 ITEM (FLC, FRONT_LEFT_OF_CENTER),
737 ITEM (FRC, FRONT_RIGHT_OF_CENTER),
738 ITEM (FLW, WIDE_LEFT),
739 ITEM (FRW, WIDE_RIGHT),
740 ITEM (TC, TOP_CENTER),
741 ITEM (TFL, TOP_FRONT_LEFT),
742 ITEM (TFR, TOP_FRONT_RIGHT),
743 ITEM (TFC, TOP_FRONT_CENTER),
744 ITEM (TRL, TOP_REAR_LEFT),
745 ITEM (TRR, TOP_REAR_RIGHT),
746 ITEM (TRC, TOP_REAR_CENTER),
747 ITEM (LLFE, LFE1),
748 ITEM (RLFE, LFE2),
749 ITEM (BC, BOTTOM_FRONT_CENTER),
750 ITEM (BLC, BOTTOM_FRONT_LEFT),
751 ITEM (BRC, BOTTOM_FRONT_LEFT),
752 };
753
754 #undef ITEM
755
756 gboolean
alsa_chmap_to_channel_positions(const snd_pcm_chmap_t * chmap,GstAudioChannelPosition * pos)757 alsa_chmap_to_channel_positions (const snd_pcm_chmap_t * chmap,
758 GstAudioChannelPosition * pos)
759 {
760 int c;
761 gboolean all_mono = TRUE;
762
763 for (c = 0; c < chmap->channels; c++) {
764 if (chmap->pos[c] > SND_CHMAP_LAST)
765 return FALSE;
766 pos[c] = gst_pos[chmap->pos[c]];
767 if (!pos[c])
768 return FALSE;
769 pos[c]--;
770
771 if (pos[c] != GST_AUDIO_CHANNEL_POSITION_MONO)
772 all_mono = FALSE;
773 }
774
775 if (all_mono && chmap->channels > 1) {
776 /* GST_AUDIO_CHANNEL_POSITION_MONO can only be used with 1 channel and
777 * GST_AUDIO_CHANNEL_POSITION_NONE is meant to be used for position-less
778 * multi channels.
779 * Converting as ALSA can only express such configuration by using an array
780 * full of SND_CHMAP_MONO.
781 */
782 for (c = 0; c < chmap->channels; c++)
783 pos[c] = GST_AUDIO_CHANNEL_POSITION_NONE;
784 }
785
786 return TRUE;
787 }
788
789 void
alsa_detect_channels_mapping(GstObject * obj,snd_pcm_t * handle,GstAudioRingBufferSpec * spec,guint channels,GstAudioRingBuffer * buf)790 alsa_detect_channels_mapping (GstObject * obj, snd_pcm_t * handle,
791 GstAudioRingBufferSpec * spec, guint channels, GstAudioRingBuffer * buf)
792 {
793 snd_pcm_chmap_t *chmap;
794 GstAudioChannelPosition pos[8];
795
796 if (spec->type != GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW || channels >= 9)
797 return;
798
799 chmap = snd_pcm_get_chmap (handle);
800 if (!chmap) {
801 GST_LOG_OBJECT (obj, "ALSA driver does not implement channels mapping API");
802 return;
803 }
804
805 if (chmap->channels != channels) {
806 GST_LOG_OBJECT (obj,
807 "got channels mapping for %u channels but stream has %u channels; ignoring",
808 chmap->channels, channels);
809 goto out;
810 }
811
812 if (alsa_chmap_to_channel_positions (chmap, pos)) {
813 #ifndef GST_DISABLE_GST_DEBUG
814 {
815 gchar *tmp = gst_audio_channel_positions_to_string (pos, channels);
816
817 GST_LOG_OBJECT (obj, "got channels mapping %s", tmp);
818 g_free (tmp);
819 }
820 #endif /* GST_DISABLE_GST_DEBUG */
821
822 gst_audio_ring_buffer_set_channel_positions (buf, pos);
823 } else {
824 GST_LOG_OBJECT (obj, "failed to convert ALSA channels mapping");
825 }
826
827 out:
828 free (chmap);
829 }
830 #endif /* SND_CHMAP_API_VERSION */
831