diff options
author | Tim-Philipp Müller <tim.muller@collabora.co.uk> | 2010-05-11 15:33:54 +0100 |
---|---|---|
committer | Tim-Philipp Müller <tim.muller@collabora.co.uk> | 2010-05-11 19:08:45 +0100 |
commit | e800ba112b29f4a9ac4465fd0676a8e3bb701d88 (patch) | |
tree | 86c653935286d35a45d20de3358da6ca972a1da2 /sys | |
parent | bb93d06ca0e7eec762e3c21a0b48a6da9471b5a7 (diff) | |
download | gstreamer-plugins-bad-e800ba112b29f4a9ac4465fd0676a8e3bb701d88.tar.gz |
Remove oss4 plugin
It has been moved to gst-plugins-good.
See #614305.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/Makefile.am | 10 | ||||
-rw-r--r-- | sys/oss4/Makefile.am | 33 | ||||
-rw-r--r-- | sys/oss4/oss4-audio.c | 714 | ||||
-rw-r--r-- | sys/oss4/oss4-audio.h | 43 | ||||
-rw-r--r-- | sys/oss4/oss4-mixer-enum.c | 269 | ||||
-rw-r--r-- | sys/oss4/oss4-mixer-enum.h | 67 | ||||
-rw-r--r-- | sys/oss4/oss4-mixer-slider.c | 311 | ||||
-rw-r--r-- | sys/oss4/oss4-mixer-slider.h | 70 | ||||
-rw-r--r-- | sys/oss4/oss4-mixer-switch.c | 153 | ||||
-rw-r--r-- | sys/oss4/oss4-mixer-switch.h | 65 | ||||
-rw-r--r-- | sys/oss4/oss4-mixer.c | 1850 | ||||
-rw-r--r-- | sys/oss4/oss4-mixer.h | 128 | ||||
-rw-r--r-- | sys/oss4/oss4-property-probe.c | 414 | ||||
-rw-r--r-- | sys/oss4/oss4-property-probe.h | 38 | ||||
-rw-r--r-- | sys/oss4/oss4-sink.c | 699 | ||||
-rw-r--r-- | sys/oss4/oss4-sink.h | 64 | ||||
-rw-r--r-- | sys/oss4/oss4-soundcard.h | 2067 | ||||
-rw-r--r-- | sys/oss4/oss4-source.c | 1006 | ||||
-rw-r--r-- | sys/oss4/oss4-source.h | 89 |
19 files changed, 2 insertions, 8088 deletions
diff --git a/sys/Makefile.am b/sys/Makefile.am index 0f864058f..bbfffcd11 100644 --- a/sys/Makefile.am +++ b/sys/Makefile.am @@ -46,12 +46,6 @@ else DVB_DIR= endif -if USE_OSS4 -OSS4_DIR=oss4 -else -OSS4_DIR= -endif - if USE_OSX_VIDEO OSX_VIDEO_DIR=osxvideo else @@ -82,9 +76,9 @@ else VDPAU_DIR= endif -SUBDIRS = $(ACM_DIR) $(DIRECTDRAW_DIR) $(DIRECTSOUND_DIR) $(DVB_DIR) $(FBDEV_DIR) $(OSS4_DIR) $(OSX_VIDEO_DIR) $(QT_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR) +SUBDIRS = $(ACM_DIR) $(DIRECTDRAW_DIR) $(DIRECTSOUND_DIR) $(DVB_DIR) $(FBDEV_DIR) $(OSX_VIDEO_DIR) $(QT_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR) DIST_SUBDIRS = acmenc acmmp3dec directdraw directsound dvb fbdev dshowdecwrapper dshowsrcwrapper dshowvideosink \ - oss4 osxvideo qtwrapper vcd vdpau wasapi wininet winks winscreencap + osxvideo qtwrapper vcd vdpau wasapi wininet winks winscreencap include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/sys/oss4/Makefile.am b/sys/oss4/Makefile.am deleted file mode 100644 index 955e90375..000000000 --- a/sys/oss4/Makefile.am +++ /dev/null @@ -1,33 +0,0 @@ -plugin_LTLIBRARIES = libgstoss4audio.la - -libgstoss4audio_la_SOURCES = \ - oss4-audio.c \ - oss4-mixer.c \ - oss4-mixer-enum.c \ - oss4-mixer-slider.c \ - oss4-mixer-switch.c \ - oss4-property-probe.c \ - oss4-sink.c \ - oss4-source.c - -libgstoss4audio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) -libgstoss4audio_la_LIBADD = \ - $(GST_PLUGINS_BASE_LIBS) \ - -lgstinterfaces-$(GST_MAJORMINOR) \ - -lgstaudio-$(GST_MAJORMINOR) \ - $(GST_LIBS) -libgstoss4audio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstoss4audio_la_LIBTOOLFLAGS = --tag=disable-static - -noinst_HEADERS = \ - oss4-audio.h \ - oss4-mixer.h \ - oss4-mixer-enum.h \ - oss4-mixer-slider.h \ - oss4-mixer-switch.h \ - oss4-property-probe.h \ - oss4-sink.h \ - oss4-soundcard.h \ - oss4-source.h - - diff --git a/sys/oss4/oss4-audio.c b/sys/oss4/oss4-audio.c deleted file mode 100644 index 09f849596..000000000 --- a/sys/oss4/oss4-audio.c +++ /dev/null @@ -1,714 +0,0 @@ -/* GStreamer OSS4 audio plugin - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> - -#include "gst/gst-i18n-plugin.h" -#include <gst/audio/multichannel.h> - -#include "oss4-audio.h" -#include "oss4-mixer.h" -#include "oss4-property-probe.h" -#include "oss4-sink.h" -#include "oss4-source.h" -#include "oss4-soundcard.h" - -GST_DEBUG_CATEGORY (oss4mixer_debug); -GST_DEBUG_CATEGORY (oss4sink_debug); -GST_DEBUG_CATEGORY (oss4src_debug); -GST_DEBUG_CATEGORY (oss4_debug); - -#define GST_CAT_DEFAULT oss4_debug - -typedef struct -{ - const GstBufferFormat gst_fmt; - const gint oss_fmt; - const gchar name[16]; - const gint depth; - const gint width; - const gint endianness; - const gboolean signedness; -} GstOss4AudioFormat; - -/* *INDENT-OFF* */ -static const GstOss4AudioFormat fmt_map[] = { - /* note: keep sorted by preference, prefered formats first */ - { - GST_MU_LAW, AFMT_MU_LAW, "audio/x-mulaw", 0, 0, 0, FALSE}, { - GST_A_LAW, AFMT_A_LAW, "audio/x-alaw", 0, 0, 0, FALSE}, { - GST_S32_LE, AFMT_S32_LE, "audio/x-raw-int", 32, 32, G_LITTLE_ENDIAN, TRUE}, { - GST_S32_BE, AFMT_S32_BE, "audio/x-raw-int", 32, 32, G_BIG_ENDIAN, TRUE}, { - GST_S24_LE, AFMT_S24_LE, "audio/x-raw-int", 24, 32, G_LITTLE_ENDIAN, TRUE}, { - GST_S24_BE, AFMT_S24_BE, "audio/x-raw-int", 24, 32, G_BIG_ENDIAN, TRUE}, { - GST_S24_3LE, AFMT_S24_PACKED, "audio/x-raw-int", 24, 24, G_LITTLE_ENDIAN, - TRUE}, { - GST_S16_LE, AFMT_S16_LE, "audio/x-raw-int", 16, 16, G_LITTLE_ENDIAN, TRUE}, { - GST_S16_BE, AFMT_S16_BE, "audio/x-raw-int", 16, 16, G_BIG_ENDIAN, TRUE}, { - GST_U16_LE, AFMT_U16_LE, "audio/x-raw-int", 16, 16, G_LITTLE_ENDIAN, FALSE}, { - GST_U16_BE, AFMT_U16_BE, "audio/x-raw-int", 16, 16, G_BIG_ENDIAN, FALSE}, { - GST_S8, AFMT_S8, "audio/x-raw-int", 8, 8, 0, TRUE}, { - GST_U8, AFMT_U8, "audio/x-raw-int", 8, 8, 0, FALSE} -}; -/* *INDENT-ON* */ - -/* formats we assume the OSS4 layer can always handle and convert internally */ -#define CONVERTIBLE_FORMATS ( \ - AFMT_MU_LAW | AFMT_A_LAW | \ - AFMT_S32_LE | AFMT_S32_BE | \ - AFMT_S24_LE | AFMT_S24_BE | \ - AFMT_S24_PACKED | \ - AFMT_S16_LE | AFMT_S16_BE | \ - AFMT_U16_LE | AFMT_U16_BE | \ - AFMT_S8 | AFMT_U8 ) - -static void -gst_oss4_append_format_to_caps (const GstOss4AudioFormat * fmt, GstCaps * caps) -{ - GstStructure *s; - - s = gst_structure_empty_new (fmt->name); - if (fmt->width != 0 && fmt->depth != 0) { - gst_structure_set (s, "width", G_TYPE_INT, fmt->width, "depth", G_TYPE_INT, - fmt->depth, "signed", G_TYPE_BOOLEAN, fmt->signedness, NULL); - } - if (fmt->endianness != 0) { - gst_structure_set (s, "endianness", G_TYPE_INT, fmt->endianness, NULL); - } - gst_caps_append_structure (caps, s); -} - -static gint -gst_oss4_audio_get_oss_format (GstBufferFormat fmt) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) { - if (fmt_map[i].gst_fmt == fmt) - return fmt_map[i].oss_fmt; - } - return 0; -} - -/* These are pretty random */ -#define GST_OSS4_MIN_SAMPLE_RATE 1 -#define GST_OSS4_MAX_SAMPLE_RATE 192000 - -static gboolean -gst_oss4_audio_detect_rates (GstObject * obj, oss_audioinfo * ai, - GstCaps * caps) -{ - GValue val = { 0, }; - int minrate, maxrate, i; - - minrate = ai->min_rate; - maxrate = ai->max_rate; - - /* sanity check */ - if (minrate > maxrate) { - GST_WARNING_OBJECT (obj, "min_rate %d > max_rate %d (buggy driver?)", - minrate, maxrate); - maxrate = ai->min_rate; /* swap */ - minrate = ai->max_rate; - } - - /* limit to something sensible */ - if (minrate < GST_OSS4_MIN_SAMPLE_RATE) - minrate = GST_OSS4_MIN_SAMPLE_RATE; - if (maxrate > GST_OSS4_MAX_SAMPLE_RATE) - maxrate = GST_OSS4_MAX_SAMPLE_RATE; - - if (maxrate < GST_OSS4_MIN_SAMPLE_RATE) { - GST_WARNING_OBJECT (obj, "max_rate < %d, which makes no sense", - GST_OSS4_MIN_SAMPLE_RATE); - return FALSE; - } - - GST_LOG_OBJECT (obj, "min_rate %d, max_rate %d (originally: %d, %d)", - minrate, maxrate, ai->min_rate, ai->max_rate); - - if ((ai->caps & PCM_CAP_FREERATE)) { - GST_LOG_OBJECT (obj, "device supports any sample rate between min and max"); - if (minrate == maxrate) { - g_value_init (&val, G_TYPE_INT); - g_value_set_int (&val, maxrate); - } else { - g_value_init (&val, GST_TYPE_INT_RANGE); - gst_value_set_int_range (&val, minrate, maxrate); - } - } else { - GST_LOG_OBJECT (obj, "%d sample rates:", ai->nrates); - g_value_init (&val, GST_TYPE_LIST); - for (i = 0; i < ai->nrates; ++i) { - GST_LOG_OBJECT (obj, " rate: %d", ai->rates[i]); - - if (ai->rates[i] >= minrate && ai->rates[i] <= maxrate) { - GValue rate_val = { 0, }; - - g_value_init (&rate_val, G_TYPE_INT); - g_value_set_int (&rate_val, ai->rates[i]); - gst_value_list_append_value (&val, &rate_val); - g_value_unset (&rate_val); - } - } - - if (gst_value_list_get_size (&val) == 0) { - g_value_unset (&val); - return FALSE; - } - } - - for (i = 0; i < gst_caps_get_size (caps); ++i) { - GstStructure *s; - - s = gst_caps_get_structure (caps, i); - gst_structure_set_value (s, "rate", &val); - } - - g_value_unset (&val); - - return TRUE; -} - -static void -gst_oss4_audio_add_channel_layout (GstObject * obj, guint64 layout, - guint num_channels, GstStructure * s) -{ - const GstAudioChannelPosition pos_map[16] = { - GST_AUDIO_CHANNEL_POSITION_NONE, /* 0 = dunno */ - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, /* 1 = left */ - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, /* 2 = right */ - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, /* 3 = center */ - GST_AUDIO_CHANNEL_POSITION_LFE, /* 4 = lfe */ - GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, /* 5 = left surround */ - GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, /* 6 = right surround */ - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, /* 7 = left rear */ - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, /* 8 = right rear */ - GST_AUDIO_CHANNEL_POSITION_NONE, - GST_AUDIO_CHANNEL_POSITION_NONE, - GST_AUDIO_CHANNEL_POSITION_NONE, - GST_AUDIO_CHANNEL_POSITION_NONE, - GST_AUDIO_CHANNEL_POSITION_NONE, - GST_AUDIO_CHANNEL_POSITION_NONE, - GST_AUDIO_CHANNEL_POSITION_NONE - }; - GstAudioChannelPosition ch_layout[8] = { 0, }; - guint speaker_pos; /* speaker position as defined by OSS */ - guint i; - - g_return_if_fail (num_channels <= G_N_ELEMENTS (ch_layout)); - - for (i = 0; i < num_channels; ++i) { - /* layout contains up to 16 speaker positions, with each taking up 4 bits */ - speaker_pos = (guint) ((layout >> (i * 4)) & 0x0f); - - /* if it's a channel position that's unknown to us, set all to NONE and - * bail out */ - if (G_UNLIKELY (pos_map[speaker_pos] == GST_AUDIO_CHANNEL_POSITION_NONE)) - goto no_layout; - - ch_layout[i] = pos_map[speaker_pos]; - } - gst_audio_set_channel_positions (s, ch_layout); - return; - -no_layout: - { - /* only warn if it's really unknown, position 0 is ok and represents NONE - * (in which case we also just set all others to NONE ignoring the other - * positions in the OSS-given layout, because that's what we currently - * require in GStreamer) */ - if (speaker_pos != 0) { - GST_WARNING_OBJECT (obj, "unknown OSS channel position %x", ch_layout[i]); - } - for (i = 0; i < num_channels; ++i) { - ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE; - } - gst_audio_set_channel_positions (s, ch_layout); - return; - } -} - -/* arbitrary max. limit */ -#define GST_OSS4_MIN_CHANNELS 1 -#define GST_OSS4_MAX_CHANNELS 4096 - -/* takes ownership of the input caps */ -static GstCaps * -gst_oss4_audio_detect_channels (GstObject * obj, int fd, oss_audioinfo * ai, - GstCaps * in_caps) -{ - const gchar *forced_layout; - GstStructure *s = NULL; - guint64 layout = 0; - GstCaps *chan_caps = NULL; - GstCaps *out_caps = NULL; - int minchans, maxchans; - int c, i, j; - - /* GST_OSS4_CHANNEL_LAYOUT environment variable: may be used to force a - * particular channel layout (if it contains an odd number of channel - * positions it will also make us advertise a channel layout for that - * channel count, even if we'd usually skip it; this is especially useful - * for folks with 2.1 speakers, I guess) */ - forced_layout = g_getenv ("GST_OSS4_CHANNEL_LAYOUT"); - - minchans = ai->min_channels; - maxchans = ai->max_channels; - - /* sanity check */ - if (minchans > maxchans) { - GST_WARNING_OBJECT (obj, "min_chans %d > max_chans %d (buggy driver?)", - minchans, maxchans); - maxchans = ai->min_channels; /* swap */ - minchans = ai->max_channels; - } - - /* limit to something sensible */ - if (minchans < GST_OSS4_MIN_CHANNELS) - minchans = GST_OSS4_MIN_CHANNELS; - if (maxchans > GST_OSS4_MAX_CHANNELS) - maxchans = GST_OSS4_MAX_CHANNELS; - - if (maxchans < GST_OSS4_MIN_CHANNELS) { - GST_WARNING_OBJECT (obj, "max_chans < %d, which makes no sense", - GST_OSS4_MIN_CHANNELS); - gst_caps_unref (in_caps); - return NULL; - } - - GST_LOG_OBJECT (obj, "min_channels %d, max_channels %d (originally: %d, %d)", - minchans, maxchans, ai->min_channels, ai->max_channels); - - chan_caps = gst_caps_new_empty (); - - /* first do the simple cases: mono + stereo (channel layout implied) */ - if (minchans == 1 && maxchans == 1) - s = gst_structure_new ("x", "channels", G_TYPE_INT, 1, NULL); - else if (minchans == 2 && maxchans >= 2) - s = gst_structure_new ("x", "channels", G_TYPE_INT, 2, NULL); - else if (minchans == 1 && maxchans >= 2) - s = gst_structure_new ("x", "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); - gst_caps_append_structure (chan_caps, s); - s = NULL; - - /* TODO: we assume all drivers use a left/right layout for stereo here */ - if (maxchans <= 2) - goto done; - - if (ioctl (fd, SNDCTL_DSP_GET_CHNORDER, &layout) == -1) { - GST_WARNING_OBJECT (obj, "couldn't query channel layout, assuming default"); - layout = CHNORDER_NORMAL; - } - GST_DEBUG_OBJECT (obj, "channel layout: %08" G_GINT64_MODIFIER "x", layout); - - /* e.g. forced 2.1 layout would be GST_OSS4_CHANNEL_LAYOUT=421 */ - if (forced_layout != NULL && *forced_layout != '\0') { - guint layout_len; - - layout_len = strlen (forced_layout); - if (layout_len >= minchans && layout_len <= maxchans) { - layout = g_ascii_strtoull (forced_layout, NULL, 16); - maxchans = layout_len; - GST_DEBUG_OBJECT (obj, "forced channel layout: %08" G_GINT64_MODIFIER "x" - " ('%s'), maxchans now %d", layout, forced_layout, maxchans); - } else { - GST_WARNING_OBJECT (obj, "ignoring forced channel layout: layout has %d " - "channel positions but maxchans is %d", layout_len, maxchans); - } - } - - /* need to advertise channel layouts for anything >2 and <=8 channels */ - for (c = MAX (3, minchans); c <= MIN (maxchans, 8); c++) { - /* "The min_channels and max_channels fields define the limits for the - * number of channels. However some devices don't support all channels - * within this range. It's possible that the odd values (3, 5, 7, 9, etc). - * are not supported. There is currently no way to check for this other - * than checking if SNDCTL_DSP_CHANNELS accepts the requested value. - * Another approach is trying to avoid using odd number of channels." - * - * So, we don't know for sure if these odd values are supported: - */ - if ((c == 3 || c == 5 || c == 7) && (c != maxchans)) { - GST_LOG_OBJECT (obj, "not adding layout with %d channels", c); - continue; - } - - s = gst_structure_new ("x", "channels", G_TYPE_INT, c, NULL); - gst_oss4_audio_add_channel_layout (obj, layout, c, s); - GST_LOG_OBJECT (obj, "c=%u, appending struct %" GST_PTR_FORMAT, c, s); - gst_caps_append_structure (chan_caps, s); - s = NULL; - } - - if (maxchans <= 8) - goto done; - - /* for everything >8 channels, CHANNEL_POSITION_NONE is implied. */ - if (minchans == maxchans || maxchans == 9) { - s = gst_structure_new ("x", "channels", G_TYPE_INT, maxchans, NULL); - } else { - s = gst_structure_new ("x", "channels", GST_TYPE_INT_RANGE, - MAX (9, minchans), maxchans, NULL); - } - gst_caps_append_structure (chan_caps, s); - s = NULL; - -done: - - GST_LOG_OBJECT (obj, "channel structures: %" GST_PTR_FORMAT, chan_caps); - - out_caps = gst_caps_new_empty (); - - /* combine each structure in the input caps with each channel caps struct */ - for (i = 0; i < gst_caps_get_size (in_caps); ++i) { - const GstStructure *in_s; - - in_s = gst_caps_get_structure (in_caps, i); - - for (j = 0; j < gst_caps_get_size (chan_caps); ++j) { - const GstStructure *chan_s; - const GValue *val; - - s = gst_structure_copy (in_s); - chan_s = gst_caps_get_structure (chan_caps, j); - if ((val = gst_structure_get_value (chan_s, "channels"))) - gst_structure_set_value (s, "channels", val); - if ((val = gst_structure_get_value (chan_s, "channel-positions"))) - gst_structure_set_value (s, "channel-positions", val); - - gst_caps_append_structure (out_caps, s); - s = NULL; - } - } - - gst_caps_unref (in_caps); - gst_caps_unref (chan_caps); - return out_caps; -} - -GstCaps * -gst_oss4_audio_probe_caps (GstObject * obj, int fd) -{ - oss_audioinfo ai = { 0, }; - gboolean output; - GstCaps *caps; - int nonnative_formats = 0; - int formats, i; - - output = GST_IS_OSS4_SINK (obj); - - /* -1 = get info for currently open device (fd). This will fail with - * OSS build <= 1013 because of a bug in OSS */ - ai.dev = -1; - if (ioctl (fd, SNDCTL_ENGINEINFO, &ai) == -1) - goto engineinfo_failed; - - formats = (output) ? ai.oformats : ai.iformats; - - GST_LOG_OBJECT (obj, "%s formats : 0x%08x", (output) ? "out" : "in", formats); - - caps = gst_caps_new_empty (); - - /* first list all the formats natively supported */ - for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) { - if ((formats & fmt_map[i].oss_fmt)) { - gst_oss4_append_format_to_caps (&fmt_map[i], caps); - } else if ((fmt_map[i].oss_fmt & CONVERTIBLE_FORMATS)) { - nonnative_formats |= fmt_map[i].oss_fmt; - } - } - - GST_LOG_OBJECT (obj, "adding non-native %s formats : 0x%08x", - (output) ? "out" : "in", nonnative_formats); - - /* now append non-native formats for which conversion would be needed */ - for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) { - if ((nonnative_formats & fmt_map[i].oss_fmt)) { - gst_oss4_append_format_to_caps (&fmt_map[i], caps); - } - } - - gst_caps_do_simplify (caps); - GST_LOG_OBJECT (obj, "formats: %" GST_PTR_FORMAT, caps); - - if (!gst_oss4_audio_detect_rates (obj, &ai, caps)) - goto detect_rates_failed; - - caps = gst_oss4_audio_detect_channels (obj, fd, &ai, caps); - if (caps == NULL) - goto detect_channels_failed; - - GST_LOG_OBJECT (obj, "probed caps: %" GST_PTR_FORMAT, caps); - - return caps; - -/* ERRORS */ -engineinfo_failed: - { - GST_WARNING ("ENGINEINFO supported formats probe failed: %s", - g_strerror (errno)); - return NULL; - } -detect_rates_failed: - { - GST_WARNING_OBJECT (obj, "failed to detect supported sample rates"); - gst_caps_unref (caps); - return NULL; - } -detect_channels_failed: - { - GST_WARNING_OBJECT (obj, "failed to detect supported channels"); - gst_caps_unref (caps); - return NULL; - } -} - -GstCaps * -gst_oss4_audio_get_template_caps (void) -{ - GstCaps *caps; - gint i; - - caps = gst_caps_new_empty (); - - for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) { - gst_oss4_append_format_to_caps (&fmt_map[i], caps); - } - - gst_caps_do_simplify (caps); - - for (i = 0; i < gst_caps_get_size (caps); ++i) { - GstStructure *s; - - s = gst_caps_get_structure (caps, i); - gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, GST_OSS4_MIN_SAMPLE_RATE, - GST_OSS4_MAX_SAMPLE_RATE, "channels", GST_TYPE_INT_RANGE, - GST_OSS4_MIN_CHANNELS, GST_OSS4_MAX_CHANNELS, NULL); - } - - return caps; -} - -/* called by gst_oss4_sink_prepare() and gst_oss4_source_prepare() */ -gboolean -gst_oss4_audio_set_format (GstObject * obj, int fd, GstRingBufferSpec * spec) -{ - struct audio_buf_info info = { 0, }; - int fmt, chans, rate; - - fmt = gst_oss4_audio_get_oss_format (spec->format); - if (fmt == 0) - goto wrong_format; - - if (spec->type == GST_BUFTYPE_LINEAR && spec->width != 32 && - spec->width != 24 && spec->width != 16 && spec->width != 8) { - goto dodgy_width; - } - - /* format */ - GST_LOG_OBJECT (obj, "setting format: %d", fmt); - if (ioctl (fd, SNDCTL_DSP_SETFMT, &fmt) == -1) - goto set_format_failed; - - /* channels */ - GST_LOG_OBJECT (obj, "setting channels: %d", spec->channels); - chans = spec->channels; - if (ioctl (fd, SNDCTL_DSP_CHANNELS, &chans) == -1) - goto set_channels_failed; - - /* rate */ - GST_LOG_OBJECT (obj, "setting rate: %d", spec->rate); - rate = spec->rate; - if (ioctl (fd, SNDCTL_DSP_SPEED, &rate) == -1) - goto set_rate_failed; - - GST_DEBUG_OBJECT (obj, "effective format : %d", fmt); - GST_DEBUG_OBJECT (obj, "effective channels : %d", chans); - GST_DEBUG_OBJECT (obj, "effective rate : %d", rate); - - /* make sure format, channels, and rate are the ones we requested */ - if (fmt != gst_oss4_audio_get_oss_format (spec->format) || - chans != spec->channels || rate != spec->rate) { - /* This shouldn't happen, but hey */ - goto format_not_what_was_requested; - } - - if (GST_IS_OSS4_SOURCE (obj)) { - if (ioctl (fd, SNDCTL_DSP_GETISPACE, &info) == -1) - goto get_ispace_failed; - } else { - if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &info) == -1) - goto get_ospace_failed; - } - - spec->segsize = info.fragsize; - - /* we add some extra fragments -- this helps us account for delays due to - * conversion buffer, streams queueing, etc. It is important that these - * be taken into account because otherwise the delay counter can wind up - * being too large, and the buffer will wrap. */ - spec->segtotal = info.fragstotal + 4; - - spec->bytes_per_sample = (spec->width / 8) * spec->channels; - - GST_DEBUG_OBJECT (obj, "got segsize: %d, segtotal: %d, value: %08x", - spec->segsize, spec->segtotal, info.fragsize); - - return TRUE; - -/* ERRORS */ -wrong_format: - { - GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL), - ("Unable to get format %d", spec->format)); - return FALSE; - } -dodgy_width: - { - GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL), - ("unexpected width %d", spec->width)); - return FALSE; - } -set_format_failed: - { - GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL), - ("DSP_SETFMT(%d) failed: %s", fmt, g_strerror (errno))); - return FALSE; - } -set_channels_failed: - { - GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL), - ("DSP_CHANNELS(%d) failed: %s", chans, g_strerror (errno))); - return FALSE; - } -set_rate_failed: - { - GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL), - ("DSP_SPEED(%d) failed: %s", rate, g_strerror (errno))); - return FALSE; - } -get_ospace_failed: - { - GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL), - ("DSP_GETOSPACE failed: %s", g_strerror (errno))); - return FALSE; - } -get_ispace_failed: - { - GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL), - ("DSP_GETISPACE failed: %s", g_strerror (errno))); - return FALSE; - } -format_not_what_was_requested: - { - GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL), - ("Format actually configured wasn't the one we requested. This is " - "probably either a bug in the driver or in the format probing code.")); - return FALSE; - } -} - -int -gst_oss4_audio_get_version (GstObject * obj, int fd) -{ - gint ver = 0; - - /* we use the old ioctl here on purpose instead of SNDCTL_SYSINFO */ - if (ioctl (fd, OSS_GETVERSION, &ver) < 0) { - GST_LOG_OBJECT (obj, "OSS_GETVERSION failed: %s", g_strerror (errno)); - return -1; - } - GST_LOG_OBJECT (obj, "OSS version: 0x%08x", ver); - return ver; -} - -gboolean -gst_oss4_audio_check_version (GstObject * obj, int fd) -{ - return (gst_oss4_audio_get_version (obj, fd) >= GST_MIN_OSS4_VERSION); -} - -gchar * -gst_oss4_audio_find_device (GstObject * oss) -{ - GValueArray *arr; - gchar *ret = NULL; - - arr = gst_property_probe_probe_and_get_values_name (GST_PROPERTY_PROBE (oss), - "device"); - - if (arr != NULL) { - if (arr->n_values > 0) { - const GValue *val; - - val = g_value_array_get_nth (arr, 0); - ret = g_value_dup_string (val); - } - g_value_array_free (arr); - } - - GST_LOG_OBJECT (oss, "first device found: %s", GST_STR_NULL (ret)); - - return ret; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - gint rank; - - GST_DEBUG_CATEGORY_INIT (oss4sink_debug, "oss4sink", 0, "OSS4 audio sink"); - GST_DEBUG_CATEGORY_INIT (oss4src_debug, "oss4src", 0, "OSS4 audio src"); - GST_DEBUG_CATEGORY_INIT (oss4mixer_debug, "oss4mixer", 0, "OSS4 mixer"); - GST_DEBUG_CATEGORY_INIT (oss4_debug, "oss4", 0, "OSS4 plugin"); - -#ifdef ENABLE_NLS - GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, - LOCALEDIR); - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); -#endif - - /* we want a higher rank than the legacy OSS elements have now */ - rank = GST_RANK_SECONDARY + 1; - - if (!gst_element_register (plugin, "oss4sink", rank, GST_TYPE_OSS4_SINK) || - !gst_element_register (plugin, "oss4src", rank, GST_TYPE_OSS4_SOURCE) || - !gst_element_register (plugin, "oss4mixer", rank, GST_TYPE_OSS4_MIXER)) { - return FALSE; - } - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "oss4", - "Open Sound System (OSS) version 4 support for GStreamer", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/sys/oss4/oss4-audio.h b/sys/oss4/oss4-audio.h deleted file mode 100644 index d22036417..000000000 --- a/sys/oss4/oss4-audio.h +++ /dev/null @@ -1,43 +0,0 @@ -/* GStreamer OSS4 audio plugin - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef GST_OSS4_AUDIO_H -#define GST_OSS4_AUDIO_H_ - -#include <gst/gst.h> -#include <gst/audio/gstringbuffer.h> - -/* This is the minimum version we require */ -#define GST_MIN_OSS4_VERSION 0x040003 - -int gst_oss4_audio_get_version (GstObject * obj, int fd); - -gboolean gst_oss4_audio_check_version (GstObject * obj, int fd); - -GstCaps * gst_oss4_audio_probe_caps (GstObject * obj, int fd); - -gboolean gst_oss4_audio_set_format (GstObject * obj, int fd, GstRingBufferSpec * spec); - -GstCaps * gst_oss4_audio_get_template_caps (void); - -gchar * gst_oss4_audio_find_device (GstObject * oss); - -#endif /* GST_OSS4_AUDIO_H */ - - diff --git a/sys/oss4/oss4-mixer-enum.c b/sys/oss4/oss4-mixer-enum.c deleted file mode 100644 index 4b64bb1fc..000000000 --- a/sys/oss4/oss4-mixer-enum.c +++ /dev/null @@ -1,269 +0,0 @@ -/* GStreamer OSS4 mixer enumeration control - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* An 'enum' in gnome-volume-control / GstMixer is represented by a - * GstMixerOptions object - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/gst-i18n-plugin.h> - -#define NO_LEGACY_MIXER -#include "oss4-mixer.h" -#include "oss4-mixer-enum.h" -#include "oss4-soundcard.h" - -GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug); -#define GST_CAT_DEFAULT oss4mixer_debug - -static GList *gst_oss4_mixer_enum_get_values (GstMixerOptions * options); - -/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */ -G_DEFINE_TYPE (GstOss4MixerEnum, gst_oss4_mixer_enum, GST_TYPE_MIXER_OPTIONS); - -static void -gst_oss4_mixer_enum_init (GstOss4MixerEnum * e) -{ - e->need_update = TRUE; -} - -static void -gst_oss4_mixer_enum_dispose (GObject * obj) -{ - GstMixerOptions *options = GST_MIXER_OPTIONS (obj); - - /* our list is a flat list with constant strings, but the GstMixerOptions - * dispose will try to g_free the contained strings, so clean up the list - * before chaining up to GstMixerOptions */ - g_list_free (options->values); - options->values = NULL; - - G_OBJECT_CLASS (gst_oss4_mixer_enum_parent_class)->dispose (obj); -} - -static void -gst_oss4_mixer_enum_class_init (GstOss4MixerEnumClass * klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - GstMixerOptionsClass *mixeroptions_class = (GstMixerOptionsClass *) klass; - - gobject_class->dispose = gst_oss4_mixer_enum_dispose; - mixeroptions_class->get_values = gst_oss4_mixer_enum_get_values; -} - -static GList * -gst_oss4_mixer_enum_get_values_locked (GstMixerOptions * options) -{ - GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM_CAST (options); - GList *oldlist, *list = NULL; - int i; - - /* if current list of values is empty, update/re-check in any case */ - if (!e->need_update && options->values != NULL) - return options->values; - - GST_LOG_OBJECT (e, "updating available values for %s", e->mc->mixext.extname); - - for (i = 0; i < e->mc->mixext.maxvalue; ++i) { - const gchar *s; - - s = g_quark_to_string (e->mc->enum_vals[i]); - if (MIXEXT_ENUM_IS_AVAILABLE (e->mc->mixext, i)) { - GST_LOG_OBJECT (e, "option '%s' is available", s); - list = g_list_prepend (list, (gpointer) s); - } else { - GST_LOG_OBJECT (e, "option '%s' is currently not available", s); - } - } - - list = g_list_reverse (list); - - /* this is not thread-safe, but then the entire GstMixer API isn't really, - * since we return foo->list and not a copy and don't take any locks, so - * not much we can do here but pray; we're usually either called from _new() - * or from within _get_values() though, so it should be okay. We could use - * atomic ops here, but I'm not sure how much more that really buys us.*/ - oldlist = options->values; /* keep window small */ - options->values = list; - g_list_free (oldlist); - - e->need_update = FALSE; - - return options->values; -} - -static GList * -gst_oss4_mixer_enum_get_values (GstMixerOptions * options) -{ - GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM (options); - GList *list; - - /* we take the lock here mostly to serialise ioctls with the watch thread */ - GST_OBJECT_LOCK (e->mixer); - - list = gst_oss4_mixer_enum_get_values_locked (options); - - GST_OBJECT_UNLOCK (e->mixer); - - return list; -} - -static const gchar * -gst_oss4_mixer_enum_get_current_value (GstOss4MixerEnum * e) -{ - const gchar *cur_val = NULL; - - if (e->mc->enum_vals != NULL && e->mc->last_val < e->mc->mixext.maxvalue) { - cur_val = g_quark_to_string (e->mc->enum_vals[e->mc->last_val]); - } - - return cur_val; -} - -static gboolean -gst_oss4_mixer_enum_update_current (GstOss4MixerEnum * e) -{ - int cur = -1; - - if (!gst_oss4_mixer_get_control_val (e->mixer, e->mc, &cur)) - return FALSE; - - if (cur < 0 || cur >= e->mc->mixext.maxvalue) { - GST_WARNING_OBJECT (e, "read value %d out of bounds [0-%d]", cur, - e->mc->mixext.maxvalue - 1); - e->mc->last_val = 0; - return FALSE; - } - - return TRUE; -} - -gboolean -gst_oss4_mixer_enum_set_option (GstOss4MixerEnum * e, const gchar * value) -{ - GQuark q; - int i; - - q = g_quark_try_string (value); - if (q == 0) { - GST_WARNING_OBJECT (e, "unknown option '%s'", value); - return FALSE; - } - - for (i = 0; i < e->mc->mixext.maxvalue; ++i) { - if (q == e->mc->enum_vals[i]) - break; - } - - if (i >= e->mc->mixext.maxvalue) { - GST_WARNING_OBJECT (e, "option '%s' is not valid for this control", value); - return FALSE; - } - - GST_LOG_OBJECT (e, "option '%s' = %d", value, i); - - if (!MIXEXT_ENUM_IS_AVAILABLE (e->mc->mixext, i)) { - GST_WARNING_OBJECT (e, "option '%s' is not selectable currently", value); - return FALSE; - } - - if (!gst_oss4_mixer_set_control_val (e->mixer, e->mc, i)) { - GST_WARNING_OBJECT (e, "could not set option '%s' (%d)", value, i); - return FALSE; - } - - /* and re-read current value with sanity checks (or could just assign here) */ - gst_oss4_mixer_enum_update_current (e); - - return TRUE; -} - -const gchar * -gst_oss4_mixer_enum_get_option (GstOss4MixerEnum * e) -{ - const gchar *cur_str = NULL; - - if (!gst_oss4_mixer_enum_update_current (e)) { - GST_WARNING_OBJECT (e, "failed to read current value"); - return NULL; - } - - cur_str = gst_oss4_mixer_enum_get_current_value (e); - GST_LOG_OBJECT (e, "%s (%d)", GST_STR_NULL (cur_str), e->mc->last_val); - return cur_str; -} - -GstMixerTrack * -gst_oss4_mixer_enum_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc) -{ - GstOss4MixerEnum *e; - GstMixerTrack *track; - - e = g_object_new (GST_TYPE_OSS4_MIXER_ENUM, "untranslated-label", - mc->mixext.extname, NULL); - e->mixer = mixer; - e->mc = mc; - - track = GST_MIXER_TRACK (e); - - /* caller will set track->label and track->flags */ - - track->num_channels = 0; - track->min_volume = 0; - track->max_volume = 0; - - (void) gst_oss4_mixer_enum_get_values_locked (GST_MIXER_OPTIONS (track)); - - if (!gst_oss4_mixer_enum_update_current (e)) { - GST_WARNING_OBJECT (track, "failed to read current value, returning NULL"); - g_object_unref (track); - track = NULL; - } - - GST_LOG_OBJECT (e, "current value: %d (%s)", e->mc->last_val, - gst_oss4_mixer_enum_get_current_value (e)); - - return track; -} - -/* This is called from the watch thread */ -void -gst_oss4_mixer_enum_process_change_unlocked (GstMixerTrack * track) -{ - GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM_CAST (track); - - gchar *cur; - - if (!e->mc->changed && !e->mc->list_changed) - return; - - if (e->mc->list_changed) { - gst_mixer_options_list_changed (GST_MIXER (e->mixer), - GST_MIXER_OPTIONS (e)); - } - - GST_OBJECT_LOCK (e->mixer); - cur = (gchar *) gst_oss4_mixer_enum_get_current_value (e); - GST_OBJECT_UNLOCK (e->mixer); - - gst_mixer_option_changed (GST_MIXER (e->mixer), GST_MIXER_OPTIONS (e), cur); -} diff --git a/sys/oss4/oss4-mixer-enum.h b/sys/oss4/oss4-mixer-enum.h deleted file mode 100644 index 9fd816690..000000000 --- a/sys/oss4/oss4-mixer-enum.h +++ /dev/null @@ -1,67 +0,0 @@ -/* GStreamer OSS4 mixer on/off enum control - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef GST_OSS4_MIXER_ENUM_H -#define GST_OSS4_MIXER_ENUM_H - -#include <gst/gst.h> -#include <gst/interfaces/mixer.h> - -#include "oss4-mixer.h" - -G_BEGIN_DECLS - -#define GST_TYPE_OSS4_MIXER_ENUM (gst_oss4_mixer_enum_get_type()) -#define GST_OSS4_MIXER_ENUM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER_ENUM,GstOss4MixerEnum)) -#define GST_OSS4_MIXER_ENUM_CAST(obj) ((GstOss4MixerEnum *)(obj)) -#define GST_OSS4_MIXER_ENUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER_ENUM,GstOss4MixerEnumClass)) -#define GST_IS_OSS4_MIXER_ENUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER_ENUM)) -#define GST_IS_OSS4_MIXER_ENUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER_ENUM)) - -typedef struct _GstOss4MixerEnum GstOss4MixerEnum; -typedef struct _GstOss4MixerEnumClass GstOss4MixerEnumClass; - -struct _GstOss4MixerEnum { - GstMixerOptions mixer_option; - - GstOss4MixerControl * mc; - GstOss4Mixer * mixer; /* the mixer we belong to (no ref taken) */ - - gboolean need_update; -}; - -struct _GstOss4MixerEnumClass { - GstMixerOptionsClass mixer_option_class; -}; - -GType gst_oss4_mixer_enum_get_type (void); - -gboolean gst_oss4_mixer_enum_set_option (GstOss4MixerEnum * e, const gchar * value); - -const gchar * gst_oss4_mixer_enum_get_option (GstOss4MixerEnum * e); - -GstMixerTrack * gst_oss4_mixer_enum_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc); - -void gst_oss4_mixer_enum_process_change_unlocked (GstMixerTrack * track); - -G_END_DECLS - -#endif /* GST_OSS4_MIXER_ENUM_H */ - - diff --git a/sys/oss4/oss4-mixer-slider.c b/sys/oss4/oss4-mixer-slider.c deleted file mode 100644 index cdc910495..000000000 --- a/sys/oss4/oss4-mixer-slider.c +++ /dev/null @@ -1,311 +0,0 @@ -/* GStreamer OSS4 mixer slider control - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* A 'slider' in gnome-volume-control / GstMixer is represented by a - * GstMixerTrack with one or more channels. - * - * A slider should be either flagged as INPUT or OUTPUT (mostly because of - * gnome-volume-control being littered with g_asserts for everything it doesn't - * expect). - * - * From mixertrack.h: - * "Input tracks can have 'recording' enabled, which means that any input will - * be hearable into the speakers that are attached to the output. Mute is - * obvious." - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <sys/ioctl.h> - -#include <gst/gst-i18n-plugin.h> - -#define NO_LEGACY_MIXER -#include "oss4-mixer-slider.h" - -GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug); -#define GST_CAT_DEFAULT oss4mixer_debug - -/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */ -G_DEFINE_TYPE (GstOss4MixerSlider, gst_oss4_mixer_slider, GST_TYPE_MIXER_TRACK); - -static void -gst_oss4_mixer_slider_class_init (GstOss4MixerSliderClass * klass) -{ - /* nothing to do here */ -} - -static void -gst_oss4_mixer_slider_init (GstOss4MixerSlider * s) -{ - /* nothing to do here */ -} - -static int -gst_oss4_mixer_slider_pack_volume (GstOss4MixerSlider * s, const gint * volumes) -{ - int val = 0; - - switch (s->mc->mixext.type) { - case MIXT_MONOSLIDER: - case MIXT_MONOSLIDER16: - case MIXT_SLIDER: - val = volumes[0]; - break; - case MIXT_STEREOSLIDER: - val = ((volumes[1] & 0xff) << 8) | (volumes[0] & 0xff); - break; - case MIXT_STEREOSLIDER16: - val = ((volumes[1] & 0xffff) << 16) | (volumes[0] & 0xffff); - break; - default: - g_return_val_if_reached (0); - } - return val; -} - -static void -gst_oss4_mixer_slider_unpack_volume (GstOss4MixerSlider * s, int v, - gint * volumes) -{ - guint32 val; /* use uint so bitshifting the highest bit works right */ - - val = (guint32) v; - switch (s->mc->mixext.type) { - case MIXT_SLIDER: - volumes[0] = val; - break; - case MIXT_MONOSLIDER: - /* oss repeats the value in the upper bits, as if it was stereo */ - volumes[0] = val & 0x00ff; - break; - case MIXT_MONOSLIDER16: - /* oss repeats the value in the upper bits, as if it was stereo */ - volumes[0] = val & 0x0000ffff; - break; - case MIXT_STEREOSLIDER: - volumes[0] = (val & 0x00ff); - volumes[1] = (val & 0xff00) >> 8; - break; - case MIXT_STEREOSLIDER16: - volumes[0] = (val & 0x0000ffff); - volumes[1] = (val & 0xffff0000) >> 16; - break; - default: - g_return_if_reached (); - } -} - -gboolean -gst_oss4_mixer_slider_get_volume (GstOss4MixerSlider * s, gint * volumes) -{ - GstMixerTrack *track = GST_MIXER_TRACK (s); - int v = 0; - - /* if we're supposed to be muted, and don't have an actual mute control - * (ie. 'simulate' the mute), then just return the volume as saved, not - * the actually set volume which is most likely 0 */ - if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE) && !s->mc->mute) { - volumes[0] = s->volumes[0]; - if (track->num_channels == 2) - volumes[1] = s->volumes[1]; - return TRUE; - } - - if (!gst_oss4_mixer_get_control_val (s->mixer, s->mc, &v)) - return FALSE; - - gst_oss4_mixer_slider_unpack_volume (s, v, volumes); - - if (track->num_channels > 1) { - GST_LOG_OBJECT (s, "volume: left=%d, right=%d", volumes[0], volumes[1]); - } else { - GST_LOG_OBJECT (s, "volume: mono=%d", volumes[0]); - } - - return TRUE; -} - -gboolean -gst_oss4_mixer_slider_set_volume (GstOss4MixerSlider * s, const gint * volumes) -{ - GstMixerTrack *track = GST_MIXER_TRACK (s); - int val = 0; - - /* if we're supposed to be muted, and are 'simulating' the mute because - * we don't have a mute control, don't actually change the volume, just - * save it as the new desired volume for later when we get unmuted again */ - if (!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_NO_MUTE)) { - if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE) && !s->mc->mute) - goto done; - } - - val = gst_oss4_mixer_slider_pack_volume (s, volumes); - - if (track->num_channels > 1) { - GST_LOG_OBJECT (s, "left=%d, right=%d", volumes[0], volumes[1]); - } else { - GST_LOG_OBJECT (s, "mono=%d", volumes[0]); - } - - if (!gst_oss4_mixer_set_control_val (s->mixer, s->mc, val)) - return FALSE; - -done: - - s->volumes[0] = volumes[0]; - if (track->num_channels == 2) - s->volumes[1] = volumes[1]; - - return TRUE; -} - -gboolean -gst_oss4_mixer_slider_set_record (GstOss4MixerSlider * s, gboolean record) -{ - /* There doesn't seem to be a way to do this using the OSS4 mixer API, so - * just do nothing here for now. */ - return FALSE; -} - -gboolean -gst_oss4_mixer_slider_set_mute (GstOss4MixerSlider * s, gboolean mute) -{ - GstMixerTrack *track = GST_MIXER_TRACK (s); - gboolean ret; - - /* if the control does not support muting, then do not do anything */ - if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_NO_MUTE)) { - return TRUE; - } - - /* If we do not have a mute control, simulate mute (which is a bit broken, - * since we can not differentiate between capture/playback volume etc., so - * we just assume that setting the volume to 0 would be the same as muting - * this control) */ - if (s->mc->mute == NULL) { - int volume; - - if (mute) { - /* make sure the current volume values get saved. */ - gst_oss4_mixer_slider_get_volume (s, s->volumes); - volume = 0; - } else { - volume = gst_oss4_mixer_slider_pack_volume (s, s->volumes); - } - ret = gst_oss4_mixer_set_control_val (s->mixer, s->mc, volume); - } else { - ret = gst_oss4_mixer_set_control_val (s->mixer, s->mc->mute, !!mute); - } - - if (mute) { - track->flags |= GST_MIXER_TRACK_MUTE; - } else { - track->flags &= ~GST_MIXER_TRACK_MUTE; - } - - return FALSE; -} - -GstMixerTrack * -gst_oss4_mixer_slider_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc) -{ - GstOss4MixerSlider *s; - GstMixerTrack *track; - gint volumes[2] = { 0, }; - - s = g_object_new (GST_TYPE_OSS4_MIXER_SLIDER, "untranslated-label", - mc->mixext.extname, NULL); - - track = GST_MIXER_TRACK (s); - - /* caller will set track->label and track->flags */ - - s->mc = mc; - s->mixer = mixer; - - /* we don't do value scaling but just present a scale of 0-maxvalue */ - track->min_volume = 0; - track->max_volume = mc->mixext.maxvalue; - - switch (mc->mixext.type) { - case MIXT_MONOSLIDER: - case MIXT_MONOSLIDER16: - case MIXT_SLIDER: - track->num_channels = 1; - break; - case MIXT_STEREOSLIDER: - case MIXT_STEREOSLIDER16: - track->num_channels = 2; - break; - default: - g_return_val_if_reached (NULL); - } - - GST_LOG_OBJECT (track, "min=%d, max=%d, channels=%d", track->min_volume, - track->max_volume, track->num_channels); - - if (!gst_oss4_mixer_slider_get_volume (s, volumes)) { - GST_WARNING_OBJECT (track, "failed to read volume, returning NULL"); - g_object_unref (track); - track = NULL; - } - - return track; -} - -/* This is called from the watch thread */ -void -gst_oss4_mixer_slider_process_change_unlocked (GstMixerTrack * track) -{ - GstOss4MixerSlider *s = GST_OSS4_MIXER_SLIDER_CAST (track); - - if (s->mc->mute != NULL && s->mc->mute->changed) { - gst_mixer_mute_toggled (GST_MIXER (s->mixer), track, - !!s->mc->mute->last_val); - } else { - /* nothing to do here, since we don't/can't easily implement the record - * flag */ - } - - if (s->mc->changed) { - gint volumes[2] = { 0, 0 }; - - gst_oss4_mixer_slider_unpack_volume (s, s->mc->last_val, volumes); - - /* if we 'simulate' the mute, update flag when the volume changes */ - if (s->mc->mute == NULL) { - if (volumes[0] == 0 && volumes[1] == 0) { - track->flags |= GST_MIXER_TRACK_MUTE; - } else { - track->flags &= ~GST_MIXER_TRACK_MUTE; - } - } - - gst_mixer_volume_changed (GST_MIXER (s->mixer), track, volumes); - } -} diff --git a/sys/oss4/oss4-mixer-slider.h b/sys/oss4/oss4-mixer-slider.h deleted file mode 100644 index 3bee33f80..000000000 --- a/sys/oss4/oss4-mixer-slider.h +++ /dev/null @@ -1,70 +0,0 @@ -/* GStreamer OSS4 mixer slider control - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef GST_OSS4_MIXER_SLIDER_H -#define GST_OSS4_MIXER_SLIDER_H - -#include <gst/gst.h> -#include <gst/interfaces/mixer.h> - -#include "oss4-mixer.h" - -G_BEGIN_DECLS - -#define GST_TYPE_OSS4_MIXER_SLIDER (gst_oss4_mixer_slider_get_type()) -#define GST_OSS4_MIXER_SLIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER_SLIDER,GstOss4MixerSlider)) -#define GST_OSS4_MIXER_SLIDER_CAST(obj) ((GstOss4MixerSlider *)(obj)) -#define GST_OSS4_MIXER_SLIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER_SLIDER,GstOss4MixerSliderClass)) -#define GST_IS_OSS4_MIXER_SLIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER_SLIDER)) -#define GST_IS_OSS4_MIXER_SLIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER_SLIDER)) - -typedef struct _GstOss4MixerSlider GstOss4MixerSlider; -typedef struct _GstOss4MixerSliderClass GstOss4MixerSliderClass; - -struct _GstOss4MixerSlider { - GstMixerTrack mixer_track; - - GstOss4MixerControl * mc; - GstOss4Mixer * mixer; /* the mixer we belong to (no ref taken) */ - gint volumes[2]; /* left/mono, right */ -}; - -struct _GstOss4MixerSliderClass { - GstMixerTrackClass mixer_track_class; -}; - -GType gst_oss4_mixer_slider_get_type (void); - -GstMixerTrack * gst_oss4_mixer_slider_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc); - -gboolean gst_oss4_mixer_slider_get_volume (GstOss4MixerSlider * s, gint * volumes); - -gboolean gst_oss4_mixer_slider_set_volume (GstOss4MixerSlider * s, const gint * volumes); - -gboolean gst_oss4_mixer_slider_set_record (GstOss4MixerSlider * s, gboolean record); - -gboolean gst_oss4_mixer_slider_set_mute (GstOss4MixerSlider * s, gboolean mute); - -void gst_oss4_mixer_slider_process_change_unlocked (GstMixerTrack * track); - -G_END_DECLS - -#endif /* GST_OSS4_MIXER_SLIDER_H */ - - diff --git a/sys/oss4/oss4-mixer-switch.c b/sys/oss4/oss4-mixer-switch.c deleted file mode 100644 index 11d74b46d..000000000 --- a/sys/oss4/oss4-mixer-switch.c +++ /dev/null @@ -1,153 +0,0 @@ -/* GStreamer OSS4 mixer on/off switch control - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* A simple ON/OFF 'switch' in gnome-volume-control / GstMixer is represented - * by a GstMixerTrack with no channels. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/gst-i18n-plugin.h> - -#define NO_LEGACY_MIXER -#include "oss4-mixer-switch.h" -#include "oss4-soundcard.h" - -GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug); -#define GST_CAT_DEFAULT oss4mixer_debug - -/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */ -G_DEFINE_TYPE (GstOss4MixerSwitch, gst_oss4_mixer_switch, GST_TYPE_MIXER_TRACK); - -static void -gst_oss4_mixer_switch_class_init (GstOss4MixerSwitchClass * klass) -{ - /* nothing to do here */ -} - -static void -gst_oss4_mixer_switch_init (GstOss4MixerSwitch * s) -{ - /* nothing to do here */ -} - -gboolean -gst_oss4_mixer_switch_set (GstOss4MixerSwitch * s, gboolean disabled) -{ - GstMixerTrack *track; - int newval; - - track = GST_MIXER_TRACK (s); - - newval = disabled ? GST_MIXER_TRACK_MUTE : 0; - - if (newval == (track->flags & GST_MIXER_TRACK_MUTE)) { - GST_LOG_OBJECT (s, "switch is already %d, doing nothing", newval); - return TRUE; - } - - if (!gst_oss4_mixer_set_control_val (s->mixer, s->mc, !disabled)) { - GST_WARNING_OBJECT (s, "could not set switch to %d", !disabled); - return FALSE; - } - - if (disabled) { - track->flags |= GST_MIXER_TRACK_MUTE; - } else { - track->flags &= ~GST_MIXER_TRACK_MUTE; - } - - GST_LOG_OBJECT (s, "set switch to %d", newval); - - return TRUE; -} - -gboolean -gst_oss4_mixer_switch_get (GstOss4MixerSwitch * s, gboolean * disabled) -{ - GstMixerTrack *track; - int flag; - int enabled = -1; - - track = GST_MIXER_TRACK (s); - - if (!gst_oss4_mixer_get_control_val (s->mixer, s->mc, &enabled) - || (enabled < 0)) { - GST_WARNING_OBJECT (s, "could not get switch state"); - return FALSE; - } - - flag = (enabled == 0) ? GST_MIXER_TRACK_MUTE : 0; - - if (enabled) { - track->flags &= ~GST_MIXER_TRACK_MUTE; - } else { - track->flags |= GST_MIXER_TRACK_MUTE; - } - *disabled = (enabled == 0); - - return TRUE; -} - -GstMixerTrack * -gst_oss4_mixer_switch_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc) -{ - GstOss4MixerSwitch *s; - GstMixerTrack *track; - int cur = -1; - - s = g_object_new (GST_TYPE_OSS4_MIXER_SWITCH, "untranslated-label", - mc->mixext.extname, NULL); - - s->mixer = mixer; - s->mc = mc; - - track = GST_MIXER_TRACK (s); - - /* caller will set track->label and track->flags */ - - track->num_channels = 0; - track->min_volume = 0; - track->max_volume = 0; - - if (!gst_oss4_mixer_get_control_val (s->mixer, s->mc, &cur) || cur < 0) - return NULL; - - if (cur) { - track->flags &= ~GST_MIXER_TRACK_MUTE; - } else { - track->flags |= GST_MIXER_TRACK_MUTE; - } - - return track; -} - -/* This is called from the watch thread */ -void -gst_oss4_mixer_switch_process_change_unlocked (GstMixerTrack * track) -{ - GstOss4MixerSwitch *s = GST_OSS4_MIXER_SWITCH_CAST (track); - - if (!s->mc->changed) - return; - - gst_mixer_mute_toggled (GST_MIXER (s->mixer), track, !s->mc->last_val); -} diff --git a/sys/oss4/oss4-mixer-switch.h b/sys/oss4/oss4-mixer-switch.h deleted file mode 100644 index a8ab83ffa..000000000 --- a/sys/oss4/oss4-mixer-switch.h +++ /dev/null @@ -1,65 +0,0 @@ -/* GStreamer OSS4 mixer on/off switch control - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef GST_OSS4_MIXER_SWITCH_H -#define GST_OSS4_MIXER_SWITCH_H - -#include <gst/gst.h> -#include <gst/interfaces/mixer.h> - -#include "oss4-mixer.h" - -G_BEGIN_DECLS - -#define GST_TYPE_OSS4_MIXER_SWITCH (gst_oss4_mixer_switch_get_type()) -#define GST_OSS4_MIXER_SWITCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER_SWITCH,GstOss4MixerSwitch)) -#define GST_OSS4_MIXER_SWITCH_CAST(obj) ((GstOss4MixerSwitch *)(obj)) -#define GST_OSS4_MIXER_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER_SWITCH,GstOss4MixerSwitchClass)) -#define GST_IS_OSS4_MIXER_SWITCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER_SWITCH)) -#define GST_IS_OSS4_MIXER_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER_SWITCH)) - -typedef struct _GstOss4MixerSwitch GstOss4MixerSwitch; -typedef struct _GstOss4MixerSwitchClass GstOss4MixerSwitchClass; - -struct _GstOss4MixerSwitch { - GstMixerTrack mixer_track; - - GstOss4MixerControl * mc; - GstOss4Mixer * mixer; /* the mixer we belong to (no ref taken) */ -}; - -struct _GstOss4MixerSwitchClass { - GstMixerTrackClass mixer_track_class; -}; - -GType gst_oss4_mixer_switch_get_type (void); - -gboolean gst_oss4_mixer_switch_set (GstOss4MixerSwitch * s, gboolean enabled); - -gboolean gst_oss4_mixer_switch_get (GstOss4MixerSwitch * s, gboolean * enabled); - -GstMixerTrack * gst_oss4_mixer_switch_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc); - -void gst_oss4_mixer_switch_process_change_unlocked (GstMixerTrack * track); - -G_END_DECLS - -#endif /* GST_OSS4_MIXER_SWITCH_H */ - - diff --git a/sys/oss4/oss4-mixer.c b/sys/oss4/oss4-mixer.c deleted file mode 100644 index f0dab870e..000000000 --- a/sys/oss4/oss4-mixer.c +++ /dev/null @@ -1,1850 +0,0 @@ -/* GStreamer OSS4 mixer implementation - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with mixer library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:element-oss4mixer - * - * This element lets you adjust sound input and output levels with the - * Open Sound System (OSS) version 4. It supports the GstMixer interface, which - * can be used to obtain a list of available mixer tracks. Set the mixer - * element to READY state before using the GstMixer interface on it. - * - * <refsect2> - * <title>Example pipelines</title> - * <para> - * oss4mixer can't be used in a sensible way in gst-launch. - * </para> - * </refsect2> - * - * Since: 0.10.7 - */ - -/* Note: ioctl calls on the same open mixer device are serialised via - * the object lock to make sure we don't do concurrent ioctls from two - * different threads (e.g. app thread and mixer watch thread), since that - * will probably confuse OSS. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <sys/ioctl.h> - -#include <gst/interfaces/mixer.h> -#include <gst/gst-i18n-plugin.h> - -#include <glib/gprintf.h> - -#define NO_LEGACY_MIXER - -#include "oss4-audio.h" -#include "oss4-mixer.h" -#include "oss4-mixer-enum.h" -#include "oss4-mixer-slider.h" -#include "oss4-mixer-switch.h" -#include "oss4-property-probe.h" -#include "oss4-soundcard.h" - -#define GST_OSS4_MIXER_WATCH_INTERVAL 500 /* in millisecs, ie. 0.5s */ - -GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug); -#define GST_CAT_DEFAULT oss4mixer_debug - -#define DEFAULT_DEVICE NULL -#define DEFAULT_DEVICE_NAME NULL - -enum -{ - PROP_0, - PROP_DEVICE, - PROP_DEVICE_NAME -}; - -static void gst_oss4_mixer_init_interfaces (GType type); - -GST_BOILERPLATE_FULL (GstOss4Mixer, gst_oss4_mixer, GstElement, - GST_TYPE_ELEMENT, gst_oss4_mixer_init_interfaces); - -static GstStateChangeReturn gst_oss4_mixer_change_state (GstElement * - element, GstStateChange transition); - -static void gst_oss4_mixer_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_oss4_mixer_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_oss4_mixer_finalize (GObject * object); - -static gboolean gst_oss4_mixer_open (GstOss4Mixer * mixer, - gboolean silent_errors); -static void gst_oss4_mixer_close (GstOss4Mixer * mixer); - -static gboolean gst_oss4_mixer_enum_control_update_enum_list (GstOss4Mixer * m, - GstOss4MixerControl * mc); - -#ifndef GST_DISABLE_GST_DEBUG -static const gchar *mixer_ext_type_get_name (gint type); -static const gchar *mixer_ext_flags_get_string (gint flags); -#endif - -static void -gst_oss4_mixer_base_init (gpointer klass) -{ - gst_element_class_set_details_simple (GST_ELEMENT_CLASS (klass), - "OSS v4 Audio Mixer", "Generic/Audio", - "Control sound input and output levels with OSS4", - "Tim-Philipp Müller <tim centricular net>"); -} - -static void -gst_oss4_mixer_class_init (GstOss4MixerClass * klass) -{ - GstElementClass *element_class; - GObjectClass *gobject_class; - - element_class = (GstElementClass *) klass; - gobject_class = (GObjectClass *) klass; - - gobject_class->finalize = gst_oss4_mixer_finalize; - gobject_class->set_property = gst_oss4_mixer_set_property; - gobject_class->get_property = gst_oss4_mixer_get_property; - - /** - * GstOss4Mixer:device - * - * OSS4 mixer device (e.g. /dev/oss/hdaudio0/mix0 or /dev/mixerN) - * - **/ - g_object_class_install_property (gobject_class, PROP_DEVICE, - g_param_spec_string ("device", "Device", - "OSS mixer device (e.g. /dev/oss/hdaudio0/mix0 or /dev/mixerN) " - "(NULL = use first mixer device found)", DEFAULT_DEVICE, - G_PARAM_READWRITE)); - - /** - * GstOss4Mixer:device-name - * - * Human-readable name of the sound device. May be NULL if the device is - * not open (ie. when the mixer is in NULL state) - * - **/ - g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, - g_param_spec_string ("device-name", "Device name", - "Human-readable name of the sound device", DEFAULT_DEVICE_NAME, - G_PARAM_READABLE)); - - element_class->change_state = GST_DEBUG_FUNCPTR (gst_oss4_mixer_change_state); -} - -static void -gst_oss4_mixer_finalize (GObject * obj) -{ - GstOss4Mixer *mixer = GST_OSS4_MIXER (obj); - - g_free (mixer->device); - - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static void -gst_oss4_mixer_reset (GstOss4Mixer * mixer) -{ - mixer->fd = -1; - mixer->need_update = TRUE; - memset (&mixer->last_mixext, 0, sizeof (oss_mixext)); -} - -static void -gst_oss4_mixer_init (GstOss4Mixer * mixer, GstOss4MixerClass * g_class) -{ - mixer->device = g_strdup (DEFAULT_DEVICE); - mixer->device_name = NULL; - - gst_oss4_mixer_reset (mixer); -} - -static void -gst_oss4_mixer_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstOss4Mixer *mixer = GST_OSS4_MIXER (object); - - switch (prop_id) { - case PROP_DEVICE: - GST_OBJECT_LOCK (mixer); - if (!GST_OSS4_MIXER_IS_OPEN (mixer)) { - g_free (mixer->device); - mixer->device = g_value_dup_string (value); - /* unset any cached device-name */ - g_free (mixer->device_name); - mixer->device_name = NULL; - } else { - g_warning ("%s: can't change \"device\" property while mixer is open", - GST_OBJECT_NAME (mixer)); - } - GST_OBJECT_UNLOCK (mixer); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_oss4_mixer_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstOss4Mixer *mixer = GST_OSS4_MIXER (object); - - switch (prop_id) { - case PROP_DEVICE: - GST_OBJECT_LOCK (mixer); - g_value_set_string (value, mixer->device); - GST_OBJECT_UNLOCK (mixer); - break; - case PROP_DEVICE_NAME: - GST_OBJECT_LOCK (mixer); - /* If device is set, try to retrieve the name even if we're not open */ - if (mixer->fd == -1 && mixer->device != NULL) { - if (gst_oss4_mixer_open (mixer, TRUE)) { - g_value_set_string (value, mixer->device_name); - gst_oss4_mixer_close (mixer); - } else { - g_value_set_string (value, mixer->device_name); - } - } else { - g_value_set_string (value, mixer->device_name); - } - GST_OBJECT_UNLOCK (mixer); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_oss4_mixer_open (GstOss4Mixer * mixer, gboolean silent_errors) -{ - struct oss_mixerinfo mi = { 0, }; - gchar *device; - - g_return_val_if_fail (!GST_OSS4_MIXER_IS_OPEN (mixer), FALSE); - - if (mixer->device) - device = g_strdup (mixer->device); - else - device = gst_oss4_audio_find_device (GST_OBJECT_CAST (mixer)); - - /* desperate times, desperate measures */ - if (device == NULL) - device = g_strdup ("/dev/mixer"); - - GST_INFO_OBJECT (mixer, "Trying to open OSS4 mixer device '%s'", device); - - mixer->fd = open (device, O_RDWR, 0); - if (mixer->fd < 0) - goto open_failed; - - /* Make sure it's OSS4. If it's old OSS, let the old ossmixer handle it */ - if (!gst_oss4_audio_check_version (GST_OBJECT (mixer), mixer->fd)) - goto legacy_oss; - - GST_INFO_OBJECT (mixer, "Opened mixer device '%s', which is mixer %d", - device, mi.dev); - - /* Get device name for currently open fd */ - mi.dev = -1; - if (ioctl (mixer->fd, SNDCTL_MIXERINFO, &mi) == 0) { - mixer->modify_counter = mi.modify_counter; - if (mi.name[0] != '\0') { - mixer->device_name = g_strdup (mi.name); - } - } else { - mixer->modify_counter = 0; - } - - if (mixer->device_name == NULL) { - mixer->device_name = g_strdup ("Unknown"); - } - GST_INFO_OBJECT (mixer, "device name = '%s'", mixer->device_name); - - mixer->open_device = device; - - return TRUE; - - /* ERRORS */ -open_failed: - { - if (!silent_errors) { - GST_ELEMENT_ERROR (mixer, RESOURCE, OPEN_READ_WRITE, - (_("Could not open audio device for mixer control handling.")), - GST_ERROR_SYSTEM); - } else { - GST_DEBUG_OBJECT (mixer, "open failed: %s (ignoring errors)", - g_strerror (errno)); - } - g_free (device); - return FALSE; - } -legacy_oss: - { - gst_oss4_mixer_close (mixer); - if (!silent_errors) { - GST_ELEMENT_ERROR (mixer, RESOURCE, OPEN_READ_WRITE, - (_("Could not open audio device for mixer control handling. " - "This version of the Open Sound System is not supported by this " - "element.")), ("Try the 'ossmixer' element instead")); - } else { - GST_DEBUG_OBJECT (mixer, "open failed: legacy oss (ignoring errors)"); - } - g_free (device); - return FALSE; - } -} - -static void -gst_oss4_mixer_control_free (GstOss4MixerControl * mc) -{ - g_list_free (mc->children); - g_list_free (mc->mute_group); - g_free (mc->enum_vals); - memset (mc, 0, sizeof (GstOss4MixerControl)); - g_free (mc); -} - -static void -gst_oss4_mixer_free_tracks (GstOss4Mixer * mixer) -{ - g_list_foreach (mixer->tracks, (GFunc) g_object_unref, NULL); - g_list_free (mixer->tracks); - mixer->tracks = NULL; - - g_list_foreach (mixer->controls, (GFunc) gst_oss4_mixer_control_free, NULL); - g_list_free (mixer->controls); - mixer->controls = NULL; -} - -static void -gst_oss4_mixer_close (GstOss4Mixer * mixer) -{ - g_free (mixer->device_name); - mixer->device_name = NULL; - - g_free (mixer->open_device); - mixer->open_device = NULL; - - gst_oss4_mixer_free_tracks (mixer); - - if (mixer->fd != -1) { - close (mixer->fd); - mixer->fd = -1; - } - - gst_oss4_mixer_reset (mixer); -} - -static void -gst_oss4_mixer_watch_process_changes (GstOss4Mixer * mixer) -{ - GList *c, *t, *tracks = NULL; - - GST_INFO_OBJECT (mixer, "mixer interface or control changed"); - - /* this is all with the mixer object lock held */ - - /* we go through the list backwards so we can bail out faster when the entire - * interface needs to be rebuilt */ - for (c = g_list_last (mixer->controls); c != NULL; c = c->prev) { - GstOss4MixerControl *mc = c->data; - oss_mixer_value ossval = { 0, }; - - mc->changed = FALSE; - mc->list_changed = FALSE; - - /* not interested in controls we don't expose in the mixer interface */ - if (!mc->used) - continue; - - /* don't try to read a value from controls that don't have one */ - if (mc->mixext.type == MIXT_DEVROOT || mc->mixext.type == MIXT_GROUP) - continue; - - /* is this an enum control whose list may change? */ - if (mc->mixext.type == MIXT_ENUM && mc->enum_version != 0) { - if (gst_oss4_mixer_enum_control_update_enum_list (mixer, mc)) - mc->list_changed = TRUE; - } - - ossval.dev = mc->mixext.dev; - ossval.ctrl = mc->mixext.ctrl; - ossval.timestamp = mc->mixext.timestamp; - - if (ioctl (mixer->fd, SNDCTL_MIX_READ, &ossval) == -1) { - if (errno == EIDRM || errno == EFAULT) { - GST_DEBUG ("%s has disappeared", mc->mixext.extname); - goto mixer_changed; - } - GST_WARNING_OBJECT (mixer, "MIX_READ failed: %s", g_strerror (errno)); - /* just ignore, move on to next one */ - continue; - } - - if (ossval.value == mc->last_val) { /* no change */ - /* GST_LOG_OBJECT (mixer, "%s hasn't changed", mc->mixext.extname); */ - continue; - } - - mc->last_val = ossval.value; - GST_LOG_OBJECT (mixer, "%s changed value to %u 0x%08x", - mc->mixext.extname, ossval.value, ossval.value); - mc->changed = TRUE; - } - - /* copy list and take track refs, so we can safely drop the object lock, - * which we need to do to be able to post messages on the bus */ - tracks = g_list_copy (mixer->tracks); - g_list_foreach (tracks, (GFunc) g_object_ref, NULL); - - GST_OBJECT_UNLOCK (mixer); - - /* since we don't know (or want to know exactly) which controls belong to - * which track, we just go through the tracks one-by-one now and make them - * check themselves if any of their controls have changed and which messages - * to post on the bus as a result */ - for (t = tracks; t != NULL; t = t->next) { - GstMixerTrack *track = t->data; - - if (GST_IS_OSS4_MIXER_SLIDER (track)) { - gst_oss4_mixer_slider_process_change_unlocked (track); - } else if (GST_IS_OSS4_MIXER_SWITCH (track)) { - gst_oss4_mixer_switch_process_change_unlocked (track); - } else if (GST_IS_OSS4_MIXER_ENUM (track)) { - gst_oss4_mixer_enum_process_change_unlocked (track); - } - - g_object_unref (track); - } - g_list_free (tracks); - - GST_OBJECT_LOCK (mixer); - return; - -mixer_changed: - { - GST_OBJECT_UNLOCK (mixer); - gst_mixer_mixer_changed (GST_MIXER (mixer)); - GST_OBJECT_LOCK (mixer); - return; - } -} - -/* This thread watches the mixer for changes in a somewhat inefficient way - * (running an ioctl every half second or so). This is still better and - * cheaper than apps polling all tracks for changes a few times a second - * though. Needs more thought. There's probably (hopefully) a way to get - * notifications via the fd directly somehow. */ -static gpointer -gst_oss4_mixer_watch_thread (gpointer thread_data) -{ - GstOss4Mixer *mixer = GST_OSS4_MIXER_CAST (thread_data); - - GST_DEBUG_OBJECT (mixer, "watch thread running"); - - GST_OBJECT_LOCK (mixer); - while (!mixer->watch_shutdown) { - oss_mixerinfo mi = { 0, }; - GTimeVal tv; - - mi.dev = -1; - if (ioctl (mixer->fd, SNDCTL_MIXERINFO, &mi) == 0) { - if (mixer->modify_counter != mi.modify_counter) { - /* GST_LOG ("processing changes"); */ - gst_oss4_mixer_watch_process_changes (mixer); - mixer->modify_counter = mi.modify_counter; - } else { - /* GST_LOG ("no changes"); */ - } - } else { - GST_WARNING_OBJECT (mixer, "MIXERINFO failed: %s", g_strerror (errno)); - } - - /* we could move the _get_current_time out of the loop and just do the - * add in ever iteration, which would be less exact, but who cares */ - g_get_current_time (&tv); - g_time_val_add (&tv, GST_OSS4_MIXER_WATCH_INTERVAL * 1000); - (void) g_cond_timed_wait (mixer->watch_cond, GST_OBJECT_GET_LOCK (mixer), - &tv); - } - GST_OBJECT_UNLOCK (mixer); - - GST_DEBUG_OBJECT (mixer, "watch thread done"); - gst_object_unref (mixer); - return NULL; -} - -/* call with object lock held */ -static void -gst_oss4_mixer_wake_up_watch_task (GstOss4Mixer * mixer) -{ - GST_LOG_OBJECT (mixer, "signalling watch thread to wake up"); - g_cond_signal (mixer->watch_cond); -} - -static void -gst_oss4_mixer_stop_watch_task (GstOss4Mixer * mixer) -{ - if (mixer->watch_thread) { - GST_OBJECT_LOCK (mixer); - mixer->watch_shutdown = TRUE; - GST_LOG_OBJECT (mixer, "signalling watch thread to stop"); - g_cond_signal (mixer->watch_cond); - GST_OBJECT_UNLOCK (mixer); - GST_LOG_OBJECT (mixer, "waiting for watch thread to join"); - g_thread_join (mixer->watch_thread); - GST_DEBUG_OBJECT (mixer, "watch thread stopped"); - mixer->watch_thread = NULL; - } - - if (mixer->watch_cond) { - g_cond_free (mixer->watch_cond); - mixer->watch_cond = NULL; - } -} - -static void -gst_oss4_mixer_start_watch_task (GstOss4Mixer * mixer) -{ - GError *err = NULL; - - mixer->watch_cond = g_cond_new (); - mixer->watch_shutdown = FALSE; - - mixer->watch_thread = g_thread_create (gst_oss4_mixer_watch_thread, - gst_object_ref (mixer), TRUE, &err); - - if (mixer->watch_thread == NULL) { - GST_ERROR_OBJECT (mixer, "Could not create watch thread: %s", err->message); - g_cond_free (mixer->watch_cond); - mixer->watch_cond = NULL; - g_error_free (err); - } -} - -static GstStateChangeReturn -gst_oss4_mixer_change_state (GstElement * element, GstStateChange transition) -{ - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstOss4Mixer *mixer = GST_OSS4_MIXER (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_oss4_mixer_open (mixer, FALSE)) - return GST_STATE_CHANGE_FAILURE; - gst_oss4_mixer_start_watch_task (mixer); - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - gst_oss4_mixer_stop_watch_task (mixer); - gst_oss4_mixer_close (mixer); - break; - default: - break; - } - - return ret; -} - -/* === GstMixer interface === */ - -static inline gboolean -gst_oss4_mixer_contains_track (GstMixer * mixer, GstMixerTrack * track) -{ - return (g_list_find (GST_OSS4_MIXER (mixer)->tracks, track) != NULL); -} - -static inline gboolean -gst_oss4_mixer_contains_options (GstMixer * mixer, GstMixerOptions * options) -{ - return (g_list_find (GST_OSS4_MIXER (mixer)->tracks, options) != NULL); -} - -static void -gst_oss4_mixer_post_mixer_changed_msg (GstOss4Mixer * mixer) -{ - /* only post mixer-changed message once */ - if (!mixer->need_update) { - gst_mixer_mixer_changed (GST_MIXER (mixer)); - mixer->need_update = TRUE; - } -} - -/* call with mixer object lock held to serialise ioctl */ -gboolean -gst_oss4_mixer_get_control_val (GstOss4Mixer * mixer, GstOss4MixerControl * mc, - int *val) -{ - oss_mixer_value ossval = { 0, }; - - if (GST_OBJECT_TRYLOCK (mixer)) { - GST_ERROR ("must be called with mixer lock held"); - GST_OBJECT_UNLOCK (mixer); - } - - ossval.dev = mc->mixext.dev; - ossval.ctrl = mc->mixext.ctrl; - ossval.timestamp = mc->mixext.timestamp; - - if (ioctl (mixer->fd, SNDCTL_MIX_READ, &ossval) == -1) { - if (errno == EIDRM) { - GST_DEBUG_OBJECT (mixer, "MIX_READ failed: mixer interface has changed"); - gst_oss4_mixer_post_mixer_changed_msg (mixer); - } else { - GST_WARNING_OBJECT (mixer, "MIX_READ failed: %s", g_strerror (errno)); - } - *val = 0; - mc->last_val = 0; - return FALSE; - } - - *val = ossval.value; - mc->last_val = ossval.value; - GST_LOG_OBJECT (mixer, "got value 0x%08x from %s)", *val, mc->mixext.extname); - return TRUE; -} - -/* call with mixer object lock held to serialise ioctl */ -gboolean -gst_oss4_mixer_set_control_val (GstOss4Mixer * mixer, GstOss4MixerControl * mc, - int val) -{ - oss_mixer_value ossval = { 0, }; - - ossval.dev = mc->mixext.dev; - ossval.ctrl = mc->mixext.ctrl; - ossval.timestamp = mc->mixext.timestamp; - ossval.value = val; - - if (GST_OBJECT_TRYLOCK (mixer)) { - GST_ERROR ("must be called with mixer lock held"); - GST_OBJECT_UNLOCK (mixer); - } - - if (ioctl (mixer->fd, SNDCTL_MIX_WRITE, &ossval) == -1) { - if (errno == EIDRM) { - GST_LOG_OBJECT (mixer, "MIX_WRITE failed: mixer interface has changed"); - gst_oss4_mixer_post_mixer_changed_msg (mixer); - } else { - GST_WARNING_OBJECT (mixer, "MIX_WRITE failed: %s", g_strerror (errno)); - } - return FALSE; - } - - mc->last_val = val; - GST_LOG_OBJECT (mixer, "set value 0x%08x on %s", val, mc->mixext.extname); - return TRUE; -} - -#if 0 -static gchar * -gst_oss4_mixer_control_get_pretty_name (GstOss4MixerControl * mc) -{ - gchar *name; - - const gchar *name, *u; - - /* "The id field is the original name given by the driver when it called - * mixer_ext_create_control. This name can be used by fully featured GUI - * mixers. However this name should be downshifted and cut before the last - * underscore ("_") to get the proper name. For example mixer control name - * created as "MYDRV_MAINVOL" will become just "mainvol" after this - * transformation." */ - name = mc->mixext.extname; - u = MAX (strrchr (name, '_'), strrchr (name, '.')); - if (u != NULL) - name = u + 1; - - /* maybe capitalize the first letter? */ - return g_ascii_strdown (name, -1); - /* the .id thing doesn't really seem to work right, ie. for some sliders - * it's just '-' so you have to use the name of the parent control etc. - * let's not use it for now, much too painful. */ - if (g_str_has_prefix (mc->mixext.extname, "misc.")) - name = g_strdup (mc->mixext.extname + 5); - else - name = g_strdup (mc->mixext.extname); - /* chop off trailing digit (only one for now) */ - if (strlen (name) > 0 && g_ascii_isdigit (name[strlen (name) - 1])) - name[strlen (name) - 1] = '\0'; - g_strdelimit (name, ".", ' '); - return name; -} -#endif - -/* these translations are a bit ad-hoc and horribly incomplete; it is not - * really going to work this way with all the different chipsets and drivers. - * We also use these for translating option values. */ -static struct -{ - const gchar oss_name[32]; - const gchar *label; -} labels[] = { - { - "volume", N_("Volume")}, { - "master", N_("Master")}, { - "front", N_("Front")}, { - "rear", N_("Rear")}, { - "headphones", N_("Headphones")}, { - "center", N_("Center")}, { - "lfe", N_("LFE")}, { - "surround", N_("Surround")}, { - "side", N_("Side")}, { - "speaker", N_("Built-in Speaker")}, { - "aux1-out", N_("AUX 1 Out")}, { - "aux2-out", N_("AUX 2 Out")}, { - "aux-out", N_("AUX Out")}, { - "bass", N_("Bass")}, { - "treble", N_("Treble")}, { - "3d-depth", N_("3D Depth")}, { - "3d-center", N_("3D Center")}, { - "3d-enhance", N_("3D Enhance")}, { - "phone", N_("Telephone")}, { - "mic", N_("Microphone")}, { - "line-out", N_("Line Out")}, { - "line-in", N_("Line In")}, { - "linein", N_("Line In")}, { - "cd", N_("Internal CD")}, { - "video", N_("Video In")}, { - "aux1-in", N_("AUX 1 In")}, { - "aux2-in", N_("AUX 2 In")}, { - "aux-in", N_("AUX In")}, { - "pcm", N_("PCM")}, { - "record-gain", N_("Record Gain")}, { - "igain", N_("Record Gain")}, { - "ogain", N_("Output Gain")}, { - "micboost", N_("Microphone Boost")}, { - "loopback", N_("Loopback")}, { - "diag", N_("Diagnostic")}, { - "loudness", N_("Bass Boost")}, { - "outputs", N_("Playback Ports")}, { - "input", N_("Input")}, { - "inputs", N_("Record Source")}, { - "record-source", N_("Record Source")}, { - "monitor-source", N_("Monitor Source")}, { - "beep", N_("Keyboard Beep")}, { - "monitor-gain", N_("Monitor")}, { - "stereo-simulate", N_("Simulate Stereo")}, { - "stereo", N_("Stereo")}, { - "multich", N_("Surround Sound")}, { - "mic-gain", N_("Microphone Gain")}, { - "speaker-source", N_("Speaker Source")}, { - "mic-source", N_("Microphone Source")}, { - "jack", N_("Jack")}, { - "center/lfe", N_("Center / LFE")}, { - "stereo-mix", N_("Stereo Mix")}, { - "mono-mix", N_("Mono Mix")}, { - "input-mix", N_("Input Mix")}, { - "spdif-in", N_("SPDIF In")}, { - "spdif-out", N_("SPDIF Out")}, { - "mic1", N_("Microphone 1")}, { - "mic2", N_("Microphone 2")}, { - "digital-out", N_("Digital Out")}, { - "digital-in", N_("Digital In")}, { - "hdmi", N_("HDMI")}, { - "modem", N_("Modem")}, { - "handset", N_("Handset")}, { - "other", N_("Other")}, { - "stereo", N_("Stereo")}, { - "none", N_("None")}, { - "on", N_("On")}, { - "off", N_("Off")}, { - "mute", N_("Mute")}, { - "fast", N_("Fast")}, { - "very-low", N_("Very Low")}, { - "low", N_("Low")}, { - "medium", N_("Medium")}, { - "high", N_("High")}, { - "very-high", N_("Very High")}, { - "high+", N_("Very High")}, { - "production", N_("Production")}, { - "fp-mic", N_("Front Panel Microphone")}, { - "fp-linein", N_("Front Panel Line In")}, { - "fp-headphones", N_("Front Panel Headphones")}, { - "fp-lineout", N_("Front Panel Line Out")}, { - "green", N_("Green Connector")}, { - "pink", N_("Pink Connector")}, { - "blue", N_("Blue Connector")}, { - "white", N_("White Connector")}, { - "black", N_("Black Connector")}, { - "gray", N_("Gray Connector")}, { - "orange", N_("Orange Connector")}, { - "red", N_("Red Connector")}, { - "yellow", N_("Yellow Connector")}, { - "fp-green", N_("Green Front Panel Connector")}, { - "fp-pink", N_("Pink Front Panel Connector")}, { - "fp-blue", N_("Blue Front Panel Connector")}, { - "fp-white", N_("White Front Panel Connector")}, { - "fp-black", N_("Black Front Panel Connector")}, { - "fp-gray", N_("Gray Front Panel Connector")}, { - "fp-orange", N_("Orange Front Panel Connector")}, { - "fp-red", N_("Red Front Panel Connector")}, { - "fp-yellow", N_("Yellow Front Panel Connector")}, { - "spread", N_("Spread Output")}, { - "downmix", N_("Downmix")}, - /* FIXME translate Audigy NX USB labels) */ -/* - { "rec.src", N_("Record Source") }, - { "output.mute", N_("Mute output") } - headph (Controller group) - headph.src (Enumeration control) - headph.mute (On/Off switch) - digital2 (Controller group) - digital2.src (Enumeration control) - digital2.mute (On/Off switch) - digital (Controller group) - digital.mute1 (On/Off switch) - digital.vol (Controller group) - digital.vol.front (Stereo slider (0-255)) - digital.vol.surr (Stereo slider (0-255)) - digital.vol.c/l (Stereo slider (0-255)) - digital.vol.center (Stereo slider (0-255)) - digital.mute2 (On/Off switch) - digital.vol (Stereo slider (0-255)) - line (Controller group) - line.mute (On/Off switch) - line.vol (Stereo slider (0-255)) - play-altset (Enumeration control) - rec-altset (Enumeration control) -*/ -}; - -/* Decent i18n is pretty much impossible with OSS's way of providing us with - * mixer labels (and the fact that they are pretty much random), but that - * doesn't mean we shouldn't at least try. */ -static gchar * -gst_oss4_mixer_control_get_translated_name (GstOss4MixerControl * mc) -{ - gchar name[128] = { 0, }; - gchar vmix_str[32] = { '\0', }; - gchar *ptr; - int dummy, i; - int num = -1; - gboolean function_suffix = FALSE; - - /* main virtual mixer controls (we hide the stream volumes) */ - if (sscanf (mc->mixext.extname, "vmix%d-%32c", &dummy, vmix_str) == 2) { - if (strcmp (vmix_str, "src") == 0) - return g_strdup (_("Virtual Mixer Input")); - else if (strcmp (vmix_str, "vol") == 0) - return g_strdup (_("Virtual Mixer Output")); - else if (strcmp (vmix_str, "channels") == 0) - return g_strdup (_("Virtual Mixer Channels")); - } - - g_strlcpy (name, mc->mixext.extname, sizeof (name)); - - /* we deal with either "connector." or "jack." */ - if ((g_str_has_prefix (name, "connector.")) || - (g_str_has_prefix (name, "jack."))) { - ptr = strchr (mc->mixext.extname, '.'); - ptr++; - g_strlcpy (name, ptr, sizeof (name)); - } - - /* special handling for jack retasking suffixes */ - if (g_str_has_suffix (name, ".function") || g_str_has_suffix (name, ".mode")) { - function_suffix = TRUE; - ptr = strrchr (name, '.'); - *ptr = 0; - } - - /* parse off trailing numbers */ - i = strlen (name); - while ((i > 0) && (g_ascii_isdigit (name[i - 1]))) { - i--; - } - /* the check catches the case where the control name is just a number */ - if ((i > 0) && (name[i] != '\0')) { - num = atoi (name + i); - name[i] = '\0'; - } - - /* look for a match, progressively skipping '.' delimited prefixes as we go */ - ptr = name; - do { - if (*ptr == '.') - ptr++; - for (i = 0; i < G_N_ELEMENTS (labels); ++i) { - if (g_strcasecmp (ptr, labels[i].oss_name) == 0) { - g_strlcpy (name, _(labels[i].label), sizeof (name)); - goto append_suffixes; - } - } - } while ((ptr = strchr (ptr, '.')) != NULL); - - /* failing that, just replace periods with spaces */ - g_strdelimit (name, ".", ' '); - -append_suffixes: - if (num > -1) { - if (function_suffix) { - /* TRANSLATORS: name + number of a volume mixer control */ - return g_strdup_printf (_("%s %d Function"), name, num); - } else { - return g_strdup_printf ("%s %d", name, num); - } - } else { - if (function_suffix) { - /* TRANSLATORS: name of a volume mixer control */ - return g_strdup_printf (_("%s Function"), name); - } else { - return g_strdup (name); - } - } -} - -static const gchar * -gst_oss4_mixer_control_get_translated_option (const gchar * name) -{ - int i; - for (i = 0; i < G_N_ELEMENTS (labels); ++i) { - if (g_strcasecmp (name, labels[i].oss_name) == 0) { - return _(labels[i].label); - } - } - return (name); -} - -#ifndef GST_DISABLE_GST_DEBUG -static const gchar * -mixer_ext_type_get_name (gint type) -{ - switch (type) { - case MIXT_DEVROOT: - return "Device root entry"; - case MIXT_GROUP: - return "Controller group"; - case MIXT_ONOFF: - return "On/Off switch"; - case MIXT_ENUM: - return "Enumeration control"; - case MIXT_MONOSLIDER: - return "Mono slider (0-255)"; - case MIXT_STEREOSLIDER: - return "Stereo slider (0-255)"; - case MIXT_MESSAGE: - return "Textual message"; /* whatever this is */ - case MIXT_MONOVU: - return "Mono VU meter value"; - case MIXT_STEREOVU: - return "Stereo VU meter value"; - case MIXT_MONOPEAK: - return "Mono VU meter peak value"; - case MIXT_STEREOPEAK: - return "Stereo VU meter peak value"; - case MIXT_RADIOGROUP: - return "Radio button group"; - case MIXT_MARKER: /* Separator between normal and extension entries */ - return "Separator"; - case MIXT_VALUE: - return "Decimal value entry"; - case MIXT_HEXVALUE: - return "Hex value entry"; - case MIXT_SLIDER: - return "Mono slider (31-bit value range)"; - case MIXT_3D: - return "3D"; /* what's this? */ - case MIXT_MONOSLIDER16: - return "Mono slider (0-32767)"; - case MIXT_STEREOSLIDER16: - return "Stereo slider (0-32767)"; - case MIXT_MUTE: - return "Mute switch"; - default: - break; - } - return "unknown"; -} -#endif /* GST_DISABLE_GST_DEBUG */ - -#ifndef GST_DISABLE_GST_DEBUG -static const gchar * -mixer_ext_flags_get_string (gint flags) -{ - struct - { - gint flag; - gchar nick[16]; - } all_flags[] = { - /* first the important ones */ - { - MIXF_MAINVOL, "MAINVOL"}, { - MIXF_PCMVOL, "PCMVOL"}, { - MIXF_RECVOL, "RECVOL"}, { - MIXF_MONVOL, "MONVOL"}, { - MIXF_DESCR, "DESCR"}, - /* now the rest in the right order */ - { - MIXF_READABLE, "READABLE"}, { - MIXF_WRITEABLE, "WRITABLE"}, { - MIXF_POLL, "POLL"}, { - MIXF_HZ, "HZ"}, { - MIXF_STRING, "STRING"}, { - MIXF_DYNAMIC, "DYNAMIC"}, { - MIXF_OKFAIL, "OKFAIL"}, { - MIXF_FLAT, "FLAT"}, { - MIXF_LEGACY, "LEGACY"}, { - MIXF_CENTIBEL, "CENTIBEL"}, { - MIXF_DECIBEL, "DECIBEL"}, { - MIXF_WIDE, "WIDE"} - }; - GString *s; - GQuark q; - gint i; - - if (flags == 0) - return "None"; - - s = g_string_new (""); - for (i = 0; i < G_N_ELEMENTS (all_flags); ++i) { - if ((flags & all_flags[i].flag)) { - if (s->len > 0) - g_string_append (s, " | "); - g_string_append (s, all_flags[i].nick); - flags &= ~all_flags[i].flag; /* unset */ - } - } - - /* unknown flags? */ - if (flags != 0) { - if (s->len > 0) - g_string_append (s, " | "); - g_string_append (s, "???"); - } - - /* we'll just put it into the global quark table (cheeky, eh?) */ - q = g_quark_from_string (s->str); - g_string_free (s, TRUE); - - return g_quark_to_string (q); -} -#endif /* GST_DISABLE_GST_DEBUG */ - -#ifndef GST_DISABLE_GST_DEBUG -static void -gst_oss4_mixer_control_dump_tree (GstOss4MixerControl * mc, gint depth) -{ - GList *c; - gchar spaces[64]; - gint i; - - depth = MIN (sizeof (spaces) - 1, depth); - for (i = 0; i < depth; ++i) - spaces[i] = ' '; - spaces[i] = '\0'; - - GST_LOG ("%s%s (%s)", spaces, mc->mixext.extname, - mixer_ext_type_get_name (mc->mixext.type)); - for (c = mc->children; c != NULL; c = c->next) { - GstOss4MixerControl *child_mc = (GstOss4MixerControl *) c->data; - - gst_oss4_mixer_control_dump_tree (child_mc, depth + 2); - } -} -#endif /* GST_DISABLE_GST_DEBUG */ - -static GList * -gst_oss4_mixer_get_controls (GstOss4Mixer * mixer) -{ - GstOss4MixerControl *root_mc = NULL; - oss_mixerinfo mi = { 0, }; - GList *controls = NULL; - GList *l; - guint i; - - /* Get info for currently open fd */ - mi.dev = -1; - if (ioctl (mixer->fd, SNDCTL_MIXERINFO, &mi) == -1) - goto no_mixerinfo; - - if (mi.nrext <= 0) { - GST_DEBUG ("mixer %s has no controls", mi.id); - return NULL; - } - - GST_INFO ("Reading controls for mixer %s", mi.id); - - for (i = 0; i < mi.nrext; ++i) { - GstOss4MixerControl *mc; - oss_mixext mix_ext = { 0, }; - - mix_ext.dev = mi.dev; - mix_ext.ctrl = i; - - if (ioctl (mixer->fd, SNDCTL_MIX_EXTINFO, &mix_ext) == -1) { - GST_DEBUG ("SNDCTL_MIX_EXTINFO failed on mixer %s, control %d: %s", - mi.id, i, g_strerror (errno)); - continue; - } - - /* if this is the last one, save it for is-interface-up-to-date checking */ - if (i == mi.nrext) - mixer->last_mixext = mix_ext; - - mc = g_new0 (GstOss4MixerControl, 1); - mc->mixext = mix_ext; - - /* both control_no and desc fields are pretty useless, ie. not always set, - * if ever, so not listed here */ - GST_INFO ("Control %d", mix_ext.ctrl); - GST_INFO (" name : %s", mix_ext.extname); - GST_INFO (" type : %s (%d)", mixer_ext_type_get_name (mix_ext.type), - mix_ext.type); - GST_INFO (" flags : %s (0x%04x)", - mixer_ext_flags_get_string (mix_ext.flags), mix_ext.flags); - GST_INFO (" parent : %d", mix_ext.parent); - - if (!MIXEXT_IS_ROOT (mix_ext)) { - /* find parent (we assume it comes in the list before the child) */ - for (l = controls; l != NULL; l = l->next) { - GstOss4MixerControl *parent_mc = (GstOss4MixerControl *) l->data; - - if (parent_mc->mixext.ctrl == mix_ext.parent) { - mc->parent = parent_mc; - parent_mc->children = g_list_append (parent_mc->children, mc); - break; - } - } - if (mc->parent == NULL) { - GST_ERROR_OBJECT (mixer, "couldn't find parent for control %d", i); - g_free (mc); - continue; - } - } else if (root_mc == NULL) { - root_mc = mc; - } else { - GST_WARNING_OBJECT (mixer, "two root controls?!"); - } - - controls = g_list_prepend (controls, mc); - } - -#ifndef GST_DISABLE_GST_DEBUG - gst_oss4_mixer_control_dump_tree (root_mc, 0); -#endif - - return g_list_reverse (controls); - -/* ERRORS */ -no_mixerinfo: - { - GST_WARNING ("SNDCTL_MIXERINFO failed on mixer device %s: %s", mi.id, - g_strerror (errno)); - return NULL; - } -} - -static void -gst_oss4_mixer_controls_guess_master (GstOss4Mixer * mixer, - const GList * controls) -{ - GstOss4MixerControl *master_mc = NULL; - const GList *l; - - for (l = controls; l != NULL; l = l->next) { - GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data; - - /* do we need to check if it's a slider type here? */ - if ((mc->mixext.flags & MIXF_PCMVOL)) { - GST_INFO_OBJECT (mixer, "First PCM control: %s", mc->mixext.extname); - master_mc = mc; - break; - } - - if (((mc->mixext.flags & MIXF_MAINVOL)) && master_mc == NULL) { - GST_INFO_OBJECT (mixer, "First main volume control: %s", - mc->mixext.extname); - master_mc = mc; - } - } - - if (master_mc != NULL) - master_mc->is_master = TRUE; -} - -/* type: -1 for all types, otherwise just return siblings with requested type */ -static GList * -gst_oss4_mixer_control_get_siblings (GstOss4MixerControl * mc, gint type) -{ - GList *s, *siblings = NULL; - - if (mc->parent == NULL) - return NULL; - - for (s = mc->parent->children; s != NULL; s = s->next) { - GstOss4MixerControl *sibling = (GstOss4MixerControl *) s->data; - - if (mc != sibling && (type < 0 || sibling->mixext.type == type)) - siblings = g_list_append (siblings, sibling); - } - - return siblings; -} - -static void -gst_oss4_mixer_controls_find_sliders (GstOss4Mixer * mixer, - const GList * controls) -{ - const GList *l; - - for (l = controls; l != NULL; l = l->next) { - GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data; - GList *s, *siblings; - - if (!MIXEXT_IS_SLIDER (mc->mixext) || mc->parent == NULL || mc->used) - continue; - - mc->is_slider = TRUE; - mc->used = TRUE; - - siblings = gst_oss4_mixer_control_get_siblings (mc, -1); - - /* Note: the names can be misleading and may not reflect the actual - * hierarchy of the controls, e.g. it's possible that a slider is called - * connector.green and the mute control then connector.green.mute, but - * both controls are in fact siblings and both children of the group - * 'green' instead of mute being a child of connector.green as the naming - * would seem to suggest */ - GST_LOG ("Slider: %s, parent=%s, %d siblings", mc->mixext.extname, - mc->parent->mixext.extname, g_list_length (siblings)); - - for (s = siblings; s != NULL; s = s->next) { - GstOss4MixerControl *sibling = (GstOss4MixerControl *) s->data; - - GST_LOG (" %s (%s)", sibling->mixext.extname, - mixer_ext_type_get_name (sibling->mixext.type)); - - if (sibling->mixext.type == MIXT_MUTE || - g_str_has_suffix (sibling->mixext.extname, ".mute")) { - /* simple case: slider with single mute sibling. We assume the .mute - * suffix in the name won't change - can't really do much else anyway */ - if (sibling->mixext.type == MIXT_ONOFF || - sibling->mixext.type == MIXT_MUTE) { - GST_LOG (" mute control for %s is %s", mc->mixext.extname, - sibling->mixext.extname); - mc->mute = sibling; - sibling->used = TRUE; - } - /* a group of .mute controls. We assume they are all switches here */ - if (sibling->mixext.type == MIXT_GROUP) { - GList *m; - - for (m = sibling->children; m != NULL; m = m->next) { - GstOss4MixerControl *grouped_sibling = m->data; - - if (grouped_sibling->mixext.type == MIXT_ONOFF || - grouped_sibling->mixext.type == MIXT_MUTE) { - GST_LOG (" %s is grouped mute control for %s", - grouped_sibling->mixext.extname, mc->mixext.extname); - mc->mute_group = g_list_append (mc->mute_group, grouped_sibling); - } - } - - GST_LOG (" %s has a group of %d mute controls", - mc->mixext.extname, g_list_length (mc->mute_group)); - - /* we don't mark the individual mute controls as used, only the - * group control, as we still want individual switches for the - * individual controls */ - sibling->used = TRUE; - } - } - } - g_list_free (siblings); - } -} - -/* should be called with the mixer object lock held because of the ioctl; - * returns TRUE if the list was read the first time or modified */ -static gboolean -gst_oss4_mixer_enum_control_update_enum_list (GstOss4Mixer * mixer, - GstOss4MixerControl * mc) -{ - oss_mixer_enuminfo ei = { 0, }; - guint num_existing = 0; - int i; - - /* count and existing values */ - while (mc->enum_vals != NULL && mc->enum_vals[num_existing] != 0) - ++num_existing; - - ei.dev = mc->mixext.dev; - ei.ctrl = mc->mixext.ctrl; - - /* if we have create a generic list with numeric IDs already and the - * number of values hasn't changed, then there's not much to do here */ - if (mc->no_list && mc->enum_vals != NULL && - num_existing == mc->mixext.maxvalue) { - return FALSE; - } - - /* if we have a list and it doesn't change, there's nothing to do either */ - if (mc->enum_vals != NULL && mc->enum_version == 0) - return FALSE; - - if (ioctl (mixer->fd, SNDCTL_MIX_ENUMINFO, &ei) == -1) { - g_free (mc->enum_vals); - mc->enum_vals = g_new0 (GQuark, mc->mixext.maxvalue + 1); - - GST_DEBUG ("no enum info available, creating numeric values from 0-%d", - mc->mixext.maxvalue - 1); - - /* "It is possible that some enum controls don't have any name list - * available. In this case the application should automatically generate - * list of numbers (0 to N-1)" */ - for (i = 0; i < mc->mixext.maxvalue; ++i) { - gchar num_str[8]; - - g_snprintf (num_str, sizeof (num_str), "%d", i); - mc->enum_vals[i] = g_quark_from_string (num_str); - } - mc->enum_version = 0; /* the only way to change is via maxvalue */ - } else { - /* old list same as current list? */ - if (mc->enum_vals != NULL && mc->enum_version == ei.version) - return FALSE; - - /* no list yet, or the list has changed */ - GST_LOG ("%s", (mc->enum_vals) ? "enum list has changed" : "reading list"); - if (ei.nvalues != mc->mixext.maxvalue) { - GST_WARNING_OBJECT (mixer, "Enum: %s, nvalues %d != maxvalue %d", - mc->mixext.extname, ei.nvalues, mc->mixext.maxvalue); - mc->mixext.maxvalue = MIN (ei.nvalues, mc->mixext.maxvalue); - } - - mc->mixext.maxvalue = MIN (mc->mixext.maxvalue, OSS_ENUM_MAXVALUE); - - g_free (mc->enum_vals); - mc->enum_vals = g_new0 (GQuark, mc->mixext.maxvalue + 1); - for (i = 0; i < mc->mixext.maxvalue; ++i) { - GST_LOG (" %s", ei.strings + ei.strindex[i]); - mc->enum_vals[i] = - g_quark_from_string (gst_oss4_mixer_control_get_translated_option - (ei.strings + ei.strindex[i])); - } - } - - return TRUE; -} - -static void -gst_oss4_mixer_controls_find_enums (GstOss4Mixer * mixer, - const GList * controls) -{ - const GList *l; - - for (l = controls; l != NULL; l = l->next) { - GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data; - - if (mc->mixext.type != MIXT_ENUM || mc->used) - continue; - - mc->is_enum = TRUE; - mc->used = TRUE; - - /* Note: enums are special: for most controls, the maxvalue is inclusive, - * but for enum controls it's actually exclusive (boggle), so that - * mixext.maxvalue = num_values */ - - GST_LOG ("Enum: %s, parent=%s, num_enums=%d", mc->mixext.extname, - mc->parent->mixext.extname, mc->mixext.maxvalue); - - gst_oss4_mixer_enum_control_update_enum_list (mixer, mc); - } -} - -static void -gst_oss4_mixer_controls_find_switches (GstOss4Mixer * mixer, - const GList * controls) -{ - const GList *l; - - for (l = controls; l != NULL; l = l->next) { - GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data; - - if (mc->used) - continue; - - if (mc->mixext.type != MIXT_ONOFF && mc->mixext.type != MIXT_MUTE) - continue; - - mc->is_switch = TRUE; - mc->used = TRUE; - - GST_LOG ("Switch: %s, parent=%s", mc->mixext.extname, - mc->parent->mixext.extname); - } -} - -static void -gst_oss4_mixer_controls_find_virtual (GstOss4Mixer * mixer, - const GList * controls) -{ - const GList *l; - - for (l = controls; l != NULL; l = l->next) { - GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data; - - /* or sscanf (mc->mixext.extname, "vmix%d-out.", &n) == 1 ? */ - /* for now we just flag all virtual controls with managed labels, those - * are really more appropriate for a pavucontrol-type control thing than - * the (more hardware-oriented) mixer interface */ - if (mc->mixext.id[0] == '@') { - mc->is_virtual = TRUE; - GST_LOG ("%s is virtual control with managed label", mc->mixext.extname); - } - } -} - -static void -gst_oss4_mixer_controls_dump_unused (GstOss4Mixer * mixer, - const GList * controls) -{ - const GList *l; - - for (l = controls; l != NULL; l = l->next) { - GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data; - - if (mc->used) - continue; - - switch (mc->mixext.type) { - case MIXT_DEVROOT: - case MIXT_GROUP: - case MIXT_MESSAGE: - case MIXT_MONOVU: - case MIXT_STEREOVU: - case MIXT_MONOPEAK: - case MIXT_STEREOPEAK: - case MIXT_MARKER: - continue; /* not interested in these types of controls */ - case MIXT_MONODB: - case MIXT_STEREODB: - GST_DEBUG ("obsolete control type %d", mc->mixext.type); - continue; - case MIXT_MONOSLIDER: - case MIXT_STEREOSLIDER: - case MIXT_SLIDER: - case MIXT_MONOSLIDER16: - case MIXT_STEREOSLIDER16: - /* this shouldn't happen */ - GST_ERROR ("unused slider control?!"); - continue; - case MIXT_VALUE: - case MIXT_HEXVALUE: - /* value entry, not sure what to do with that, skip for now */ - continue; - case MIXT_ONOFF: - case MIXT_MUTE: - case MIXT_ENUM: - case MIXT_3D: - case MIXT_RADIOGROUP: - GST_DEBUG ("FIXME: handle %s %s", - mixer_ext_type_get_name (mc->mixext.type), mc->mixext.extname); - break; - default: - GST_WARNING ("unknown control type %d", mc->mixext.type); - continue; - } - } -} - -static GList * -gst_oss4_mixer_create_tracks (GstOss4Mixer * mixer, const GList * controls) -{ - const GList *c; - GList *tracks = NULL; - - for (c = controls; c != NULL; c = c->next) { - GstOss4MixerControl *mc = (GstOss4MixerControl *) c->data; - GstMixerTrack *track = NULL; - - if (mc->is_virtual) - continue; - - if (mc->is_slider) { - track = gst_oss4_mixer_slider_new (mixer, mc); - } else if (mc->is_enum) { - track = gst_oss4_mixer_enum_new (mixer, mc); - } else if (mc->is_switch) { - track = gst_oss4_mixer_switch_new (mixer, mc); - } - - if (track == NULL) - continue; - - track->label = gst_oss4_mixer_control_get_translated_name (mc); - track->flags = 0; - - GST_LOG ("translated label: %s [%s] = %s", track->label, mc->mixext.id, - track->label); - - /* This whole 'a track is either INPUT or OUTPUT' model is just flawed, - * esp. if a slider's role can be changed on the fly, like when you change - * function of a connector. What should we do in that case? Change the flag - * and make the app rebuild the interface? Ignore it? */ - if (mc->mixext.flags & (MIXF_MAINVOL | MIXF_PCMVOL)) { - track->flags = GST_MIXER_TRACK_OUTPUT | GST_MIXER_TRACK_WHITELIST; - - } else if (mc->mixext.flags & MIXF_RECVOL) { - /* record gain whitelisted by default */ - track->flags = GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_NO_RECORD | - GST_MIXER_TRACK_WHITELIST; - - } else if (mc->mixext.flags & MIXF_MONVOL) { - /* monitor sources not whitelisted by default */ - track->flags = GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_NO_RECORD; - } - - /* - * The kernel may give us better clues about the scope of a control. - * If so, try to honor it. - */ - switch (mc->mixext.desc & MIXEXT_SCOPE_MASK) { - case MIXEXT_SCOPE_INPUT: - case MIXEXT_SCOPE_RECSWITCH: - track->flags |= GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_NO_RECORD | - GST_MIXER_TRACK_WHITELIST; - break; - case MIXEXT_SCOPE_MONITOR: - /* don't whitelist monitor tracks by default */ - track->flags |= GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_NO_RECORD; - break; - case MIXEXT_SCOPE_OUTPUT: - track->flags = GST_MIXER_TRACK_OUTPUT | GST_MIXER_TRACK_WHITELIST; - break; - } - - if (mc->is_master) { - track->flags |= GST_MIXER_TRACK_OUTPUT; - } - - if (mc->is_master) - track->flags |= GST_MIXER_TRACK_MASTER; - - tracks = g_list_append (tracks, track); - } - - return tracks; -} - -static void -gst_oss4_mixer_update_tracks (GstOss4Mixer * mixer) -{ - GList *controls, *tracks; - - /* read and process controls */ - controls = gst_oss4_mixer_get_controls (mixer); - - gst_oss4_mixer_controls_guess_master (mixer, controls); - - gst_oss4_mixer_controls_find_sliders (mixer, controls); - - gst_oss4_mixer_controls_find_enums (mixer, controls); - - gst_oss4_mixer_controls_find_switches (mixer, controls); - - gst_oss4_mixer_controls_find_virtual (mixer, controls); - - gst_oss4_mixer_controls_dump_unused (mixer, controls); - - tracks = gst_oss4_mixer_create_tracks (mixer, controls); - - /* free old tracks and controls */ - gst_oss4_mixer_free_tracks (mixer); - - /* replace old with new */ - mixer->tracks = tracks; - mixer->controls = controls; -} - -static const GList * -gst_oss4_mixer_list_tracks (GstMixer * mixer_iface) -{ - GstOss4Mixer *mixer = GST_OSS4_MIXER (mixer_iface); - - g_return_val_if_fail (mixer != NULL, NULL); - g_return_val_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer), NULL); - - GST_OBJECT_LOCK (mixer); - - /* Do a read on the last control to check if the interface has changed */ - if (!mixer->need_update && mixer->last_mixext.ctrl > 0) { - GstOss4MixerControl mc = { {0,} - , - }; - int val; - - mc.mixext = mixer->last_mixext; - gst_oss4_mixer_get_control_val (mixer, &mc, &val); - } - - if (mixer->need_update || mixer->tracks == NULL) { - gst_oss4_mixer_update_tracks (mixer); - mixer->need_update = FALSE; - } - - GST_OBJECT_UNLOCK (mixer); - - return (const GList *) mixer->tracks; -} - -static void -gst_oss4_mixer_set_volume (GstMixer * mixer, GstMixerTrack * track, - gint * volumes) -{ - GstOss4Mixer *oss; - - g_return_if_fail (mixer != NULL); - g_return_if_fail (GST_IS_OSS4_MIXER (mixer)); - g_return_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer)); - g_return_if_fail (gst_oss4_mixer_contains_track (mixer, track)); - g_return_if_fail (volumes != NULL); - - oss = GST_OSS4_MIXER (mixer); - - GST_OBJECT_LOCK (oss); - - if (GST_IS_OSS4_MIXER_SLIDER (track)) { - gst_oss4_mixer_slider_set_volume (GST_OSS4_MIXER_SLIDER (track), volumes); - } - - GST_OBJECT_UNLOCK (oss); -} - -static void -gst_oss4_mixer_get_volume (GstMixer * mixer, GstMixerTrack * track, - gint * volumes) -{ - GstOss4Mixer *oss; - - g_return_if_fail (mixer != NULL); - g_return_if_fail (GST_IS_OSS4_MIXER (mixer)); - g_return_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer)); - g_return_if_fail (gst_oss4_mixer_contains_track (mixer, track)); - g_return_if_fail (volumes != NULL); - - oss = GST_OSS4_MIXER (mixer); - - GST_OBJECT_LOCK (oss); - - memset (volumes, 0, track->num_channels * sizeof (gint)); - - if (GST_IS_OSS4_MIXER_SWITCH (track)) { - gboolean enabled = FALSE; - gst_oss4_mixer_switch_get (GST_OSS4_MIXER_SWITCH (track), &enabled); - } - if (GST_IS_OSS4_MIXER_SLIDER (track)) { - gst_oss4_mixer_slider_get_volume (GST_OSS4_MIXER_SLIDER (track), volumes); - } - - GST_OBJECT_UNLOCK (oss); -} - -static void -gst_oss4_mixer_set_record (GstMixer * mixer, GstMixerTrack * track, - gboolean record) -{ - GstOss4Mixer *oss; - - g_return_if_fail (mixer != NULL); - g_return_if_fail (GST_IS_OSS4_MIXER (mixer)); - g_return_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer)); - g_return_if_fail (gst_oss4_mixer_contains_track (mixer, track)); - - oss = GST_OSS4_MIXER (mixer); - - GST_OBJECT_LOCK (oss); - - if (GST_IS_OSS4_MIXER_SLIDER (track)) { - gst_oss4_mixer_slider_set_record (GST_OSS4_MIXER_SLIDER (track), record); - } else if (GST_IS_OSS4_MIXER_SWITCH (track)) { - if ((track->flags & GST_MIXER_TRACK_INPUT)) { - gst_oss4_mixer_switch_set (GST_OSS4_MIXER_SWITCH (track), record); - } else { - GST_WARNING_OBJECT (track, "set_record called on non-INPUT track"); - } - } - - GST_OBJECT_UNLOCK (oss); -} - -static void -gst_oss4_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute) -{ - GstOss4Mixer *oss; - - g_return_if_fail (mixer != NULL); - g_return_if_fail (GST_IS_OSS4_MIXER (mixer)); - g_return_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer)); - g_return_if_fail (gst_oss4_mixer_contains_track (mixer, track)); - - oss = GST_OSS4_MIXER (mixer); - - GST_OBJECT_LOCK (oss); - - if (GST_IS_OSS4_MIXER_SLIDER (track)) { - gst_oss4_mixer_slider_set_mute (GST_OSS4_MIXER_SLIDER (track), mute); - } else if (GST_IS_OSS4_MIXER_SWITCH (track)) { - gst_oss4_mixer_switch_set (GST_OSS4_MIXER_SWITCH (track), mute); - } - - GST_OBJECT_UNLOCK (oss); -} - -static void -gst_oss4_mixer_set_option (GstMixer * mixer, GstMixerOptions * options, - gchar * value) -{ - GstOss4Mixer *oss; - - g_return_if_fail (mixer != NULL); - g_return_if_fail (value != NULL); - g_return_if_fail (GST_IS_OSS4_MIXER (mixer)); - g_return_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer)); - g_return_if_fail (GST_IS_OSS4_MIXER_ENUM (options)); - g_return_if_fail (gst_oss4_mixer_contains_options (mixer, options)); - - oss = GST_OSS4_MIXER (mixer); - - GST_OBJECT_LOCK (oss); - - if (!gst_oss4_mixer_enum_set_option (GST_OSS4_MIXER_ENUM (options), value)) { - /* not much we can do here but wake up the watch thread early, so it - * can do its thing and post messages if anything has changed */ - gst_oss4_mixer_wake_up_watch_task (oss); - } - - GST_OBJECT_UNLOCK (oss); -} - -static const gchar * -gst_oss4_mixer_get_option (GstMixer * mixer, GstMixerOptions * options) -{ - GstOss4Mixer *oss; - const gchar *current_val; - - g_return_val_if_fail (mixer != NULL, NULL); - g_return_val_if_fail (GST_IS_OSS4_MIXER (mixer), NULL); - g_return_val_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer), NULL); - g_return_val_if_fail (GST_IS_OSS4_MIXER_ENUM (options), NULL); - g_return_val_if_fail (gst_oss4_mixer_contains_options (mixer, options), NULL); - - oss = GST_OSS4_MIXER (mixer); - - GST_OBJECT_LOCK (oss); - - current_val = gst_oss4_mixer_enum_get_option (GST_OSS4_MIXER_ENUM (options)); - - if (current_val == NULL) { - /* not much we can do here but wake up the watch thread early, so it - * can do its thing and post messages if anything has changed */ - gst_oss4_mixer_wake_up_watch_task (oss); - } - - GST_OBJECT_UNLOCK (oss); - - return current_val; -} - -static GstMixerFlags -gst_oss4_mixer_get_mixer_flags (GstMixer * mixer) -{ - return GST_MIXER_FLAG_AUTO_NOTIFICATIONS | GST_MIXER_FLAG_HAS_WHITELIST | - GST_MIXER_FLAG_GROUPING; -} - -static void -gst_oss4_mixer_interface_init (GstMixerClass * klass) -{ - GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE; - - klass->list_tracks = gst_oss4_mixer_list_tracks; - klass->set_volume = gst_oss4_mixer_set_volume; - klass->get_volume = gst_oss4_mixer_get_volume; - klass->set_mute = gst_oss4_mixer_set_mute; - klass->set_record = gst_oss4_mixer_set_record; - klass->set_option = gst_oss4_mixer_set_option; - klass->get_option = gst_oss4_mixer_get_option; - klass->get_mixer_flags = gst_oss4_mixer_get_mixer_flags; -} - -/* Implement the horror that is GstImplementsInterface */ - -static gboolean -gst_oss4_mixer_supported (GstImplementsInterface * iface, GType iface_type) -{ - GstOss4Mixer *mixer; - - g_return_val_if_fail (iface_type == GST_TYPE_MIXER, FALSE); - - mixer = GST_OSS4_MIXER (iface); - - return GST_OSS4_MIXER_IS_OPEN (mixer); -} - -static void -gst_oss4_mixer_implements_interface_init (GstImplementsInterfaceClass * klass) -{ - klass->supported = gst_oss4_mixer_supported; -} - -static void -gst_oss4_mixer_init_interfaces (GType type) -{ - static const GInterfaceInfo implements_iface_info = { - (GInterfaceInitFunc) gst_oss4_mixer_implements_interface_init, - NULL, - NULL, - }; - static const GInterfaceInfo mixer_iface_info = { - (GInterfaceInitFunc) gst_oss4_mixer_interface_init, - NULL, - NULL, - }; - - g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, - &implements_iface_info); - g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info); - - gst_oss4_add_property_probe_interface (type); -} diff --git a/sys/oss4/oss4-mixer.h b/sys/oss4/oss4-mixer.h deleted file mode 100644 index 4eaff50c5..000000000 --- a/sys/oss4/oss4-mixer.h +++ /dev/null @@ -1,128 +0,0 @@ -/* GStreamer OSS4 mixer implementation - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef OSS4_MIXER_H -#define OSS4_MIXER_H - -#include <gst/gst.h> - -#include "oss4-soundcard.h" - -#define GST_OSS4_MIXER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER,GstOss4Mixer)) -#define GST_OSS4_MIXER_CAST(obj) ((GstOss4Mixer *)(obj)) -#define GST_OSS4_MIXER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER,GstOss4MixerClass)) -#define GST_IS_OSS4_MIXER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER)) -#define GST_IS_OSS4_MIXER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER)) -#define GST_TYPE_OSS4_MIXER (gst_oss4_mixer_get_type()) - -#define GST_OSS4_MIXER_IS_OPEN(obj) (GST_OSS4_MIXER(obj)->fd != -1) - -typedef struct _GstOss4Mixer GstOss4Mixer; -typedef struct _GstOss4MixerClass GstOss4MixerClass; - -struct _GstOss4Mixer { - GstElement element; - - /*< private >*/ - - /* element bits'n'bops */ - gchar * device; - - /* mixer details */ - gint fd; /* file descriptor if open, or -1 */ - gchar * device_name; /* device description, or NULL */ - gchar * open_device; /* the device we opened */ - - GList * tracks; /* list of available tracks */ - GList * controls; /* list of available controls */ - gboolean need_update; /* re-read list of available tracks? */ - - oss_mixext last_mixext; /* we keep this around so we can - * easily check if the mixer - * interface has changed */ - - GThread * watch_thread; /* thread watching for value changes */ - GCond * watch_cond; - gint watch_shutdown; - gint modify_counter; /* from MIXERINFO */ - - /* for property probe interface */ - GList * property_probe_list; -}; - -struct _GstOss4MixerClass { - GstElementClass element_class; -}; - -/* helper struct holding info about one control */ -typedef struct _GstOss4MixerControl GstOss4MixerControl; - -struct _GstOss4MixerControl { - oss_mixext mixext; - GstOss4MixerControl *parent; /* NULL if root */ - GstOss4MixerControl *mute; /* sibling with mute function, or NULL */ - GList *mute_group; /* group of mute controls, or NULL */ - GList *children; /* GstOss4MixerControls (no ownership) */ - - GQuark *enum_vals; /* 0-terminated array of values or NULL */ - int enum_version; /* 0 = list won't change */ - - int last_val; /* last value seen */ - - gboolean is_virtual : 1; /* is a vmix control with dynamic label */ - gboolean is_master : 1; - gboolean is_slider : 1; /* represent as slider */ - gboolean is_switch : 1; /* represent as switch */ - gboolean is_enum : 1; /* represent as combo/enumeration */ - gboolean no_list : 1; /* enumeration with no list available */ - gboolean is_input : 1; /* is an input-related control */ - gboolean is_output : 1; /* is an output-related control */ - gboolean used : 1; /* whether we know what to do with this */ - - gboolean changed : 1; /* transient flag used by watch thread */ - gboolean list_changed : 1; /* transient flag used by watch thread */ -}; - -/* header says parent=-1 means root, but it can also be parent=ctrl */ -#define MIXEXT_IS_ROOT(me) ((me).parent == -1 || (me).parent == (me).ctrl) - -#define MIXEXT_IS_SLIDER(me) ((me).type == MIXT_MONOSLIDER || \ - (me).type == MIXT_STEREOSLIDER || (me).type == MIXT_MONOSLIDER16 || \ - (me).type == MIXT_STEREOSLIDER16 || (me).type == MIXT_SLIDER) - -#define MIXEXT_HAS_DESCRIPTION(me) (((me).flags & MIXF_DESCR) != 0) - -#define MIXEXT_ENUM_IS_AVAILABLE(me,num) \ - (((me).enum_present[num/8]) & (1 << (num % 8))) - - -GType gst_oss4_mixer_get_type (void); - -gboolean gst_oss4_mixer_get_control_val (GstOss4Mixer * mixer, - GstOss4MixerControl * mc, - int * val); - -gboolean gst_oss4_mixer_set_control_val (GstOss4Mixer * mixer, - GstOss4MixerControl * mc, - int val); - -G_END_DECLS - -#endif /* OSS4_MIXER_H */ - diff --git a/sys/oss4/oss4-property-probe.c b/sys/oss4/oss4-property-probe.c deleted file mode 100644 index 9a625d84f..000000000 --- a/sys/oss4/oss4-property-probe.c +++ /dev/null @@ -1,414 +0,0 @@ -/* GStreamer OSS4 audio property probe interface implementation - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gst/gst.h> - -#define NO_LEGACY_MIXER -#include "oss4-audio.h" -#include "oss4-mixer.h" -#include "oss4-sink.h" -#include "oss4-source.h" -#include "oss4-soundcard.h" -#include "oss4-property-probe.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> - -GST_DEBUG_CATEGORY_EXTERN (oss4_debug); -#define GST_CAT_DEFAULT oss4_debug - -static const GList * -gst_oss4_property_probe_get_properties (GstPropertyProbe * probe) -{ - GObjectClass *klass = G_OBJECT_GET_CLASS (probe); - GList *list; - - GST_OBJECT_LOCK (GST_OBJECT (probe)); - - /* we create a new list and store it in the instance struct, since apparently - * we forgot to update the API for 0.10 (and why don't we mark probable - * properties with a flag instead anyway?). A bit hackish, but what can you - * do (can't really use a static variable since the pspec will be different - * for src and sink class); this isn't particularly pretty, but the best - * we can do given that we can't create a common base class (we could do - * fancy things with the interface, or use g_object_set_data instead, but - * it's not really going to make it much better) */ - if (GST_IS_AUDIO_SINK_CLASS (klass)) { - list = GST_OSS4_SINK (probe)->property_probe_list; - } else if (GST_IS_AUDIO_SRC_CLASS (klass)) { - list = GST_OSS4_SOURCE (probe)->property_probe_list; - } else if (GST_IS_OSS4_MIXER_CLASS (klass)) { - list = GST_OSS4_MIXER (probe)->property_probe_list; - } else { - GST_OBJECT_UNLOCK (GST_OBJECT (probe)); - g_return_val_if_reached (NULL); - } - - if (list == NULL) { - GParamSpec *pspec; - - pspec = g_object_class_find_property (klass, "device"); - list = g_list_prepend (NULL, pspec); - - if (GST_IS_AUDIO_SINK_CLASS (klass)) { - GST_OSS4_SINK (probe)->property_probe_list = list; - } else if (GST_IS_AUDIO_SRC_CLASS (klass)) { - GST_OSS4_SOURCE (probe)->property_probe_list = list; - } else if (GST_IS_OSS4_MIXER_CLASS (klass)) { - GST_OSS4_MIXER (probe)->property_probe_list = list; - } - } - - GST_OBJECT_UNLOCK (GST_OBJECT (probe)); - - return list; -} - -static void -gst_oss4_property_probe_probe_property (GstPropertyProbe * probe, - guint prop_id, const GParamSpec * pspec) -{ - if (!g_str_equal (pspec->name, "device")) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); - } -} - -static gboolean -gst_oss4_property_probe_needs_probe (GstPropertyProbe * probe, - guint prop_id, const GParamSpec * pspec) -{ - /* don't cache probed data */ - return TRUE; -} - -static gint -oss4_mixerinfo_priority_cmp (struct oss_mixerinfo *mi1, - struct oss_mixerinfo *mi2) -{ - /* return negative vaue if mi1 comes before mi2 */ - if (mi1->priority != mi2->priority) - return mi2->priority - mi1->priority; - - return strcmp (mi1->devnode, mi2->devnode); -} - -/* caller must ensure LOCK is taken (e.g. if ioctls need to be serialised) */ -gboolean -gst_oss4_property_probe_find_device_name (GstObject * obj, int fd, - const gchar * device_handle, gchar ** device_name) -{ - struct oss_sysinfo si = { {0,}, }; - gchar *name = NULL; - - if (ioctl (fd, SNDCTL_SYSINFO, &si) == 0) { - int i; - - for (i = 0; i < si.numaudios; ++i) { - struct oss_audioinfo ai = { 0, }; - - ai.dev = i; - if (ioctl (fd, SNDCTL_AUDIOINFO, &ai) == -1) { - GST_DEBUG_OBJECT (obj, "AUDIOINFO ioctl for device %d failed", i); - continue; - } - if (strcmp (ai.devnode, device_handle) == 0) { - name = g_strdup (ai.name); - break; - } - } - } else { - GST_WARNING_OBJECT (obj, "SYSINFO ioctl failed: %s", g_strerror (errno)); - } - - /* try ENGINEINFO as fallback (which is better than nothing) */ - if (name == NULL) { - struct oss_audioinfo ai = { 0, }; - - GST_LOG_OBJECT (obj, "device %s not listed in AUDIOINFO", device_handle); - ai.dev = -1; - if (ioctl (fd, SNDCTL_ENGINEINFO, &ai) == 0) - name = g_strdup (ai.name); - } - - GST_DEBUG_OBJECT (obj, "Device name: %s", GST_STR_NULL (name)); - - if (name != NULL) - *device_name = name; - - return (name != NULL); -} - -gboolean -gst_oss4_property_probe_find_device_name_nofd (GstObject * obj, - const gchar * device_handle, gchar ** device_name) -{ - gboolean res; - int fd; - - fd = open ("/dev/mixer", O_RDONLY); - if (fd < 0) - return FALSE; - - res = gst_oss4_property_probe_find_device_name (obj, fd, device_handle, - device_name); - - close (fd); - return res; -} - -static GList * -gst_oss4_property_probe_get_mixer_devices (GstObject * obj, int fd, - struct oss_sysinfo *si) -{ - GList *m, *mixers = NULL; - GList *devices = NULL; - - int i; - - GST_LOG_OBJECT (obj, "%d mixer devices", si->nummixers); - - /* first, find suitable mixer devices and sort by priority */ - for (i = 0; i < si->nummixers; ++i) { - struct oss_mixerinfo mi = { 0, }; - - mi.dev = i; - if (ioctl (fd, SNDCTL_MIXERINFO, &mi) == -1) { - GST_DEBUG_OBJECT (obj, "MIXERINFO ioctl for device %d failed", i); - continue; - } - - GST_INFO_OBJECT (obj, "mixer device %d:", i); - GST_INFO_OBJECT (obj, " enabled : %s", (mi.enabled) ? "yes" : - "no (powered off or unplugged)"); - GST_INFO_OBJECT (obj, " priority : %d", mi.priority); - GST_INFO_OBJECT (obj, " devnode : %s", mi.devnode); - GST_INFO_OBJECT (obj, " handle : %s", mi.handle); - GST_INFO_OBJECT (obj, " caps : 0x%02x", mi.caps); - GST_INFO_OBJECT (obj, " name : %s", mi.name); - - if (!mi.enabled) { - GST_DEBUG_OBJECT (obj, "mixer device is not usable/enabled, skipping"); - continue; - } - - /* only want mixers that control hardware directly */ - if ((mi.caps & MIXER_CAP_VIRTUAL)) { - GST_DEBUG_OBJECT (obj, "mixer device is a virtual device, skipping"); - continue; - } - - mixers = g_list_insert_sorted (mixers, g_memdup (&mi, sizeof (mi)), - (GCompareFunc) oss4_mixerinfo_priority_cmp); - } - - /* then create device list according to priority */ - for (m = mixers; m != NULL; m = m->next) { - struct oss_mixerinfo *mi = (struct oss_mixerinfo *) m->data; - - GST_LOG_OBJECT (obj, "mixer device: '%s'", mi->devnode); - devices = g_list_prepend (devices, g_strdup (mi->devnode)); - g_free (m->data); - } - g_list_free (mixers); - mixers = NULL; - - return g_list_reverse (devices); -} - -static GList * -gst_oss4_property_probe_get_audio_devices (GstObject * obj, int fd, - struct oss_sysinfo *si, int cap_mask) -{ - GList *devices = NULL; - int i; - - GST_LOG_OBJECT (obj, "%d audio/dsp devices", si->numaudios); - - for (i = 0; i < si->numaudios; ++i) { - struct oss_audioinfo ai = { 0, }; - - ai.dev = i; - if (ioctl (fd, SNDCTL_AUDIOINFO, &ai) == -1) { - GST_DEBUG_OBJECT (obj, "AUDIOINFO ioctl for device %d failed", i); - continue; - } - - if ((ai.caps & cap_mask) == 0) { - GST_DEBUG_OBJECT (obj, "audio device %d is not an %s device", i, - (cap_mask == PCM_CAP_OUTPUT) ? "output" : "input"); - continue; - } - - if (!ai.enabled) { - GST_DEBUG_OBJECT (obj, "audio device %d is not usable/enabled", i); - continue; - } - - GST_DEBUG_OBJECT (obj, "audio device %d looks ok: %s (\"%s\")", i, - ai.devnode, ai.name); - - devices = g_list_prepend (devices, g_strdup (ai.devnode)); - } - - return g_list_reverse (devices); -} - -static GValueArray * -gst_oss4_property_probe_get_values (GstPropertyProbe * probe, - guint prop_id, const GParamSpec * pspec) -{ - struct oss_sysinfo si = { {0,}, }; - GstElementClass *klass; - GValueArray *array = NULL; - GstObject *obj; - GList *devices, *l; - int cap_mask, fd = -1; - - if (!g_str_equal (pspec->name, "device")) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); - return NULL; - } - - obj = GST_OBJECT (probe); - - GST_OBJECT_LOCK (obj); - - /* figure out whether the element is a source or sink */ - klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe)); - if (GST_IS_OSS4_SINK (probe)) { - GST_DEBUG_OBJECT (probe, "probing available output devices"); - cap_mask = PCM_CAP_OUTPUT; - fd = GST_OSS4_SINK (probe)->fd; - } else if (GST_IS_OSS4_SOURCE (probe)) { - GST_DEBUG_OBJECT (probe, "probing available input devices"); - cap_mask = PCM_CAP_INPUT; - fd = GST_OSS4_SOURCE (probe)->fd; - } else if (GST_IS_OSS4_MIXER (probe)) { - fd = GST_OSS4_MIXER (probe)->fd; - cap_mask = 0; - } else { - GST_OBJECT_UNLOCK (obj); - g_return_val_if_reached (NULL); - } - - /* copy fd if it's open, so we can just unconditionally close() later */ - if (fd != -1) - fd = dup (fd); - - /* this will also catch the unlikely case where the above dup() failed */ - if (fd == -1) { - fd = open ("/dev/mixer", O_RDONLY | O_NONBLOCK, 0); - if (fd < 0) - goto open_failed; - else if (!gst_oss4_audio_check_version (GST_OBJECT (probe), fd)) - goto legacy_oss; - } - - if (ioctl (fd, SNDCTL_SYSINFO, &si) == -1) - goto no_sysinfo; - - if (cap_mask != 0) { - devices = - gst_oss4_property_probe_get_audio_devices (obj, fd, &si, cap_mask); - } else { - devices = gst_oss4_property_probe_get_mixer_devices (obj, fd, &si); - } - - if (devices == NULL) { - GST_DEBUG_OBJECT (obj, "No devices found"); - goto done; - } - - array = g_value_array_new (1); - - for (l = devices; l != NULL; l = l->next) { - GValue val = { 0, }; - - g_value_init (&val, G_TYPE_STRING); - g_value_take_string (&val, (gchar *) l->data); - l->data = NULL; - g_value_array_append (array, &val); - g_value_unset (&val); - } - - GST_OBJECT_UNLOCK (obj); - - g_list_free (devices); - -done: - - close (fd); - - return array; - -/* ERRORS */ -open_failed: - { - GST_OBJECT_UNLOCK (GST_OBJECT (probe)); - GST_WARNING_OBJECT (probe, "Can't open file descriptor to probe " - "available devices: %s", g_strerror (errno)); - return NULL; - } -legacy_oss: - { - close (fd); - GST_OBJECT_UNLOCK (GST_OBJECT (probe)); - GST_DEBUG_OBJECT (probe, "Legacy OSS (ie. not OSSv4), not supported"); - return NULL; - } -no_sysinfo: - { - close (fd); - GST_OBJECT_UNLOCK (GST_OBJECT (probe)); - GST_WARNING_OBJECT (probe, "Can't open file descriptor to probe " - "available devices: %s", g_strerror (errno)); - return NULL; - } -} - -static void -gst_oss4_property_probe_interface_init (GstPropertyProbeInterface * iface) -{ - iface->get_properties = gst_oss4_property_probe_get_properties; - iface->probe_property = gst_oss4_property_probe_probe_property; - iface->needs_probe = gst_oss4_property_probe_needs_probe; - iface->get_values = gst_oss4_property_probe_get_values; -} - -void -gst_oss4_add_property_probe_interface (GType type) -{ - static const GInterfaceInfo probe_iface_info = { - (GInterfaceInitFunc) gst_oss4_property_probe_interface_init, - NULL, - NULL, - }; - - g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE, - &probe_iface_info); -} diff --git a/sys/oss4/oss4-property-probe.h b/sys/oss4/oss4-property-probe.h deleted file mode 100644 index 707af024c..000000000 --- a/sys/oss4/oss4-property-probe.h +++ /dev/null @@ -1,38 +0,0 @@ -/* GStreamer OSS4 audio property probe interface implementation - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef GST_OSS4_PROPERTY_PROBE_H -#define GST_OSS4_PROPERTY_PROBE_H - -#include <gst/interfaces/propertyprobe.h> - -void gst_oss4_add_property_probe_interface (GType type); - -gboolean gst_oss4_property_probe_find_device_name (GstObject * obj, - int fd, - const gchar * device_handle, - gchar ** device_name); - -gboolean gst_oss4_property_probe_find_device_name_nofd (GstObject * obj, - const gchar * device_handle, - gchar ** device_name); - -#endif /* GST_OSS4_PROPERTY_PROBE_H */ - - diff --git a/sys/oss4/oss4-sink.c b/sys/oss4/oss4-sink.c deleted file mode 100644 index e59d87821..000000000 --- a/sys/oss4/oss4-sink.c +++ /dev/null @@ -1,699 +0,0 @@ -/* GStreamer OSS4 audio sink - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/** - * SECTION:element-oss4sink - * - * This element lets you output sound using the Open Sound System (OSS) - * version 4. - * - * Note that you should almost always use generic audio conversion elements - * like audioconvert and audioresample in front of an audiosink to make sure - * your pipeline works under all circumstances (those conversion elements will - * act in passthrough-mode if no conversion is necessary). - * - * <refsect2> - * <title>Example pipelines</title> - * |[ - * gst-launch -v audiotestsrc ! audioconvert ! volume volume=0.1 ! oss4sink - * ]| will output a sine wave (continuous beep sound) to your sound card (with - * a very low volume as precaution). - * |[ - * gst-launch -v filesrc location=music.ogg ! decodebin ! audioconvert ! audioresample ! oss4sink - * ]| will play an Ogg/Vorbis audio file and output it using the Open Sound System - * version 4. - * </refsect2> - * - * Since: 0.10.7 - */ - -/* TODO: - add "volume" property for stream volume control and intercept tags - * to set stream title - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <errno.h> -#include <unistd.h> -#include <string.h> - -#include <gst/gst-i18n-plugin.h> -#include <gst/interfaces/streamvolume.h> - -#define NO_LEGACY_MIXER -#include "oss4-audio.h" -#include "oss4-sink.h" -#include "oss4-property-probe.h" -#include "oss4-soundcard.h" - -GST_DEBUG_CATEGORY_EXTERN (oss4sink_debug); -#define GST_CAT_DEFAULT oss4sink_debug - -static void gst_oss4_sink_init_interfaces (GType type); -static void gst_oss4_sink_dispose (GObject * object); -static void gst_oss4_sink_finalise (GObject * object); - -static void gst_oss4_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_oss4_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); - -static GstCaps *gst_oss4_sink_getcaps (GstBaseSink * bsink); -static gboolean gst_oss4_sink_open (GstAudioSink * asink, - gboolean silent_errors); -static gboolean gst_oss4_sink_open_func (GstAudioSink * asink); -static gboolean gst_oss4_sink_close (GstAudioSink * asink); -static gboolean gst_oss4_sink_prepare (GstAudioSink * asink, - GstRingBufferSpec * spec); -static gboolean gst_oss4_sink_unprepare (GstAudioSink * asink); -static guint gst_oss4_sink_write (GstAudioSink * asink, gpointer data, - guint length); -static guint gst_oss4_sink_delay (GstAudioSink * asink); -static void gst_oss4_sink_reset (GstAudioSink * asink); - -#define DEFAULT_DEVICE NULL -#define DEFAULT_DEVICE_NAME NULL -#define DEFAULT_MUTE FALSE -#define DEFAULT_VOLUME 1.0 -#define MAX_VOLUME 10.0 - -enum -{ - PROP_0, - PROP_DEVICE, - PROP_DEVICE_NAME, - PROP_VOLUME, - PROP_MUTE, - PROP_LAST -}; - -GST_BOILERPLATE_FULL (GstOss4Sink, gst_oss4_sink, GstAudioSink, - GST_TYPE_AUDIO_SINK, gst_oss4_sink_init_interfaces); - -static void -gst_oss4_sink_dispose (GObject * object) -{ - GstOss4Sink *osssink = GST_OSS4_SINK (object); - - if (osssink->probed_caps) { - gst_caps_unref (osssink->probed_caps); - osssink->probed_caps = NULL; - } - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -gst_oss4_sink_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - GstPadTemplate *templ; - - gst_element_class_set_details_simple (element_class, - "OSS v4 Audio Sink", "Sink/Audio", - "Output to a sound card via OSS version 4", - "Tim-Philipp Müller <tim centricular net>"); - - templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - gst_oss4_audio_get_template_caps ()); - gst_element_class_add_pad_template (element_class, templ); -} - -static void -gst_oss4_sink_class_init (GstOss4SinkClass * klass) -{ - GstAudioSinkClass *audiosink_class = (GstAudioSinkClass *) klass; - GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass; - GObjectClass *gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_oss4_sink_dispose); - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_oss4_sink_finalise); - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_oss4_sink_get_property); - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_oss4_sink_set_property); - - g_object_class_install_property (gobject_class, PROP_DEVICE, - g_param_spec_string ("device", "Device", - "OSS4 device (e.g. /dev/oss/hdaudio0/pcm0 or /dev/dspN) " - "(NULL = use first available playback device)", - DEFAULT_DEVICE, G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, - g_param_spec_string ("device-name", "Device name", - "Human-readable name of the sound device", DEFAULT_DEVICE_NAME, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_VOLUME, - g_param_spec_double ("volume", "Volume", - "Linear volume of this stream, 1.0=100%", 0.0, MAX_VOLUME, - DEFAULT_VOLUME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_MUTE, - g_param_spec_boolean ("mute", "Mute", - "Mute state of this stream", DEFAULT_MUTE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss4_sink_getcaps); - - audiosink_class->open = GST_DEBUG_FUNCPTR (gst_oss4_sink_open_func); - audiosink_class->close = GST_DEBUG_FUNCPTR (gst_oss4_sink_close); - audiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_oss4_sink_prepare); - audiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss4_sink_unprepare); - audiosink_class->write = GST_DEBUG_FUNCPTR (gst_oss4_sink_write); - audiosink_class->delay = GST_DEBUG_FUNCPTR (gst_oss4_sink_delay); - audiosink_class->reset = GST_DEBUG_FUNCPTR (gst_oss4_sink_reset); -} - -static void -gst_oss4_sink_init (GstOss4Sink * osssink, GstOss4SinkClass * klass) -{ - const gchar *device; - - device = g_getenv ("AUDIODEV"); - if (device == NULL) - device = DEFAULT_DEVICE; - osssink->device = g_strdup (device); - osssink->fd = -1; - osssink->bytes_per_sample = 0; - osssink->probed_caps = NULL; - osssink->device_name = NULL; - osssink->mute_volume = 100 | (100 << 8); -} - -static void -gst_oss4_sink_finalise (GObject * object) -{ - GstOss4Sink *osssink = GST_OSS4_SINK (object); - - g_free (osssink->device); - osssink->device = NULL; - - g_list_free (osssink->property_probe_list); - osssink->property_probe_list = NULL; - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_oss4_sink_set_volume (GstOss4Sink * oss, gdouble volume) -{ - int ivol; - - volume = volume * 100.0; - ivol = (int) volume | ((int) volume << 8); - GST_OBJECT_LOCK (oss); - if (ioctl (oss->fd, SNDCTL_DSP_SETPLAYVOL, &ivol) < 0) { - GST_LOG_OBJECT (oss, "SETPLAYVOL failed"); - } - GST_OBJECT_UNLOCK (oss); -} - -static gdouble -gst_oss4_sink_get_volume (GstOss4Sink * oss) -{ - int ivol, lvol, rvol; - gdouble dvol = DEFAULT_VOLUME; - - GST_OBJECT_LOCK (oss); - if (ioctl (oss->fd, SNDCTL_DSP_GETPLAYVOL, &ivol) < 0) { - GST_LOG_OBJECT (oss, "GETPLAYVOL failed"); - } else { - /* Return the higher of the two volume channels, if different */ - lvol = ivol & 0xff; - rvol = (ivol >> 8) & 0xff; - dvol = MAX (lvol, rvol) / 100.0; - } - GST_OBJECT_UNLOCK (oss); - - return dvol; -} - -static void -gst_oss4_sink_set_mute (GstOss4Sink * oss, gboolean mute) -{ - int ivol; - - if (mute) { - /* - * OSSv4 does not have a per-channel mute, so simulate by setting - * the value to 0. Save the volume before doing a mute so we can - * reset the value when the user un-mutes. - */ - ivol = 0; - - GST_OBJECT_LOCK (oss); - if (ioctl (oss->fd, SNDCTL_DSP_GETPLAYVOL, &oss->mute_volume) < 0) { - GST_LOG_OBJECT (oss, "GETPLAYVOL failed"); - } - if (ioctl (oss->fd, SNDCTL_DSP_SETPLAYVOL, &ivol) < 0) { - GST_LOG_OBJECT (oss, "SETPLAYVOL failed"); - } - GST_OBJECT_UNLOCK (oss); - } else { - /* - * If the saved volume is 0, then reset it to 100. Otherwise the mute - * can get stuck. This can happen, for example, due to rounding - * errors in converting from the float to an integer. - */ - if (oss->mute_volume == 0) { - oss->mute_volume = 100 | (100 << 8); - } - GST_OBJECT_LOCK (oss); - if (ioctl (oss->fd, SNDCTL_DSP_SETPLAYVOL, &oss->mute_volume) < 0) { - GST_LOG_OBJECT (oss, "SETPLAYVOL failed"); - } - GST_OBJECT_UNLOCK (oss); - } -} - -static gboolean -gst_oss4_sink_get_mute (GstOss4Sink * oss) -{ - int ivol, lvol, rvol; - - GST_OBJECT_LOCK (oss); - if (ioctl (oss->fd, SNDCTL_DSP_GETPLAYVOL, &ivol) < 0) { - GST_LOG_OBJECT (oss, "GETPLAYVOL failed"); - lvol = rvol = 100; - } else { - lvol = ivol & 0xff; - rvol = (ivol >> 8) & 0xff; - } - GST_OBJECT_UNLOCK (oss); - - return (lvol == 0 && rvol == 0); -} - -static void -gst_oss4_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstOss4Sink *oss = GST_OSS4_SINK (object); - - switch (prop_id) { - case PROP_DEVICE: - GST_OBJECT_LOCK (oss); - if (oss->fd == -1) { - g_free (oss->device); - oss->device = g_value_dup_string (value); - if (oss->probed_caps) { - gst_caps_unref (oss->probed_caps); - oss->probed_caps = NULL; - } - g_free (oss->device_name); - oss->device_name = NULL; - } else { - g_warning ("%s: can't change \"device\" property while audio sink " - "is open", GST_OBJECT_NAME (oss)); - } - GST_OBJECT_UNLOCK (oss); - break; - case PROP_VOLUME: - gst_oss4_sink_set_volume (oss, g_value_get_double (value)); - break; - case PROP_MUTE: - gst_oss4_sink_set_mute (oss, g_value_get_boolean (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_oss4_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstOss4Sink *oss = GST_OSS4_SINK (object); - - switch (prop_id) { - case PROP_DEVICE: - GST_OBJECT_LOCK (oss); - g_value_set_string (value, oss->device); - GST_OBJECT_UNLOCK (oss); - break; - case PROP_DEVICE_NAME: - GST_OBJECT_LOCK (oss); - if (oss->fd == -1 && oss->device != NULL) { - /* If device is set, try to retrieve the name even if we're not open */ - if (gst_oss4_sink_open (GST_AUDIO_SINK (oss), TRUE)) { - g_value_set_string (value, oss->device_name); - gst_oss4_sink_close (GST_AUDIO_SINK (oss)); - } else { - gchar *name = NULL; - - gst_oss4_property_probe_find_device_name_nofd (GST_OBJECT (oss), - oss->device, &name); - g_value_set_string (value, name); - g_free (name); - } - } else { - g_value_set_string (value, oss->device_name); - } - GST_OBJECT_UNLOCK (oss); - break; - case PROP_VOLUME: - g_value_set_double (value, gst_oss4_sink_get_volume (oss)); - break; - case PROP_MUTE: - g_value_set_boolean (value, gst_oss4_sink_get_mute (oss)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstCaps * -gst_oss4_sink_getcaps (GstBaseSink * bsink) -{ - GstOss4Sink *oss; - GstCaps *caps; - - oss = GST_OSS4_SINK (bsink); - - if (oss->fd == -1) { - caps = gst_caps_copy (gst_oss4_audio_get_template_caps ()); - } else if (oss->probed_caps) { - caps = gst_caps_copy (oss->probed_caps); - } else { - caps = gst_oss4_audio_probe_caps (GST_OBJECT (oss), oss->fd); - if (caps != NULL && !gst_caps_is_empty (caps)) { - oss->probed_caps = gst_caps_copy (caps); - } - } - - return caps; -} - -/* note: we must not take the object lock here unless we fix up get_property */ -static gboolean -gst_oss4_sink_open (GstAudioSink * asink, gboolean silent_errors) -{ - GstOss4Sink *oss; - gchar *device; - int mode; - - oss = GST_OSS4_SINK (asink); - - if (oss->device) - device = g_strdup (oss->device); - else - device = gst_oss4_audio_find_device (GST_OBJECT_CAST (oss)); - - /* desperate times, desperate measures */ - if (device == NULL) - device = g_strdup ("/dev/dsp0"); - - GST_INFO_OBJECT (oss, "Trying to open OSS4 device '%s'", device); - - /* we open in non-blocking mode even if we don't really want to do writes - * non-blocking because we can't be sure that this is really a genuine - * OSS4 device with well-behaved drivers etc. We really don't want to - * hang forever under any circumstances. */ - oss->fd = open (device, O_WRONLY | O_NONBLOCK, 0); - if (oss->fd == -1) { - switch (errno) { - case EBUSY: - goto busy; - case EACCES: - goto no_permission; - default: - goto open_failed; - } - } - - GST_INFO_OBJECT (oss, "Opened device '%s'", device); - - /* Make sure it's OSS4. If it's old OSS, let osssink handle it */ - if (!gst_oss4_audio_check_version (GST_OBJECT_CAST (oss), oss->fd)) - goto legacy_oss; - - /* now remove the non-blocking flag. */ - mode = fcntl (oss->fd, F_GETFL); - mode &= ~O_NONBLOCK; - if (fcntl (oss->fd, F_SETFL, mode) < 0) { - /* some drivers do no support unsetting the non-blocking flag, try to - * close/open the device then. This is racy but we error out properly. */ - GST_WARNING_OBJECT (oss, "failed to unset O_NONBLOCK (buggy driver?), " - "will try to re-open device now"); - gst_oss4_sink_close (asink); - if ((oss->fd = open (device, O_WRONLY, 0)) == -1) - goto non_block; - } - - oss->open_device = device; - - /* not using ENGINEINFO here because it sometimes returns a different and - * less useful name than AUDIOINFO for the same device */ - if (!gst_oss4_property_probe_find_device_name (GST_OBJECT (oss), oss->fd, - oss->open_device, &oss->device_name)) { - oss->device_name = NULL; - } - - /* list output routings, for informational purposes only so far */ - { - oss_mixer_enuminfo routings = { 0, }; - guint i; - - if (ioctl (oss->fd, SNDCTL_DSP_GET_PLAYTGT_NAMES, &routings) != -1) { - GST_LOG_OBJECT (oss, "%u output routings (static list: %d)", - routings.nvalues, !!(routings.version == 0)); - for (i = 0; i < routings.nvalues; ++i) { - GST_LOG_OBJECT (oss, " output routing %d: %s", i, - &routings.strings[routings.strindex[i]]); - } - } - } - - return TRUE; - - /* ERRORS */ -busy: - { - if (!silent_errors) { - GST_ELEMENT_ERROR (oss, RESOURCE, BUSY, - (_("Could not open audio device for playback. " - "Device is being used by another application.")), (NULL)); - } - g_free (device); - return FALSE; - } -no_permission: - { - if (!silent_errors) { - GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE, - (_("Could not open audio device for playback. " - "You don't have permission to open the device.")), - GST_ERROR_SYSTEM); - } - g_free (device); - return FALSE; - } -open_failed: - { - if (!silent_errors) { - GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE, - (_("Could not open audio device for playback.")), GST_ERROR_SYSTEM); - } - g_free (device); - return FALSE; - } -legacy_oss: - { - if (!silent_errors) { - GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE, - (_("Could not open audio device for playback. " - "This version of the Open Sound System is not supported by this " - "element.")), ("Try the 'osssink' element instead")); - } - gst_oss4_sink_close (asink); - g_free (device); - return FALSE; - } -non_block: - { - if (!silent_errors) { - GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL), - ("Unable to set device %s into non-blocking mode: %s", - oss->device, g_strerror (errno))); - } - g_free (device); - return FALSE; - } -} - -static gboolean -gst_oss4_sink_open_func (GstAudioSink * asink) -{ - return gst_oss4_sink_open (asink, FALSE); -} - -static gboolean -gst_oss4_sink_close (GstAudioSink * asink) -{ - GstOss4Sink *oss = GST_OSS4_SINK (asink); - - if (oss->fd != -1) { - GST_DEBUG_OBJECT (oss, "closing device"); - close (oss->fd); - oss->fd = -1; - } - - oss->bytes_per_sample = 0; - /* we keep the probed caps cached, at least until the device changes */ - - g_free (oss->open_device); - oss->open_device = NULL; - - g_free (oss->device_name); - oss->device_name = NULL; - - if (oss->probed_caps) { - gst_caps_unref (oss->probed_caps); - oss->probed_caps = NULL; - } - - return TRUE; -} - -static gboolean -gst_oss4_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) -{ - GstOss4Sink *oss; - - oss = GST_OSS4_SINK (asink); - - if (!gst_oss4_audio_set_format (GST_OBJECT_CAST (oss), oss->fd, spec)) { - GST_WARNING_OBJECT (oss, "Couldn't set requested format %" GST_PTR_FORMAT, - spec->caps); - return FALSE; - } - - oss->bytes_per_sample = spec->bytes_per_sample; - return TRUE; -} - -static gboolean -gst_oss4_sink_unprepare (GstAudioSink * asink) -{ - /* could do a SNDCTL_DSP_HALT, but the OSS manual recommends a close/open, - * since HALT won't properly reset some devices, apparently */ - - if (!gst_oss4_sink_close (asink)) - goto couldnt_close; - - if (!gst_oss4_sink_open_func (asink)) - goto couldnt_reopen; - - return TRUE; - - /* ERRORS */ -couldnt_close: - { - GST_DEBUG_OBJECT (asink, "Couldn't close the audio device"); - return FALSE; - } -couldnt_reopen: - { - GST_DEBUG_OBJECT (asink, "Couldn't reopen the audio device"); - return FALSE; - } -} - -static guint -gst_oss4_sink_write (GstAudioSink * asink, gpointer data, guint length) -{ - GstOss4Sink *oss; - int n; - - oss = GST_OSS4_SINK_CAST (asink); - - n = write (oss->fd, data, length); - GST_LOG_OBJECT (asink, "wrote %d/%d samples, %d bytes", - n / oss->bytes_per_sample, length / oss->bytes_per_sample, n); - - if (G_UNLIKELY (n < 0)) { - switch (errno) { - case ENOTSUP: - case EACCES:{ - /* This is the most likely cause, I think */ - GST_ELEMENT_ERROR (asink, RESOURCE, WRITE, - (_("Playback is not supported by this audio device.")), - ("write: %s (device: %s) (maybe this is an input-only device?)", - g_strerror (errno), oss->open_device)); - break; - } - default:{ - GST_ELEMENT_ERROR (asink, RESOURCE, WRITE, - (_("Audio playback error.")), - ("write: %s (device: %s)", g_strerror (errno), oss->open_device)); - break; - } - } - } - - return n; -} - -static guint -gst_oss4_sink_delay (GstAudioSink * asink) -{ - GstOss4Sink *oss; - gint delay = -1; - - oss = GST_OSS4_SINK_CAST (asink); - - GST_OBJECT_LOCK (oss); - if (ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay) < 0 || delay < 0) { - GST_LOG_OBJECT (oss, "GETODELAY failed"); - } - GST_OBJECT_UNLOCK (oss); - - if (G_UNLIKELY (delay < 0)) /* error case */ - return 0; - - return delay / oss->bytes_per_sample; -} - -static void -gst_oss4_sink_reset (GstAudioSink * asink) -{ - /* There's nothing we can do here really: OSS can't handle access to the - * same device/fd from multiple threads and might deadlock or blow up in - * other ways if we try an ioctl SNDCTL_DSP_HALT or similar */ -} - -static void -gst_oss4_sink_init_interfaces (GType type) -{ - static const GInterfaceInfo svol_iface_info = { - NULL, NULL, NULL - }; - - g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_iface_info); - - gst_oss4_add_property_probe_interface (type); -} diff --git a/sys/oss4/oss4-sink.h b/sys/oss4/oss4-sink.h deleted file mode 100644 index b1489a7d8..000000000 --- a/sys/oss4/oss4-sink.h +++ /dev/null @@ -1,64 +0,0 @@ -/* GStreamer OSS4 audio sink - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef GST_OSS4_SINK_H -#define GST_OSS4_SINK_H - - -#include <gst/gst.h> -#include <gst/audio/gstaudiosink.h> - -G_BEGIN_DECLS - -#define GST_TYPE_OSS4_SINK (gst_oss4_sink_get_type()) -#define GST_OSS4_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_SINK,GstOss4Sink)) -#define GST_OSS4_SINK_CAST(obj) ((GstOss4Sink *)(obj)) -#define GST_OSS4_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_SINK,GstOss4SinkClass)) -#define GST_IS_OSS4_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_SINK)) -#define GST_IS_OSS4_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_SINK)) - -typedef struct _GstOss4Sink GstOss4Sink; -typedef struct _GstOss4SinkClass GstOss4SinkClass; - -struct _GstOss4Sink { - GstAudioSink audio_sink; - - gchar * device; /* NULL if none was set */ - gchar * open_device; /* the device we opened */ - gchar * device_name; /* set if the device is open */ - gint fd; /* -1 if not open */ - gint bytes_per_sample; - gint mute_volume; - - GstCaps * probed_caps; - - GList * property_probe_list; -}; - -struct _GstOss4SinkClass { - GstAudioSinkClass audio_sink_class; -}; - -GType gst_oss4_sink_get_type (void); - -G_END_DECLS - -#endif /* GST_OSS4_SINK_H */ - - diff --git a/sys/oss4/oss4-soundcard.h b/sys/oss4/oss4-soundcard.h deleted file mode 100644 index 8b124892b..000000000 --- a/sys/oss4/oss4-soundcard.h +++ /dev/null @@ -1,2067 +0,0 @@ -/* - * Purpose: The C/C++ header file that defines the OSS API. - * Description: - * This header file contains all the declarations required to compile OSS - * programs. The latest version is always installed together with OSS - * use of the latest version is strongly recommended. - * - * {!notice This header file contains many obsolete definitions - * (for compatibility with older applications that still ned them). - * Do not use this file as a reference manual of OSS. - * Please check the OSS Programmer's guide for descriptions - * of the supported API details (http://manuals.opensound.com/developer).} - */ - -#ifndef SOUNDCARD_H -#define SOUNDCARD_H - -#define COPYING40 Copyright (C) 4Front Technologies 2000-2006. Released under the BSD license. - -#if defined(__cplusplus) -#define EXTERNC extern "C" -#else -#define EXTERNC extern -#endif /* EXTERN_C_WRAPPERS */ - -#define OSS_VERSION 0x040090 // Pre 4.1 - -#define SOUND_VERSION OSS_VERSION -#define OPEN_SOUND_SYSTEM - -#if defined(__hpux) && !defined(_HPUX_SOURCE) -# error "-D_HPUX_SOURCE must be used when compiling OSS applications" -#endif - -#ifdef __hpux -#include <sys/ioctl.h> -#endif - -#ifdef linux -/* In Linux we need to be prepared for cross compiling */ -#include <linux/ioctl.h> -#else -# ifdef __FreeBSD__ -# include <sys/ioccom.h> -# else -# include <sys/ioctl.h> -# endif -#endif - -#ifndef __SIOWR -#if defined(__hpux) || (defined(_IOWR) && (defined(_AIX) || (!defined(sun) && !defined(sparc) && !defined(__INCioctlh) && !defined(__Lynx__)))) - -/* - * Make sure the ioctl macros are compatible with the ones already used - * by this operating system. - */ -#define SIOCPARM_MASK IOCPARM_MASK -#define SIOC_VOID IOC_VOID -#define SIOC_OUT IOC_OUT -#define SIOC_IN IOC_IN -#define SIOC_INOUT IOC_INOUT -#define __SIOC_SIZE _IOC_SIZE -#define __SIOC_DIR _IOC_DIR -#define __SIOC_NONE _IOC_NONE -#define __SIOC_READ _IOC_READ -#define __SIOC_WRITE _IOC_WRITE -#define __SIO _IO -#define __SIOR _IOR -#define __SIOW _IOW -#define __SIOWR _IOWR -#else - -/* #define SIOCTYPE (0xff<<8) */ -#define SIOCPARM_MASK 0x1fff /* parameters must be < 8192 bytes */ -#define SIOC_VOID 0x00000000 /* no parameters */ -#define SIOC_OUT 0x20000000 /* copy out parameters */ -#define SIOC_IN 0x40000000 /* copy in parameters */ -#define SIOC_INOUT (SIOC_IN|SIOC_OUT) - -#define __SIO(x,y) ((int)(SIOC_VOID|(x<<8)|y)) -#define __SIOR(x,y,t) ((int)(SIOC_OUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y)) -#define __SIOW(x,y,t) ((int)(SIOC_IN|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y)) -#define __SIOWR(x,y,t) ((int)(SIOC_INOUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y)) -#define __SIOC_SIZE(x) ((x>>16)&SIOCPARM_MASK) -#define __SIOC_DIR(x) (x & 0xf0000000) -#define __SIOC_NONE SIOC_VOID -#define __SIOC_READ SIOC_OUT -#define __SIOC_WRITE SIOC_IN -# endif /* _IOWR */ -#endif /* !__SIOWR */ - -#define OSS_LONGNAME_SIZE 64 -#define OSS_LABEL_SIZE 16 -#define OSS_DEVNODE_SIZE 32 -typedef char oss_longname_t[OSS_LONGNAME_SIZE]; -typedef char oss_label_t[OSS_LABEL_SIZE]; -typedef char oss_devnode_t[OSS_DEVNODE_SIZE]; - -#ifndef DISABLE_SEQUENCER -/* - **************************************************************************** - * IOCTL Commands for /dev/sequencer and /dev/music (AKA /dev/sequencer2) - * - * Note that this interface is obsolete and no longer developed. New - * applications should use /dev/midi instead. - ****************************************************************************/ -#define SNDCTL_SEQ_RESET __SIO ('Q', 0) -#define SNDCTL_SEQ_SYNC __SIO ('Q', 1) -#define SNDCTL_SYNTH_INFO __SIOWR('Q', 2, struct synth_info) -#define SNDCTL_SEQ_CTRLRATE __SIOWR('Q', 3, int) /* Set/get timer resolution (HZ) */ -#define SNDCTL_SEQ_GETOUTCOUNT __SIOR ('Q', 4, int) -#define SNDCTL_SEQ_GETINCOUNT __SIOR ('Q', 5, int) -#define SNDCTL_SEQ_PERCMODE __SIOW ('Q', 6, int) -#define SNDCTL_FM_LOAD_INSTR __SIOW ('Q', 7, struct sbi_instrument) /* Obsolete. Don't use!!!!!! */ -#define SNDCTL_SEQ_TESTMIDI __SIOW ('Q', 8, int) -#define SNDCTL_SEQ_RESETSAMPLES __SIOW ('Q', 9, int) -#define SNDCTL_SEQ_NRSYNTHS __SIOR ('Q',10, int) -#define SNDCTL_SEQ_NRMIDIS __SIOR ('Q',11, int) -#define SNDCTL_MIDI_INFO __SIOWR('Q',12, struct midi_info) /* OBSOLETE - use SNDCTL_MIDIINFO instead */ -#define SNDCTL_SEQ_THRESHOLD __SIOW ('Q',13, int) -#define SNDCTL_SYNTH_MEMAVL __SIOWR('Q',14, int) /* in=dev#, out=memsize */ -#define SNDCTL_FM_4OP_ENABLE __SIOW ('Q',15, int) /* in=dev# */ -#define SNDCTL_SEQ_PANIC __SIO ('Q',17) -#define SNDCTL_SEQ_OUTOFBAND __SIOW ('Q',18, struct seq_event_rec) -#define SNDCTL_SEQ_GETTIME __SIOR ('Q',19, int) -#define SNDCTL_SYNTH_ID __SIOWR('Q',20, struct synth_info) -#define SNDCTL_SYNTH_CONTROL __SIOWR('Q',21, struct synth_control) -#define SNDCTL_SYNTH_REMOVESAMPLE __SIOWR('Q',22, struct remove_sample) /* Reserved for future use */ -#define SNDCTL_SEQ_TIMING_ENABLE __SIO ('Q', 23) /* Enable incoming MIDI timing messages */ -#define SNDCTL_SEQ_ACTSENSE_ENABLE __SIO ('Q', 24) /* Enable incoming active sensing messages */ -#define SNDCTL_SEQ_RT_ENABLE __SIO ('Q', 25) /* Enable other incoming realtime messages */ - -typedef struct synth_control -{ - int devno; /* Synthesizer # */ - char data[4000]; /* Device spesific command/data record */ -} synth_control; - -typedef struct remove_sample -{ - int devno; /* Synthesizer # */ - int bankno; /* MIDI bank # (0=General MIDI) */ - int instrno; /* MIDI instrument number */ -} remove_sample; - -typedef struct seq_event_rec -{ - unsigned char arr[8]; -} seq_event_rec; - -#define SNDCTL_TMR_TIMEBASE __SIOWR('T', 1, int) -#define SNDCTL_TMR_START __SIO ('T', 2) -#define SNDCTL_TMR_STOP __SIO ('T', 3) -#define SNDCTL_TMR_CONTINUE __SIO ('T', 4) -#define SNDCTL_TMR_TEMPO __SIOWR('T', 5, int) -#define SNDCTL_TMR_SOURCE __SIOWR('T', 6, int) -# define TMR_INTERNAL 0x00000001 -# define TMR_EXTERNAL 0x00000002 -# define TMR_MODE_MIDI 0x00000010 -# define TMR_MODE_FSK 0x00000020 -# define TMR_MODE_CLS 0x00000040 -# define TMR_MODE_SMPTE 0x00000080 -#define SNDCTL_TMR_METRONOME __SIOW ('T', 7, int) -#define SNDCTL_TMR_SELECT __SIOW ('T', 8, int) - -/* - * Sample loading mechanism for internal synthesizers (/dev/sequencer) - * (for the .PAT format). - */ - -struct patch_info -{ - unsigned short key; /* Use WAVE_PATCH here */ -#define WAVE_PATCH _PATCHKEY(0x04) -#define GUS_PATCH WAVE_PATCH -#define WAVEFRONT_PATCH _PATCHKEY(0x06) - - short device_no; /* Synthesizer number */ - short instr_no; /* Midi pgm# */ - - unsigned int mode; -/* - * The least significant byte has the same format than the GUS .PAT - * files - */ -#define WAVE_16_BITS 0x01 /* bit 0 = 8 or 16 bit wave data. */ -#define WAVE_UNSIGNED 0x02 /* bit 1 = Signed - Unsigned data. */ -#define WAVE_LOOPING 0x04 /* bit 2 = looping enabled-1. */ -#define WAVE_BIDIR_LOOP 0x08 /* bit 3 = Set is bidirectional looping. */ -#define WAVE_LOOP_BACK 0x10 /* bit 4 = Set is looping backward. */ -#define WAVE_SUSTAIN_ON 0x20 /* bit 5 = Turn sustaining on. (Env. pts. 3) */ -#define WAVE_ENVELOPES 0x40 /* bit 6 = Enable envelopes - 1 */ -#define WAVE_FAST_RELEASE 0x80 /* bit 7 = Shut off immediately after note off */ - /* (use the env_rate/env_offs fields). */ -/* Linux specific bits */ -#define WAVE_VIBRATO 0x00010000 /* The vibrato info is valid */ -#define WAVE_TREMOLO 0x00020000 /* The tremolo info is valid */ -#define WAVE_SCALE 0x00040000 /* The scaling info is valid */ -#define WAVE_FRACTIONS 0x00080000 /* Fraction information is valid */ -/* Reserved bits */ -#define WAVE_ROM 0x40000000 /* For future use */ -#define WAVE_MULAW 0x20000000 /* For future use */ -/* Other bits must be zeroed */ - - int len; /* Size of the wave data in bytes */ - int loop_start, loop_end; /* Byte offsets from the beginning */ - -/* - * The base_freq and base_note fields are used when computing the - * playback speed for a note. The base_note defines the tone frequency - * which is heard if the sample is played using the base_freq as the - * playback speed. - * - * The low_note and high_note fields define the minimum and maximum note - * frequencies for which this sample is valid. It is possible to define - * more than one samples for an instrument number at the same time. The - * low_note and high_note fields are used to select the most suitable one. - * - * The fields base_note, high_note and low_note should contain - * the note frequency multiplied by 1000. For example value for the - * middle A is 440*1000. - */ - - unsigned int base_freq; - unsigned int base_note; - unsigned int high_note; - unsigned int low_note; - int panning; /* -128=left, 127=right */ - int detuning; - - /* Envelope. Enabled by mode bit WAVE_ENVELOPES */ - unsigned char env_rate[6]; /* GUS HW ramping rate */ - unsigned char env_offset[6]; /* 255 == 100% */ - - /* - * The tremolo, vibrato and scale info are not supported yet. - * Enable by setting the mode bits WAVE_TREMOLO, WAVE_VIBRATO or - * WAVE_SCALE - */ - - unsigned char tremolo_sweep; - unsigned char tremolo_rate; - unsigned char tremolo_depth; - - unsigned char vibrato_sweep; - unsigned char vibrato_rate; - unsigned char vibrato_depth; - - int scale_frequency; - unsigned int scale_factor; /* from 0 to 2048 or 0 to 2 */ - - int volume; - int fractions; - int reserved1; - int spare[2]; - char data[1]; /* The waveform data starts here */ -}; - -struct sysex_info -{ - short key; /* Use SYSEX_PATCH or MAUI_PATCH here */ -#define SYSEX_PATCH _PATCHKEY(0x05) -#define MAUI_PATCH _PATCHKEY(0x06) - short device_no; /* Synthesizer number */ - int len; /* Size of the sysex data in bytes */ - unsigned char data[1]; /* Sysex data starts here */ -}; - -/* - * /dev/sequencer input events. - * - * The data written to the /dev/sequencer is a stream of events. Events - * are records of 4 or 8 bytes. The first byte defines the size. - * Any number of events can be written with a write call. There - * is a set of macros for sending these events. Use these macros if you - * want to maximize portability of your program. - * - * Events SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO. Are also input events. - * (All input events are currently 4 bytes long. Be prepared to support - * 8 byte events also. If you receive any event having first byte >= 128, - * it's a 8 byte event. - * - * The events are documented at the end of this file. - * - * Normal events (4 bytes) - * There is also a 8 byte version of most of the 4 byte events. The - * 8 byte one is recommended. - * - * NOTE! All 4 byte events are now obsolete. Applications should not write - * them. However 4 byte events are still used as inputs from - * /dev/sequencer (/dev/music uses only 8 byte ones). - */ -#define SEQ_NOTEOFF 0 -#define SEQ_FMNOTEOFF SEQ_NOTEOFF /* Just old name */ -#define SEQ_NOTEON 1 -#define SEQ_FMNOTEON SEQ_NOTEON -#define SEQ_WAIT TMR_WAIT_ABS -#define SEQ_PGMCHANGE 3 -#define SEQ_FMPGMCHANGE SEQ_PGMCHANGE -#define SEQ_SYNCTIMER TMR_START -#define SEQ_MIDIPUTC 5 -#define SEQ_DRUMON 6 /*** OBSOLETE ***/ -#define SEQ_DRUMOFF 7 /*** OBSOLETE ***/ -#define SEQ_ECHO TMR_ECHO /* For synching programs with output */ -#define SEQ_AFTERTOUCH 9 -#define SEQ_CONTROLLER 10 -#define SEQ_BALANCE 11 -#define SEQ_VOLMODE 12 - -/************************************ - * Midi controller numbers * - ************************************/ -/* - * Controllers 0 to 31 (0x00 to 0x1f) and - * 32 to 63 (0x20 to 0x3f) are continuous - * controllers. - * In the MIDI 1.0 these controllers are sent using - * two messages. Controller numbers 0 to 31 are used - * to send the MSB and the controller numbers 32 to 63 - * are for the LSB. Note that just 7 bits are used in MIDI bytes. - */ - -#define CTL_BANK_SELECT 0x00 -#define CTL_MODWHEEL 0x01 -#define CTL_BREATH 0x02 -/* undefined 0x03 */ -#define CTL_FOOT 0x04 -#define CTL_PORTAMENTO_TIME 0x05 -#define CTL_DATA_ENTRY 0x06 -#define CTL_MAIN_VOLUME 0x07 -#define CTL_BALANCE 0x08 -/* undefined 0x09 */ -#define CTL_PAN 0x0a -#define CTL_EXPRESSION 0x0b -/* undefined 0x0c */ -/* undefined 0x0d */ -/* undefined 0x0e */ -/* undefined 0x0f */ -#define CTL_GENERAL_PURPOSE1 0x10 -#define CTL_GENERAL_PURPOSE2 0x11 -#define CTL_GENERAL_PURPOSE3 0x12 -#define CTL_GENERAL_PURPOSE4 0x13 -/* undefined 0x14 - 0x1f */ - -/* undefined 0x20 */ -/* The controller numbers 0x21 to 0x3f are reserved for the */ -/* least significant bytes of the controllers 0x00 to 0x1f. */ -/* These controllers are not recognised by the driver. */ - -/* Controllers 64 to 69 (0x40 to 0x45) are on/off switches. */ -/* 0=OFF and 127=ON (intermediate values are possible) */ -#define CTL_DAMPER_PEDAL 0x40 -#define CTL_SUSTAIN 0x40 /* Alias */ -#define CTL_HOLD 0x40 /* Alias */ -#define CTL_PORTAMENTO 0x41 -#define CTL_SOSTENUTO 0x42 -#define CTL_SOFT_PEDAL 0x43 -/* undefined 0x44 */ -#define CTL_HOLD2 0x45 -/* undefined 0x46 - 0x4f */ - -#define CTL_GENERAL_PURPOSE5 0x50 -#define CTL_GENERAL_PURPOSE6 0x51 -#define CTL_GENERAL_PURPOSE7 0x52 -#define CTL_GENERAL_PURPOSE8 0x53 -/* undefined 0x54 - 0x5a */ -#define CTL_EXT_EFF_DEPTH 0x5b -#define CTL_TREMOLO_DEPTH 0x5c -#define CTL_CHORUS_DEPTH 0x5d -#define CTL_DETUNE_DEPTH 0x5e -#define CTL_CELESTE_DEPTH 0x5e /* Alias for the above one */ -#define CTL_PHASER_DEPTH 0x5f -#define CTL_DATA_INCREMENT 0x60 -#define CTL_DATA_DECREMENT 0x61 -#define CTL_NONREG_PARM_NUM_LSB 0x62 -#define CTL_NONREG_PARM_NUM_MSB 0x63 -#define CTL_REGIST_PARM_NUM_LSB 0x64 -#define CTL_REGIST_PARM_NUM_MSB 0x65 -/* undefined 0x66 - 0x78 */ -/* reserved 0x79 - 0x7f */ - -/* Pseudo controllers (not midi compatible) */ -#define CTRL_PITCH_BENDER 255 -#define CTRL_PITCH_BENDER_RANGE 254 -#define CTRL_EXPRESSION 253 /* Obsolete */ -#define CTRL_MAIN_VOLUME 252 /* Obsolete */ - -/* - * Volume mode defines how volumes are used - */ - -#define VOL_METHOD_ADAGIO 1 -#define VOL_METHOD_LINEAR 2 - -/* - * Note! SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO are used also as - * input events. - */ - -/* - * Event codes 0xf0 to 0xfc are reserved for future extensions. - */ - -#define SEQ_FULLSIZE 0xfd /* Long events */ -/* - * SEQ_FULLSIZE events are used for loading patches/samples to the - * synthesizer devices. These events are passed directly to the driver - * of the associated synthesizer device. There is no limit to the size - * of the extended events. These events are not queued but executed - * immediately when the write() is called (execution can take several - * seconds of time). - * - * When a SEQ_FULLSIZE message is written to the device, it must - * be written using exactly one write() call. Other events cannot - * be mixed to the same write. - * - * For FM synths (YM3812/OPL3) use struct sbi_instrument and write it to the - * /dev/sequencer. Don't write other data together with the instrument structure - * Set the key field of the structure to FM_PATCH. The device field is used to - * route the patch to the corresponding device. - * - * For wave table use struct patch_info. Initialize the key field - * to WAVE_PATCH. - */ -#define SEQ_PRIVATE 0xfe /* Low level HW dependent events (8 bytes) */ -#define SEQ_EXTENDED 0xff /* Extended events (8 bytes) OBSOLETE */ - -/* - * Record for FM patches - */ - -typedef unsigned char sbi_instr_data[32]; - -struct sbi_instrument -{ - unsigned short key; /* FM_PATCH or OPL3_PATCH */ -#define FM_PATCH _PATCHKEY(0x01) -#define OPL3_PATCH _PATCHKEY(0x03) - short device; /* Synth# (0-4) */ - int channel; /* Program# to be initialized */ - sbi_instr_data operators; /* Register settings for operator cells (.SBI format) */ -}; - -struct synth_info -{ /* Read only */ - char name[30]; - int device; /* 0-N. INITIALIZE BEFORE CALLING */ - int synth_type; -#define SYNTH_TYPE_FM 0 -#define SYNTH_TYPE_SAMPLE 1 -#define SYNTH_TYPE_MIDI 2 /* Midi interface */ - - int synth_subtype; -#define FM_TYPE_ADLIB 0x00 -#define FM_TYPE_OPL3 0x01 -#define MIDI_TYPE_MPU401 0x401 - -#define SAMPLE_TYPE_BASIC 0x10 -#define SAMPLE_TYPE_GUS SAMPLE_TYPE_BASIC -#define SAMPLE_TYPE_WAVEFRONT 0x11 - - int perc_mode; /* No longer supported */ - int nr_voices; - int nr_drums; /* Obsolete field */ - int instr_bank_size; - unsigned int capabilities; -#define SYNTH_CAP_PERCMODE 0x00000001 /* No longer used */ -#define SYNTH_CAP_OPL3 0x00000002 /* Set if OPL3 supported */ -#define SYNTH_CAP_INPUT 0x00000004 /* Input (MIDI) device */ - int dummies[19]; /* Reserve space */ -}; - -struct sound_timer_info -{ - char name[32]; - int caps; -}; - -struct midi_info /* OBSOLETE */ -{ - char name[30]; - int device; /* 0-N. INITIALIZE BEFORE CALLING */ - unsigned int capabilities; /* To be defined later */ - int dev_type; - int dummies[18]; /* Reserve space */ -}; - -/* - * Level 2 event types for /dev/sequencer - */ - -/* - * The 4 most significant bits of byte 0 specify the class of - * the event: - * - * 0x8X = system level events, - * 0x9X = device/port specific events, event[1] = device/port, - * The last 4 bits give the subtype: - * 0x02 = Channel event (event[3] = chn). - * 0x01 = note event (event[4] = note). - * (0x01 is not used alone but always with bit 0x02). - * event[2] = MIDI message code (0x80=note off etc.) - * - */ - -#define EV_SEQ_LOCAL 0x80 -#define EV_TIMING 0x81 -#define EV_CHN_COMMON 0x92 -#define EV_CHN_VOICE 0x93 -#define EV_SYSEX 0x94 -#define EV_SYSTEM 0x95 /* MIDI system and real time messages (input only) */ -/* - * Event types 200 to 220 are reserved for application use. - * These numbers will not be used by the driver. - */ - -/* - * Events for event type EV_CHN_VOICE - */ - -#define MIDI_NOTEOFF 0x80 -#define MIDI_NOTEON 0x90 -#define MIDI_KEY_PRESSURE 0xA0 - -/* - * Events for event type EV_CHN_COMMON - */ - -#define MIDI_CTL_CHANGE 0xB0 -#define MIDI_PGM_CHANGE 0xC0 -#define MIDI_CHN_PRESSURE 0xD0 -#define MIDI_PITCH_BEND 0xE0 - -#define MIDI_SYSTEM_PREFIX 0xF0 - -/* - * Timer event types - */ -#define TMR_WAIT_REL 1 /* Time relative to the prev time */ -#define TMR_WAIT_ABS 2 /* Absolute time since TMR_START */ -#define TMR_STOP 3 -#define TMR_START 4 -#define TMR_CONTINUE 5 -#define TMR_TEMPO 6 -#define TMR_ECHO 8 -#define TMR_CLOCK 9 /* MIDI clock */ -#define TMR_SPP 10 /* Song position pointer */ -#define TMR_TIMESIG 11 /* Time signature */ - -/* - * Local event types - */ -#define LOCL_STARTAUDIO 1 -#define LOCL_STARTAUDIO2 2 -#define LOCL_STARTAUDIO3 3 -#define LOCL_STARTAUDIO4 4 - -#if (!defined(__KERNEL__) && !defined(KERNEL) && !defined(INKERNEL) && !defined(_KERNEL)) || defined(USE_SEQ_MACROS) -/* - * Some convenience macros to simplify programming of the - * /dev/sequencer interface - * - * These macros define the API which should be used when possible. - */ -#define SEQ_DECLAREBUF() SEQ_USE_EXTBUF() - -void seqbuf_dump (void); /* This function must be provided by programs */ - -EXTERNC int OSS_init (int seqfd, int buflen); -EXTERNC void OSS_seqbuf_dump (int fd, unsigned char *buf, int buflen); -EXTERNC void OSS_seq_advbuf (int len, int fd, unsigned char *buf, int buflen); -EXTERNC void OSS_seq_needbuf (int len, int fd, unsigned char *buf, - int buflen); -EXTERNC void OSS_patch_caching (int dev, int chn, int patch, int fd, - unsigned char *buf, int buflen); -EXTERNC void OSS_drum_caching (int dev, int chn, int patch, int fd, - unsigned char *buf, int buflen); -EXTERNC void OSS_write_patch (int fd, unsigned char *buf, int len); -EXTERNC int OSS_write_patch2 (int fd, unsigned char *buf, int len); - -#define SEQ_PM_DEFINES int __foo_bar___ -#ifdef OSSLIB -# define SEQ_USE_EXTBUF() \ - EXTERNC unsigned char *_seqbuf; \ - EXTERNC int _seqbuflen;EXTERNC int _seqbufptr -# define SEQ_DEFINEBUF(len) SEQ_USE_EXTBUF();static int _requested_seqbuflen=len -# define _SEQ_ADVBUF(len) OSS_seq_advbuf(len, seqfd, _seqbuf, _seqbuflen) -# define _SEQ_NEEDBUF(len) OSS_seq_needbuf(len, seqfd, _seqbuf, _seqbuflen) -# define SEQ_DUMPBUF() OSS_seqbuf_dump(seqfd, _seqbuf, _seqbuflen) - -# define SEQ_LOAD_GMINSTR(dev, instr) \ - OSS_patch_caching(dev, -1, instr, seqfd, _seqbuf, _seqbuflen) -# define SEQ_LOAD_GMDRUM(dev, drum) \ - OSS_drum_caching(dev, -1, drum, seqfd, _seqbuf, _seqbuflen) -#else /* !OSSLIB */ - -# define SEQ_LOAD_GMINSTR(dev, instr) -# define SEQ_LOAD_GMDRUM(dev, drum) - -# define SEQ_USE_EXTBUF() \ - EXTERNC unsigned char _seqbuf[]; \ - EXTERNC int _seqbuflen;EXTERNC int _seqbufptr - -#ifndef USE_SIMPLE_MACROS -/* Sample seqbuf_dump() implementation: - * - * SEQ_DEFINEBUF (2048); -- Defines a buffer for 2048 bytes - * - * int seqfd; -- The file descriptor for /dev/sequencer. - * - * void - * seqbuf_dump () - * { - * if (_seqbufptr) - * if (write (seqfd, _seqbuf, _seqbufptr) == -1) - * { - * perror ("write /dev/sequencer"); - * exit (-1); - * } - * _seqbufptr = 0; - * } - */ - -#define SEQ_DEFINEBUF(len) \ - unsigned char _seqbuf[len]; int _seqbuflen = len;int _seqbufptr = 0 -#define _SEQ_NEEDBUF(len) \ - if ((_seqbufptr+(len)) > _seqbuflen) seqbuf_dump() -#define _SEQ_ADVBUF(len) _seqbufptr += len -#define SEQ_DUMPBUF seqbuf_dump -#else -/* - * This variation of the sequencer macros is used just to format one event - * using fixed buffer. - * - * The program using the macro library must define the following macros before - * using this library. - * - * #define _seqbuf name of the buffer (unsigned char[]) - * #define _SEQ_ADVBUF(len) If the applic needs to know the exact - * size of the event, this macro can be used. - * Otherwise this must be defined as empty. - * #define _seqbufptr Define the name of index variable or 0 if - * not required. - */ -#define _SEQ_NEEDBUF(len) /* empty */ -#endif -#endif /* !OSSLIB */ - -#define SEQ_VOLUME_MODE(dev, mode) \ - {_SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr] = SEQ_EXTENDED;\ - _seqbuf[_seqbufptr+1] = SEQ_VOLMODE;\ - _seqbuf[_seqbufptr+2] = (dev);\ - _seqbuf[_seqbufptr+3] = (mode);\ - _seqbuf[_seqbufptr+4] = 0;\ - _seqbuf[_seqbufptr+5] = 0;\ - _seqbuf[_seqbufptr+6] = 0;\ - _seqbuf[_seqbufptr+7] = 0;\ - _SEQ_ADVBUF(8);} - -/* - * Midi voice messages - */ - -#define _CHN_VOICE(dev, event, chn, note, parm) \ - {_SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr] = EV_CHN_VOICE;\ - _seqbuf[_seqbufptr+1] = (dev);\ - _seqbuf[_seqbufptr+2] = (event);\ - _seqbuf[_seqbufptr+3] = (chn);\ - _seqbuf[_seqbufptr+4] = (note);\ - _seqbuf[_seqbufptr+5] = (parm);\ - _seqbuf[_seqbufptr+6] = (0);\ - _seqbuf[_seqbufptr+7] = 0;\ - _SEQ_ADVBUF(8);} - -#define SEQ_START_NOTE(dev, chn, note, vol) \ - _CHN_VOICE(dev, MIDI_NOTEON, chn, note, vol) - -#define SEQ_STOP_NOTE(dev, chn, note, vol) \ - _CHN_VOICE(dev, MIDI_NOTEOFF, chn, note, vol) - -#define SEQ_KEY_PRESSURE(dev, chn, note, pressure) \ - _CHN_VOICE(dev, MIDI_KEY_PRESSURE, chn, note, pressure) - -/* - * Midi channel messages - */ - -#define _CHN_COMMON(dev, event, chn, p1, p2, w14) \ - {_SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr] = EV_CHN_COMMON;\ - _seqbuf[_seqbufptr+1] = (dev);\ - _seqbuf[_seqbufptr+2] = (event);\ - _seqbuf[_seqbufptr+3] = (chn);\ - _seqbuf[_seqbufptr+4] = (p1);\ - _seqbuf[_seqbufptr+5] = (p2);\ - *(short *)&_seqbuf[_seqbufptr+6] = (w14);\ - _SEQ_ADVBUF(8);} -/* - * SEQ_SYSEX permits sending of sysex messages. (It may look that it permits - * sending any MIDI bytes but it's absolutely not possible. Trying to do - * so _will_ cause problems with MPU401 intelligent mode). - * - * Sysex messages are sent in blocks of 1 to 6 bytes. Longer messages must be - * sent by calling SEQ_SYSEX() several times (there must be no other events - * between them). First sysex fragment must have 0xf0 in the first byte - * and the last byte (buf[len-1] of the last fragment must be 0xf7. No byte - * between these sysex start and end markers cannot be larger than 0x7f. Also - * lengths of each fragments (except the last one) must be 6. - * - * Breaking the above rules may work with some MIDI ports but is likely to - * cause fatal problems with some other devices (such as MPU401). - */ -#define SEQ_SYSEX(dev, buf, len) \ - {int ii, ll=(len); \ - unsigned char *bufp=buf;\ - if (ll>6)ll=6;\ - _SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr] = EV_SYSEX;\ - _seqbuf[_seqbufptr+1] = (dev);\ - for(ii=0;ii<ll;ii++)\ - _seqbuf[_seqbufptr+ii+2] = bufp[ii];\ - for(ii=ll;ii<6;ii++)\ - _seqbuf[_seqbufptr+ii+2] = 0xff;\ - _SEQ_ADVBUF(8);} - -#define SEQ_CHN_PRESSURE(dev, chn, pressure) \ - _CHN_COMMON(dev, MIDI_CHN_PRESSURE, chn, pressure, 0, 0) - -#define SEQ_SET_PATCH SEQ_PGM_CHANGE -#ifdef OSSLIB -# define SEQ_PGM_CHANGE(dev, chn, patch) \ - {OSS_patch_caching(dev, chn, patch, seqfd, _seqbuf, _seqbuflen); \ - _CHN_COMMON(dev, MIDI_PGM_CHANGE, chn, patch, 0, 0);} -#else -# define SEQ_PGM_CHANGE(dev, chn, patch) \ - _CHN_COMMON(dev, MIDI_PGM_CHANGE, chn, patch, 0, 0) -#endif - -#define SEQ_CONTROL(dev, chn, controller, value) \ - _CHN_COMMON(dev, MIDI_CTL_CHANGE, chn, controller, 0, value) - -#define SEQ_BENDER(dev, chn, value) \ - _CHN_COMMON(dev, MIDI_PITCH_BEND, chn, 0, 0, value) - -#define SEQ_V2_X_CONTROL(dev, voice, controller, value) \ - {_SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr] = SEQ_EXTENDED;\ - _seqbuf[_seqbufptr+1] = SEQ_CONTROLLER;\ - _seqbuf[_seqbufptr+2] = (dev);\ - _seqbuf[_seqbufptr+3] = (voice);\ - _seqbuf[_seqbufptr+4] = (controller);\ - _seqbuf[_seqbufptr+5] = ((value)&0xff);\ - _seqbuf[_seqbufptr+6] = ((value>>8)&0xff);\ - _seqbuf[_seqbufptr+7] = 0;\ - _SEQ_ADVBUF(8);} -/* - * The following 5 macros are incorrectly implemented and obsolete. - * Use SEQ_BENDER and SEQ_CONTROL (with proper controller) instead. - */ -#define SEQ_PITCHBEND(dev, voice, value) \ - SEQ_V2_X_CONTROL(dev, voice, CTRL_PITCH_BENDER, value) -#define SEQ_BENDER_RANGE(dev, voice, value) \ - SEQ_V2_X_CONTROL(dev, voice, CTRL_PITCH_BENDER_RANGE, value) -#define SEQ_EXPRESSION(dev, voice, value) \ - SEQ_CONTROL(dev, voice, CTL_EXPRESSION, value*128) -#define SEQ_MAIN_VOLUME(dev, voice, value) \ - SEQ_CONTROL(dev, voice, CTL_MAIN_VOLUME, (value*16383)/100) -#define SEQ_PANNING(dev, voice, pos) \ - SEQ_CONTROL(dev, voice, CTL_PAN, (pos+128) / 2) - -/* - * Timing and syncronization macros - */ - -#define _TIMER_EVENT(ev, parm) {_SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr+0] = EV_TIMING; \ - _seqbuf[_seqbufptr+1] = (ev); \ - _seqbuf[_seqbufptr+2] = 0;\ - _seqbuf[_seqbufptr+3] = 0;\ - *(unsigned int *)&_seqbuf[_seqbufptr+4] = (parm); \ - _SEQ_ADVBUF(8);} - -#define SEQ_START_TIMER() _TIMER_EVENT(TMR_START, 0) -#define SEQ_STOP_TIMER() _TIMER_EVENT(TMR_STOP, 0) -#define SEQ_CONTINUE_TIMER() _TIMER_EVENT(TMR_CONTINUE, 0) -#define SEQ_WAIT_TIME(ticks) _TIMER_EVENT(TMR_WAIT_ABS, ticks) -#define SEQ_DELTA_TIME(ticks) _TIMER_EVENT(TMR_WAIT_REL, ticks) -#define SEQ_ECHO_BACK(key) _TIMER_EVENT(TMR_ECHO, key) -#define SEQ_SET_TEMPO(value) _TIMER_EVENT(TMR_TEMPO, value) -#define SEQ_SONGPOS(pos) _TIMER_EVENT(TMR_SPP, pos) -#define SEQ_TIME_SIGNATURE(sig) _TIMER_EVENT(TMR_TIMESIG, sig) - -/* - * Local control events - */ - -#define _LOCAL_EVENT(ev, parm) {_SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr+0] = EV_SEQ_LOCAL; \ - _seqbuf[_seqbufptr+1] = (ev); \ - _seqbuf[_seqbufptr+2] = 0;\ - _seqbuf[_seqbufptr+3] = 0;\ - *(unsigned int *)&_seqbuf[_seqbufptr+4] = (parm); \ - _SEQ_ADVBUF(8);} - -#define SEQ_PLAYAUDIO(devmask) _LOCAL_EVENT(LOCL_STARTAUDIO, devmask) -#define SEQ_PLAYAUDIO2(devmask) _LOCAL_EVENT(LOCL_STARTAUDIO2, devmask) -#define SEQ_PLAYAUDIO3(devmask) _LOCAL_EVENT(LOCL_STARTAUDIO3, devmask) -#define SEQ_PLAYAUDIO4(devmask) _LOCAL_EVENT(LOCL_STARTAUDIO4, devmask) -/* - * Events for the level 1 interface only - */ - -#define SEQ_MIDIOUT(device, byte) {_SEQ_NEEDBUF(4);\ - _seqbuf[_seqbufptr] = SEQ_MIDIPUTC;\ - _seqbuf[_seqbufptr+1] = (byte);\ - _seqbuf[_seqbufptr+2] = (device);\ - _seqbuf[_seqbufptr+3] = 0;\ - _SEQ_ADVBUF(4);} - -/* - * Patch loading. - */ -#ifdef OSSLIB -# define SEQ_WRPATCH(patchx, len) \ - OSS_write_patch(seqfd, (char*)(patchx), len) -# define SEQ_WRPATCH2(patchx, len) \ - OSS_write_patch2(seqfd, (char*)(patchx), len) -#else -# define SEQ_WRPATCH(patchx, len) \ - {if (_seqbufptr) SEQ_DUMPBUF();\ - if (write(seqfd, (char*)(patchx), len)==-1) \ - perror("Write patch: /dev/sequencer");} -# define SEQ_WRPATCH2(patchx, len) \ - (SEQ_DUMPBUF(), write(seqfd, (char*)(patchx), len)) -#endif - -#endif -#endif /* ifndef DISABLE_SEQUENCER */ - -/* - **************************************************************************** - * ioctl commands for the /dev/midi## - ****************************************************************************/ -#define SNDCTL_MIDI_PRETIME __SIOWR('m', 0, int) - -#if 0 -/* - * The SNDCTL_MIDI_MPUMODE and SNDCTL_MIDI_MPUCMD calls - * are completely obsolete. The hardware device (MPU-401 "intelligent mode" - * and compatibles) has disappeared from the market 10 years ago so there - * is no need for this stuff. The MPU-401 "UART" mode devices don't support - * this stuff. - */ -typedef struct -{ - unsigned char cmd; - char nr_args, nr_returns; - unsigned char data[30]; -} mpu_command_rec; - -#define SNDCTL_MIDI_MPUMODE __SIOWR('m', 1, int) -#define SNDCTL_MIDI_MPUCMD __SIOWR('m', 2, mpu_command_rec) -#endif - -/* - * SNDCTL_MIDI_MTCINPUT turns on a mode where OSS automatically inserts - * MTC quarter frame messages (F1 xx) to the input. - * The argument is the MTC mode: - * - * -1 = Turn MTC messages OFF (default) - * 24 = 24 FPS - * 25 = 25 FPS - * 29 = 30 FPS drop frame - * 30 = 30 FPS - * - * Note that 25 FPS mode is probably the only mode that is supported. Other - * modes may be supported in the future versions of OSS, 25 FPS is handy - * because it generates 25*4=100 quarter frame messages per second which - * matches the usual 100 HZ system timer rate). - * - * The quarter frame timer will be reset to 0:00:00:00.0 at the moment this - * ioctl is made. - */ -#define SNDCTL_MIDI_MTCINPUT __SIOWR('m', 3, int) - -/* - * MTC/SMPTE time code record (for future use) - */ -typedef struct -{ - unsigned char hours, minutes, seconds, frames, qframes; - char direction; -#define MTC_DIR_STOPPED 0 -#define MTC_DIR_FORWARD 1 -#define MTC_DIR_BACKWARD -1 - unsigned char time_code_type; - unsigned int flags; -} oss_mtc_data_t; - -#define SNDCTL_MIDI_SETMODE __SIOWR('m', 6, int) -# define MIDI_MODE_TRADITIONAL 0 -# define MIDI_MODE_TIMED 1 /* Input times are in MIDI ticks */ -# define MIDI_MODE_TIMED_ABS 2 /* Input times are absolute (usecs) */ - -/* - * Packet header for MIDI_MODE_TIMED and MIDI_MODE_TIMED_ABS - */ -typedef unsigned long long oss_midi_time_t; /* Variable type for MIDI time (clock ticks) */ - -typedef struct -{ - int magic; /* Initialize to MIDI_HDR_MAGIC */ -#define MIDI_HDR_MAGIC -1 - unsigned short event_type; -#define MIDI_EV_WRITE 0 /* Write or read (with payload) */ -#define MIDI_EV_TEMPO 1 -#define MIDI_EV_ECHO 2 -#define MIDI_EV_START 3 -#define MIDI_EV_STOP 4 -#define MIDI_EV_CONTINUE 5 -#define MIDI_EV_XPRESSWRITE 6 -#define MIDI_EV_TIMEBASE 7 -#define MIDI_EV_DEVCTL 8 /* Device control read/write */ - unsigned short options; -#define MIDI_OPT_NONE 0x0000 -#define MIDI_OPT_TIMED 0x0001 -#define MIDI_OPT_CONTINUATION 0x0002 -#define MIDI_OPT_USECTIME 0x0004 /* Time is absolute (in usecs) */ -#define MIDI_OPT_BUSY 0x0008 /* Reserved for internal use */ - oss_midi_time_t time; - int parm; - int filler[3]; /* Fur future expansion - init to zeros */ -} midi_packet_header_t; -/* - * MIDI_PAYLOAD_SIZE is the maximum size of one MIDI input chunk. It must be - * less (or equal) than 1024 which is the read size recommended in the - * documentation. TODO: Explain this better. - */ -#define MIDI_PAYLOAD_SIZE 1000 - -typedef struct -{ - midi_packet_header_t hdr; - unsigned char payload[MIDI_PAYLOAD_SIZE]; -} midi_packet_t; - -#define SNDCTL_MIDI_TIMEBASE __SIOWR('m', 7, int) -#define SNDCTL_MIDI_TEMPO __SIOWR('m', 8, int) -/* - * User land MIDI servers (synths) can use SNDCTL_MIDI_SET_LATENCY - * to request MIDI events to be sent to them in advance. The parameter - * (in microseconds) tells how much before the events are submitted. - * - * This feature is only valid for loopback devices and possibly some other - * types of virtual devices. - */ -#define SNDCTL_MIDI_SET_LATENCY __SIOW ('m', 9, int) -/* - **************************************************************************** - * IOCTL commands for /dev/dsp - ****************************************************************************/ - -#define SNDCTL_DSP_HALT __SIO ('P', 0) -#define SNDCTL_DSP_RESET SNDCTL_DSP_HALT /* Old name */ -#define SNDCTL_DSP_SYNC __SIO ('P', 1) -#define SNDCTL_DSP_SPEED __SIOWR('P', 2, int) - -/* SNDCTL_DSP_STEREO is obsolete - use SNDCTL_DSP_CHANNELS instead */ -#define SNDCTL_DSP_STEREO __SIOWR('P', 3, int) -/* SNDCTL_DSP_STEREO is obsolete - use SNDCTL_DSP_CHANNELS instead */ - -#define SNDCTL_DSP_GETBLKSIZE __SIOWR('P', 4, int) -#define SNDCTL_DSP_SAMPLESIZE SNDCTL_DSP_SETFMT -#define SNDCTL_DSP_CHANNELS __SIOWR('P', 6, int) -#define SNDCTL_DSP_POST __SIO ('P', 8) -#define SNDCTL_DSP_SUBDIVIDE __SIOWR('P', 9, int) -#define SNDCTL_DSP_SETFRAGMENT __SIOWR('P',10, int) - -/* Audio data formats (Note! U8=8 and S16_LE=16 for compatibility) */ -#define SNDCTL_DSP_GETFMTS __SIOR ('P',11, int) /* Returns a mask */ -#define SNDCTL_DSP_SETFMT __SIOWR('P',5, int) /* Selects ONE fmt */ -# define AFMT_QUERY 0x00000000 /* Return current fmt */ -# define AFMT_MU_LAW 0x00000001 -# define AFMT_A_LAW 0x00000002 -# define AFMT_IMA_ADPCM 0x00000004 -# define AFMT_U8 0x00000008 -# define AFMT_S16_LE 0x00000010 /* Little endian signed 16 */ -# define AFMT_S16_BE 0x00000020 /* Big endian signed 16 */ -# define AFMT_S8 0x00000040 -# define AFMT_U16_LE 0x00000080 /* Little endian U16 */ -# define AFMT_U16_BE 0x00000100 /* Big endian U16 */ -# define AFMT_MPEG 0x00000200 /* MPEG (2) audio */ - -/* AC3 _compressed_ bitstreams (See Programmer's Guide for details). */ -# define AFMT_AC3 0x00000400 -/* Ogg Vorbis _compressed_ bit streams */ -# define AFMT_VORBIS 0x00000800 - -/* 32 bit formats (MSB aligned) formats */ -# define AFMT_S32_LE 0x00001000 -# define AFMT_S32_BE 0x00002000 - -/* Reserved for _native_ endian double precision IEEE floating point */ -# define AFMT_FLOAT 0x00004000 - -/* 24 bit formats (LSB aligned in 32 bit word) formats */ -# define AFMT_S24_LE 0x00008000 -# define AFMT_S24_BE 0x00010000 - -/* - * S/PDIF raw format. In this format the S/PDIF frames (including all - * control and user bits) are included in the data stream. Each sample - * is stored in a 32 bit frame (see IEC-958 for more info). This format - * is supported by very few devices and it's only usable for purposes - * where full access to the control/user bits is required (real time control). - */ -# define AFMT_SPDIF_RAW 0x00020000 - -/* 24 bit packed (3 byte) little endian format (USB compatibility) */ -# define AFMT_S24_PACKED 0x00040000 - - -/* - * Some big endian/little endian handling macros (native endian and opposite - * endian formats). The usage of these macros is described in the OSS - * Programmer's Manual. - */ - -#if defined(_AIX) || defined(AIX) || defined(sparc) || defined(__hppa) || defined(PPC) || defined(__powerpc__) && !defined(i386) && !defined(__i386) && !defined(__i386__) - -/* Big endian machines */ -# define _PATCHKEY(id) (0xfd00|id) -# define AFMT_S16_NE AFMT_S16_BE -# define AFMT_U16_NE AFMT_U16_BE -# define AFMT_S32_NE AFMT_S32_BE -# define AFMT_S24_NE AFMT_S24_BE -# define AFMT_S16_OE AFMT_S16_LE -# define AFMT_S32_OE AFMT_S32_LE -# define AFMT_S24_OE AFMT_S24_LE -#else -# define _PATCHKEY(id) ((id<<8)|0xfd) -# define AFMT_S16_NE AFMT_S16_LE -# define AFMT_U16_NE AFMT_U16_LE -# define AFMT_S32_NE AFMT_S32_LE -# define AFMT_S24_NE AFMT_S24_LE -# define AFMT_S16_OE AFMT_S16_BE -# define AFMT_S32_OE AFMT_S32_BE -# define AFMT_S24_OE AFMT_S24_BE -#endif -/* - * Buffer status queries. - */ -typedef struct audio_buf_info -{ - int fragments; /* # of available fragments (partially usend ones not counted) */ - int fragstotal; /* Total # of fragments allocated */ - int fragsize; /* Size of a fragment in bytes */ - int bytes; /* Available space in bytes (includes partially used fragments) */ - /* Note! 'bytes' could be more than fragments*fragsize */ -} audio_buf_info; - -#define SNDCTL_DSP_GETOSPACE __SIOR ('P',12, audio_buf_info) -#define SNDCTL_DSP_GETISPACE __SIOR ('P',13, audio_buf_info) -#define SNDCTL_DSP_GETCAPS __SIOR ('P',15, int) -# define PCM_CAP_REVISION 0x000000ff /* Bits for revision level (0 to 255) */ -# define PCM_CAP_DUPLEX 0x00000100 /* Full duplex record/playback */ -# define PCM_CAP_REALTIME 0x00000200 /* Not in use */ -# define PCM_CAP_BATCH 0x00000400 /* Device has some kind of */ - /* internal buffers which may */ - /* cause some delays and */ - /* decrease precision of timing */ -# define PCM_CAP_COPROC 0x00000800 /* Has a coprocessor */ - /* Sometimes it's a DSP */ - /* but usually not */ -# define PCM_CAP_TRIGGER 0x00001000 /* Supports SETTRIGGER */ -# define PCM_CAP_MMAP 0x00002000 /* Supports mmap() */ -# define PCM_CAP_MULTI 0x00004000 /* Supports multiple open */ -# define PCM_CAP_BIND 0x00008000 /* Supports binding to front/rear/center/lfe */ -# define PCM_CAP_INPUT 0x00010000 /* Supports recording */ -# define PCM_CAP_OUTPUT 0x00020000 /* Supports playback */ -# define PCM_CAP_VIRTUAL 0x00040000 /* Virtual device */ -/* 0x00040000 and 0x00080000 reserved for future use */ - -/* Analog/digital control capabilities */ -# define PCM_CAP_ANALOGOUT 0x00100000 -# define PCM_CAP_ANALOGIN 0x00200000 -# define PCM_CAP_DIGITALOUT 0x00400000 -# define PCM_CAP_DIGITALIN 0x00800000 -# define PCM_CAP_ADMASK 0x00f00000 -/* - * NOTE! (capabilities & PCM_CAP_ADMASK)==0 means just that the - * digital/analog interface control features are not supported by the - * device/driver. However the device still supports analog, digital or - * both inputs/outputs (depending on the device). See the OSS Programmer's - * Guide for full details. - */ -# define PCM_CAP_SHADOW 0x01000000 /* "Shadow" device */ - -/* - * Preferred channel usage. These bits can be used to - * give recommendations to the application. Used by few drivers. - * For example if ((caps & DSP_CH_MASK) == DSP_CH_MONO) means that - * the device works best in mono mode. However it doesn't necessarily mean - * that the device cannot be used in stereo. These bits should only be used - * by special applications such as multi track hard disk recorders to find - * out the initial setup. However the user should be able to override this - * selection. - * - * To find out which modes are actually supported the application should - * try to select them using SNDCTL_DSP_CHANNELS. - */ -# define DSP_CH_MASK 0x06000000 /* Mask */ -# define DSP_CH_ANY 0x00000000 /* No preferred mode */ -# define DSP_CH_MONO 0x02000000 -# define DSP_CH_STEREO 0x04000000 -# define DSP_CH_MULTI 0x06000000 /* More than two channels */ - -# define PCM_CAP_HIDDEN 0x08000000 /* Hidden device */ -# define PCM_CAP_FREERATE 0x10000000 -# define PCM_CAP_MODEM 0x20000000 /* Modem device */ -# define PCM_CAP_DEFAULT 0x40000000 /* "Default" device */ - -/* - * The PCM_CAP_* capability names were known as DSP_CAP_* prior OSS 4.0 - * so it's necessary to define the older names too. - */ -#define DSP_CAP_ADMASK PCM_CAP_ADMASK -#define DSP_CAP_ANALOGIN PCM_CAP_ANALOGIN -#define DSP_CAP_ANALOGOUT PCM_CAP_ANALOGOUT -#define DSP_CAP_BATCH PCM_CAP_BATCH -#define DSP_CAP_BIND PCM_CAP_BIND -#define DSP_CAP_COPROC PCM_CAP_COPROC -#define DSP_CAP_DEFAULT PCM_CAP_DEFAULT -#define DSP_CAP_DIGITALIN PCM_CAP_DIGITALIN -#define DSP_CAP_DIGITALOUT PCM_CAP_DIGITALOUT -#define DSP_CAP_DUPLEX PCM_CAP_DUPLEX -#define DSP_CAP_FREERATE PCM_CAP_FREERATE -#define DSP_CAP_HIDDEN PCM_CAP_HIDDEN -#define DSP_CAP_INPUT PCM_CAP_INPUT -#define DSP_CAP_MMAP PCM_CAP_MMAP -#define DSP_CAP_MODEM PCM_CAP_MODEM -#define DSP_CAP_MULTI PCM_CAP_MULTI -#define DSP_CAP_OUTPUT PCM_CAP_OUTPUT -#define DSP_CAP_REALTIME PCM_CAP_REALTIME -#define DSP_CAP_REVISION PCM_CAP_REVISION -#define DSP_CAP_SHADOW PCM_CAP_SHADOW -#define DSP_CAP_TRIGGER PCM_CAP_TRIGGER -#define DSP_CAP_VIRTUAL PCM_CAP_VIRTUAL - -#define SNDCTL_DSP_GETTRIGGER __SIOR ('P',16, int) -#define SNDCTL_DSP_SETTRIGGER __SIOW ('P',16, int) -# define PCM_ENABLE_INPUT 0x00000001 -# define PCM_ENABLE_OUTPUT 0x00000002 - -typedef struct count_info -{ - unsigned int bytes; /* Total # of bytes processed */ - int blocks; /* # of fragment transitions since last time */ - int ptr; /* Current DMA pointer value */ -} count_info; - -#define SNDCTL_DSP_GETIPTR __SIOR ('P',17, count_info) -#define SNDCTL_DSP_GETOPTR __SIOR ('P',18, count_info) - -typedef struct buffmem_desc -{ - unsigned *buffer; - int size; -} buffmem_desc; -#define SNDCTL_DSP_SETSYNCRO __SIO ('P', 21) -#define SNDCTL_DSP_SETDUPLEX __SIO ('P', 22) - -#define SNDCTL_DSP_PROFILE __SIOW ('P', 23, int) /* OBSOLETE */ -#define APF_NORMAL 0 /* Normal applications */ -#define APF_NETWORK 1 /* Underruns probably caused by an "external" delay */ -#define APF_CPUINTENS 2 /* Underruns probably caused by "overheating" the CPU */ - -#define SNDCTL_DSP_GETODELAY __SIOR ('P', 23, int) - -typedef struct audio_errinfo -{ - int play_underruns; - int rec_overruns; - unsigned int play_ptradjust; - unsigned int rec_ptradjust; - int play_errorcount; - int rec_errorcount; - int play_lasterror; - int rec_lasterror; - int play_errorparm; - int rec_errorparm; - int filler[16]; -} audio_errinfo; - -#define SNDCTL_DSP_GETPLAYVOL __SIOR ('P', 24, int) -#define SNDCTL_DSP_SETPLAYVOL __SIOWR('P', 24, int) -#define SNDCTL_DSP_GETERROR __SIOR ('P', 25, audio_errinfo) -/* - **************************************************************************** - * Digital interface (S/PDIF) control interface - */ - -typedef struct oss_digital_control -{ - unsigned int caps; -#define DIG_CBITIN_NONE 0x00000000 -#define DIG_CBITIN_LIMITED 0x00000001 -#define DIG_CBITIN_DATA 0x00000002 -#define DIG_CBITIN_BYTE0 0x00000004 -#define DIG_CBITIN_FULL 0x00000008 -#define DIG_CBITIN_MASK 0x0000000f -#define DIG_CBITOUT_NONE 0x00000000 -#define DIG_CBITOUT_LIMITED 0x00000010 -#define DIG_CBITOUT_BYTE0 0x00000020 -#define DIG_CBITOUT_FULL 0x00000040 -#define DIG_CBITOUT_DATA 0x00000080 -#define DIG_CBITOUT_MASK 0x000000f0 -#define DIG_UBITIN 0x00000100 -#define DIG_UBITOUT 0x00000200 -#define DIG_VBITOUT 0x00000400 -#define DIG_OUTRATE 0x00000800 -#define DIG_INRATE 0x00001000 -#define DIG_INBITS 0x00002000 -#define DIG_OUTBITS 0x00004000 -#define DIG_EXACT 0x00010000 -#define DIG_PRO 0x00020000 -#define DIG_CONSUMER 0x00040000 -#define DIG_PASSTHROUGH 0x00080000 -#define DIG_OUTSEL 0x00100000 - - unsigned int valid; -#define VAL_CBITIN 0x00000001 -#define VAL_UBITIN 0x00000002 -#define VAL_CBITOUT 0x00000004 -#define VAL_UBITOUT 0x00000008 -#define VAL_ISTATUS 0x00000010 -#define VAL_IRATE 0x00000020 -#define VAL_ORATE 0x00000040 -#define VAL_INBITS 0x00000080 -#define VAL_OUTBITS 0x00000100 -#define VAL_REQUEST 0x00000200 -#define VAL_OUTSEL 0x00000400 - -#define VAL_OUTMASK (VAL_CBITOUT|VAL_UBITOUT|VAL_ORATE|VAL_OUTBITS|VAL_OUTSEL) - - unsigned int request, param; -#define SPD_RQ_PASSTHROUGH 1 - - unsigned char cbitin[24]; - unsigned char ubitin[24]; - unsigned char cbitout[24]; - unsigned char ubitout[24]; - - unsigned int outsel; -#define OUTSEL_DIGITAL 1 -#define OUTSEL_ANALOG 2 -#define OUTSEL_BOTH (OUTSEL_DIGITAL|OUTSEL_ANALOG) - - int in_data; /* Audio/data if autodetectable by the receiver */ -#define IND_UNKNOWN 0 -#define IND_AUDIO 1 -#define IND_DATA 2 - - int in_locked; /* Receiver locked */ -#define LOCK_NOT_INDICATED 0 -#define LOCK_UNLOCKED 1 -#define LOCK_LOCKED 2 - - int in_quality; /* Input signal quality */ -#define IN_QUAL_NOT_INDICATED 0 -#define IN_QUAL_POOR 1 -#define IN_QUAL_GOOD 2 - - int in_vbit, out_vbit; /* V bits */ -#define VBIT_NOT_INDICATED 0 -#define VBIT_OFF 1 -#define VBIT_ON 2 - - unsigned int in_errors; /* Various input error conditions */ -#define INERR_CRC 0x0001 -#define INERR_QCODE_CRC 0x0002 -#define INERR_PARITY 0x0004 -#define INERR_BIPHASE 0x0008 - - int srate_in, srate_out; - int bits_in, bits_out; - - int filler[32]; -} oss_digital_control; - -#define SNDCTL_DSP_READCTL __SIOWR('P', 26, oss_digital_control) -#define SNDCTL_DSP_WRITECTL __SIOWR('P', 27, oss_digital_control) - -/* - **************************************************************************** - * Sync groups for audio devices - */ -typedef struct oss_syncgroup -{ - int id; - int mode; - int filler[16]; -} oss_syncgroup; - -#define SNDCTL_DSP_SYNCGROUP __SIOWR('P', 28, oss_syncgroup) -#define SNDCTL_DSP_SYNCSTART __SIOW ('P', 29, int) - -/* - ************************************************************************** - * "cooked" mode enables software based conversions for sample rate, sample - * format (bits) and number of channels (mono/stereo). These conversions are - * required with some devices that support only one sample rate or just stereo - * to let the applications to use other formats. The cooked mode is enabled by - * default. However it's necessary to disable this mode when mmap() is used or - * when very deterministic timing is required. SNDCTL_DSP_COOKEDMODE is an - * optional call introduced in OSS 3.9.6f. It's _error return must be ignored_ - * since normally this call will return erno=EINVAL. - * - * SNDCTL_DSP_COOKEDMODE must be called immediately after open before doing - * anything else. Otherwise the call will not have any effect. - */ -#define SNDCTL_DSP_COOKEDMODE __SIOW ('P', 30, int) - -/* - ************************************************************************** - * SNDCTL_DSP_SILENCE and SNDCTL_DSP_SKIP are new calls in OSS 3.99.0 - * that can be used to implement pause/continue during playback (no effect - * on recording). - */ -#define SNDCTL_DSP_SILENCE __SIO ('P', 31) -#define SNDCTL_DSP_SKIP __SIO ('P', 32) -/* - **************************************************************************** - * Abort transfer (reset) functions for input and output - */ -#define SNDCTL_DSP_HALT_INPUT __SIO ('P', 33) -#define SNDCTL_DSP_RESET_INPUT SNDCTL_DSP_HALT_INPUT /* Old name */ -#define SNDCTL_DSP_HALT_OUTPUT __SIO ('P', 34) -#define SNDCTL_DSP_RESET_OUTPUT SNDCTL_DSP_HALT_OUTPUT /* Old name */ -/* - **************************************************************************** - * Low water level control - */ -#define SNDCTL_DSP_LOW_WATER __SIOW ('P', 34, int) - -/* - **************************************************************************** - * 64 bit pointer support. Only available in environments that support - * the 64 bit (long long) integer type. - */ -#ifndef OSS_NO_LONG_LONG -typedef struct -{ - long long samples; - int fifo_samples; - int filler[32]; /* For future use */ -} oss_count_t; - -#define SNDCTL_DSP_CURRENT_IPTR __SIOR ('P', 35, oss_count_t) -#define SNDCTL_DSP_CURRENT_OPTR __SIOR ('P', 36, oss_count_t) -#endif - -/* - **************************************************************************** - * Interface for selecting recording sources and playback output routings. - */ -#define SNDCTL_DSP_GET_RECSRC_NAMES __SIOR ('P', 37, oss_mixer_enuminfo) -#define SNDCTL_DSP_GET_RECSRC __SIOR ('P', 38, int) -#define SNDCTL_DSP_SET_RECSRC __SIOWR('P', 38, int) - -#define SNDCTL_DSP_GET_PLAYTGT_NAMES __SIOR ('P', 39, oss_mixer_enuminfo) -#define SNDCTL_DSP_GET_PLAYTGT __SIOR ('P', 40, int) -#define SNDCTL_DSP_SET_PLAYTGT __SIOWR('P', 40, int) -#define SNDCTL_DSP_GETRECVOL __SIOR ('P', 41, int) -#define SNDCTL_DSP_SETRECVOL __SIOWR('P', 41, int) - -/* - *************************************************************************** - * Some calls for setting the channel assignment with multi channel devices - * (see the manual for details). - */ -#ifndef OSS_NO_LONG_LONG -#define SNDCTL_DSP_GET_CHNORDER __SIOR ('P', 42, unsigned long long) -#define SNDCTL_DSP_SET_CHNORDER __SIOWR('P', 42, unsigned long long) -# define CHID_UNDEF 0 -# define CHID_L 1 -# define CHID_R 2 -# define CHID_C 3 -# define CHID_LFE 4 -# define CHID_LS 5 -# define CHID_RS 6 -# define CHID_LR 7 -# define CHID_RR 8 -#define CHNORDER_UNDEF 0x0000000000000000ULL -#define CHNORDER_NORMAL 0x0000000087654321ULL -#endif - -#define MAX_PEAK_CHANNELS 128 -typedef unsigned short oss_peaks_t[MAX_PEAK_CHANNELS]; -#define SNDCTL_DSP_GETIPEAKS __SIOR('P', 43, oss_peaks_t) -#define SNDCTL_DSP_GETOPEAKS __SIOR('P', 44, oss_peaks_t) - -#define SNDCTL_DSP_POLICY __SIOW('P', 45, int) /* See the manual */ - -/* - **************************************************************************** - * Few ioctl calls that are not official parts of OSS. They have been used - * by few freeware implementations of OSS. - */ -#define SNDCTL_DSP_GETCHANNELMASK __SIOWR('P', 64, int) -#define SNDCTL_DSP_BIND_CHANNEL __SIOWR('P', 65, int) -# define DSP_BIND_QUERY 0x00000000 -# define DSP_BIND_FRONT 0x00000001 -# define DSP_BIND_SURR 0x00000002 -# define DSP_BIND_CENTER_LFE 0x00000004 -# define DSP_BIND_HANDSET 0x00000008 -# define DSP_BIND_MIC 0x00000010 -# define DSP_BIND_MODEM1 0x00000020 -# define DSP_BIND_MODEM2 0x00000040 -# define DSP_BIND_I2S 0x00000080 -# define DSP_BIND_SPDIF 0x00000100 -# define DSP_BIND_REAR 0x00000200 - -#ifdef sun -/* Not part of OSS. Reserved for internal use by Solaris */ -#define X_SADA_GET_PLAYTGT_MASK __SIOR ('P', 66, int) -#define X_SADA_GET_PLAYTGT __SIOR ('P', 67, int) -#define X_SADA_SET_PLAYTGT __SIOWR('P', 68, int) -#endif - -#ifndef NO_LEGACY_MIXER -/* - **************************************************************************** - * IOCTL commands for the "legacy " /dev/mixer API (obsolete) - * - * Mixer controls - * - * There can be up to 20 different analog mixer channels. The - * SOUND_MIXER_NRDEVICES gives the currently supported maximum. - * The SOUND_MIXER_READ_DEVMASK returns a bitmask which tells - * the devices supported by the particular mixer. - * - * {!notice This "legacy" mixer API is obsolete. It has been superceded - * by a new one (see below). - */ - -#define SOUND_MIXER_NRDEVICES 28 -#define SOUND_MIXER_VOLUME 0 -#define SOUND_MIXER_BASS 1 -#define SOUND_MIXER_TREBLE 2 -#define SOUND_MIXER_SYNTH 3 -#define SOUND_MIXER_PCM 4 -#define SOUND_MIXER_SPEAKER 5 -#define SOUND_MIXER_LINE 6 -#define SOUND_MIXER_MIC 7 -#define SOUND_MIXER_CD 8 -#define SOUND_MIXER_IMIX 9 /* Recording monitor */ -#define SOUND_MIXER_ALTPCM 10 -#define SOUND_MIXER_RECLEV 11 /* Recording level */ -#define SOUND_MIXER_IGAIN 12 /* Input gain */ -#define SOUND_MIXER_OGAIN 13 /* Output gain */ -/* - * Some soundcards have three line level inputs (line, aux1 and aux2). - * Since each card manufacturer has assigned different meanings to - * these inputs, it's impractical to assign specific meanings - * (eg line, cd, synth etc.) to them. - */ -#define SOUND_MIXER_LINE1 14 /* Input source 1 (aux1) */ -#define SOUND_MIXER_LINE2 15 /* Input source 2 (aux2) */ -#define SOUND_MIXER_LINE3 16 /* Input source 3 (line) */ -#define SOUND_MIXER_DIGITAL1 17 /* Digital I/O 1 */ -#define SOUND_MIXER_DIGITAL2 18 /* Digital I/O 2 */ -#define SOUND_MIXER_DIGITAL3 19 /* Digital I/O 3 */ -#define SOUND_MIXER_PHONE 20 /* Phone */ -#define SOUND_MIXER_MONO 21 /* Mono Output */ -#define SOUND_MIXER_VIDEO 22 /* Video/TV (audio) in */ -#define SOUND_MIXER_RADIO 23 /* Radio in */ -#define SOUND_MIXER_DEPTH 24 /* Surround depth */ -#define SOUND_MIXER_REARVOL 25 /* Rear/Surround speaker vol */ -#define SOUND_MIXER_CENTERVOL 26 /* Center/LFE speaker vol */ -#define SOUND_MIXER_SIDEVOL 27 /* Side-Surround (8speaker) vol */ - -/* - * Warning: SOUND_MIXER_SURRVOL is an old name of SOUND_MIXER_SIDEVOL. - * They are both assigned to the same mixer control. Don't - * use both control names in the same program/driver. - */ -#define SOUND_MIXER_SURRVOL SOUND_MIXER_SIDEVOL - -/* Some on/off settings (SOUND_SPECIAL_MIN - SOUND_SPECIAL_MAX) */ -/* Not counted to SOUND_MIXER_NRDEVICES, but use the same number space */ -#define SOUND_ONOFF_MIN 28 -#define SOUND_ONOFF_MAX 30 - -/* Note! Number 31 cannot be used since the sign bit is reserved */ -#define SOUND_MIXER_NONE 31 - -/* - * The following unsupported macros are no longer functional. - * Use SOUND_MIXER_PRIVATE# macros in future. - */ -#define SOUND_MIXER_ENHANCE SOUND_MIXER_NONE -#define SOUND_MIXER_MUTE SOUND_MIXER_NONE -#define SOUND_MIXER_LOUD SOUND_MIXER_NONE - -#define SOUND_DEVICE_LABELS \ - {"Vol ", "Bass ", "Treble", "Synth", "Pcm ", "Speaker ", "Line ", \ - "Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", \ - "Aux1", "Aux2", "Aux3", "Digital1", "Digital2", "Digital3", \ - "Phone", "Mono", "Video", "Radio", "Depth", \ - "Rear", "Center", "Side"} - -#define SOUND_DEVICE_NAMES \ - {"vol", "bass", "treble", "synth", "pcm", "speaker", "line", \ - "mic", "cd", "mix", "pcm2", "rec", "igain", "ogain", \ - "aux1", "aux2", "aux3", "dig1", "dig2", "dig3", \ - "phone", "mono", "video", "radio", "depth", \ - "rear", "center", "side"} - -/* Device bitmask identifiers */ - -#define SOUND_MIXER_RECSRC 0xff /* Arg contains a bit for each recording source */ -#define SOUND_MIXER_DEVMASK 0xfe /* Arg contains a bit for each supported device */ -#define SOUND_MIXER_RECMASK 0xfd /* Arg contains a bit for each supported recording source */ -#define SOUND_MIXER_CAPS 0xfc -# define SOUND_CAP_EXCL_INPUT 0x00000001 /* Only one recording source at a time */ -# define SOUND_CAP_NOLEGACY 0x00000004 /* For internal use only */ -# define SOUND_CAP_NORECSRC 0x00000008 -#define SOUND_MIXER_STEREODEVS 0xfb /* Mixer channels supporting stereo */ - -/* OSS/Free ONLY */ -#define SOUND_MIXER_OUTSRC 0xfa /* Arg contains a bit for each input source to output */ -#define SOUND_MIXER_OUTMASK 0xf9 /* Arg contains a bit for each supported input source to output */ -/* OSS/Free ONLY */ - -/* Device mask bits */ - -#define SOUND_MASK_VOLUME (1 << SOUND_MIXER_VOLUME) -#define SOUND_MASK_BASS (1 << SOUND_MIXER_BASS) -#define SOUND_MASK_TREBLE (1 << SOUND_MIXER_TREBLE) -#define SOUND_MASK_SYNTH (1 << SOUND_MIXER_SYNTH) -#define SOUND_MASK_PCM (1 << SOUND_MIXER_PCM) -#define SOUND_MASK_SPEAKER (1 << SOUND_MIXER_SPEAKER) -#define SOUND_MASK_LINE (1 << SOUND_MIXER_LINE) -#define SOUND_MASK_MIC (1 << SOUND_MIXER_MIC) -#define SOUND_MASK_CD (1 << SOUND_MIXER_CD) -#define SOUND_MASK_IMIX (1 << SOUND_MIXER_IMIX) -#define SOUND_MASK_ALTPCM (1 << SOUND_MIXER_ALTPCM) -#define SOUND_MASK_RECLEV (1 << SOUND_MIXER_RECLEV) -#define SOUND_MASK_IGAIN (1 << SOUND_MIXER_IGAIN) -#define SOUND_MASK_OGAIN (1 << SOUND_MIXER_OGAIN) -#define SOUND_MASK_LINE1 (1 << SOUND_MIXER_LINE1) -#define SOUND_MASK_LINE2 (1 << SOUND_MIXER_LINE2) -#define SOUND_MASK_LINE3 (1 << SOUND_MIXER_LINE3) -#define SOUND_MASK_DIGITAL1 (1 << SOUND_MIXER_DIGITAL1) -#define SOUND_MASK_DIGITAL2 (1 << SOUND_MIXER_DIGITAL2) -#define SOUND_MASK_DIGITAL3 (1 << SOUND_MIXER_DIGITAL3) -#define SOUND_MASK_MONO (1 << SOUND_MIXER_MONO) -#define SOUND_MASK_PHONE (1 << SOUND_MIXER_PHONE) -#define SOUND_MASK_RADIO (1 << SOUND_MIXER_RADIO) -#define SOUND_MASK_VIDEO (1 << SOUND_MIXER_VIDEO) -#define SOUND_MASK_DEPTH (1 << SOUND_MIXER_DEPTH) -#define SOUND_MASK_REARVOL (1 << SOUND_MIXER_REARVOL) -#define SOUND_MASK_CENTERVOL (1 << SOUND_MIXER_CENTERVOL) -#define SOUND_MASK_SIDEVOL (1 << SOUND_MIXER_SIDEVOL) - -/* Note! SOUND_MASK_SURRVOL is alias of SOUND_MASK_SIDEVOL */ -#define SOUND_MASK_SURRVOL (1 << SOUND_MIXER_SIDEVOL) - -/* Obsolete macros */ -#define SOUND_MASK_MUTE (1 << SOUND_MIXER_MUTE) -#define SOUND_MASK_ENHANCE (1 << SOUND_MIXER_ENHANCE) -#define SOUND_MASK_LOUD (1 << SOUND_MIXER_LOUD) - -#define MIXER_READ(dev) __SIOR('M', dev, int) -#define SOUND_MIXER_READ_VOLUME MIXER_READ(SOUND_MIXER_VOLUME) -#define SOUND_MIXER_READ_BASS MIXER_READ(SOUND_MIXER_BASS) -#define SOUND_MIXER_READ_TREBLE MIXER_READ(SOUND_MIXER_TREBLE) -#define SOUND_MIXER_READ_SYNTH MIXER_READ(SOUND_MIXER_SYNTH) -#define SOUND_MIXER_READ_PCM MIXER_READ(SOUND_MIXER_PCM) -#define SOUND_MIXER_READ_SPEAKER MIXER_READ(SOUND_MIXER_SPEAKER) -#define SOUND_MIXER_READ_LINE MIXER_READ(SOUND_MIXER_LINE) -#define SOUND_MIXER_READ_MIC MIXER_READ(SOUND_MIXER_MIC) -#define SOUND_MIXER_READ_CD MIXER_READ(SOUND_MIXER_CD) -#define SOUND_MIXER_READ_IMIX MIXER_READ(SOUND_MIXER_IMIX) -#define SOUND_MIXER_READ_ALTPCM MIXER_READ(SOUND_MIXER_ALTPCM) -#define SOUND_MIXER_READ_RECLEV MIXER_READ(SOUND_MIXER_RECLEV) -#define SOUND_MIXER_READ_IGAIN MIXER_READ(SOUND_MIXER_IGAIN) -#define SOUND_MIXER_READ_OGAIN MIXER_READ(SOUND_MIXER_OGAIN) -#define SOUND_MIXER_READ_LINE1 MIXER_READ(SOUND_MIXER_LINE1) -#define SOUND_MIXER_READ_LINE2 MIXER_READ(SOUND_MIXER_LINE2) -#define SOUND_MIXER_READ_LINE3 MIXER_READ(SOUND_MIXER_LINE3) - -/* Obsolete macros */ -#define SOUND_MIXER_READ_MUTE MIXER_READ(SOUND_MIXER_MUTE) -#define SOUND_MIXER_READ_ENHANCE MIXER_READ(SOUND_MIXER_ENHANCE) -#define SOUND_MIXER_READ_LOUD MIXER_READ(SOUND_MIXER_LOUD) - -#define SOUND_MIXER_READ_RECSRC MIXER_READ(SOUND_MIXER_RECSRC) -#define SOUND_MIXER_READ_DEVMASK MIXER_READ(SOUND_MIXER_DEVMASK) -#define SOUND_MIXER_READ_RECMASK MIXER_READ(SOUND_MIXER_RECMASK) -#define SOUND_MIXER_READ_STEREODEVS MIXER_READ(SOUND_MIXER_STEREODEVS) -#define SOUND_MIXER_READ_CAPS MIXER_READ(SOUND_MIXER_CAPS) - -#define MIXER_WRITE(dev) __SIOWR('M', dev, int) -#define SOUND_MIXER_WRITE_VOLUME MIXER_WRITE(SOUND_MIXER_VOLUME) -#define SOUND_MIXER_WRITE_BASS MIXER_WRITE(SOUND_MIXER_BASS) -#define SOUND_MIXER_WRITE_TREBLE MIXER_WRITE(SOUND_MIXER_TREBLE) -#define SOUND_MIXER_WRITE_SYNTH MIXER_WRITE(SOUND_MIXER_SYNTH) -#define SOUND_MIXER_WRITE_PCM MIXER_WRITE(SOUND_MIXER_PCM) -#define SOUND_MIXER_WRITE_SPEAKER MIXER_WRITE(SOUND_MIXER_SPEAKER) -#define SOUND_MIXER_WRITE_LINE MIXER_WRITE(SOUND_MIXER_LINE) -#define SOUND_MIXER_WRITE_MIC MIXER_WRITE(SOUND_MIXER_MIC) -#define SOUND_MIXER_WRITE_CD MIXER_WRITE(SOUND_MIXER_CD) -#define SOUND_MIXER_WRITE_IMIX MIXER_WRITE(SOUND_MIXER_IMIX) -#define SOUND_MIXER_WRITE_ALTPCM MIXER_WRITE(SOUND_MIXER_ALTPCM) -#define SOUND_MIXER_WRITE_RECLEV MIXER_WRITE(SOUND_MIXER_RECLEV) -#define SOUND_MIXER_WRITE_IGAIN MIXER_WRITE(SOUND_MIXER_IGAIN) -#define SOUND_MIXER_WRITE_OGAIN MIXER_WRITE(SOUND_MIXER_OGAIN) -#define SOUND_MIXER_WRITE_LINE1 MIXER_WRITE(SOUND_MIXER_LINE1) -#define SOUND_MIXER_WRITE_LINE2 MIXER_WRITE(SOUND_MIXER_LINE2) -#define SOUND_MIXER_WRITE_LINE3 MIXER_WRITE(SOUND_MIXER_LINE3) - -/* Obsolete macros */ -#define SOUND_MIXER_WRITE_MUTE MIXER_WRITE(SOUND_MIXER_MUTE) -#define SOUND_MIXER_WRITE_ENHANCE MIXER_WRITE(SOUND_MIXER_ENHANCE) -#define SOUND_MIXER_WRITE_LOUD MIXER_WRITE(SOUND_MIXER_LOUD) - -#define SOUND_MIXER_WRITE_RECSRC MIXER_WRITE(SOUND_MIXER_RECSRC) - -typedef struct mixer_info /* OBSOLETE */ -{ - char id[16]; - char name[32]; - int modify_counter; - int card_number; - int port_number; - char handle[32]; -} mixer_info; - -/* SOUND_MIXER_INFO is obsolete - use SNDCTL_MIXERINFO instead */ -#define SOUND_MIXER_INFO __SIOR ('M', 101, mixer_info) - -/* - * Two ioctls for special souncard function (OSS/Free only) - */ -#define SOUND_MIXER_AGC _SIOWR('M', 103, int) -#define SOUND_MIXER_3DSE _SIOWR('M', 104, int) -/* - * The SOUND_MIXER_PRIVATE# commands can be redefined by low level drivers. - * These features can be used when accessing device specific features. - */ -#define SOUND_MIXER_PRIVATE1 __SIOWR('M', 111, int) -#define SOUND_MIXER_PRIVATE2 __SIOWR('M', 112, int) -#define SOUND_MIXER_PRIVATE3 __SIOWR('M', 113, int) -#define SOUND_MIXER_PRIVATE4 __SIOWR('M', 114, int) -#define SOUND_MIXER_PRIVATE5 __SIOWR('M', 115, int) - -/* The following two controls were never implemented and they should not be used. */ -#define SOUND_MIXER_READ_MAINVOL __SIOR ('M', 116, int) -#define SOUND_MIXER_WRITE_MAINVOL __SIOWR('M', 116, int) - -/* - * SOUND_MIXER_GETLEVELS and SOUND_MIXER_SETLEVELS calls can be used - * for querying current mixer settings from the driver and for loading - * default volume settings _prior_ activating the mixer (loading - * doesn't affect current state of the mixer hardware). These calls - * are for internal use by the driver software only. - */ - -typedef struct mixer_vol_table -{ - int num; /* Index to volume table */ - char name[32]; - int levels[32]; -} mixer_vol_table; - -#define SOUND_MIXER_GETLEVELS __SIOWR('M', 116, mixer_vol_table) -#define SOUND_MIXER_SETLEVELS __SIOWR('M', 117, mixer_vol_table) - -#define OSS_GETVERSION __SIOR ('M', 118, int) - -/* - * Calls to set/get the recording gain for the currently active - * recording source. These calls automatically map to the right control. - * Note that these calls are not supported by all drivers. In this case - * the call will return -1 with errno set to EINVAL - * - * The _MONGAIN work in similar way but set/get the monitoring gain for - * the currently selected recording source. - */ -#define SOUND_MIXER_READ_RECGAIN __SIOR ('M', 119, int) -#define SOUND_MIXER_WRITE_RECGAIN __SIOWR('M', 119, int) -#define SOUND_MIXER_READ_MONGAIN __SIOR ('M', 120, int) -#define SOUND_MIXER_WRITE_MONGAIN __SIOWR('M', 120, int) - -/* The following call is for driver development time purposes. It's not - * present in any released drivers. - */ -typedef unsigned char oss_reserved_t[512]; -#define SOUND_MIXER_RESERVED __SIOWR('M', 121, oss_reserved_t) -#endif /* ifndef NO_LEGACY_MIXER */ - -/* - ************************************************************************* - * The "new" mixer API of OSS 4.0 and later. - * - * This improved mixer API makes it possible to access every possible feature - * of every possible device. However you should read the mixer programming - * section of the OSS API Developer's Manual. There is no chance that you - * could use this interface correctly just by examining this header. - */ - -typedef struct oss_sysinfo -{ - char product[32]; /* For example OSS/Free, OSS/Linux or OSS/Solaris */ - char version[32]; /* For example 4.0a */ - int versionnum; /* See OSS_GETVERSION */ - char options[128]; /* Reserved */ - - int numaudios; /* # of audio/dsp devices */ - int openedaudio[8]; /* Bit mask telling which audio devices are busy */ - - int numsynths; /* # of availavle synth devices */ - int nummidis; /* # of available MIDI ports */ - int numtimers; /* # of available timer devices */ - int nummixers; /* # of mixer devices */ - - int openedmidi[8]; /* Bit mask telling which midi devices are busy */ - int numcards; /* Number of sound cards in the system */ - int numaudioengines; /* Number of audio engines in the system */ - char license[16]; /* For example "GPL" or "CDDL" */ - int filler[236]; /* For future expansion (set to -1) */ -} oss_sysinfo; - -typedef struct oss_mixext -{ - int dev; /* Mixer device number */ - int ctrl; /* Controller number */ - int type; /* Entry type */ -# define MIXT_DEVROOT 0 /* Device root entry */ -# define MIXT_GROUP 1 /* Controller group */ -# define MIXT_ONOFF 2 /* OFF (0) or ON (1) */ -# define MIXT_ENUM 3 /* Enumerated (0 to maxvalue) */ -# define MIXT_MONOSLIDER 4 /* Mono slider (0 to 255) */ -# define MIXT_STEREOSLIDER 5 /* Stereo slider (dual 0 to 255) */ -# define MIXT_MESSAGE 6 /* (Readable) textual message */ -# define MIXT_MONOVU 7 /* VU meter value (mono) */ -# define MIXT_STEREOVU 8 /* VU meter value (stereo) */ -# define MIXT_MONOPEAK 9 /* VU meter peak value (mono) */ -# define MIXT_STEREOPEAK 10 /* VU meter peak value (stereo) */ -# define MIXT_RADIOGROUP 11 /* Radio button group */ -# define MIXT_MARKER 12 /* Separator between normal and extension entries */ -# define MIXT_VALUE 13 /* Decimal value entry */ -# define MIXT_HEXVALUE 14 /* Hexadecimal value entry */ -# define MIXT_MONODB 15 /* OBSOLETE */ -# define MIXT_STEREODB 16 /* OBSOLETE */ -# define MIXT_SLIDER 17 /* Slider (mono) with full (31 bit) postitive integer range */ -# define MIXT_3D 18 - -/* - * Sliders with range expanded to 15 bits per channel (0-32767) - */ -# define MIXT_MONOSLIDER16 19 -# define MIXT_STEREOSLIDER16 20 -# define MIXT_MUTE 21 /* Mute=1, unmute=0 */ - - /**************************************************************/ - - /* Possible value range (minvalue to maxvalue) */ - /* Note that maxvalue may also be smaller than minvalue */ - int maxvalue; - int minvalue; - - int flags; -# define MIXF_READABLE 0x00000001 /* Has readable value */ -# define MIXF_WRITEABLE 0x00000002 /* Has writeable value */ -# define MIXF_POLL 0x00000004 /* May change itself */ -# define MIXF_HZ 0x00000008 /* Herz scale */ -# define MIXF_STRING 0x00000010 /* Use dynamic extensions for value */ -# define MIXF_DYNAMIC 0x00000010 /* Supports dynamic extensions */ -# define MIXF_OKFAIL 0x00000020 /* Interpret value as 1=OK, 0=FAIL */ -# define MIXF_FLAT 0x00000040 /* Flat vertical space requirements */ -# define MIXF_LEGACY 0x00000080 /* Legacy mixer control group */ -# define MIXF_CENTIBEL 0x00000100 /* Centibel (0.1 dB) step size */ -# define MIXF_DECIBEL 0x00000200 /* Step size of 1 dB */ -# define MIXF_MAINVOL 0x00000400 /* Main volume control */ -# define MIXF_PCMVOL 0x00000800 /* PCM output volume control */ -# define MIXF_RECVOL 0x00001000 /* PCM recording volume control */ -# define MIXF_MONVOL 0x00002000 /* Input->output monitor volume */ -# define MIXF_WIDE 0x00004000 /* Enum control has wide labels */ -# define MIXF_DESCR 0x00008000 /* Description (tooltip) available */ - char id[16]; /* Mnemonic ID (mainly for internal use) */ - int parent; /* Entry# of parent (group) node (-1 if root) */ - - int dummy; /* Internal use */ - - int timestamp; - - char data[64]; /* Misc data (entry type dependent) */ - unsigned char enum_present[32]; /* Mask of allowed enum values */ - int control_no; /* SOUND_MIXER_VOLUME..SOUND_MIXER_MIDI */ - /* (-1 means not indicated) */ - -/* - * The desc field is reserved for internal purposes of OSS. It should not be - * used by applications. - */ - unsigned int desc; -#define MIXEXT_SCOPE_MASK 0x0000003f -#define MIXEXT_SCOPE_OTHER 0x00000000 -#define MIXEXT_SCOPE_INPUT 0x00000001 -#define MIXEXT_SCOPE_OUTPUT 0x00000002 -#define MIXEXT_SCOPE_MONITOR 0x00000003 -#define MIXEXT_SCOPE_RECSWITCH 0x00000004 - - char extname[32]; - int update_counter; - int rgbcolor; /* 0 means default color (not black) . Otherwise 24 bit RGB color */ - int filler[6]; -} oss_mixext; - -/* - * Recommended colors to be used in the rgbcolor field. These match the - * colors used as the audio jack colors in HD audio motherboards. - */ -#define OSS_RGB_BLUE 0x7aabde // Light blue -#define OSS_RGB_GREEN 0xb3c98c // Lime green -#define OSS_RGB_PINK 0xe88c99 -#define OSS_RGB_GRAY 0xd1ccc4 -#define OSS_RGB_BLACK 0x2b2926 // Light black -#define OSS_RGB_ORANGE 0xe89e47 -#define OSS_RGB_RED 0xff0000 -#define OSS_RGB_YELLOW 0xffff00 -#define OSS_RGB_PURPLE 0x800080 -#define OSS_RGB_WHITE 0xf8f8ff - -typedef struct oss_mixext_root -{ - char id[16]; - char name[48]; -} oss_mixext_root; - -typedef struct oss_mixer_value -{ - int dev; - int ctrl; - int value; - int flags; /* Reserved for future use. Initialize to 0 */ - int timestamp; /* Must be set to oss_mixext.timestamp */ - int filler[8]; /* Reserved for future use. Initialize to 0 */ -} oss_mixer_value; - -#define OSS_ENUM_MAXVALUE 255 -#define OSS_ENUM_STRINGSIZE 3000 -typedef struct oss_mixer_enuminfo -{ - int dev; - int ctrl; - int nvalues; - int version; /* Read the manual */ - short strindex[OSS_ENUM_MAXVALUE]; - char strings[OSS_ENUM_STRINGSIZE]; -} oss_mixer_enuminfo; - -#define OPEN_READ PCM_ENABLE_INPUT -#define OPEN_WRITE PCM_ENABLE_OUTPUT -#define OPEN_READWRITE (OPEN_READ|OPEN_WRITE) - -typedef struct oss_audioinfo -{ - int dev; /* Audio device number */ - char name[64]; - int busy; /* 0, OPEN_READ, OPEN_WRITE or OPEN_READWRITE */ - int pid; - int caps; /* PCM_CAP_INPUT, PCM_CAP_OUTPUT */ - int iformats, oformats; - int magic; /* Reserved for internal use */ - char cmd[64]; /* Command using the device (if known) */ - int card_number; - int port_number; - int mixer_dev; - int legacy_device; /* Obsolete field. Replaced by devnode */ - int enabled; /* 1=enabled, 0=device not ready at this moment */ - int flags; /* For internal use only - no practical meaning */ - int min_rate, max_rate; /* Sample rate limits */ - int min_channels, max_channels; /* Number of channels supported */ - int binding; /* DSP_BIND_FRONT, etc. 0 means undefined */ - int rate_source; - char handle[32]; -#define OSS_MAX_SAMPLE_RATES 20 /* Cannot be changed */ - unsigned int nrates, rates[OSS_MAX_SAMPLE_RATES]; /* Please read the manual before using these */ - oss_longname_t song_name; /* Song name (if given) */ - oss_label_t label; /* Device label (if given) */ - int latency; /* In usecs, -1=unknown */ - oss_devnode_t devnode; /* Device special file name (absolute path) */ - int next_play_engine; /* Read the documentation for more info */ - int next_rec_engine; /* Read the documentation for more info */ - int filler[184]; -} oss_audioinfo; - -typedef struct oss_mixerinfo -{ - int dev; - char id[16]; - char name[32]; - int modify_counter; - int card_number; - int port_number; - char handle[32]; - int magic; /* Reserved */ - int enabled; /* Reserved */ - int caps; -#define MIXER_CAP_VIRTUAL 0x00000001 -#define MIXER_CAP_LAYOUT_B 0x00000002 /* For internal use only */ -#define MIXER_CAP_NARROW 0x00000004 /* Conserve horiz space */ - int flags; /* Reserved */ - int nrext; - /* - * The priority field can be used to select the default (motherboard) - * mixer device. The mixer with the highest priority is the - * most preferred one. -2 or less means that this device cannot be used - * as the default mixer. - */ - int priority; - oss_devnode_t devnode; /* Device special file name (absolute path) */ - int legacy_device; - int filler[245]; /* Reserved */ -} oss_mixerinfo; - -typedef struct oss_midi_info -{ - int dev; /* Midi device number */ - char name[64]; - int busy; /* 0, OPEN_READ, OPEN_WRITE or OPEN_READWRITE */ - int pid; - char cmd[64]; /* Command using the device (if known) */ - int caps; -#define MIDI_CAP_MPU401 0x00000001 /**** OBSOLETE ****/ -#define MIDI_CAP_INPUT 0x00000002 -#define MIDI_CAP_OUTPUT 0x00000004 -#define MIDI_CAP_INOUT (MIDI_CAP_INPUT|MIDI_CAP_OUTPUT) -#define MIDI_CAP_VIRTUAL 0x00000008 /* Pseudo device */ -#define MIDI_CAP_MTCINPUT 0x00000010 /* Supports SNDCTL_MIDI_MTCINPUT */ -#define MIDI_CAP_CLIENT 0x00000020 /* Virtual client side device */ -#define MIDI_CAP_SERVER 0x00000040 /* Virtual server side device */ -#define MIDI_CAP_INTERNAL 0x00000080 /* Internal (synth) device */ -#define MIDI_CAP_EXTERNAL 0x00000100 /* external (MIDI port) device */ -#define MIDI_CAP_PTOP 0x00000200 /* Point to point link to one device */ -#define MIDI_CAP_MTC 0x00000400 /* MTC/SMPTE (control) device */ - int magic; /* Reserved for internal use */ - int card_number; - int port_number; - int enabled; /* 1=enabled, 0=device not ready at this moment */ - int flags; /* For internal use only - no practical meaning */ - char handle[32]; - oss_longname_t song_name; /* Song name (if known) */ - oss_label_t label; /* Device label (if given) */ - int latency; /* In usecs, -1=unknown */ - oss_devnode_t devnode; /* Device special file name (absolute path) */ - int legacy_device; /* Legacy device mapping */ - int filler[235]; -} oss_midi_info; - -typedef struct oss_card_info -{ - int card; - char shortname[16]; - char longname[128]; - int flags; - char hw_info[400]; - int intr_count, ack_count; - int filler[154]; -} oss_card_info; - -#define SNDCTL_SYSINFO __SIOR ('X', 1, oss_sysinfo) -#define OSS_SYSINFO SNDCTL_SYSINFO /* Old name */ - -#define SNDCTL_MIX_NRMIX __SIOR ('X', 2, int) -#define SNDCTL_MIX_NREXT __SIOWR('X', 3, int) -#define SNDCTL_MIX_EXTINFO __SIOWR('X', 4, oss_mixext) -#define SNDCTL_MIX_READ __SIOWR('X', 5, oss_mixer_value) -#define SNDCTL_MIX_WRITE __SIOWR('X', 6, oss_mixer_value) - -#define SNDCTL_AUDIOINFO __SIOWR('X', 7, oss_audioinfo) -#define SNDCTL_MIX_ENUMINFO __SIOWR('X', 8, oss_mixer_enuminfo) -#define SNDCTL_MIDIINFO __SIOWR('X', 9, oss_midi_info) -#define SNDCTL_MIXERINFO __SIOWR('X',10, oss_mixerinfo) -#define SNDCTL_CARDINFO __SIOWR('X',11, oss_card_info) -#define SNDCTL_ENGINEINFO __SIOWR('X',12, oss_audioinfo) -#define SNDCTL_AUDIOINFO_EX __SIOWR('X',13, oss_audioinfo) - -#define SNDCTL_MIX_DESCRIPTION __SIOWR('X',14, oss_mixer_enuminfo) - -/* ioctl codes 'X', 200-255 are reserved for internal use */ - -/* - * Few more "globally" available ioctl calls. - */ -#define SNDCTL_SETSONG __SIOW ('Y', 2, oss_longname_t) -#define SNDCTL_GETSONG __SIOR ('Y', 2, oss_longname_t) -#define SNDCTL_SETNAME __SIOW ('Y', 3, oss_longname_t) -#define SNDCTL_SETLABEL __SIOW ('Y', 4, oss_label_t) -#define SNDCTL_GETLABEL __SIOR ('Y', 4, oss_label_t) -/* - * The "new" mixer API definitions end here. - *************************************** - */ - -/* - ********************************************************* - * Few routines that are included in -lOSSlib - * - * At this moment this interface is not used. OSSlib contains just - * stubs that call the related system calls directly. - */ -#ifdef OSSLIB -extern int osslib_open (const char *path, int flags, int dummy); -extern void osslib_close (int fd); -extern int osslib_write (int fd, const void *buf, int count); -extern int osslib_read (int fd, void *buf, int count); -extern int osslib_ioctl (int fd, unsigned int request, void *arg); -#else -# define osslib_open open -# define osslib_close close -# define osslib_write write -# define osslib_read read -# define osslib_ioctl ioctl -#endif - -#if 1 -#define SNDCTL_DSP_NONBLOCK __SIO ('P',14) /* Obsolete. Not supported any more */ -#endif - -#if 1 -/* - * Some obsolete macros that are not part of Open Sound System API. - */ -#define SOUND_PCM_READ_RATE SOUND_PCM_READ_RATE_is_obsolete -#define SOUND_PCM_READ_BITS SOUND_PCM_READ_BITS_is_obsolete -#define SOUND_PCM_READ_CHANNELS SOUND_PCM_READ_CHANNELS_is_obsolete -#define SOUND_PCM_WRITE_RATE SOUND_PCM_WRITE_RATE_is_obsolet_use_SNDCTL_DSP_SPEED_instead -#define SOUND_PCM_WRITE_CHANNELS SOUND_PCM_WRITE_CHANNELS_is_obsolete_use_SNDCTL_DSP_CHANNELS_instead -#define SOUND_PCM_WRITE_BITS SOUND_PCM_WRITE_BITS_is_obsolete_use_SNDCTL_DSP_SETFMT_instead -#define SOUND_PCM_POST SOUND_PCM_POST_is_obsolete_use_SNDCTL_DSP_POST_instead -#define SOUND_PCM_RESET SOUND_PCM_RESET_is_obsolete_use_SNDCTL_DSP_HALT_instead -#define SOUND_PCM_SYNC SOUND_PCM_SYNC_is_obsolete_use_SNDCTL_DSP_SYNC_instead -#define SOUND_PCM_SUBDIVIDE SOUND_PCM_SUBDIVIDE_is_obsolete_use_SNDCTL_DSP_SUBDIVIDE_instead -#define SOUND_PCM_SETFRAGMENT SOUND_PCM_SETFRAGMENT_is_obsolete_use_SNDCTL_DSP_SETFRAGMENT_instead -#define SOUND_PCM_GETFMTS SOUND_PCM_GETFMTS_is_obsolete_use_SNDCTL_DSP_GETFMTS_instead -#define SOUND_PCM_SETFMT SOUND_PCM_SETFMT_is_obsolete_use_SNDCTL_DSP_SETFMT_instead -#define SOUND_PCM_GETOSPACE SOUND_PCM_GETOSPACE_is_obsolete_use_SNDCTL_DSP_GETOSPACE_instead -#define SOUND_PCM_GETISPACE SOUND_PCM_GETISPACE_is_obsolete_use_SNDCTL_DSP_GETISPACE_instead -#define SOUND_PCM_NONBLOCK SOUND_PCM_NONBLOCK_is_obsolete_use_SNDCTL_DSP_NONBLOCK_instead -#define SOUND_PCM_GETCAPS SOUND_PCM_GETCAPS_is_obsolete_use_SNDCTL_DSP_GETCAPS_instead -#define SOUND_PCM_GETTRIGGER SOUND_PCM_GETTRIGGER_is_obsolete_use_SNDCTL_DSP_GETTRIGGER_instead -#define SOUND_PCM_SETTRIGGER SOUND_PCM_SETTRIGGER_is_obsolete_use_SNDCTL_DSP_SETTRIGGER_instead -#define SOUND_PCM_SETSYNCRO SOUND_PCM_SETSYNCRO_is_obsolete_use_SNDCTL_DSP_SETSYNCRO_instead -#define SOUND_PCM_GETIPTR SOUND_PCM_GETIPTR_is_obsolete_use_SNDCTL_DSP_GETIPTR_instead -#define SOUND_PCM_GETOPTR SOUND_PCM_GETOPTR_is_obsolete_use_SNDCTL_DSP_GETOPTR_instead -#define SOUND_PCM_MAPINBUF SOUND_PCM_MAPINBUF_is_obsolete_use_SNDCTL_DSP_MAPINBUF_instead -#define SOUND_PCM_MAPOUTBUF SOUND_PCM_MAPOUTBUF_is_obsolete_use_SNDCTL_DSP_MAPOUTBUF_instead -#endif - -#endif diff --git a/sys/oss4/oss4-source.c b/sys/oss4/oss4-source.c deleted file mode 100644 index d3b92f716..000000000 --- a/sys/oss4/oss4-source.c +++ /dev/null @@ -1,1006 +0,0 @@ -/* GStreamer OSS4 audio source - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:element-oss4src - * - * This element lets you record sound using the Open Sound System (OSS) - * version 4. - * - * <refsect2> - * <title>Example pipelines</title> - * |[ - * gst-launch -v oss4src ! queue ! audioconvert ! vorbisenc ! oggmux ! filesink location=mymusic.ogg - * ]| will record sound from your sound card using OSS4 and encode it to an - * Ogg/Vorbis file (this will only work if your mixer settings are right - * and the right inputs areenabled etc.) - * </refsect2> - * - * Since: 0.10.7 - */ - -/* FIXME: make sure we're not doing ioctls from the app thread (e.g. via the - * mixer interface) while recording */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <errno.h> -#include <unistd.h> -#include <string.h> - -#include <gst/interfaces/mixer.h> -#include <gst/gst-i18n-plugin.h> - -#define NO_LEGACY_MIXER -#include "oss4-audio.h" -#include "oss4-source.h" -#include "oss4-property-probe.h" -#include "oss4-soundcard.h" - -#define GST_OSS4_SOURCE_IS_OPEN(src) (GST_OSS4_SOURCE(src)->fd != -1) - -GST_DEBUG_CATEGORY_EXTERN (oss4src_debug); -#define GST_CAT_DEFAULT oss4src_debug - -#define DEFAULT_DEVICE NULL -#define DEFAULT_DEVICE_NAME NULL - -enum -{ - PROP_0, - PROP_DEVICE, - PROP_DEVICE_NAME -}; - -static void gst_oss4_source_init_interfaces (GType type); - -GST_BOILERPLATE_FULL (GstOss4Source, gst_oss4_source, GstAudioSrc, - GST_TYPE_AUDIO_SRC, gst_oss4_source_init_interfaces); - -static void gst_oss4_source_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_oss4_source_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); - -static void gst_oss4_source_dispose (GObject * object); -static void gst_oss4_source_finalize (GstOss4Source * osssrc); - -static GstCaps *gst_oss4_source_getcaps (GstBaseSrc * bsrc); - -static gboolean gst_oss4_source_open (GstAudioSrc * asrc, - gboolean silent_errors); -static gboolean gst_oss4_source_open_func (GstAudioSrc * asrc); -static gboolean gst_oss4_source_close (GstAudioSrc * asrc); -static gboolean gst_oss4_source_prepare (GstAudioSrc * asrc, - GstRingBufferSpec * spec); -static gboolean gst_oss4_source_unprepare (GstAudioSrc * asrc); -static guint gst_oss4_source_read (GstAudioSrc * asrc, gpointer data, - guint length); -static guint gst_oss4_source_delay (GstAudioSrc * asrc); -static void gst_oss4_source_reset (GstAudioSrc * asrc); - -static void -gst_oss4_source_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - GstPadTemplate *templ; - - gst_element_class_set_details_simple (element_class, - "OSS v4 Audio Source", "Source/Audio", - "Capture from a sound card via OSS version 4", - "Tim-Philipp Müller <tim centricular net>"); - - templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - gst_oss4_audio_get_template_caps ()); - gst_element_class_add_pad_template (element_class, templ); -} -static void -gst_oss4_source_class_init (GstOss4SourceClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSrcClass *gstbasesrc_class; - GstBaseAudioSrcClass *gstbaseaudiosrc_class; - GstAudioSrcClass *gstaudiosrc_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesrc_class = (GstBaseSrcClass *) klass; - gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass; - gstaudiosrc_class = (GstAudioSrcClass *) klass; - - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_oss4_source_dispose); - gobject_class->finalize = - (GObjectFinalizeFunc) GST_DEBUG_FUNCPTR (gst_oss4_source_finalize); - gobject_class->get_property = - GST_DEBUG_FUNCPTR (gst_oss4_source_get_property); - gobject_class->set_property = - GST_DEBUG_FUNCPTR (gst_oss4_source_set_property); - - gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss4_source_getcaps); - - gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_oss4_source_open_func); - gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_oss4_source_prepare); - gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss4_source_unprepare); - gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_oss4_source_close); - gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_oss4_source_read); - gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_oss4_source_delay); - gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_oss4_source_reset); - - g_object_class_install_property (gobject_class, PROP_DEVICE, - g_param_spec_string ("device", "Device", - "OSS4 device (e.g. /dev/oss/hdaudio0/pcm0 or /dev/dspN) " - "(NULL = use first available device)", - DEFAULT_DEVICE, G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, - g_param_spec_string ("device-name", "Device name", - "Human-readable name of the sound device", DEFAULT_DEVICE_NAME, - G_PARAM_READABLE)); -} - -static void -gst_oss4_source_init (GstOss4Source * osssrc, GstOss4SourceClass * g_class) -{ - const gchar *device; - - device = g_getenv ("AUDIODEV"); - if (device == NULL) - device = DEFAULT_DEVICE; - - osssrc->fd = -1; - osssrc->device = g_strdup (device); - osssrc->device_name = g_strdup (DEFAULT_DEVICE_NAME); - osssrc->device_name = NULL; -} - -static void -gst_oss4_source_finalize (GstOss4Source * oss) -{ - g_free (oss->device); - oss->device = NULL; - - g_list_free (oss->property_probe_list); - oss->property_probe_list = NULL; - - G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (oss)); -} - -static void -gst_oss4_source_dispose (GObject * object) -{ - GstOss4Source *oss = GST_OSS4_SOURCE (object); - - if (oss->probed_caps) { - gst_caps_unref (oss->probed_caps); - oss->probed_caps = NULL; - } - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -gst_oss4_source_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstOss4Source *oss; - - oss = GST_OSS4_SOURCE (object); - - switch (prop_id) { - case PROP_DEVICE: - GST_OBJECT_LOCK (oss); - if (oss->fd == -1) { - g_free (oss->device); - oss->device = g_value_dup_string (value); - g_free (oss->device_name); - oss->device_name = NULL; - } else { - g_warning ("%s: can't change \"device\" property while audio source " - "is open", GST_OBJECT_NAME (oss)); - } - GST_OBJECT_UNLOCK (oss); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_oss4_source_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstOss4Source *oss; - - oss = GST_OSS4_SOURCE (object); - - switch (prop_id) { - case PROP_DEVICE: - GST_OBJECT_LOCK (oss); - g_value_set_string (value, oss->device); - GST_OBJECT_UNLOCK (oss); - break; - case PROP_DEVICE_NAME: - GST_OBJECT_LOCK (oss); - /* If device is set, try to retrieve the name even if we're not open */ - if (oss->fd == -1 && oss->device != NULL) { - if (gst_oss4_source_open (GST_AUDIO_SRC (oss), TRUE)) { - g_value_set_string (value, oss->device_name); - gst_oss4_source_close (GST_AUDIO_SRC (oss)); - } else { - gchar *name = NULL; - - gst_oss4_property_probe_find_device_name_nofd (GST_OBJECT (oss), - oss->device, &name); - g_value_set_string (value, name); - g_free (name); - } - } else { - g_value_set_string (value, oss->device_name); - } - - GST_OBJECT_UNLOCK (oss); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstCaps * -gst_oss4_source_getcaps (GstBaseSrc * bsrc) -{ - GstOss4Source *oss; - GstCaps *caps; - - oss = GST_OSS4_SOURCE (bsrc); - - if (oss->fd == -1) { - caps = gst_caps_copy (gst_oss4_audio_get_template_caps ()); - } else if (oss->probed_caps) { - caps = gst_caps_copy (oss->probed_caps); - } else { - caps = gst_oss4_audio_probe_caps (GST_OBJECT (oss), oss->fd); - if (caps != NULL && !gst_caps_is_empty (caps)) { - oss->probed_caps = gst_caps_copy (caps); - } - } - - return caps; -} - -/* note: we must not take the object lock here unless we fix up get_property */ -static gboolean -gst_oss4_source_open (GstAudioSrc * asrc, gboolean silent_errors) -{ - GstOss4Source *oss; - gchar *device; - int mode; - - oss = GST_OSS4_SOURCE (asrc); - - if (oss->device) - device = g_strdup (oss->device); - else - device = gst_oss4_audio_find_device (GST_OBJECT_CAST (oss)); - - /* desperate times, desperate measures */ - if (device == NULL) - device = g_strdup ("/dev/dsp0"); - - GST_INFO_OBJECT (oss, "Trying to open OSS4 device '%s'", device); - - /* we open in non-blocking mode even if we don't really want to do writes - * non-blocking because we can't be sure that this is really a genuine - * OSS4 device with well-behaved drivers etc. We really don't want to - * hang forever under any circumstances. */ - oss->fd = open (device, O_RDONLY | O_NONBLOCK, 0); - if (oss->fd == -1) { - switch (errno) { - case EBUSY: - goto busy; - case EACCES: - goto no_permission; - default: - goto open_failed; - } - } - - GST_INFO_OBJECT (oss, "Opened device"); - - /* Make sure it's OSS4. If it's old OSS, let osssink handle it */ - if (!gst_oss4_audio_check_version (GST_OBJECT_CAST (oss), oss->fd)) - goto legacy_oss; - - /* now remove the non-blocking flag. */ - mode = fcntl (oss->fd, F_GETFL); - mode &= ~O_NONBLOCK; - if (fcntl (oss->fd, F_SETFL, mode) < 0) { - /* some drivers do no support unsetting the non-blocking flag, try to - * close/open the device then. This is racy but we error out properly. */ - GST_WARNING_OBJECT (oss, "failed to unset O_NONBLOCK (buggy driver?), " - "will try to re-open device now"); - gst_oss4_source_close (asrc); - if ((oss->fd = open (device, O_RDONLY, 0)) == -1) - goto non_block; - } - - oss->open_device = device; - - /* not using ENGINEINFO here because it sometimes returns a different and - * less useful name than AUDIOINFO for the same device */ - if (!gst_oss4_property_probe_find_device_name (GST_OBJECT (oss), oss->fd, - oss->open_device, &oss->device_name)) { - oss->device_name = NULL; - } - - return TRUE; - - /* ERRORS */ -busy: - { - if (!silent_errors) { - GST_ELEMENT_ERROR (oss, RESOURCE, BUSY, - (_("Could not open audio device for playback. " - "Device is being used by another application.")), (NULL)); - } - g_free (device); - return FALSE; - } -no_permission: - { - if (!silent_errors) { - GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ, - (_("Could not open audio device for playback. " - "You don't have permission to open the device.")), - GST_ERROR_SYSTEM); - } - g_free (device); - return FALSE; - } -open_failed: - { - if (!silent_errors) { - GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ, - (_("Could not open audio device for playback.")), GST_ERROR_SYSTEM); - } - g_free (device); - return FALSE; - } -legacy_oss: - { - gst_oss4_source_close (asrc); - if (!silent_errors) { - GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ, - (_("Could not open audio device for playback. " - "This version of the Open Sound System is not supported by this " - "element.")), ("Try the 'osssink' element instead")); - } - g_free (device); - return FALSE; - } -non_block: - { - if (!silent_errors) { - GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL), - ("Unable to set device %s into non-blocking mode: %s", - oss->device, g_strerror (errno))); - } - g_free (device); - return FALSE; - } -} - -static gboolean -gst_oss4_source_open_func (GstAudioSrc * asrc) -{ - return gst_oss4_source_open (asrc, FALSE); -} - -static void -gst_oss4_source_free_mixer_tracks (GstOss4Source * oss) -{ - g_list_foreach (oss->tracks, (GFunc) g_object_unref, NULL); - g_list_free (oss->tracks); - oss->tracks = NULL; -} - -static gboolean -gst_oss4_source_close (GstAudioSrc * asrc) -{ - GstOss4Source *oss; - - oss = GST_OSS4_SOURCE (asrc); - - if (oss->fd != -1) { - GST_DEBUG_OBJECT (oss, "closing device"); - close (oss->fd); - oss->fd = -1; - } - - oss->bytes_per_sample = 0; - - gst_caps_replace (&oss->probed_caps, NULL); - - g_free (oss->open_device); - oss->open_device = NULL; - - g_free (oss->device_name); - oss->device_name = NULL; - - gst_oss4_source_free_mixer_tracks (oss); - - return TRUE; -} - -static gboolean -gst_oss4_source_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec) -{ - GstOss4Source *oss; - - oss = GST_OSS4_SOURCE (asrc); - - if (!gst_oss4_audio_set_format (GST_OBJECT_CAST (oss), oss->fd, spec)) { - GST_WARNING_OBJECT (oss, "Couldn't set requested format %" GST_PTR_FORMAT, - spec->caps); - return FALSE; - } - - oss->bytes_per_sample = spec->bytes_per_sample; - return TRUE; -} - -static gboolean -gst_oss4_source_unprepare (GstAudioSrc * asrc) -{ - /* could do a SNDCTL_DSP_HALT, but the OSS manual recommends a close/open, - * since HALT won't properly reset some devices, apparently */ - - if (!gst_oss4_source_close (asrc)) - goto couldnt_close; - - if (!gst_oss4_source_open_func (asrc)) - goto couldnt_reopen; - - return TRUE; - - /* ERRORS */ -couldnt_close: - { - GST_DEBUG_OBJECT (asrc, "Couldn't close the audio device"); - return FALSE; - } -couldnt_reopen: - { - GST_DEBUG_OBJECT (asrc, "Couldn't reopen the audio device"); - return FALSE; - } -} - -static guint -gst_oss4_source_read (GstAudioSrc * asrc, gpointer data, guint length) -{ - GstOss4Source *oss; - int n; - - oss = GST_OSS4_SOURCE_CAST (asrc); - - n = read (oss->fd, data, length); - GST_LOG_OBJECT (asrc, "%u bytes, %u samples", n, n / oss->bytes_per_sample); - - if (G_UNLIKELY (n < 0)) { - switch (errno) { - case ENOTSUP: - case EACCES:{ - /* This is the most likely cause, I think */ - GST_ELEMENT_ERROR (asrc, RESOURCE, READ, - (_("Recording is not supported by this audio device.")), - ("read: %s (device: %s) (maybe this is an output-only device?)", - g_strerror (errno), oss->open_device)); - break; - } - default:{ - GST_ELEMENT_ERROR (asrc, RESOURCE, READ, - (_("Error recording from audio device.")), - ("read: %s (device: %s)", g_strerror (errno), oss->open_device)); - break; - } - } - } - - return (guint) n; -} - -static guint -gst_oss4_source_delay (GstAudioSrc * asrc) -{ - audio_buf_info info = { 0, }; - GstOss4Source *oss; - guint delay; - - oss = GST_OSS4_SOURCE_CAST (asrc); - - if (ioctl (oss->fd, SNDCTL_DSP_GETISPACE, &info) == -1) { - GST_LOG_OBJECT (oss, "GETISPACE failed: %s", g_strerror (errno)); - return 0; - } - - delay = (info.fragstotal * info.fragsize) - info.bytes; - GST_LOG_OBJECT (oss, "fragstotal:%d, fragsize:%d, bytes:%d, delay:%d", - info.fragstotal, info.fragsize, info.bytes, delay); - return delay; -} - -static void -gst_oss4_source_reset (GstAudioSrc * asrc) -{ - /* There's nothing we can do here really: OSS can't handle access to the - * same device/fd from multiple threads and might deadlock or blow up in - * other ways if we try an ioctl SNDCTL_DSP_HALT or similar */ -} - -/* GstMixer interface, which we abuse here for input selection, because we - * don't have a proper interface for that and because that's what - * gnome-sound-recorder does. */ - -/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */ -G_DEFINE_TYPE (GstOss4SourceInput, gst_oss4_source_input, GST_TYPE_MIXER_TRACK); - -static void -gst_oss4_source_input_class_init (GstOss4SourceInputClass * klass) -{ - /* nothing to do here */ -} - -static void -gst_oss4_source_input_init (GstOss4SourceInput * i) -{ - /* nothing to do here */ -} - -#if 0 - -static void -gst_ossmixer_ensure_track_list (GstOssMixer * mixer) -{ - gint i, master = -1; - - g_return_if_fail (mixer->fd != -1); - - if (mixer->tracklist) - return; - - /* find master volume */ - if (mixer->devmask & SOUND_MASK_VOLUME) - master = SOUND_MIXER_VOLUME; - else if (mixer->devmask & SOUND_MASK_PCM) - master = SOUND_MIXER_PCM; - else if (mixer->devmask & SOUND_MASK_SPEAKER) - master = SOUND_MIXER_SPEAKER; /* doubtful... */ - /* else: no master, so we won't set any */ - - /* build track list */ - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { - if (mixer->devmask & (1 << i)) { - GstMixerTrack *track; - gboolean input = FALSE, stereo = FALSE, record = FALSE; - - /* track exists, make up capabilities */ - if (MASK_BIT_IS_SET (mixer->stereomask, i)) - stereo = TRUE; - if (MASK_BIT_IS_SET (mixer->recmask, i)) - input = TRUE; - if (MASK_BIT_IS_SET (mixer->recdevs, i)) - record = TRUE; - - /* do we want mixer in our list? */ - if (!((mixer->dir & GST_OSS_MIXER_CAPTURE && input == TRUE) || - (mixer->dir & GST_OSS_MIXER_PLAYBACK && i != SOUND_MIXER_PCM))) - /* the PLAYBACK case seems hacky, but that's how 0.8 had it */ - continue; - - /* add track to list */ - track = gst_ossmixer_track_new (mixer->fd, i, stereo ? 2 : 1, - (record ? GST_MIXER_TRACK_RECORD : 0) | - (input ? GST_MIXER_TRACK_INPUT : - GST_MIXER_TRACK_OUTPUT) | - ((master != i) ? 0 : GST_MIXER_TRACK_MASTER)); - mixer->tracklist = g_list_append (mixer->tracklist, track); - } - } -} - -/* unused with G_DISABLE_* */ -static G_GNUC_UNUSED gboolean -gst_ossmixer_contains_track (GstOssMixer * mixer, GstOssMixerTrack * osstrack) -{ - const GList *item; - - for (item = mixer->tracklist; item != NULL; item = item->next) - if (item->data == osstrack) - return TRUE; - - return FALSE; -} - -const GList * -gst_ossmixer_list_tracks (GstOssMixer * mixer) -{ - gst_ossmixer_ensure_track_list (mixer); - - return (const GList *) mixer->tracklist; -} - -void -gst_ossmixer_get_volume (GstOssMixer * mixer, - GstMixerTrack * track, gint * volumes) -{ - gint volume; - GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track); - - g_return_if_fail (mixer->fd != -1); - g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack)); - - if (track->flags & GST_MIXER_TRACK_MUTE) { - volumes[0] = osstrack->lvol; - if (track->num_channels == 2) { - volumes[1] = osstrack->rvol; - } - } else { - /* get */ - if (ioctl (mixer->fd, MIXER_READ (osstrack->track_num), &volume) < 0) { - g_warning ("Error getting recording device (%d) volume: %s", - osstrack->track_num, g_strerror (errno)); - volume = 0; - } - - osstrack->lvol = volumes[0] = (volume & 0xff); - if (track->num_channels == 2) { - osstrack->rvol = volumes[1] = ((volume >> 8) & 0xff); - } - } -} - -void -gst_ossmixer_set_mute (GstOssMixer * mixer, GstMixerTrack * track, - gboolean mute) -{ - int volume; - GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track); - - g_return_if_fail (mixer->fd != -1); - g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack)); - - if (mute) { - volume = 0; - } else { - volume = (osstrack->lvol & 0xff); - if (MASK_BIT_IS_SET (mixer->stereomask, osstrack->track_num)) { - volume |= ((osstrack->rvol & 0xff) << 8); - } - } - - if (ioctl (mixer->fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) { - g_warning ("Error setting mixer recording device volume (0x%x): %s", - volume, g_strerror (errno)); - return; - } - - if (mute) { - track->flags |= GST_MIXER_TRACK_MUTE; - } else { - track->flags &= ~GST_MIXER_TRACK_MUTE; - } -} -#endif - -static gint -gst_oss4_source_mixer_get_current_input (GstOss4Source * oss) -{ - int cur = -1; - - if (ioctl (oss->fd, SNDCTL_DSP_GET_RECSRC, &cur) == -1 || cur < 0) - return -1; - - return cur; -} - -static const gchar * -gst_oss4_source_mixer_update_record_flags (GstOss4Source * oss, gint cur_route) -{ - const gchar *cur_name = ""; - GList *t; - - for (t = oss->tracks; t != NULL; t = t->next) { - GstMixerTrack *track = t->data; - - if (GST_OSS4_SOURCE_INPUT (track)->route == cur_route) { - if (!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) { - track->flags |= GST_MIXER_TRACK_RECORD; - /* no point in sending a mixer-record-changes message here */ - } - cur_name = track->label; - } else { - if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) { - track->flags &= ~GST_MIXER_TRACK_RECORD; - /* no point in sending a mixer-record-changes message here */ - } - } - } - - return cur_name; -} - -static const GList * -gst_oss4_source_mixer_list_tracks (GstMixer * mixer) -{ - oss_mixer_enuminfo names = { 0, }; - GstOss4Source *oss; - const gchar *cur_name; - GList *tracks = NULL; - gint i, cur; - - g_return_val_if_fail (mixer != NULL, NULL); - g_return_val_if_fail (GST_IS_OSS4_SOURCE (mixer), NULL); - g_return_val_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer), NULL); - - oss = GST_OSS4_SOURCE (mixer); - - if (oss->tracks != NULL && oss->tracks_static) - goto done; - - if (ioctl (oss->fd, SNDCTL_DSP_GET_RECSRC_NAMES, &names) == -1) - goto get_recsrc_names_error; - - oss->tracks_static = (names.version == 0); - - GST_INFO_OBJECT (oss, "%d inputs (list is static: %s):", names.nvalues, - (oss->tracks_static) ? "yes" : "no"); - - for (i = 0; i < MIN (names.nvalues, OSS_ENUM_MAXVALUE + 1); ++i) { - GstMixerTrack *track; - - track = g_object_new (GST_TYPE_OSS4_SOURCE_INPUT, NULL); - track->label = g_strdup (&names.strings[names.strindex[i]]); - track->flags = GST_MIXER_TRACK_INPUT; - track->num_channels = 2; - track->min_volume = 0; - track->max_volume = 100; - GST_OSS4_SOURCE_INPUT (track)->route = i; - - GST_INFO_OBJECT (oss, " [%d] %s", i, track->label); - tracks = g_list_append (tracks, track); - } - - gst_oss4_source_free_mixer_tracks (oss); - oss->tracks = tracks; - -done: - - /* update RECORD flags */ - cur = gst_oss4_source_mixer_get_current_input (oss); - cur_name = gst_oss4_source_mixer_update_record_flags (oss, cur); - GST_DEBUG_OBJECT (oss, "current input route: %d (%s)", cur, cur_name); - - return (const GList *) oss->tracks; - -/* ERRORS */ -get_recsrc_names_error: - { - GST_WARNING_OBJECT (oss, "GET_RECSRC_NAMES failed: %s", g_strerror (errno)); - return NULL; - } -} - -static void -gst_oss4_source_mixer_set_volume (GstMixer * mixer, GstMixerTrack * track, - gint * volumes) -{ - GstOss4Source *oss; - int new_vol, cur; - - g_return_if_fail (mixer != NULL); - g_return_if_fail (track != NULL); - g_return_if_fail (GST_IS_MIXER_TRACK (track)); - g_return_if_fail (GST_IS_OSS4_SOURCE (mixer)); - g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer)); - - oss = GST_OSS4_SOURCE (mixer); - - cur = gst_oss4_source_mixer_get_current_input (oss); - if (cur != GST_OSS4_SOURCE_INPUT (track)->route) { - GST_DEBUG_OBJECT (oss, "track not selected input route, ignoring request"); - return; - } - - new_vol = (volumes[1] << 8) | volumes[0]; - if (ioctl (oss->fd, SNDCTL_DSP_SETRECVOL, &new_vol) == -1) { - GST_WARNING_OBJECT (oss, "SETRECVOL failed: %s", g_strerror (errno)); - } -} - -static void -gst_oss4_source_mixer_get_volume (GstMixer * mixer, GstMixerTrack * track, - gint * volumes) -{ - GstOss4Source *oss; - int cur; - - g_return_if_fail (mixer != NULL); - g_return_if_fail (GST_IS_OSS4_SOURCE (mixer)); - g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer)); - - oss = GST_OSS4_SOURCE (mixer); - - cur = gst_oss4_source_mixer_get_current_input (oss); - if (cur != GST_OSS4_SOURCE_INPUT (track)->route) { - volumes[0] = 0; - volumes[1] = 0; - } else { - int vol = -1; - - if (ioctl (oss->fd, SNDCTL_DSP_GETRECVOL, &vol) == -1 || vol < 0) { - GST_WARNING_OBJECT (oss, "GETRECVOL failed: %s", g_strerror (errno)); - volumes[0] = 100; - volumes[1] = 100; - } else { - volumes[0] = MIN (100, vol & 0xff); - volumes[1] = MIN (100, (vol >> 8) & 0xff); - } - } -} - -static void -gst_oss4_source_mixer_set_record (GstMixer * mixer, GstMixerTrack * track, - gboolean record) -{ - GstOss4Source *oss; - const gchar *cur_name; - gint cur; - - g_return_if_fail (mixer != NULL); - g_return_if_fail (track != NULL); - g_return_if_fail (GST_IS_MIXER_TRACK (track)); - g_return_if_fail (GST_IS_OSS4_SOURCE (mixer)); - g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer)); - - oss = GST_OSS4_SOURCE (mixer); - - cur = gst_oss4_source_mixer_get_current_input (oss); - - /* stop recording for an input that's not selected anyway => nothing to do */ - if (!record && cur != GST_OSS4_SOURCE_INPUT (track)->route) - goto done; - - /* select recording for an input that's already selected => nothing to do - * (or should we mess with the recording volume in this case maybe?) */ - if (record && cur == GST_OSS4_SOURCE_INPUT (track)->route) - goto done; - - /* make current input stop recording: we can't really make an input stop - * recording, we can only select an input FOR recording, so we'll just ignore - * all requests to stop for now */ - if (!record) { - GST_WARNING_OBJECT (oss, "Can't un-select an input as such, only switch " - "to a different input source"); - /* FIXME: set recording volume to 0 maybe? */ - } else { - int new_route = GST_OSS4_SOURCE_INPUT (track)->route; - - /* select this input for recording */ - - if (ioctl (oss->fd, SNDCTL_DSP_SET_RECSRC, &new_route) == -1) { - GST_WARNING_OBJECT (oss, "Could not select input %d for recording: %s", - new_route, g_strerror (errno)); - } else { - cur = new_route; - } - } - -done: - - cur_name = gst_oss4_source_mixer_update_record_flags (oss, cur); - GST_DEBUG_OBJECT (oss, "active input route: %d (%s)", cur, cur_name); -} - -static void -gst_oss4_source_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track, - gboolean mute) -{ - GstOss4Source *oss; - - g_return_if_fail (mixer != NULL); - g_return_if_fail (track != NULL); - g_return_if_fail (GST_IS_MIXER_TRACK (track)); - g_return_if_fail (GST_IS_OSS4_SOURCE (mixer)); - g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer)); - - oss = GST_OSS4_SOURCE (mixer); - - /* FIXME: implement gst_oss4_source_mixer_set_mute() - what to do here? */ - /* oss4_mixer_set_mute (mixer->mixer, track, mute); */ -} - -static void -gst_oss4_source_mixer_interface_init (GstMixerClass * klass) -{ - GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE; - - klass->list_tracks = gst_oss4_source_mixer_list_tracks; - klass->set_volume = gst_oss4_source_mixer_set_volume; - klass->get_volume = gst_oss4_source_mixer_get_volume; - klass->set_mute = gst_oss4_source_mixer_set_mute; - klass->set_record = gst_oss4_source_mixer_set_record; -} - -/* Implement the horror that is GstImplementsInterface */ - -static gboolean -gst_oss4_source_mixer_supported (GstImplementsInterface * iface, - GType iface_type) -{ - GstOss4Source *oss; - gboolean is_open; - - g_return_val_if_fail (GST_IS_OSS4_SOURCE (iface), FALSE); - g_return_val_if_fail (iface_type == GST_TYPE_MIXER, FALSE); - - oss = GST_OSS4_SOURCE (iface); - - GST_OBJECT_LOCK (oss); - is_open = GST_OSS4_SOURCE_IS_OPEN (iface); - GST_OBJECT_UNLOCK (oss); - - return is_open; -} - -static void -gst_oss4_source_mixer_implements_interface_init (GstImplementsInterfaceClass * - klass) -{ - klass->supported = gst_oss4_source_mixer_supported; -} - -static void -gst_oss4_source_init_interfaces (GType type) -{ - static const GInterfaceInfo implements_iface_info = { - (GInterfaceInitFunc) gst_oss4_source_mixer_implements_interface_init, - NULL, - NULL, - }; - static const GInterfaceInfo mixer_iface_info = { - (GInterfaceInitFunc) gst_oss4_source_mixer_interface_init, - NULL, - NULL, - }; - - g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, - &implements_iface_info); - g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info); - - gst_oss4_add_property_probe_interface (type); -} diff --git a/sys/oss4/oss4-source.h b/sys/oss4/oss4-source.h deleted file mode 100644 index 3a86b43ad..000000000 --- a/sys/oss4/oss4-source.h +++ /dev/null @@ -1,89 +0,0 @@ -/* GStreamer OSS4 audio source - * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef GST_OSS4_SOURCE_H -#define GST_OSS4_SOURCE_H - -#include <gst/gst.h> -#include <gst/audio/gstaudiosrc.h> -#include <gst/interfaces/mixertrack.h> - -G_BEGIN_DECLS - -#define GST_TYPE_OSS4_SOURCE (gst_oss4_source_get_type()) -#define GST_OSS4_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_SOURCE,GstOss4Source)) -#define GST_OSS4_SOURCE_CAST(obj) ((GstOss4Source *)(obj)) -#define GST_OSS4_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_SOURCE,GstOss4SourceClass)) -#define GST_IS_OSS4_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_SOURCE)) -#define GST_IS_OSS4_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_SOURCE)) - -typedef struct _GstOss4Source GstOss4Source; -typedef struct _GstOss4SourceClass GstOss4SourceClass; - -struct _GstOss4Source { - GstAudioSrc audiosrc; - - gchar * device; /* NULL if none was set */ - gchar * open_device; /* the device we opened */ - gchar * device_name; /* set if the device is open */ - gint fd; /* -1 if not open */ - gint bytes_per_sample; - - GstCaps * probed_caps; - - /* property probe interface */ - GList * property_probe_list; - - /* mixer interface */ - GList * tracks; - gboolean tracks_static; /* FALSE if the list of inputs may change */ -}; - -struct _GstOss4SourceClass { - GstAudioSrcClass audiosrc_class; -}; - -GType gst_oss4_source_get_type (void); - -/* our mixer track for input selection */ -#define GST_TYPE_OSS4_SOURCE_INPUT (gst_oss4_source_input_get_type()) -#define GST_OSS4_SOURCE_INPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_SOURCE_INPUT,GstOss4SourceInput)) -#define GST_OSS4_SOURCE_INPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_SOURCE_INPUT,GstOss4SourceInputClass)) -#define GST_IS_OSS4_SOURCE_INPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_SOURCE_INPUT)) -#define GST_IS_OSS4_SOURCE_INPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_SOURCE_INPUT)) - -typedef struct _GstOss4SourceInput GstOss4SourceInput; -typedef struct _GstOss4SourceInputClass GstOss4SourceInputClass; - -struct _GstOss4SourceInput { - GstMixerTrack mixer_track; - - int route; /* number for SNDCTL_DSP_SET_RECSRC etc. */ -}; - -struct _GstOss4SourceInputClass { - GstMixerTrackClass mixer_track_class; -}; - -GType gst_oss4_source_input_get_type (void); - -G_END_DECLS - -#endif /* GST_OSS4_SOURCE_H */ - |