1 /* GStreamer OSS4 audio plugin
2 * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
20 /* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
21 * with newer GLib versions (>= 2.31.0) */
22 #define GLIB_DISABLE_DEPRECATION_WARNINGS
28 #include <sys/ioctl.h>
29 #include <sys/types.h>
35 #include "gst/gst-i18n-plugin.h"
36 #include <gst/audio/audio.h>
38 #include "oss4-audio.h"
39 #include "oss4-property-probe.h"
40 #include "oss4-sink.h"
41 #include "oss4-source.h"
42 #include "oss4-soundcard.h"
44 GST_DEBUG_CATEGORY (oss4mixer_debug);
45 GST_DEBUG_CATEGORY (oss4sink_debug);
46 GST_DEBUG_CATEGORY (oss4src_debug);
47 GST_DEBUG_CATEGORY (oss4_debug);
49 #define GST_CAT_DEFAULT oss4_debug
53 const GstAudioRingBufferFormatType gst_rbfmt;
54 const GstAudioFormat gst_rfmt;
60 static const GstOss4AudioFormat fmt_map[] = {
61 /* note: keep sorted by preference, prefered formats first */
63 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW, 0,
64 AFMT_MU_LAW, "audio/x-mulaw"}, {
65 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW, 0,
66 AFMT_A_LAW, "audio/x-alaw"}, {
67 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S32LE,
68 AFMT_S32_LE, "audio/x-raw"}, {
69 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S32BE,
70 AFMT_S32_BE, "audio/x-raw"}, {
71 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S24_32LE,
72 AFMT_S24_LE, "audio/x-raw"}, {
73 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S24_32BE,
74 AFMT_S24_BE, "audio/x-raw"}, {
75 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S24LE,
76 AFMT_S24_PACKED, "audio/x-raw"}, {
77 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S16LE,
78 AFMT_S16_LE, "audio/x-raw"}, {
79 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S16BE,
80 AFMT_S16_BE, "audio/x-raw"}, {
81 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_U16LE,
82 AFMT_U16_LE, "audio/x-raw"}, {
83 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_U16BE,
84 AFMT_U16_BE, "audio/x-raw"}, {
85 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S8,
86 AFMT_S8, "audio/x-raw"}, {
87 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_U8,
88 AFMT_U8, "audio/x-raw"}
92 /* formats we assume the OSS4 layer can always handle and convert internally */
93 #define CONVERTIBLE_FORMATS ( \
94 AFMT_MU_LAW | AFMT_A_LAW | \
95 AFMT_S32_LE | AFMT_S32_BE | \
96 AFMT_S24_LE | AFMT_S24_BE | \
98 AFMT_S16_LE | AFMT_S16_BE | \
99 AFMT_U16_LE | AFMT_U16_BE | \
103 gst_oss4_append_format_to_caps (const GstOss4AudioFormat * fmt, GstCaps * caps)
107 s = gst_structure_new_empty (fmt->name);
108 if (fmt->gst_rbfmt == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) {
109 gst_structure_set (s, "format", G_TYPE_STRING,
110 gst_audio_format_to_string (fmt->gst_rfmt),
111 "layout", G_TYPE_STRING, "interleaved", NULL);
113 gst_caps_append_structure (caps, s);
117 gst_oss4_audio_get_oss_format (GstAudioRingBufferFormatType fmt,
122 for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
123 if (fmt_map[i].gst_rbfmt == fmt && fmt_map[i].gst_rfmt == rfmt)
124 return fmt_map[i].oss_fmt;
129 /* These are pretty random */
130 #define GST_OSS4_MIN_SAMPLE_RATE 1
131 #define GST_OSS4_MAX_SAMPLE_RATE 192000
134 gst_oss4_audio_detect_rates (GstObject * obj, oss_audioinfo * ai,
138 int minrate, maxrate, i;
140 minrate = ai->min_rate;
141 maxrate = ai->max_rate;
144 if (minrate > maxrate) {
145 GST_WARNING_OBJECT (obj, "min_rate %d > max_rate %d (buggy driver?)",
147 maxrate = ai->min_rate; /* swap */
148 minrate = ai->max_rate;
151 /* limit to something sensible */
152 if (minrate < GST_OSS4_MIN_SAMPLE_RATE)
153 minrate = GST_OSS4_MIN_SAMPLE_RATE;
154 if (maxrate > GST_OSS4_MAX_SAMPLE_RATE)
155 maxrate = GST_OSS4_MAX_SAMPLE_RATE;
157 if (maxrate < GST_OSS4_MIN_SAMPLE_RATE) {
158 GST_WARNING_OBJECT (obj, "max_rate < %d, which makes no sense",
159 GST_OSS4_MIN_SAMPLE_RATE);
163 GST_LOG_OBJECT (obj, "min_rate %d, max_rate %d (originally: %d, %d)",
164 minrate, maxrate, ai->min_rate, ai->max_rate);
166 if ((ai->caps & PCM_CAP_FREERATE)) {
167 GST_LOG_OBJECT (obj, "device supports any sample rate between min and max");
168 if (minrate == maxrate) {
169 g_value_init (&val, G_TYPE_INT);
170 g_value_set_int (&val, maxrate);
172 g_value_init (&val, GST_TYPE_INT_RANGE);
173 gst_value_set_int_range (&val, minrate, maxrate);
176 GST_LOG_OBJECT (obj, "%d sample rates:", ai->nrates);
177 g_value_init (&val, GST_TYPE_LIST);
178 for (i = 0; i < ai->nrates; ++i) {
179 GST_LOG_OBJECT (obj, " rate: %d", ai->rates[i]);
181 if (ai->rates[i] >= minrate && ai->rates[i] <= maxrate) {
182 GValue rate_val = { 0, };
184 g_value_init (&rate_val, G_TYPE_INT);
185 g_value_set_int (&rate_val, ai->rates[i]);
186 gst_value_list_append_value (&val, &rate_val);
187 g_value_unset (&rate_val);
191 if (gst_value_list_get_size (&val) == 0) {
192 g_value_unset (&val);
197 for (i = 0; i < gst_caps_get_size (caps); ++i) {
200 s = gst_caps_get_structure (caps, i);
201 gst_structure_set_value (s, "rate", &val);
204 g_value_unset (&val);
210 gst_oss4_audio_get_channel_layout (GstObject * obj, guint64 layout,
211 guint num_channels, GstAudioChannelPosition * ch_layout)
213 const GstAudioChannelPosition pos_map[16] = {
214 GST_AUDIO_CHANNEL_POSITION_NONE, /* 0 = dunno */
215 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, /* 1 = left */
216 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, /* 2 = right */
217 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, /* 3 = center */
218 GST_AUDIO_CHANNEL_POSITION_LFE1, /* 4 = lfe */
219 GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, /* 5 = left surround */
220 GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, /* 6 = right surround */
221 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, /* 7 = left rear */
222 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, /* 8 = right rear */
223 GST_AUDIO_CHANNEL_POSITION_NONE,
224 GST_AUDIO_CHANNEL_POSITION_NONE,
225 GST_AUDIO_CHANNEL_POSITION_NONE,
226 GST_AUDIO_CHANNEL_POSITION_NONE,
227 GST_AUDIO_CHANNEL_POSITION_NONE,
228 GST_AUDIO_CHANNEL_POSITION_NONE,
229 GST_AUDIO_CHANNEL_POSITION_NONE
231 guint speaker_pos; /* speaker position as defined by OSS */
234 for (i = 0; i < num_channels; ++i) {
235 /* layout contains up to 16 speaker positions, with each taking up 4 bits */
236 speaker_pos = (guint) ((layout >> (i * 4)) & 0x0f);
238 /* if it's a channel position that's unknown to us, set all to NONE and
240 if (G_UNLIKELY (pos_map[speaker_pos] == GST_AUDIO_CHANNEL_POSITION_NONE))
243 ch_layout[i] = pos_map[speaker_pos];
250 /* only warn if it's really unknown, position 0 is ok and represents NONE
251 * (in which case we also just set all others to NONE ignoring the other
252 * positions in the OSS-given layout, because that's what we currently
253 * require in GStreamer) */
254 if (speaker_pos != 0) {
255 GST_WARNING_OBJECT (obj, "unknown OSS channel position %x", ch_layout[i]);
257 for (i = 0; i < num_channels; ++i) {
258 ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
265 gst_oss4_audio_set_ringbuffer_channel_layout (GstObject * obj, gint fd,
266 GstAudioRingBufferSpec * spec)
270 GstAudioRingBuffer *rb;
271 GstAudioChannelPosition ch_layout[8] = { 0, };
273 num_channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
274 if (num_channels < 3 || num_channels > 8)
277 if (spec->type != GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW)
280 if (GST_IS_OSS4_SINK (obj)) {
281 rb = GST_AUDIO_BASE_SINK (obj)->ringbuffer;
282 } else if (GST_IS_OSS4_SOURCE (obj)) {
283 rb = GST_AUDIO_BASE_SRC (obj)->ringbuffer;
285 g_return_if_reached ();
287 /* -1 = get info for currently open device (fd). This will fail with
288 * OSS build <= 1013 because of a bug in OSS */
289 if (ioctl (fd, SNDCTL_DSP_GET_CHNORDER, &layout) == -1) {
290 GST_WARNING_OBJECT (obj, "couldn't query channel layout, assuming default");
291 layout = CHNORDER_NORMAL;
293 GST_DEBUG_OBJECT (obj, "channel layout: %08" G_GINT64_MODIFIER "x", layout);
296 gst_oss4_audio_get_channel_layout (obj, layout, num_channels, ch_layout);
297 gst_audio_ring_buffer_set_channel_positions (rb, ch_layout);
303 gst_oss4_audio_add_channel_layout (GstObject * obj, guint64 layout,
304 guint num_channels, GstStructure * s)
306 GstAudioChannelPosition ch_layout[8] = { 0, };
309 g_return_if_fail (num_channels <= G_N_ELEMENTS (ch_layout));
311 gst_oss4_audio_get_channel_layout (obj, layout, num_channels, ch_layout);
312 if (gst_audio_channel_positions_to_mask (ch_layout, num_channels, FALSE,
314 gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK, mask, NULL);
319 /* arbitrary max. limit */
320 #define GST_OSS4_MIN_CHANNELS 1
321 #define GST_OSS4_MAX_CHANNELS 4096
323 /* takes ownership of the input caps */
325 gst_oss4_audio_detect_channels (GstObject * obj, int fd, oss_audioinfo * ai,
328 const gchar *forced_layout;
329 GstStructure *s = NULL;
331 GstCaps *chan_caps = NULL;
332 GstCaps *out_caps = NULL;
333 int minchans, maxchans;
336 /* GST_OSS4_CHANNEL_LAYOUT environment variable: may be used to force a
337 * particular channel layout (if it contains an odd number of channel
338 * positions it will also make us advertise a channel layout for that
339 * channel count, even if we'd usually skip it; this is especially useful
340 * for folks with 2.1 speakers, I guess) */
341 forced_layout = g_getenv ("GST_OSS4_CHANNEL_LAYOUT");
343 minchans = ai->min_channels;
344 maxchans = ai->max_channels;
347 if (minchans > maxchans) {
348 GST_WARNING_OBJECT (obj, "min_chans %d > max_chans %d (buggy driver?)",
350 maxchans = ai->min_channels; /* swap */
351 minchans = ai->max_channels;
354 /* limit to something sensible */
355 if (minchans < GST_OSS4_MIN_CHANNELS)
356 minchans = GST_OSS4_MIN_CHANNELS;
357 if (maxchans > GST_OSS4_MAX_CHANNELS)
358 maxchans = GST_OSS4_MAX_CHANNELS;
360 if (maxchans < GST_OSS4_MIN_CHANNELS) {
361 GST_WARNING_OBJECT (obj, "max_chans < %d, which makes no sense",
362 GST_OSS4_MIN_CHANNELS);
363 gst_caps_unref (in_caps);
367 GST_LOG_OBJECT (obj, "min_channels %d, max_channels %d (originally: %d, %d)",
368 minchans, maxchans, ai->min_channels, ai->max_channels);
370 chan_caps = gst_caps_new_empty ();
372 /* first do the simple cases: mono + stereo (channel layout implied) */
373 if (minchans == 1 && maxchans == 1)
374 s = gst_structure_new ("x", "channels", G_TYPE_INT, 1, NULL);
375 else if (minchans == 2 && maxchans >= 2)
376 s = gst_structure_new ("x", "channels", G_TYPE_INT, 2, NULL);
377 else if (minchans == 1 && maxchans >= 2)
378 s = gst_structure_new ("x", "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
379 gst_caps_append_structure (chan_caps, s);
382 /* TODO: we assume all drivers use a left/right layout for stereo here */
386 if (ioctl (fd, SNDCTL_DSP_GET_CHNORDER, &layout) == -1) {
387 GST_WARNING_OBJECT (obj, "couldn't query channel layout, assuming default");
388 layout = CHNORDER_NORMAL;
390 GST_DEBUG_OBJECT (obj, "channel layout: %08" G_GINT64_MODIFIER "x", layout);
392 /* e.g. forced 2.1 layout would be GST_OSS4_CHANNEL_LAYOUT=421 */
393 if (forced_layout != NULL && *forced_layout != '\0') {
396 layout_len = strlen (forced_layout);
397 if (layout_len >= minchans && layout_len <= maxchans) {
398 layout = g_ascii_strtoull (forced_layout, NULL, 16);
399 maxchans = layout_len;
400 GST_DEBUG_OBJECT (obj, "forced channel layout: %08" G_GINT64_MODIFIER "x"
401 " ('%s'), maxchans now %d", layout, forced_layout, maxchans);
403 GST_WARNING_OBJECT (obj, "ignoring forced channel layout: layout has %d "
404 "channel positions but maxchans is %d", layout_len, maxchans);
408 /* need to advertise channel layouts for anything >2 and <=8 channels */
409 for (c = MAX (3, minchans); c <= MIN (maxchans, 8); c++) {
410 /* "The min_channels and max_channels fields define the limits for the
411 * number of channels. However some devices don't support all channels
412 * within this range. It's possible that the odd values (3, 5, 7, 9, etc).
413 * are not supported. There is currently no way to check for this other
414 * than checking if SNDCTL_DSP_CHANNELS accepts the requested value.
415 * Another approach is trying to avoid using odd number of channels."
417 * So, we don't know for sure if these odd values are supported:
419 if ((c == 3 || c == 5 || c == 7) && (c != maxchans)) {
420 GST_LOG_OBJECT (obj, "not adding layout with %d channels", c);
424 s = gst_structure_new ("x", "channels", G_TYPE_INT, c, NULL);
425 gst_oss4_audio_add_channel_layout (obj, layout, c, s);
426 GST_LOG_OBJECT (obj, "c=%u, appending struct %" GST_PTR_FORMAT, c, s);
427 gst_caps_append_structure (chan_caps, s);
434 /* for everything >8 channels, CHANNEL_POSITION_NONE is implied. */
435 if (minchans == maxchans || maxchans == 9) {
436 s = gst_structure_new ("x", "channels", G_TYPE_INT, maxchans, NULL);
438 s = gst_structure_new ("x", "channels", GST_TYPE_INT_RANGE,
439 MAX (9, minchans), maxchans, NULL);
441 gst_caps_append_structure (chan_caps, s);
446 GST_LOG_OBJECT (obj, "channel structures: %" GST_PTR_FORMAT, chan_caps);
448 out_caps = gst_caps_new_empty ();
450 /* combine each structure in the input caps with each channel caps struct */
451 for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
452 const GstStructure *in_s;
454 in_s = gst_caps_get_structure (in_caps, i);
456 for (j = 0; j < gst_caps_get_size (chan_caps); ++j) {
457 const GstStructure *chan_s;
460 s = gst_structure_copy (in_s);
461 chan_s = gst_caps_get_structure (chan_caps, j);
462 if ((val = gst_structure_get_value (chan_s, "channels")))
463 gst_structure_set_value (s, "channels", val);
464 if ((val = gst_structure_get_value (chan_s, "channel-mask")))
465 gst_structure_set_value (s, "channel-mask", val);
467 gst_caps_append_structure (out_caps, s);
472 gst_caps_unref (in_caps);
473 gst_caps_unref (chan_caps);
478 gst_oss4_audio_probe_caps (GstObject * obj, int fd)
480 oss_audioinfo ai = { 0, };
483 int nonnative_formats = 0;
486 output = GST_IS_OSS4_SINK (obj);
488 /* -1 = get info for currently open device (fd). This will fail with
489 * OSS build <= 1013 because of a bug in OSS */
491 if (ioctl (fd, SNDCTL_ENGINEINFO, &ai) == -1)
492 goto engineinfo_failed;
494 formats = (output) ? ai.oformats : ai.iformats;
496 GST_LOG_OBJECT (obj, "%s formats : 0x%08x", (output) ? "out" : "in", formats);
498 caps = gst_caps_new_empty ();
500 /* first list all the formats natively supported */
501 for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
502 if ((formats & fmt_map[i].oss_fmt)) {
503 gst_oss4_append_format_to_caps (&fmt_map[i], caps);
504 } else if ((fmt_map[i].oss_fmt & CONVERTIBLE_FORMATS)) {
505 nonnative_formats |= fmt_map[i].oss_fmt;
509 GST_LOG_OBJECT (obj, "adding non-native %s formats : 0x%08x",
510 (output) ? "out" : "in", nonnative_formats);
512 /* now append non-native formats for which conversion would be needed */
513 for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
514 if ((nonnative_formats & fmt_map[i].oss_fmt)) {
515 gst_oss4_append_format_to_caps (&fmt_map[i], caps);
519 caps = gst_caps_simplify (caps);
520 GST_LOG_OBJECT (obj, "formats: %" GST_PTR_FORMAT, caps);
522 if (!gst_oss4_audio_detect_rates (obj, &ai, caps))
523 goto detect_rates_failed;
525 caps = gst_oss4_audio_detect_channels (obj, fd, &ai, caps);
527 goto detect_channels_failed;
529 GST_LOG_OBJECT (obj, "probed caps: %" GST_PTR_FORMAT, caps);
536 GST_WARNING ("ENGINEINFO supported formats probe failed: %s",
542 GST_WARNING_OBJECT (obj, "failed to detect supported sample rates");
543 gst_caps_unref (caps);
546 detect_channels_failed:
548 GST_WARNING_OBJECT (obj, "failed to detect supported channels");
549 gst_caps_unref (caps);
555 gst_oss4_audio_get_template_caps (void)
560 caps = gst_caps_new_empty ();
562 for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
563 gst_oss4_append_format_to_caps (&fmt_map[i], caps);
566 caps = gst_caps_simplify (caps);
568 for (i = 0; i < gst_caps_get_size (caps); ++i) {
571 s = gst_caps_get_structure (caps, i);
572 gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, GST_OSS4_MIN_SAMPLE_RATE,
573 GST_OSS4_MAX_SAMPLE_RATE, "channels", GST_TYPE_INT_RANGE,
574 GST_OSS4_MIN_CHANNELS, GST_OSS4_MAX_CHANNELS, NULL);
580 /* called by gst_oss4_sink_prepare() and gst_oss4_source_prepare() */
582 gst_oss4_audio_set_format (GstObject * obj, int fd,
583 GstAudioRingBufferSpec * spec)
585 struct audio_buf_info info = { 0, };
586 int ofmt, fmt, chans, rate, width;
588 fmt = gst_oss4_audio_get_oss_format (spec->type,
589 GST_AUDIO_INFO_FORMAT (&spec->info));
595 chans = GST_AUDIO_INFO_CHANNELS (&spec->info);
596 rate = GST_AUDIO_INFO_RATE (&spec->info);
597 width = GST_AUDIO_INFO_WIDTH (&spec->info);
599 if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW &&
600 width != 32 && width != 24 && width != 16 && width != 8) {
605 GST_LOG_OBJECT (obj, "setting format: %d", fmt);
606 if (ioctl (fd, SNDCTL_DSP_SETFMT, &fmt) == -1)
607 goto set_format_failed;
610 GST_LOG_OBJECT (obj, "setting channels: %d", chans);
611 if (ioctl (fd, SNDCTL_DSP_CHANNELS, &chans) == -1)
612 goto set_channels_failed;
615 GST_LOG_OBJECT (obj, "setting rate: %d", rate);
616 if (ioctl (fd, SNDCTL_DSP_SPEED, &rate) == -1)
617 goto set_rate_failed;
619 GST_DEBUG_OBJECT (obj, "effective format : %d", fmt);
620 GST_DEBUG_OBJECT (obj, "effective channels : %d", chans);
621 GST_DEBUG_OBJECT (obj, "effective rate : %d", rate);
623 /* make sure format, channels, and rate are the ones we requested */
624 if (fmt != ofmt || chans != GST_AUDIO_INFO_CHANNELS (&spec->info) ||
625 rate != GST_AUDIO_INFO_RATE (&spec->info)) {
626 /* This shouldn't happen, but hey */
627 goto format_not_what_was_requested;
630 if (GST_IS_OSS4_SOURCE (obj)) {
631 if (ioctl (fd, SNDCTL_DSP_GETISPACE, &info) == -1)
632 goto get_ispace_failed;
634 if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
635 goto get_ospace_failed;
638 spec->segsize = info.fragsize;
640 /* we add some extra fragments -- this helps us account for delays due to
641 * conversion buffer, streams queueing, etc. It is important that these
642 * be taken into account because otherwise the delay counter can wind up
643 * being too large, and the buffer will wrap. */
644 spec->segtotal = info.fragstotal + 4;
646 GST_DEBUG_OBJECT (obj, "got segsize: %d, segtotal: %d, value: %08x",
647 spec->segsize, spec->segtotal, info.fragsize);
649 gst_oss4_audio_set_ringbuffer_channel_layout (obj, fd, spec);
656 GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
657 ("Unable to get format (%d, %d)", spec->type,
658 GST_AUDIO_INFO_FORMAT (&spec->info)));
663 GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
664 ("unexpected width %d", width));
669 GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
670 ("DSP_SETFMT(%d) failed: %s", fmt, g_strerror (errno)));
675 GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
676 ("DSP_CHANNELS(%d) failed: %s", chans, g_strerror (errno)));
681 GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
682 ("DSP_SPEED(%d) failed: %s", rate, g_strerror (errno)));
687 GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
688 ("DSP_GETOSPACE failed: %s", g_strerror (errno)));
693 GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
694 ("DSP_GETISPACE failed: %s", g_strerror (errno)));
697 format_not_what_was_requested:
699 GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
700 ("Format actually configured wasn't the one we requested. This is "
701 "probably either a bug in the driver or in the format probing code."));
707 gst_oss4_audio_get_version (GstObject * obj, int fd)
711 /* we use the old ioctl here on purpose instead of SNDCTL_SYSINFO */
712 if (ioctl (fd, OSS_GETVERSION, &ver) < 0) {
713 GST_LOG_OBJECT (obj, "OSS_GETVERSION failed: %s", g_strerror (errno));
716 GST_LOG_OBJECT (obj, "OSS version: 0x%08x", ver);
721 gst_oss4_audio_check_version (GstObject * obj, int fd)
723 return (gst_oss4_audio_get_version (obj, fd) >= GST_MIN_OSS4_VERSION);
727 gst_oss4_audio_find_device (GstObject * oss)
732 arr = gst_oss4_property_probe_get_values (GST_OBJECT (oss), "device");
735 if (arr->n_values > 0) {
738 val = g_value_array_get_nth (arr, 0);
739 ret = g_value_dup_string (val);
741 g_value_array_free (arr);
744 GST_LOG_OBJECT (oss, "first device found: %s", GST_STR_NULL (ret));
750 plugin_init (GstPlugin * plugin)
754 GST_DEBUG_CATEGORY_INIT (oss4sink_debug, "oss4sink", 0, "OSS4 audio sink");
755 GST_DEBUG_CATEGORY_INIT (oss4src_debug, "oss4src", 0, "OSS4 audio src");
756 GST_DEBUG_CATEGORY_INIT (oss4mixer_debug, "oss4mixer", 0, "OSS4 mixer");
757 GST_DEBUG_CATEGORY_INIT (oss4_debug, "oss4", 0, "OSS4 plugin");
760 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
762 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
763 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
766 /* we want a higher rank than the legacy OSS elements have now */
767 rank = GST_RANK_SECONDARY + 1;
769 if (!gst_element_register (plugin, "oss4sink", rank, GST_TYPE_OSS4_SINK) ||
770 !gst_element_register (plugin, "oss4src", rank, GST_TYPE_OSS4_SOURCE)) {
777 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
780 "Open Sound System (OSS) version 4 support for GStreamer",
781 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)