--- a/patches/gst-plugins-good-05-ossv4.diff Mon Jun 21 07:08:51 2010 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8130 +0,0 @@
---- gst-plugins-good-0.10.21/configure.ac-orig 2009-03-06 13:27:01.028182000 -0600
-+++ gst-plugins-good-0.10.21/configure.ac 2009-03-06 13:27:09.314297000 -0600
-@@ -1147,6 +1147,7 @@ sys/osxvideo/Makefile
- sys/v4l2/Makefile
- sys/waveform/Makefile
- sys/ximage/Makefile
-+sys/ossv4/Makefile
- po/Makefile.in
- tests/Makefile
- tests/check/Makefile
---- gst-plugins-good-0.10.21/sys/Makefile.am-orig 2009-05-21 15:31:32.651158000 -0500
-+++ gst-plugins-good-0.10.21/sys/Makefile.am 2009-05-21 15:31:59.791998000 -0500
-@@ -70,7 +70,7 @@ else
- XIMAGE_DIR=
- endif
-
--SUBDIRS=$(DIRECTSOUND_DIR) $(OSS_DIR) $(OSX_AUDIO_DIR) $(OSX_VIDEO_DIR) $(SUNAUDIO_DIR) $(V4L2_DIR) $(XIMAGE_DIR)
-+SUBDIRS=$(DIRECTSOUND_DIR) $(OSS_DIR) $(OSX_AUDIO_DIR) $(OSX_VIDEO_DIR) $(SUNAUDIO_DIR) $(V4L2_DIR) $(XIMAGE_DIR) ossv4
-
- DIST_SUBDIRS=directsound oss osxaudio osxvideo sunaudio v4l2 waveform ximage
-
---- /dev/null 2009-03-06 13:26:44.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/Makefile.am 2009-03-06 13:25:06.888308000 -0600
-@@ -0,0 +1,33 @@
-+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
-+
-+
---- /dev/null 2009-03-06 13:28:04.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-audio.h 2009-03-06 13:25:06.888521000 -0600
-@@ -0,0 +1,43 @@
-+/* 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 */
-+
-+
---- /dev/null 2009-03-06 13:28:09.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-mixer-enum.h 2009-03-06 13:25:06.888646000 -0600
-@@ -0,0 +1,67 @@
-+/* 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 */
-+
-+
---- /dev/null 2009-03-06 13:28:14.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-mixer-slider.h 2009-03-06 13:25:06.888791000 -0600
-@@ -0,0 +1,70 @@
-+/* 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 */
-+
-+
---- /dev/null 2009-03-06 13:28:24.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-mixer-switch.h 2009-03-06 13:25:06.888953000 -0600
-@@ -0,0 +1,65 @@
-+/* 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 */
-+
-+
---- /dev/null 2009-03-06 13:28:29.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-mixer.h 2009-03-06 13:25:06.889206000 -0600
-@@ -0,0 +1,128 @@
-+/* 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 */
-+
---- /dev/null 2009-03-06 13:28:39.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-property-probe.h 2009-03-06 13:25:06.889358000 -0600
-@@ -0,0 +1,38 @@
-+/* 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 */
-+
-+
---- /dev/null 2009-03-06 13:28:44.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-sink.h 2009-03-06 13:25:06.889531000 -0600
-@@ -0,0 +1,63 @@
-+/* 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;
-+
-+ 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 */
-+
-+
---- /dev/null 2009-03-06 13:28:54.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-soundcard.h 2009-03-06 13:25:06.889730000 -0600
-@@ -0,0 +1,2067 @@
-+/*
-+ * 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
---- /dev/null 2009-03-06 13:28:59.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-source.h 2009-03-06 13:25:06.889923000 -0600
-@@ -0,0 +1,89 @@
-+/* 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 */
-+
-
---- /dev/null 2009-03-06 13:29:24.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-mixer-enum.c 2009-03-06 13:25:06.888587000 -0600
-@@ -0,0 +1,269 @@
-+/* 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);
-+}
---- /dev/null 2009-06-03 13:20:03.000000000 -0500
-+++ gst-plugins-bad-0.10.12/sys/ossv4/oss4-mixer-slider.c 2009-06-03 13:26:45.996546000 -0500
-@@ -0,0 +1,311 @@
-+/* 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);
-+ }
-+}
---- /dev/null 2009-06-03 13:20:03.000000000 -0500
-+++ gst-plugins-bad-0.10.12/sys/ossv4/oss4-mixer-switch.c 2009-06-03 13:26:45.998451000 -0500
-@@ -0,0 +1,153 @@
-+/* 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);
-+}
---- /dev/null 2009-06-03 13:31:14.000000000 -0500
-+++ gst-plugins-bad-0.10.12/sys/ossv4/oss4-mixer.c 2009-06-03 13:39:53.474560000 -0500
-@@ -0,0 +1,1955 @@
-+/* 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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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[] = {
-+ {
-+ /* SUN_BRANDING */
-+ "volume", N_("Volume")}, {
-+ /* SUN_BRANDING */
-+ "master", N_("Master")}, {
-+ /* SUN_BRANDING */
-+ "front", N_("Front")}, {
-+ /* SUN_BRANDING */
-+ "rear", N_("Rear")}, {
-+ /* SUN_BRANDING */
-+ "headphones", N_("Headphones")}, {
-+ /* SUN_BRANDING */
-+ "center", N_("Center")}, {
-+ /* SUN_BRANDING */
-+ "lfe", N_("LFE")}, {
-+ /* SUN_BRANDING */
-+ "surround", N_("Surround")}, {
-+ /* SUN_BRANDING */
-+ "side", N_("Side")}, {
-+ /* SUN_BRANDING */
-+ "speaker", N_("Built-in Speaker")}, {
-+ /* SUN_BRANDING */
-+ "aux1-out", N_("AUX 1 Out")}, {
-+ /* SUN_BRANDING */
-+ "aux2-out", N_("AUX 2 Out")}, {
-+ /* SUN_BRANDING */
-+ "aux-out", N_("AUX Out")}, {
-+ /* SUN_BRANDING */
-+ "bass", N_("Bass")}, {
-+ /* SUN_BRANDING */
-+ "treble", N_("Treble")}, {
-+ /* SUN_BRANDING */
-+ "3d-depth", N_("3D Depth")}, {
-+ /* SUN_BRANDING */
-+ "3d-center", N_("3D Center")}, {
-+ /* SUN_BRANDING */
-+ "3d-enhance", N_("3D Enhance")}, {
-+ /* SUN_BRANDING */
-+ "phone", N_("Telephone")}, {
-+ /* SUN_BRANDING */
-+ "mic", N_("Microphone")}, {
-+ /* SUN_BRANDING */
-+ "line-out", N_("Line Out")}, {
-+ /* SUN_BRANDING */
-+ "line-in", N_("Line In")}, {
-+ /* SUN_BRANDING */
-+ "linein", N_("Line In")}, {
-+ /* SUN_BRANDING */
-+ "cd", N_("Internal CD")}, {
-+ /* SUN_BRANDING */
-+ "video", N_("Video In")}, {
-+ /* SUN_BRANDING */
-+ "aux1-in", N_("AUX 1 In")}, {
-+ /* SUN_BRANDING */
-+ "aux2-in", N_("AUX 2 In")}, {
-+ /* SUN_BRANDING */
-+ "aux-in", N_("AUX In")}, {
-+ /* SUN_BRANDING */
-+ "pcm", N_("PCM")}, {
-+ /* SUN_BRANDING */
-+ "record-gain", N_("Record Gain")}, {
-+ /* SUN_BRANDING */
-+ "igain", N_("Record Gain")}, {
-+ /* SUN_BRANDING */
-+ "ogain", N_("Output Gain")}, {
-+ /* SUN_BRANDING */
-+ "micboost", N_("Microphone Boost")}, {
-+ /* SUN_BRANDING */
-+ "loopback", N_("Loopback")}, {
-+ /* SUN_BRANDING */
-+ "diag", N_("Diagnostic")}, {
-+ /* SUN_BRANDING */
-+ "loudness", N_("Bass Boost")}, {
-+ /* SUN_BRANDING */
-+ "outputs", N_("Playback Ports")}, {
-+ /* SUN_BRANDING */
-+ "input", N_("Input")}, {
-+ /* SUN_BRANDING */
-+ "inputs", N_("Record Source")}, {
-+ /* SUN_BRANDING */
-+ "record-source", N_("Record Source")}, {
-+ /* SUN_BRANDING */
-+ "monitor-source", N_("Monitor Source")}, {
-+ /* SUN_BRANDING */
-+ "beep", N_("Keyboard Beep")}, {
-+ /* SUN_BRANDING */
-+ "monitor-gain", N_("Monitor")}, {
-+ /* SUN_BRANDING */
-+ "stereo-simulate", N_("Simulate Stereo")}, {
-+ /* SUN_BRANDING */
-+ "stereo", N_("Stereo")}, {
-+ /* SUN_BRANDING */
-+ "multich", N_("Surround Sound")}, {
-+ /* SUN_BRANDING */
-+ "mic-gain", N_("Microphone Gain")}, {
-+ /* SUN_BRANDING */
-+ "speaker-source", N_("Speaker Source")}, {
-+ /* SUN_BRANDING */
-+ "mic-source", N_("Microphone Source")}, {
-+ /* SUN_BRANDING */
-+ "jack", N_("Jack")}, {
-+ /* SUN_BRANDING */
-+ "center/lfe", N_("Center / LFE")}, {
-+ /* SUN_BRANDING */
-+ "stereo-mix", N_("Stereo Mix")}, {
-+ /* SUN_BRANDING */
-+ "mono-mix", N_("Mono Mix")}, {
-+ /* SUN_BRANDING */
-+ "input-mix", N_("Input Mix")}, {
-+ /* SUN_BRANDING */
-+ "spdif-in", N_("SPDIF In")}, {
-+ /* SUN_BRANDING */
-+ "spdif-out", N_("SPDIF Out")}, {
-+ /* SUN_BRANDING */
-+ "mic1", N_("Microphone 1")}, {
-+ /* SUN_BRANDING */
-+ "mic2", N_("Microphone 2")}, {
-+ /* SUN_BRANDING */
-+ "digital-out", N_("Digital Out")}, {
-+ /* SUN_BRANDING */
-+ "digital-in", N_("Digital In")}, {
-+ /* SUN_BRANDING */
-+ "hdmi", N_("HDMI")}, {
-+ /* SUN_BRANDING */
-+ "modem", N_("Modem")}, {
-+ /* SUN_BRANDING */
-+ "handset", N_("Handset")}, {
-+ /* SUN_BRANDING */
-+ "other", N_("Other")}, {
-+ /* SUN_BRANDING */
-+ "stereo", N_("Stereo")}, {
-+ /* SUN_BRANDING */
-+ "none", N_("None")}, {
-+ /* SUN_BRANDING */
-+ "on", N_("On")}, {
-+ /* SUN_BRANDING */
-+ "off", N_("Off")}, {
-+ /* SUN_BRANDING */
-+ "mute", N_("Mute")}, {
-+ /* SUN_BRANDING */
-+ "fast", N_("Fast")}, {
-+ /* SUN_BRANDING */
-+ "very-low", N_("Very Low")}, {
-+ /* SUN_BRANDING */
-+ "low", N_("Low")}, {
-+ /* SUN_BRANDING */
-+ "medium", N_("Medium")}, {
-+ /* SUN_BRANDING */
-+ "high", N_("High")}, {
-+ /* SUN_BRANDING */
-+ "very-high", N_("Very High")}, {
-+ /* SUN_BRANDING */
-+ "high+", N_("Very High")}, {
-+ /* SUN_BRANDING */
-+ "production", N_("Production")}, {
-+ /* SUN_BRANDING */
-+ "fp-mic", N_("Front Panel Microphone")}, {
-+ /* SUN_BRANDING */
-+ "fp-linein", N_("Front Panel Line In")}, {
-+ /* SUN_BRANDING */
-+ "fp-headphones", N_("Front Panel Headphones")}, {
-+ /* SUN_BRANDING */
-+ "fp-lineout", N_("Front Panel Line Out")}, {
-+ /* SUN_BRANDING */
-+ "green", N_("Green Connector")}, {
-+ /* SUN_BRANDING */
-+ "pink", N_("Pink Connector")}, {
-+ /* SUN_BRANDING */
-+ "blue", N_("Blue Connector")}, {
-+ /* SUN_BRANDING */
-+ "white", N_("White Connector")}, {
-+ /* SUN_BRANDING */
-+ "black", N_("Black Connector")}, {
-+ /* SUN_BRANDING */
-+ "gray", N_("Gray Connector")}, {
-+ /* SUN_BRANDING */
-+ "orange", N_("Orange Connector")}, {
-+ /* SUN_BRANDING */
-+ "red", N_("Red Connector")}, {
-+ /* SUN_BRANDING */
-+ "yellow", N_("Yellow Connector")}, {
-+ /* SUN_BRANDING */
-+ "fp-green", N_("Green Front Panel Connector")}, {
-+ /* SUN_BRANDING */
-+ "fp-pink", N_("Pink Front Panel Connector")}, {
-+ /* SUN_BRANDING */
-+ "fp-blue", N_("Blue Front Panel Connector")}, {
-+ /* SUN_BRANDING */
-+ "fp-white", N_("White Front Panel Connector")}, {
-+ /* SUN_BRANDING */
-+ "fp-black", N_("Black Front Panel Connector")}, {
-+ /* SUN_BRANDING */
-+ "fp-gray", N_("Gray Front Panel Connector")}, {
-+ /* SUN_BRANDING */
-+ "fp-orange", N_("Orange Front Panel Connector")}, {
-+ /* SUN_BRANDING */
-+ "fp-red", N_("Red Front Panel Connector")}, {
-+ /* SUN_BRANDING */
-+ "fp-yellow", N_("Yellow Front Panel Connector")}, {
-+ /* SUN_BRANDING */
-+ "spread", N_("Spread Output")}, {
-+ /* SUN_BRANDING */
-+ "downmix", N_("Downmix")},
-+
-+ /* FIXME translate Audigy NX USB labels) */
-+/*
-+ // SUN_BRANDING
-+ { "rec.src", N_("Record Source") },
-+ // SUN_BRANDING
-+ { "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. */
-+const gchar *
-+gst_oss4_mixer_control_get_translated_name (GstOss4MixerControl * mc)
-+{
-+ gchar name[128] = { 0, };
-+ gchar scratch[128] = { 0, };
-+ gchar fmtbuf[128] = { 0, };
-+ gchar vmix_str[32] = { '\0', };
-+ gchar *ptr;
-+ int dummy, i;
-+ int num = -1;
-+
-+ g_strlcpy (fmtbuf, "%s", sizeof (fmtbuf));
-+
-+ /* 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)
-+ /* SUN_BRANDING */
-+ return _("Virtual Mixer Input");
-+ else if (strcmp (vmix_str, "vol") == 0)
-+ /* SUN_BRANDING */
-+ return _("Virtual Mixer Output");
-+ else if (strcmp (vmix_str, "channels") == 0)
-+ /* SUN_BRANDING */
-+ return _("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 (scratch, ptr, sizeof (scratch));
-+ g_strlcpy (name, scratch, sizeof (name));
-+ }
-+
-+ /* special handling for jack retasking suffixes */
-+ if (g_str_has_suffix (name, ".function") || g_str_has_suffix (name, ".mode")) {
-+ /* SUN_BRANDING */
-+ g_strlcpy (fmtbuf, _("%s Function"), sizeof (fmtbuf));
-+ 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';
-+ /* SUN_BRANDING */
-+ /* format appends a number to the base, but preserves any surrounding
-+ format */
-+ g_snprintf (scratch, sizeof (scratch), fmtbuf, _("%s %d"));
-+ g_strlcpy (fmtbuf, scratch, sizeof (fmtbuf));
-+ }
-+
-+ /* 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_snprintf (name, sizeof (name), fmtbuf, _(labels[i].label), num);
-+ return g_quark_to_string (g_quark_from_string (name));
-+ }
-+ }
-+ } while ((ptr = strchr (ptr, '.')) != NULL);
-+
-+ /* failing that, just replace periods with spaces */
-+ g_strdelimit (name, ".", ' ');
-+ g_snprintf (scratch, sizeof (scratch), fmtbuf, name);
-+ return g_quark_to_string (g_quark_from_string (scratch)); /* eek */
-+}
-+
-+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;
-+
-+ /* The mixer API requires this to be g_strdup'd */
-+ track->label = g_strdup (gst_oss4_mixer_control_get_translated_name (mc));
-+ track->flags = 0;
-+
-+ GST_LOG ("translated label: %s [%s] = %s", track->label, mc->mixext.id,
-+ gst_oss4_mixer_control_get_translated_name (mc));
-+
-+ /* 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);
-+}
---- /dev/null 2009-03-06 13:29:44.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-property-probe.c 2009-03-06 13:25:06.889292000 -0600
-@@ -0,0 +1,414 @@
-+/* 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);
-+}
---- /dev/null 2009-03-06 13:29:49.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-sink.c 2009-03-06 13:25:06.889452000 -0600
-@@ -0,0 +1,573 @@
-+/* 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>
-+
-+#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
-+
-+enum
-+{
-+ PROP_0,
-+ PROP_DEVICE,
-+ PROP_DEVICE_NAME
-+};
-+
-+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));
-+
-+ 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;
-+}
-+
-+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_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;
-+ 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;
-+ 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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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);
-+
-+ if (ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay) < 0 || delay < 0) {
-+ GST_LOG_OBJECT (oss, "GETODELAY failed");
-+ 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)
-+{
-+ gst_oss4_add_property_probe_interface (type);
-+}
---- /dev/null 2009-03-06 13:29:59.000000000 -0600
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-source.c 2009-03-06 13:25:06.889854000 -0600
-@@ -0,0 +1,1012 @@
-+/* 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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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,
-+ /* SUN_BRANDING */
-+ (_("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);
-+}
---- /dev/null 2009-07-01 18:19:01.000000000 +0800
-+++ gst-plugins-good-0.10.21/sys/ossv4/oss4-audio.c 2009-07-01 18:05:44.476126000 +0800
-@@ -0,0 +1,704 @@
-+/* 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
-+
-+static const 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;
-+} 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}
-+};
-+
-+static gboolean
-+gst_oss4_append_format_to_caps (gint fmt, GstCaps * caps)
-+{
-+ gint i;
-+
-+ for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
-+ if (fmt_map[i].oss_fmt == fmt) {
-+ GstStructure *s;
-+
-+ s = gst_structure_empty_new (fmt_map[i].name);
-+ if (fmt_map[i].width != 0 && fmt_map[i].depth != 0) {
-+ gst_structure_set (s, "width", G_TYPE_INT, fmt_map[i].width,
-+ "depth", G_TYPE_INT, fmt_map[i].depth, "endianness", G_TYPE_INT,
-+ fmt_map[i].endianness, "signed", G_TYPE_BOOLEAN,
-+ fmt_map[i].signedness, NULL);
-+ }
-+ gst_caps_append_structure (caps, s);
-+ return TRUE;
-+ }
-+ }
-+ return FALSE;
-+}
-+
-+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 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);
-+
-+ int all_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;
-+ int other_formats = (all_formats & ~ai.oformats);
-+
-+ caps = gst_caps_new_empty ();
-+
-+ 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].oss_fmt, caps);
-+ }
-+ }
-+
-+ for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
-+ if ((other_formats & fmt_map[i].oss_fmt)) {
-+ gst_oss4_append_format_to_caps (fmt_map[i].oss_fmt, 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].oss_fmt, 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)