summaryrefslogtreecommitdiffstats
path: root/sys/oss
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2005-08-23 13:26:21 +0000
committerAndy Wingo <wingo@pobox.com>2005-08-23 13:26:21 +0000
commitd1d21600f86907f1dbd1fe4204be443eeda6cafc (patch)
tree52725fea0103ecd999811dd30868043a768640d8 /sys/oss
parentffaaa7528a2348853c1a89963646012f2edba310 (diff)
sys/oss/gstossmixer.*: Refactored to be more like alsamixer.
Original commit message from CVS: 2005-08-23 Andy Wingo <wingo@pobox.com> * sys/oss/gstossmixer.h: * sys/oss/gstossmixer.c: Refactored to be more like alsamixer. * sys/oss/gstossmixertrack.h: * sys/oss/gstossmixertrack.c: Split out from gstossmixer.[ch], like gstalsamixer. * sys/oss/gstosssrc.c: * sys/oss/gstosssink.c: Where before we used a gstosselement object as a helper library, now just call functions from gstosshelper. * sys/oss/gstosshelper.h: * sys/oss/gstosshelper.c: Made a real library. Removed propertyprobe for now, should add it back later. * sys/oss/gstosselement.h: * sys/oss/gstosselement.c: Removed, we don't have a shared base class. * sys/oss/gstosshelper.c (gst_oss_helper_probe_caps): Search higher-to-lower, makes 16 bit appear earlier in the caps, which makes it preferred.
Diffstat (limited to 'sys/oss')
-rw-r--r--sys/oss/Makefile.am6
-rw-r--r--sys/oss/gstossaudio.c1
-rw-r--r--sys/oss/gstossdmabuffer.h2
-rw-r--r--sys/oss/gstosselement.c1319
-rw-r--r--sys/oss/gstosselement.h122
-rw-r--r--sys/oss/gstosshelper.c907
-rw-r--r--sys/oss/gstosshelper.h122
-rw-r--r--sys/oss/gstossmixer.c475
-rw-r--r--sys/oss/gstossmixer.h167
-rw-r--r--sys/oss/gstossmixertrack.c180
-rw-r--r--sys/oss/gstossmixertrack.h62
-rw-r--r--sys/oss/gstosssink.c13
-rw-r--r--sys/oss/gstosssink.h4
-rw-r--r--sys/oss/gstosssrc.c14
-rw-r--r--sys/oss/gstosssrc.h4
15 files changed, 594 insertions, 2804 deletions
diff --git a/sys/oss/Makefile.am b/sys/oss/Makefile.am
index d298b7ce..d4fc2394 100644
--- a/sys/oss/Makefile.am
+++ b/sys/oss/Makefile.am
@@ -1,9 +1,9 @@
plugin_LTLIBRARIES = libgstossaudio.la
libgstossaudio_la_SOURCES = gstossaudio.c \
- gstosselement.c \
gstosshelper.c \
gstossmixer.c \
+ gstossmixertrack.c \
gstosssink.c \
gstosssrc.c
@@ -17,10 +17,10 @@ libgstossaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gstosssink.h \
gstosssrc.h \
- gstosselement.h \
gstosshelper.h \
gstossdmabuffer.h \
- gstossmixer.h
+ gstossmixer.h \
+ gstossmixertrack.h
# noinst_PROGRAMS = #oss_probe
diff --git a/sys/oss/gstossaudio.c b/sys/oss/gstossaudio.c
index 65cf7037..219a0367 100644
--- a/sys/oss/gstossaudio.c
+++ b/sys/oss/gstossaudio.c
@@ -23,7 +23,6 @@
#include "gst/gst-i18n-plugin.h"
-#include "gstosselement.h"
#include "gstosssink.h"
#include "gstosssrc.h"
diff --git a/sys/oss/gstossdmabuffer.h b/sys/oss/gstossdmabuffer.h
index 3a2c6ea7..fef24923 100644
--- a/sys/oss/gstossdmabuffer.h
+++ b/sys/oss/gstossdmabuffer.h
@@ -25,7 +25,7 @@
#include <gst/gst.h>
-#include "gstosselement.h"
+#include "gstosshelper.h"
#include <gst/audio/gstringbuffer.h>
G_BEGIN_DECLS
diff --git a/sys/oss/gstosselement.c b/sys/oss/gstosselement.c
deleted file mode 100644
index 5b59bd7f..00000000
--- a/sys/oss/gstosselement.c
+++ /dev/null
@@ -1,1319 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000 Wim Taymans <wim.taymans@chello.be>
- *
- * gstosssink.c:
- *
- * 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-i18n-plugin.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>
-
-#include <sys/soundcard.h>
-
-#include <gst/interfaces/propertyprobe.h>
-
-#include "gstosselement.h"
-#include "gstossmixer.h"
-
-enum
-{
- ARG_ZERO,
- ARG_DEVICE,
- ARG_MIXERDEV,
- ARG_DEVICE_NAME
-};
-
-/* elementfactory information */
-static GstElementDetails gst_osselement_details =
-GST_ELEMENT_DETAILS ("OSS Mixer",
- "Generic/Audio",
- "OSS-based mixer element",
- "Ronald Bultje <rbultje@ronald.bitfreak.net>");
-
-static void gst_osselement_base_init (GstOssElementClass * klass);
-static void gst_osselement_class_init (GstOssElementClass * klass);
-
-static void gst_ossprobe_interface_init (GstPropertyProbeInterface * iface);
-static void gst_osselement_init (GstOssElement * oss);
-static void gst_osselement_finalize (GObject * object);
-
-static void gst_osselement_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_osselement_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-
-static GstElementClass *parent_class = NULL;
-
-/*static guint gst_oss_src_signals[LAST_SIGNAL] = { 0 }; */
-
-GType
-gst_osselement_get_type (void)
-{
- static GType osselement_type = 0;
-
- if (!osselement_type) {
- static const GTypeInfo osselement_info = {
- sizeof (GstOssElementClass),
- (GBaseInitFunc) gst_osselement_base_init,
- NULL,
- (GClassInitFunc) gst_osselement_class_init,
- NULL,
- NULL,
- sizeof (GstOssElement),
- 0,
- (GInstanceInitFunc) gst_osselement_init
- };
- static const GInterfaceInfo ossiface_info = {
- (GInterfaceInitFunc) gst_oss_interface_init,
- NULL,
- NULL
- };
- static const GInterfaceInfo ossmixer_info = {
- (GInterfaceInitFunc) gst_ossmixer_interface_init,
- NULL,
- NULL
- };
- static const GInterfaceInfo ossprobe_info = {
- (GInterfaceInitFunc) gst_ossprobe_interface_init,
- NULL,
- NULL
- };
-
- osselement_type = g_type_register_static (GST_TYPE_ELEMENT,
- "GstOssElement", &osselement_info, 0);
- g_type_add_interface_static (osselement_type,
- GST_TYPE_IMPLEMENTS_INTERFACE, &ossiface_info);
- g_type_add_interface_static (osselement_type,
- GST_TYPE_MIXER, &ossmixer_info);
- g_type_add_interface_static (osselement_type,
- GST_TYPE_PROPERTY_PROBE, &ossprobe_info);
- }
-
- return osselement_type;
-}
-
-static void
-gst_osselement_base_init (GstOssElementClass * klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
- klass->device_combinations = NULL;
-
- gst_element_class_set_details (element_class, &gst_osselement_details);
-}
-
-static void
-gst_osselement_class_init (GstOssElementClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
-
- gobject_class->set_property = gst_osselement_set_property;
- gobject_class->get_property = gst_osselement_get_property;
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE,
- g_param_spec_string ("device", "Device", "OSS device (/dev/dspN usually)",
- "default", G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIXERDEV,
- g_param_spec_string ("mixerdev", "Mixer device",
- "OSS mixer device (/dev/mixerN usually)",
- "default", G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE_NAME,
- g_param_spec_string ("device_name", "Device name", "Name of the device",
- NULL, G_PARAM_READABLE));
-
- gobject_class->finalize = gst_osselement_finalize;
-}
-
-static const GList *
-gst_ossprobe_get_properties (GstPropertyProbe * probe)
-{
- GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
- static GList *list = NULL;
-
- if (!list) {
- list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
- }
-
- return list;
-}
-
-/* OSS (without devfs) allows at max. 16 devices */
-#define MAX_OSS_DEVICES 16
-
-static void
-gst_osselement_probe (gchar * device_base,
- gint device_num, gchar ** name, dev_t * devno)
-{
- gchar *device = NULL;
- struct stat s;
-
- if ((name == NULL) || (devno == NULL)) {
- goto end;
- }
-
- *name = NULL;
- *devno = 0;
-
- if (device_num == -1)
- device = g_strdup (device_base);
- else if ((device_num >= -1) && (device_num <= MAX_OSS_DEVICES)) {
- device = g_strdup_printf ("%s%d", device_base, device_num);
- } else {
- goto end;
- }
-
- if (stat (device, &s) || !S_ISCHR (s.st_mode))
- goto end;
-
- *name = device;
- *devno = s.st_rdev;
- return;
-
-end:
- g_free (device);
-}
-
-static GList *
-device_combination_append (GList * device_combinations,
- GstOssDeviceCombination * combi)
-{
- GList *it;
-
- for (it = device_combinations; it != NULL; it = it->next) {
- GstOssDeviceCombination *cur;
-
- cur = (GstOssDeviceCombination *) it->data;
- if (cur->dev == combi->dev) {
- return device_combinations;
- }
- }
-
- return g_list_append (device_combinations, combi);
-}
-
-static gboolean
-gst_osselement_class_probe_devices (GstOssElementClass * klass, gboolean check)
-{
- GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
- static gboolean init = FALSE;
- static GList *device_combinations;
- GList *padtempllist;
- gint openmode = O_RDONLY;
- gboolean mixer = FALSE;
-
- /* Ok, so how do we open the device? We assume that we have (max.) one
- * pad, and if this is a sinkpad, we're osssink (w). else, we're osssrc
- * (r) */
- padtempllist = gst_element_class_get_pad_template_list (eklass);
- if (padtempllist != NULL) {
- GstPadTemplate *firstpadtempl = padtempllist->data;
-
- if (GST_PAD_TEMPLATE_DIRECTION (firstpadtempl) == GST_PAD_SINK) {
- openmode = O_WRONLY;
- }
- mixer = TRUE;
- }
-
- if (!init && !check) {
-#define MIXER 0
-#define DSP 1
- gchar *dev_base[][2] = { {"/dev/mixer", "/dev/dsp"}
- ,
- {"/dev/sound/mixer", "/dev/sound/dsp"}
- ,
- {NULL, NULL}
- };
- gint n;
- gint base;
-
- while (device_combinations) {
- GList *item = device_combinations;
- GstOssDeviceCombination *combi = item->data;
-
- device_combinations = g_list_remove (device_combinations, item);
-
- g_free (combi->dsp);
- g_free (combi->mixer);
- g_free (combi);
- }
-
- /* probe for all /dev entries */
- for (base = 0; dev_base[base][DSP] != NULL; base++) {
- gint fd;
-
- for (n = -1; n < MAX_OSS_DEVICES; n++) {
- gchar *dsp = NULL;
- gchar *mixer = NULL;
- dev_t dsp_dev;
- dev_t mixer_dev;
-
- gst_osselement_probe (dev_base[base][DSP], n, &dsp, &dsp_dev);
- if (dsp == NULL) {
- continue;
- }
- gst_osselement_probe (dev_base[base][MIXER], n, &mixer, &mixer_dev);
- /* does the device exist (can we open them)? */
-
- /* we just check the dsp. we assume the mixer always works.
- * we don't need a mixer anyway (says OSS)... If we are a
- * mixer element, we use the mixer anyway. */
- if ((fd = open (mixer ? mixer :
- dsp, openmode | O_NONBLOCK)) > 0 || errno == EBUSY) {
- GstOssDeviceCombination *combi;
-
- if (fd > 0)
- close (fd);
-
- /* yay! \o/ */
- combi = g_new0 (GstOssDeviceCombination, 1);
- combi->dsp = dsp;
- combi->mixer = mixer;
- combi->dev = mixer ? mixer_dev : dsp_dev;
- device_combinations = device_combination_append (device_combinations,
- combi);
- } else {
- g_free (dsp);
- g_free (mixer);
- }
- }
- }
-
- init = TRUE;
- }
-
- klass->device_combinations = device_combinations;
-
- return init;
-}
-
-static GValueArray *
-gst_osselement_class_list_devices (GstOssElementClass * klass)
-{
- GValueArray *array;
- GValue value = { 0 };
- GList *item;
-
- if (!klass->device_combinations)
- return NULL;
-
- array = g_value_array_new (g_list_length (klass->device_combinations));
- item = klass->device_combinations;
- g_value_init (&value, G_TYPE_STRING);
- while (item) {
- GstOssDeviceCombination *combi = item->data;
-
- g_value_set_string (&value, combi->dsp);
- g_value_array_append (array, &value);
-
- item = item->next;
- }
- g_value_unset (&value);
-
- return array;
-}
-
-static void
-gst_ossprobe_probe_property (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstOssElementClass *klass = GST_OSSELEMENT_GET_CLASS (probe);
-
- switch (prop_id) {
- case ARG_DEVICE:
- gst_osselement_class_probe_devices (klass, FALSE);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gst_ossprobe_needs_probe (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstOssElementClass *klass = GST_OSSELEMENT_GET_CLASS (probe);
- gboolean ret = FALSE;
-
- switch (prop_id) {
- case ARG_DEVICE:
- ret = !gst_osselement_class_probe_devices (klass, TRUE);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-
- return ret;
-}
-
-static GValueArray *
-gst_ossprobe_get_values (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstOssElementClass *klass = GST_OSSELEMENT_GET_CLASS (probe);
- GValueArray *array = NULL;
-
- switch (prop_id) {
- case ARG_DEVICE:
- array = gst_osselement_class_list_devices (klass);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-
- return array;
-}
-
-static void
-gst_ossprobe_interface_init (GstPropertyProbeInterface * iface)
-{
- iface->get_properties = gst_ossprobe_get_properties;
- iface->probe_property = gst_ossprobe_probe_property;
- iface->needs_probe = gst_ossprobe_needs_probe;
- iface->get_values = gst_ossprobe_get_values;
-}
-
-static void
-gst_osselement_init (GstOssElement * oss)
-{
- oss->device = g_strdup ("/dev/dsp");
- oss->mixer_dev = g_strdup ("/dev/mixer");
- oss->fd = -1;
- oss->mixer_fd = -1;
- oss->tracklist = NULL;
- oss->device_name = NULL;
-
- gst_osselement_reset (oss);
-}
-
-static void
-gst_osselement_finalize (GObject * object)
-{
- GstOssElement *oss = (GstOssElement *) object;
-
- g_free (oss->device);
- g_free (oss->mixer_dev);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-void
-gst_osselement_reset (GstOssElement * oss)
-{
- oss->law = 0;
- oss->endianness = G_BYTE_ORDER;
- oss->sign = TRUE;
- oss->width = 16;
- oss->depth = 16;
- oss->channels = 2;
- oss->rate = 44100;
- oss->fragment = 0;
- oss->bps = 0;
- oss->sample_width = 0;
-
-/* AFMT_*_BE not available on all OSS includes (e.g. FBSD) */
-#ifdef WORDS_BIGENDIAN
- oss->format = AFMT_S16_BE;
-#else
- oss->format = AFMT_S16_LE;
-#endif /* WORDS_BIGENDIAN */
-}
-
-static gboolean
-gst_ossformat_get (gint law, gint endianness, gboolean sign, gint width,
- gint depth, gint * format, gint * bps)
-{
- if (width != depth)
- return FALSE;
-
- *bps = 1;
-
- if (law == 0) {
- if (width == 16) {
- if (sign == TRUE) {
- if (endianness == G_LITTLE_ENDIAN) {
- *format = AFMT_S16_LE;
- GST_DEBUG ("16 bit signed LE, no law (%d)", *format);
- } else if (endianness == G_BIG_ENDIAN) {
- *format = AFMT_S16_BE;
- GST_DEBUG ("16 bit signed BE, no law (%d)", *format);
- }
- } else {
- if (endianness == G_LITTLE_ENDIAN) {
- *format = AFMT_U16_LE;
- GST_DEBUG ("16 bit unsigned LE, no law (%d)", *format);
- } else if (endianness == G_BIG_ENDIAN) {
- *format = AFMT_U16_BE;
- GST_DEBUG ("16 bit unsigned BE, no law (%d)", *format);
- }
- }
- *bps = 2;
- } else if (width == 8) {
- if (sign == TRUE) {
- *format = AFMT_S8;
- GST_DEBUG ("8 bit signed, no law (%d)", *format);
- } else {
- *format = AFMT_U8;
- GST_DEBUG ("8 bit unsigned, no law (%d)", *format);
- }
- *bps = 1;
- }
- } else if (law == 1) {
- *format = AFMT_MU_LAW;
- GST_DEBUG ("mu law (%d)", *format);
- } else if (law == 2) {
- *format = AFMT_A_LAW;
- GST_DEBUG ("a law (%d)", *format);
- } else {
- g_critical ("unknown law");
- return FALSE;
- }
-
- return TRUE;
-}
-
-gboolean
-gst_osselement_parse_caps (GstOssElement * oss, const GstCaps * caps)
-{
- gint bps, format;
- GstStructure *structure;
- gboolean res;
-
- structure = gst_caps_get_structure (caps, 0);
-
- res = gst_structure_get_int (structure, "width", &oss->width);
- res &= gst_structure_get_int (structure, "depth", &oss->depth);
-
- if (!res || oss->width != oss->depth)
- return FALSE;
-
- res = gst_structure_get_int (structure, "law", &oss->law);
- res &= gst_structure_get_int (structure, "endianness", &oss->endianness);
- res &= gst_structure_get_boolean (structure, "signed", &oss->sign);
-
- if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign,
- oss->width, oss->depth, &format, &bps)) {
- GST_DEBUG ("could not get format");
- return FALSE;
- }
-
- gst_structure_get_int (structure, "channels", &oss->channels);
- gst_structure_get_int (structure, "rate", &oss->rate);
-
- oss->sample_width = bps * oss->channels;
- oss->bps = bps * oss->channels * oss->rate;
- oss->format = format;
-
- return TRUE;
-}
-
-#define GET_FIXED_INT(caps, name, dest) \
-G_STMT_START { \
- if (gst_caps_has_fixed_property (caps, name)) \
- gst_structure_get_int (structure, name, dest); \
-} G_STMT_END
-#define GET_FIXED_BOOLEAN(caps, name, dest) \
-G_STMT_START { \
- if (gst_caps_has_fixed_property (caps, name)) \
- gst_structure_get_boolean (structure, name, dest); \
-} G_STMT_END
-
-gboolean
-gst_osselement_merge_fixed_caps (GstOssElement * oss, GstCaps * caps)
-{
- gint bps, format;
- GstStructure *structure;
-
- structure = gst_caps_get_structure (caps, 0);
-
- /* peel off fixed stuff from the caps */
- gst_structure_get_int (structure, "law", &oss->law);
- gst_structure_get_int (structure, "endianness", &oss->endianness);
- gst_structure_get_boolean (structure, "signed", &oss->sign);
- gst_structure_get_int (structure, "width", &oss->width);
- gst_structure_get_int (structure, "depth", &oss->depth);
-
- if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign,
- oss->width, oss->depth, &format, &bps)) {
- return FALSE;
- }
-
- gst_structure_get_int (structure, "rate", &oss->rate);
- gst_structure_get_int (structure, "channels", &oss->channels);
-
- oss->bps = bps * oss->channels * oss->rate;
- oss->format = format;
-
- return TRUE;
-}
-
-gboolean
-gst_osselement_sync_parms (GstOssElement * oss)
-{
- audio_buf_info space;
- int frag;
- gint target_format;
- gint target_channels;
- gint target_rate;
-
- /* gint fragscale, frag_ln; */
-
- if (oss->fd == -1) {
- GST_INFO ("osselement: no fd");
- return FALSE;
- }
-
- if ((oss->fragment & 0xFFFF) == 0) {
- frag = 0;
- } else if (oss->fragment >> 16) {
- frag = oss->fragment;
- } else {
- frag = 0x7FFF0000 | oss->fragment;
- }
-
- GST_INFO
- ("osselement: setting sound card to %dHz %d format %s (%08x fragment)",
- oss->rate, oss->format, (oss->channels == 2) ? "stereo" : "mono", frag);
-
- if (frag)
- ioctl (oss->fd, SNDCTL_DSP_SETFRAGMENT, &frag);
- ioctl (oss->fd, SNDCTL_DSP_RESET, 0);
-
- target_format = oss->format;
- target_channels = oss->channels;
- target_rate = oss->rate;
-
- ioctl (oss->fd, SNDCTL_DSP_SETFMT, &oss->format);
- ioctl (oss->fd, SNDCTL_DSP_CHANNELS, &oss->channels);
- ioctl (oss->fd, SNDCTL_DSP_SPEED, &oss->rate);
-
- ioctl (oss->fd, SNDCTL_DSP_GETBLKSIZE, &oss->fragment_size);
-
- if (oss->mode == 1) {
- ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &space);
- } else {
- ioctl (oss->fd, SNDCTL_DSP_GETISPACE, &space);
- }
-
-#if 0
- /* FIXME: make the current fragment info available somehow
- * the current way overrides preset values and that sucks */
- /* calculate new fragment using a poor man's logarithm function */
- fragscale = 1;
- frag_ln = 0;
- while (fragscale < space.fragsize) {
- fragscale <<= 1;
- frag_ln++;
- }
- oss->fragment = space.fragstotal << 16 | frag_ln;
-#endif
-
- GST_INFO ("osselement: set sound card to %dHz, %d format, %s "
- "(%d bytes buffer, %08x fragment)",
- oss->rate, oss->format,
- (oss->channels == 2) ? "stereo" : "mono", space.bytes, oss->fragment);
-
- oss->fragment_time = (GST_SECOND * oss->fragment_size) / oss->bps;
- GST_INFO ("fragment time %u %" G_GUINT64_FORMAT,
- oss->bps, oss->fragment_time);
-
- if (target_format != oss->format ||
- target_channels != oss->channels || target_rate != oss->rate) {
- if (target_channels != oss->channels)
- g_warning
- ("couldn't set the right number of channels (wanted %d, got %d), enjoy the tone difference",
- target_channels, oss->channels);
- if (target_rate < oss->rate - 1 || target_rate > oss->rate + 1)
- g_warning
- ("couldn't set the right sample rate (wanted %d, got %d), enjoy the speed difference",
- target_rate, oss->rate);
- if (target_format != oss->format)
- g_warning ("couldn't set requested OSS format, enjoy the noise :)");
- /* we could eventually return FALSE here, or just do some additional tests
- * to see that the frequencies don't differ too much etc.. */
- }
- return TRUE;
-}
-
-gboolean
-gst_osselement_open_audio (GstOssElement * oss, GstOssOpenMode mode)
-{
- gint caps;
-
- g_return_val_if_fail (oss->fd == -1, FALSE);
- GST_INFO ("osselement: attempting to open sound device");
-
- if (mode == GST_OSS_MODE_MIXER)
- goto do_mixer;
-
- /* first try to open the sound card */
- if (mode == 1) {
- /* open non blocking first so that it returns immediatly with an error
- * when we cannot get to the device */
- oss->fd = open (oss->device, O_WRONLY | O_NONBLOCK);
-
- if (oss->fd >= 0) {
- close (oss->fd);
-
- /* re-open the sound device in blocking mode */
- oss->fd = open (oss->device, O_WRONLY);
- }
- } else {
- oss->fd = open (oss->device, O_RDONLY);
- }
-
- if (oss->fd < 0) {
- switch (errno) {
- case EBUSY:
- GST_ELEMENT_ERROR (oss, RESOURCE, BUSY,
- (_("OSS device \"%s\" is already in use by another program."),
- oss->device), (NULL));
- break;
- case EACCES:
- case ETXTBSY:
- if (mode == 1)
- GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
- (_("Could not access device \"%s\", check its permissions."),
- oss->device), GST_ERROR_SYSTEM);
- else
- GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
- (_("Could not access device \"%s\", check its permissions."),
- oss->device), GST_ERROR_SYSTEM);
- break;
- case ENXIO:
- case ENODEV:
- case ENOENT:
- GST_ELEMENT_ERROR (oss, RESOURCE, NOT_FOUND,
- (_("Device \"%s\" does not exist."), oss->device),
- GST_ERROR_SYSTEM);
- break;
- default:
- if (mode == 1)
- GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
- (_("Could not open device \"%s\" for writing."), oss->device),
- GST_ERROR_SYSTEM);
- else
- GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
- (_("Could not open device \"%s\" for reading."), oss->device),
- GST_ERROR_SYSTEM);
- break;
- }
- return FALSE;
- }
-
- oss->mode = mode;
-
- /* we have it, set the default parameters and go have fun */
- /* set card state */
- ioctl (oss->fd, SNDCTL_DSP_GETCAPS, &caps);
-
- GST_INFO ("osselement: Capabilities %08x", caps);
-
- if (caps & DSP_CAP_DUPLEX)
- GST_INFO ("osselement: Full duplex");
- if (caps & DSP_CAP_REALTIME)
- GST_INFO ("osselement: Realtime");
- if (caps & DSP_CAP_BATCH)
- GST_INFO ("osselement: Batch");
- if (caps & DSP_CAP_COPROC)
- GST_INFO ("osselement: Has coprocessor");
- if (caps & DSP_CAP_TRIGGER)
- GST_INFO ("osselement: Trigger");
- if (caps & DSP_CAP_MMAP)
- GST_INFO ("osselement: Direct access");
-
-#ifdef DSP_CAP_MULTI
- if (caps & DSP_CAP_MULTI)
- GST_INFO ("osselement: Multiple open");
-#endif /* DSP_CAP_MULTI */
-
-#ifdef DSP_CAP_BIND
- if (caps & DSP_CAP_BIND)
- GST_INFO ("osselement: Channel binding");
-#endif /* DSP_CAP_BIND */
-
- ioctl (oss->fd, SNDCTL_DSP_GETFMTS, &caps);
-
- GST_INFO ("osselement: Formats %08x", caps);
- if (caps & AFMT_MU_LAW)
- GST_INFO ("osselement: MU_LAW");
- if (caps & AFMT_A_LAW)
- GST_INFO ("osselement: A_LAW");
- if (caps & AFMT_IMA_ADPCM)
- GST_INFO ("osselement: IMA_ADPCM");
- if (caps & AFMT_U8)
- GST_INFO ("osselement: U8");
- if (caps & AFMT_S16_LE)
- GST_INFO ("osselement: S16_LE");
- if (caps & AFMT_S16_BE)
- GST_INFO ("osselement: S16_BE");
- if (caps & AFMT_S8)
- GST_INFO ("osselement: S8");
- if (caps & AFMT_U16_LE)
- GST_INFO ("osselement: U16_LE");
- if (caps & AFMT_U16_BE)
- GST_INFO ("osselement: U16_BE");
- if (caps & AFMT_MPEG)
- GST_INFO ("osselement: MPEG");
-#ifdef AFMT_AC3
- if (caps & AFMT_AC3)
- GST_INFO ("osselement: AC3");
-#endif
-
- GST_INFO ("osselement: opened audio (%s) with fd=%d", oss->device, oss->fd);
-
- oss->caps = caps;
-
-do_mixer:
- gst_ossmixer_build_list (NULL, NULL);
-
- return TRUE;
-}
-
-void
-gst_osselement_close_audio (GstOssElement * oss)
-{
- gst_ossmixer_free_list (NULL);
- if (oss->probed_caps) {
- gst_caps_unref (oss->probed_caps);
- oss->probed_caps = NULL;
- }
-
- if (oss->fd < 0)
- return;
-
- close (oss->fd);
- oss->fd = -1;
-}
-
-gboolean
-gst_osselement_convert (GstOssElement * oss,
- GstFormat src_format,
- gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
-{
- gboolean res = TRUE;
-
- if (src_format == *dest_format) {
- *dest_value = src_value;
- return TRUE;
- }
-
- if (oss->bps == 0 || oss->channels == 0 || oss->width == 0)
- return FALSE;
-
- switch (src_format) {
- case GST_FORMAT_BYTES:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- *dest_value = src_value * GST_SECOND / oss->bps;
- break;
- case GST_FORMAT_DEFAULT:
- *dest_value = src_value / (oss->width * oss->channels / 8);
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- *dest_value = src_value * oss->bps / GST_SECOND;
- break;
- case GST_FORMAT_DEFAULT:
- *dest_value = src_value * oss->rate / GST_SECOND;
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_DEFAULT:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- *dest_value = src_value * GST_SECOND / oss->rate;
- break;
- case GST_FORMAT_BYTES:
- *dest_value = src_value * oss->width * oss->channels / 8;
- break;
- default:
- res = FALSE;
- }
- break;
- default:
- res = FALSE;
- }
-
- return res;
-}
-
-static void
-gst_osselement_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec)
-{
- GstOssElement *oss = GST_OSSELEMENT (object);
-
- switch (prop_id) {
- case ARG_DEVICE:
- /* disallow changing the device while it is opened
- get_property("device") should return the right one */
- if (oss->fd == -1) {
- g_free (oss->device);
- oss->device = g_strdup (g_value_get_string (value));
-
- /* let's assume that if we have a device map for the mixer,
- * we're allowed to do all that automagically here */
- if (GST_OSSELEMENT_GET_CLASS (oss)->device_combinations != NULL) {
- GList *list = GST_OSSELEMENT_GET_CLASS (oss)->device_combinations;
-
- while (list) {
- GstOssDeviceCombination *combi = list->data;
-
- if (!strcmp (combi->dsp, oss->device)) {
- g_free (oss->mixer_dev);
- oss->mixer_dev = g_strdup (combi->mixer);
- break;
- }
-
- list = list->next;
- }
- }
- }
- break;
- case ARG_MIXERDEV:
- /* disallow changing the device while it is opened
- get_property("mixerdev") should return the right one */
- if (oss->fd == -1) {
- g_free (oss->mixer_dev);
- oss->mixer_dev = g_strdup (g_value_get_string (value));
- }
- break;
- default:
- break;
- }
-}
-
-static void
-gst_osselement_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec)
-{
- GstOssElement *oss = GST_OSSELEMENT (object);
-
- switch (prop_id) {
- case ARG_DEVICE:
- g_value_set_string (value, oss->device);
- break;
- case ARG_MIXERDEV:
- g_value_set_string (value, oss->mixer_dev);
- break;
- case ARG_DEVICE_NAME:
- g_value_set_string (value, oss->device_name);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* rate probing code */
-
-
-#if 0
-
-#ifdef HAVE_OSS_INCLUDE_IN_SYS
-#include <sys/soundcard.h>
-#else
-
-#ifdef HAVE_OSS_INCLUDE_IN_ROOT
-#include <soundcard.h>
-#else
-
-#include <machine/soundcard.h>
-
-#endif /* HAVE_OSS_INCLUDE_IN_ROOT */
-
-#endif /* HAVE_OSS_INCLUDE_IN_SYS */
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <glib.h>
-#endif
-
-typedef struct _GstOssProbe GstOssProbe;
-struct _GstOssProbe
-{
- int fd;
- int format;
- int n_channels;
- GArray *rates;
- int min;
- int max;
-};
-
-typedef struct _GstOssRange GstOssRange;
-struct _GstOssRange
-{
- int min;
- int max;
-};
-
-static GstStructure *gst_osselement_get_format_structure (unsigned int
- format_bit);
-static gboolean gst_osselement_rate_probe_check (GstOssProbe * probe);
-static int gst_osselement_rate_check_rate (GstOssProbe * probe, int irate);
-static void gst_osselement_rate_add_range (GQueue * queue, int min, int max);
-static void gst_osselement_rate_add_rate (GArray * array, int rate);
-static int gst_osselement_rate_int_compare (gconstpointer a, gconstpointer b);
-
-void
-gst_osselement_probe_caps (GstOssElement * oss)
-{
- GstOssProbe *probe;
- int i;
- gboolean ret;
- GstStructure *structure;
- unsigned int format_bit;
- unsigned int format_mask;
- GstCaps *caps;
-
- if (oss->probed_caps != NULL)
- return;
- if (oss->fd == -1)
- return;
-
- /* FIXME test make sure we're not currently playing */
- /* FIXME test both mono and stereo */
-
- format_mask = AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_S8 |
- AFMT_U16_LE | AFMT_U16_BE;
- format_mask &= oss->caps;
-
- caps = gst_caps_new_empty ();
-
- /* assume that the most significant bit of format_mask is 0 */
- for (format_bit = 1; format_bit <= format_mask; format_bit <<= 1) {
- if (format_bit & format_mask) {
- GValue rate_value = { 0 };
-
- probe = g_new0 (GstOssProbe, 1);
- probe->fd = oss->fd;
- probe->format = format_bit;
- probe->n_channels = 2;
-
- ret = gst_osselement_rate_probe_check (probe);
- if (probe->min == -1 || probe->max == -1) {
- g_array_free (probe->rates, TRUE);
- g_free (probe);
- continue;
- }
-
- if (ret) {
- GValue value = { 0 };
-
- g_array_sort (probe->rates, gst_osselement_rate_int_compare);
-
- g_value_init (&rate_value, GST_TYPE_LIST);
- g_value_init (&value, G_TYPE_INT);
-
- for (i = 0; i < probe->rates->len; i++) {
- g_value_set_int (&value, g_array_index (probe->rates, int, i));
-
- gst_value_list_append_value (&rate_value, &value);
- }
-
- g_value_unset (&value);
- } else {
- /* one big range */
- g_value_init (&rate_value, GST_TYPE_INT_RANGE);
- gst_value_set_int_range (&rate_value, probe->min, probe->max);
- }
-
- g_array_free (probe->rates, TRUE);
- g_free (probe);
-
- structure = gst_osselement_get_format_structure (format_bit);
- gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
- gst_structure_set_value (structure, "rate", &rate_value);
- g_value_unset (&rate_value);
-
- gst_caps_append_structure (caps, structure);
- }
- }
-
- if (gst_caps_is_empty (caps)) {
- GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS,
- (_("Your OSS device could not be probed correctly")), (NULL));
- return;
- }
- GST_DEBUG ("probed caps: %" GST_PTR_FORMAT, caps);
- oss->probed_caps = caps;
-}
-
-static GstStructure *
-gst_osselement_get_format_structure (unsigned int format_bit)
-{
- GstStructure *structure;
- int endianness;
- gboolean sign;
- int width;
-
- switch (format_bit) {
- case AFMT_U8:
- endianness = 0;
- sign = FALSE;
- width = 8;
- break;
- case AFMT_S16_LE:
- endianness = G_LITTLE_ENDIAN;
- sign = TRUE;
- width = 16;
- break;
- case AFMT_S16_BE:
- endianness = G_BIG_ENDIAN;
- sign = TRUE;
- width = 16;
- break;
- case AFMT_S8:
- endianness = 0;
- sign = TRUE;
- width = 8;
- break;
- case AFMT_U16_LE:
- endianness = G_LITTLE_ENDIAN;
- sign = FALSE;
- width = 16;
- break;
- case AFMT_U16_BE:
- endianness = G_BIG_ENDIAN;
- sign = FALSE;
- width = 16;
- break;
- default:
- g_assert_not_reached ();
- return NULL;
- }
-
- structure = gst_structure_new ("audio/x-raw-int",
- "width", G_TYPE_INT, width,
- "depth", G_TYPE_INT, width, "signed", G_TYPE_BOOLEAN, sign, NULL);
-
- if (endianness) {
- gst_structure_set (structure, "endianness", G_TYPE_INT, endianness, NULL);
- }
-
- return structure;
-}
-
-static gboolean
-gst_osselement_rate_probe_check (GstOssProbe * probe)
-{
- GstOssRange *range;
- GQueue *ranges;
- int exact_rates = 0;
- gboolean checking_exact_rates = TRUE;
- int n_checks = 0;
- gboolean result = TRUE;
-
- ranges = g_queue_new ();
-
- probe->rates = g_array_new (FALSE, FALSE, sizeof (int));
-
- probe->min = gst_osselement_rate_check_rate (probe, 1000);
- n_checks++;
- probe->max = gst_osselement_rate_check_rate (probe, 100000);
- /* a little bug workaround */
- {
- int max;
-
- max = gst_osselement_rate_check_rate (probe, 48000);
- if (max > probe->max) {
- GST_ERROR
- ("Driver bug recognized (driver does not round rates correctly). Please file a bug report.");
- probe->max = max;
- }
- }
- n_checks++;
- if (probe->min == -1 || probe->max == -1) {
- /* This is a workaround for drivers that return -EINVAL (or another
- * error) for rates outside of [8000,48000]. If this fails, the
- * driver is seriously buggy, and probably doesn't work with other
- * media libraries/apps. */
- probe->min = gst_osselement_rate_check_rate (probe, 8000);
- probe->max = gst_osselement_rate_check_rate (probe, 48000);
- }
- if (probe->min == -1 || probe->max == -1) {
- GST_DEBUG ("unexpected check_rate error");
- return FALSE;
- }
- gst_osselement_rate_add_range (ranges, probe->min + 1, probe->max - 1);
-
- while ((range = g_queue_pop_head (ranges))) {
- int min1;
- int max1;
- int mid;
- int mid_ret;
-
- GST_DEBUG ("checking [%d,%d]", range->min, range->max);
-
- mid = (range->min + range->max) / 2;
- mid_ret = gst_osselement_rate_check_rate (probe, mid);
- if (mid_ret == -1) {
- /* FIXME ioctl returned an error. do something */
- GST_DEBUG ("unexpected check_rate error");
- }
- n_checks++;
-
- if (mid == mid_ret && checking_exact_rates) {
- int max_exact_matches = 20;
-
- exact_rates++;
- if (exact_rates > max_exact_matches) {
- GST_DEBUG ("got %d exact rates, assuming all are exact",
- max_exact_matches);
- result = FALSE;
- g_free (range);
- break;
- }
- } else {
- checking_exact_rates = FALSE;
- }
-
- /* Assume that the rate is arithmetically rounded to the nearest
- * supported rate. */
- if (mid == mid_ret) {
- min1 = mid - 1;
- max1 = mid + 1;
- } else {
- if (mid < mid_ret) {
- min1 = mid - (mid_ret - mid);
- max1 = mid_ret + 1;
- } else {
- min1 = mid_ret - 1;
- max1 = mid + (mid - mid_ret);
- }
- }
-
- gst_osselement_rate_add_range (ranges, range->min, min1);
- gst_osselement_rate_add_range (ranges, max1, range->max);
-
- g_free (range);
- }
-
- while ((range = g_queue_pop_head (ranges))) {
- g_free (range);
- }
- g_queue_free (ranges);
-
- return result;
-}
-
-static void
-gst_osselement_rate_add_range (GQueue * queue, int min, int max)
-{
- if (min <= max) {
- GstOssRange *range = g_new0 (GstOssRange, 1);
-
- range->min = min;
- range->max = max;
-
- g_queue_push_tail (queue, range);
- /* push_head also works, but has different probing behavior */
- /*g_queue_push_head (queue, range); */
- }
-}
-
-static int
-gst_osselement_rate_check_rate (GstOssProbe * probe, int irate)
-{
- int rate;
- int format;
- int n_channels;
- int ret;
-
- rate = irate;
- format = probe->format;
- n_channels = probe->n_channels;
-
- GST_LOG ("checking format %d, channels %d, rate %d",
- format, n_channels, rate);
- ret = ioctl (probe->fd, SNDCTL_DSP_SETFMT, &format);
- if (ret < 0)
- return -1;
- ret = ioctl (probe->fd, SNDCTL_DSP_CHANNELS, &n_channels);
- if (ret < 0)
- return -1;
- ret = ioctl (probe->fd, SNDCTL_DSP_SPEED, &rate);
- if (ret < 0)
- return -1;
-
- GST_DEBUG ("rate %d -> %d", irate, rate);
-
- if (rate == irate - 1 || rate == irate + 1) {
- rate = irate;
- }
- gst_osselement_rate_add_rate (probe->rates, rate);
- return rate;
-}
-
-static void
-gst_osselement_rate_add_rate (GArray * array, int rate)
-{
- int i;
- int val;
-
- for (i = 0; i < array->len; i++) {
- val = g_array_index (array, int, i);
-
- if (val == rate)
- return;
- }
- GST_DEBUG ("supported rate: %d", rate);
- g_array_append_val (array, rate);
-}
-
-static int
-gst_osselement_rate_int_compare (gconstpointer a, gconstpointer b)
-{
- const int *va = (const int *) a;
- const int *vb = (const int *) b;
-
- if (*va < *vb)
- return -1;
- if (*va > *vb)
- return 1;
- return 0;
-}
diff --git a/sys/oss/gstosselement.h b/sys/oss/gstosselement.h
deleted file mode 100644
index b895d42b..00000000
--- a/sys/oss/gstosselement.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000 Wim Taymans <wim.taymans@chello.be>
- *
- * gstosselement.h:
- *
- * 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_OSS_ELEMENT_H__
-#define __GST_OSS_ELEMENT_H__
-
-#include <gst/gst.h>
-#include <sys/types.h>
-
-#include "gstosshelper.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_OSSELEMENT \
- (gst_osselement_get_type())
-#define GST_OSSELEMENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSSELEMENT,GstOssElement))
-#define GST_OSSELEMENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSSELEMENT,GstOssElementClass))
-#define GST_IS_OSSELEMENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSSELEMENT))
-#define GST_IS_OSSELEMENT_CLASS(obj) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSSELEMENT))
-#define GST_OSSELEMENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_OSSELEMENT, GstOssElementClass))
-
-typedef struct _GstOssElement GstOssElement;
-typedef struct _GstOssElementClass GstOssElementClass;
-
-struct _GstOssElement
-{
- /* yes, we're a gstelement too */
- GstElement parent;
-
- gchar *device,
- *mixer_dev;
-
- /* device state */
- int fd;
- int caps; /* the capabilities */
- gint format;
- gint fragment;
- guint64 fragment_time;
- gint fragment_size;
- GstCaps *probed_caps;
-
- /* stats bytes per *second* */
- guint bps;
-
- /* sample width in bytes */
- guint sample_width;
-
- /* parameters */
- gint law;
- gint endianness;
- gboolean sign;
- gint width;
- gint depth;
- gint channels;
- gint rate;
- gint mode;
-
- /* mixer stuff */
- GList *tracklist;
- guint32 stereomask,
- recdevs,
- recmask,
- mixcaps;
- gint mixer_fd;
- gchar *device_name;
-};
-
-struct _GstOssElementClass {
- GstElementClass klass;
-
- GList *device_combinations;
-};
-
-GType gst_osselement_get_type (void);
-
-/* some useful functions */
-gboolean gst_osselement_parse_caps (GstOssElement *oss,
- const GstCaps *caps);
-gboolean gst_osselement_merge_fixed_caps (GstOssElement *oss,
- GstCaps *caps);
-
-gboolean gst_osselement_open_audio (GstOssElement *oss, GstOssOpenMode mode);
-gboolean gst_osselement_sync_parms (GstOssElement *oss);
-void gst_osselement_reset (GstOssElement *oss);
-void gst_osselement_close_audio (GstOssElement *oss);
-
-
-
-gboolean gst_osselement_convert (GstOssElement *oss,
- GstFormat src_format,
- gint64 src_value,
- GstFormat *dest_format,
- gint64 *dest_value);
-void gst_osselement_probe_caps (GstOssElement *oss);
-
-G_END_DECLS
-
-#endif /* __GST_OSS_ELEMENT_H__ */
diff --git a/sys/oss/gstosshelper.c b/sys/oss/gstosshelper.c
index dfd503e4..987047a9 100644
--- a/sys/oss/gstosshelper.c
+++ b/sys/oss/gstosshelper.c
@@ -2,8 +2,7 @@
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wim.taymans@chello.be>
*
- * gstosshelper.c: helper functions for easy OSS device handling.
- * See gstosshelper.h for details.
+ * gstosshelper.c: OSS helper routines
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -33,6 +32,7 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
+
#include <sys/soundcard.h>
#include <gst/interfaces/propertyprobe.h>
@@ -40,822 +40,6 @@
#include "gstosshelper.h"
#include "gstossmixer.h"
-static void gst_ossprobe_interface_init (GstPropertyProbeInterface * iface);
-
-static GList *device_combinations = NULL;
-
-void
-gst_oss_add_mixer_type (GType type)
-{
- static const GInterfaceInfo ossiface_info = {
- (GInterfaceInitFunc) gst_oss_interface_init,
- NULL,
- NULL
- };
- static const GInterfaceInfo ossmixer_info = {
- (GInterfaceInitFunc) gst_ossmixer_interface_init,
- NULL,
- NULL
- };
- static const GInterfaceInfo ossprobe_info = {
- (GInterfaceInitFunc) gst_ossprobe_interface_init,
- NULL,
- NULL
- };
-
- g_type_add_interface_static (type,
- GST_TYPE_IMPLEMENTS_INTERFACE, &ossiface_info);
- g_type_add_interface_static (type, GST_TYPE_MIXER, &ossmixer_info);
- g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE, &ossprobe_info);
-}
-
-void
-gst_oss_add_device_properties (GstElementClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- g_object_class_install_property (gobject_class, OSS_ARG_DEVICE,
- g_param_spec_string ("device", "Device", "OSS device (/dev/dspN usually)",
- "default", G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, OSS_ARG_MIXER_DEVICE,
- g_param_spec_string ("mixerdev", "Mixer device",
- "OSS mixer device (/dev/mixerN usually)",
- "default", G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, OSS_ARG_DEVICE_NAME,
- g_param_spec_string ("device_name", "Device name", "Name of the device",
- NULL, G_PARAM_READABLE));
-}
-
-void
-gst_oss_set_device_property (GstElement * element,
- GstOssDeviceCombination * c, GstOssDevice * oss,
- guint prop_id, GParamSpec * pspec, const GValue * value)
-{
- switch (prop_id) {
- case OSS_ARG_DEVICE:
- /* disallow changing the device while it is opened
- get_property("device") should return the right one */
- if (oss->fd == -1) {
- g_free (c->dsp);
- c->dsp = g_strdup (g_value_get_string (value));
-
- /* let's assume that if we have a device map for the mixer,
- * we're allowed to do all that automagically here */
- if (device_combinations != NULL) {
- GList *list = device_combinations;
-
- while (list) {
- GstOssDeviceCombination *combi = list->data;
-
- if (!strcmp (combi->dsp, c->dsp)) {
- g_free (c->mixer);
- c->mixer = g_strdup (combi->mixer);
- break;
- }
-
- list = list->next;
- }
- }
- }
- break;
- case OSS_ARG_MIXER_DEVICE:
- /* disallow changing the device while it is opened
- get_property("mixerdev") should return the right one */
- if (oss->fd == -1) {
- g_free (c->mixer);
- c->mixer = g_strdup (g_value_get_string (value));
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (element, prop_id, pspec);
- break;
- }
-}
-
-void
-gst_oss_get_device_property (GstElement * element, GstOssDeviceCombination * c,
- GstOssDevice * oss, guint prop_id, GParamSpec * pspec, GValue * value)
-{
- switch (prop_id) {
- case OSS_ARG_DEVICE:
- g_value_set_string (value, c->dsp);
- break;
- case OSS_ARG_MIXER_DEVICE:
- g_value_set_string (value, c->mixer);
- break;
- case OSS_ARG_DEVICE_NAME:
- g_value_set_string (value, oss->device_name);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (element, prop_id, pspec);
- break;
- }
-}
-
-static const GList *
-gst_oss_probe_get_properties (GstPropertyProbe * probe)
-{
- GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
- static GList *list = NULL;
-
- if (!list) {
- list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
- }
-
- return list;
-}
-
-/* OSS (without devfs) allows at max. 16 devices */
-#define MAX_OSS_DEVICES 16
-
-static void
-gst_oss_do_probe (gchar * device_base,
- gint device_num, gchar ** name, dev_t * devno)
-{
- gchar *device = NULL;
- struct stat s;
-
- if ((name == NULL) || (devno == NULL)) {
- goto end;
- }
-
- *name = NULL;
- *devno = 0;
-
- if (device_num == -1)
- device = g_strdup (device_base);
- else if ((device_num >= -1) && (device_num <= MAX_OSS_DEVICES)) {
- device = g_strdup_printf ("%s%d", device_base, device_num);
- } else {
- goto end;
- }
-
- if (stat (device, &s) || !S_ISCHR (s.st_mode))
- goto end;
-
- *name = device;
- *devno = s.st_rdev;
- return;
-
-end:
- g_free (device);
-}
-
-static GList *
-device_combination_append (GList * device_combinations,
- GstOssDeviceCombination * combi)
-{
- GList *it;
-
- for (it = device_combinations; it != NULL; it = it->next) {
- GstOssDeviceCombination *cur;
-
- cur = (GstOssDeviceCombination *) it->data;
- if (cur->dev == combi->dev) {
- return device_combinations;
- }
- }
-
- return g_list_append (device_combinations, combi);
-}
-
-static gboolean
-gst_oss_probe_devices (GstOssOpenMode mode, gboolean check)
-{
- static gboolean init = FALSE;
- gint openmode = (mode == GST_OSS_MODE_WRITE) ? O_WRONLY : O_RDONLY;
- gboolean do_mixer = (mode == GST_OSS_MODE_VOLUME);
-
- if (!init && !check) {
-#define MIXER 0
-#define DSP 1
- gchar *dev_base[][2] = { {"/dev/mixer", "/dev/dsp"}
- ,
- {"/dev/sound/mixer", "/dev/sound/dsp"}
- ,
- {NULL, NULL}
- };
- gint n;
- gint base;
-
- while (device_combinations) {
- GList *item = device_combinations;
- GstOssDeviceCombination *combi = item->data;
-
- device_combinations = g_list_remove (device_combinations, item);
-
- g_free (combi->dsp);
- g_free (combi->mixer);
- g_free (combi);
- }
-
- /* probe for all /dev entries */
- for (base = 0; dev_base[base][DSP] != NULL; base++) {
- gint fd;
-
- for (n = -1; n < MAX_OSS_DEVICES; n++) {
- gchar *dsp = NULL;
- gchar *mixer = NULL;
- dev_t dsp_dev;
- dev_t mixer_dev;
-
- gst_oss_do_probe (dev_base[base][DSP], n, &dsp, &dsp_dev);
- if (dsp == NULL) {
- continue;
- }
- gst_oss_do_probe (dev_base[base][MIXER], n, &mixer, &mixer_dev);
- /* does the device exist (can we open them)? */
-
- /* we just check the dsp. we assume the mixer always works.
- * we don't need a mixer anyway (says OSS)... If we are a
- * mixer element, we use the mixer anyway. */
- if ((fd = open (do_mixer ? mixer :
- dsp, openmode | O_NONBLOCK)) > 0 || errno == EBUSY) {
- GstOssDeviceCombination *combi;
-
- if (fd > 0)
- close (fd);
-
- /* yay! \o/ */
- combi = g_new0 (GstOssDeviceCombination, 1);
- combi->dsp = dsp;
- combi->mixer = mixer;
- combi->dev = do_mixer ? mixer_dev : dsp_dev;
- device_combinations = device_combination_append (device_combinations,
- combi);
- } else {
- g_free (dsp);
- g_free (mixer);
- }
- }
- }
-
- init = TRUE;
- }
-
- return init;
-}
-
-static GValueArray *
-gst_oss_probe_list_devices (void)
-{
- GValueArray *array;
- GValue value = { 0 };
- GList *item;
-
- if (!device_combinations)
- return NULL;
-
- array = g_value_array_new (g_list_length (device_combinations));
- item = device_combinations;
- g_value_init (&value, G_TYPE_STRING);
- while (item) {
- GstOssDeviceCombination *combi = item->data;
-
- g_value_set_string (&value, combi->dsp);
- g_value_array_append (array, &value);
-
- item = item->next;
- }
- g_value_unset (&value);
-
- return array;
-}
-
-static void
-gst_oss_probe_property (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstOssDevice *oss = g_object_get_data (G_OBJECT (probe), "oss-data");
-
- switch (prop_id) {
- case OSS_ARG_DEVICE:
- gst_oss_probe_devices (oss ? oss->mode : GST_OSS_MODE_READ, FALSE);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gst_oss_needs_probe (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstOssDevice *oss = g_object_get_data (G_OBJECT (probe), "oss-data");
- gboolean ret = FALSE;
-
- switch (prop_id) {
- case OSS_ARG_DEVICE:
- ret = !gst_oss_probe_devices (oss ? oss->mode : GST_OSS_MODE_READ, TRUE);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-
- return ret;
-}
-
-static GValueArray *
-gst_oss_probe_get_values (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GValueArray *array = NULL;
-
- switch (prop_id) {
- case OSS_ARG_DEVICE:
- array = gst_oss_probe_list_devices ();
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-
- return array;
-}
-
-static void
-gst_ossprobe_interface_init (GstPropertyProbeInterface * iface)
-{
- iface->get_properties = gst_oss_probe_get_properties;
- iface->probe_property = gst_oss_probe_property;
- iface->needs_probe = gst_oss_needs_probe;
- iface->get_values = gst_oss_probe_get_values;
-}
-
-void
-gst_oss_init (GObject * obj, GstOssDeviceCombination * c, GstOssDevice * oss,
- GstOssOpenMode mode)
-{
- g_object_set_data (obj, "oss-data", oss);
-
- c->dsp = g_strdup ("/dev/dsp");
- c->mixer = g_strdup ("/dev/mixer");
-
- oss->fd = -1;
- oss->mixer_fd = -1;
- oss->mode = mode;
-
- gst_oss_reset (oss);
-}
-
-void
-gst_oss_dispose (GstOssDeviceCombination * c, GstOssDevice * oss)
-{
- g_free (c->dsp);
- c->dsp = NULL;
- g_free (c->mixer);
- c->mixer = NULL;
-}
-
-void
-gst_oss_reset (GstOssDevice * oss)
-{
- oss->law = 0;
- oss->endianness = G_BYTE_ORDER;
- oss->sign = TRUE;
- oss->width = 16;
- oss->depth = 16;
- oss->channels = 2;
- oss->rate = 44100;
- oss->fragment = 0;
- oss->bps = 0;
- oss->sample_width = 0;
-
-/* AFMT_*_BE not available on all OSS includes (e.g. FBSD) */
-#ifdef WORDS_BIGENDIAN
- oss->format = AFMT_S16_BE;
-#else
- oss->format = AFMT_S16_LE;
-#endif /* WORDS_BIGENDIAN */
-}
-
-static gboolean
-gst_ossformat_get (gint law, gint endianness, gboolean sign, gint width,
- gint depth, gint * format, gint * bps)
-{
- if (width != depth)
- return FALSE;
-
- *bps = 1;
-
- if (law == 0) {
- if (width == 16) {
- if (sign == TRUE) {
- if (endianness == G_LITTLE_ENDIAN) {
- *format = AFMT_S16_LE;
- GST_DEBUG ("16 bit signed LE, no law (%d)", *format);
- } else if (endianness == G_BIG_ENDIAN) {
- *format = AFMT_S16_BE;
- GST_DEBUG ("16 bit signed BE, no law (%d)", *format);
- }
- } else {
- if (endianness == G_LITTLE_ENDIAN) {
- *format = AFMT_U16_LE;
- GST_DEBUG ("16 bit unsigned LE, no law (%d)", *format);
- } else if (endianness == G_BIG_ENDIAN) {
- *format = AFMT_U16_BE;
- GST_DEBUG ("16 bit unsigned BE, no law (%d)", *format);
- }
- }
- *bps = 2;
- } else if (width == 8) {
- if (sign == TRUE) {
- *format = AFMT_S8;
- GST_DEBUG ("8 bit signed, no law (%d)", *format);
- } else {
- *format = AFMT_U8;
- GST_DEBUG ("8 bit unsigned, no law (%d)", *format);
- }
- *bps = 1;
- }
- } else if (law == 1) {
- *format = AFMT_MU_LAW;
- GST_DEBUG ("mu law (%d)", *format);
- } else if (law == 2) {
- *format = AFMT_A_LAW;
- GST_DEBUG ("a law (%d)", *format);
- } else {
- g_critical ("unknown law");
- return FALSE;
- }
-
- return TRUE;
-}
-
-gboolean
-gst_oss_parse_caps (GstOssDevice * oss, const GstCaps * caps)
-{
- gint bps, format;
- GstStructure *structure;
- gboolean res;
-
- structure = gst_caps_get_structure (caps, 0);
-
- res = gst_structure_get_int (structure, "width", &oss->width);
- res &= gst_structure_get_int (structure, "depth", &oss->depth);
-
- if (!res || oss->width != oss->depth)
- return FALSE;
-
- res = gst_structure_get_int (structure, "law", &oss->law);
- res &= gst_structure_get_int (structure, "endianness", &oss->endianness);
- res &= gst_structure_get_boolean (structure, "signed", &oss->sign);
-
- if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign,
- oss->width, oss->depth, &format, &bps)) {
- GST_DEBUG ("could not get format");
- return FALSE;
- }
-
- gst_structure_get_int (structure, "channels", &oss->channels);
- gst_structure_get_int (structure, "rate", &oss->rate);
-
- oss->sample_width = bps * oss->channels;
- oss->bps = bps * oss->channels * oss->rate;
- oss->format = format;
-
- return TRUE;
-}
-
-#define GET_FIXED_INT(caps, name, dest) \
-G_STMT_START { \
- if (gst_caps_has_fixed_property (caps, name)) \
- gst_structure_get_int (structure, name, dest); \
-} G_STMT_END
-#define GET_FIXED_BOOLEAN(caps, name, dest) \
-G_STMT_START { \
- if (gst_caps_has_fixed_property (caps, name)) \
- gst_structure_get_boolean (structure, name, dest); \
-} G_STMT_END
-
-gboolean
-gst_oss_merge_fixed_caps (GstOssDevice * oss, GstCaps * caps)
-{
- gint bps, format;
- GstStructure *structure;
-
- structure = gst_caps_get_structure (caps, 0);
-
- /* peel off fixed stuff from the caps */
- gst_structure_get_int (structure, "law", &oss->law);
- gst_structure_get_int (structure, "endianness", &oss->endianness);
- gst_structure_get_boolean (structure, "signed", &oss->sign);
- gst_structure_get_int (structure, "width", &oss->width);
- gst_structure_get_int (structure, "depth", &oss->depth);
-
- if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign,
- oss->width, oss->depth, &format, &bps)) {
- return FALSE;
- }
-
- gst_structure_get_int (structure, "rate", &oss->rate);
- gst_structure_get_int (structure, "channels", &oss->channels);
-
- oss->bps = bps * oss->channels * oss->rate;
- oss->format = format;
-
- return TRUE;
-}
-
-gboolean
-gst_oss_sync_parms (GstOssDevice * oss)
-{
- audio_buf_info space;
- int frag;
- gint target_format;
- gint target_channels;
- gint target_rate;
-
- /* gint fragscale, frag_ln; */
-
- if (oss->fd == -1)
- return FALSE;
-
- if ((oss->fragment & 0xFFFF) == 0) {
- frag = 0;
- } else if (oss->fragment >> 16) {
- frag = oss->fragment;
- } else {
- frag = 0x7FFF0000 | oss->fragment;
- }
-
- GST_INFO
- ("oss: setting sound card to %dHz %d format %s (%08x fragment)",
- oss->rate, oss->format, (oss->channels == 2) ? "stereo" : "mono", frag);
-
- if (frag)
- ioctl (oss->fd, SNDCTL_DSP_SETFRAGMENT, &frag);
- ioctl (oss->fd, SNDCTL_DSP_RESET, 0);
-
- target_format = oss->format;
- target_channels = oss->channels;
- target_rate = oss->rate;
-
- ioctl (oss->fd, SNDCTL_DSP_SETFMT, &oss->format);
- ioctl (oss->fd, SNDCTL_DSP_CHANNELS, &oss->channels);
- ioctl (oss->fd, SNDCTL_DSP_SPEED, &oss->rate);
-
- ioctl (oss->fd, SNDCTL_DSP_GETBLKSIZE, &oss->fragment_size);
-
- if (oss->mode == GST_OSS_MODE_WRITE) {
- ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &space);
- } else {
- ioctl (oss->fd, SNDCTL_DSP_GETISPACE, &space);
- }
-
-#if 0
- /* FIXME: make the current fragment info available somehow
- * the current way overrides preset values and that sucks */
- /* calculate new fragment using a poor man's logarithm function */
- fragscale = 1;
- frag_ln = 0;
- while (fragscale < space.fragsize) {
- fragscale <<= 1;
- frag_ln++;
- }
- oss->fragment = space.fragstotal << 16 | frag_ln;
-#endif
-
- GST_INFO ("oss: set sound card to %dHz, %d format, %s "
- "(%d bytes buffer, %08x fragment)",
- oss->rate, oss->format,
- (oss->channels == 2) ? "stereo" : "mono", space.bytes, oss->fragment);
-
- oss->fragment_time = (GST_SECOND * oss->fragment_size) / oss->bps;
- GST_INFO ("fragment time %u %" G_GUINT64_FORMAT,
- oss->bps, oss->fragment_time);
-
- if (target_format != oss->format ||
- target_channels != oss->channels || target_rate != oss->rate) {
- if (target_channels != oss->channels)
- g_warning
- ("couldn't set the right number of channels (wanted %d, got %d), enjoy the tone difference",
- target_channels, oss->channels);
- if (target_rate < oss->rate - 1 || target_rate > oss->rate + 1)
- g_warning
- ("couldn't set the right sample rate (wanted %d, got %d), enjoy the speed difference",
- target_rate, oss->rate);
- if (target_format != oss->format)
- g_warning ("couldn't set requested OSS format, enjoy the noise :)");
- /* we could eventually return FALSE here, or just do some additional tests
- * to see that the frequencies don't differ too much etc.. */
- }
- return TRUE;
-}
-
-gboolean
-gst_oss_open (GstElement * element,
- GstOssDeviceCombination * c, GstOssDevice * oss)
-{
- gint caps;
-
- g_return_val_if_fail (oss->fd == -1, FALSE);
- GST_INFO ("oss: attempting to open sound device");
-
- /* first try to open the sound card */
- if (oss->mode == GST_OSS_MODE_VOLUME) {
- goto do_mixer;
- } else if (oss->mode == GST_OSS_MODE_WRITE) {
- /* open non blocking first so that it returns immediatly with an error
- * when we cannot get to the device */
- oss->fd = open (c->dsp, O_WRONLY | O_NONBLOCK);
-
- if (oss->fd >= 0) {
- close (oss->fd);
-
- /* re-open the sound device in blocking mode */
- oss->fd = open (c->dsp, O_WRONLY);
- }
- } else {
- oss->fd = open (c->dsp, O_RDONLY);
- }
-
- if (oss->fd < 0) {
- switch (errno) {
- case EBUSY:
- GST_ELEMENT_ERROR (element, RESOURCE, BUSY,
- (_("OSS device \"%s\" is already in use by another program."),
- c->dsp), (NULL));
- break;
- case EACCES:
- case ETXTBSY:
- if (oss->mode == GST_OSS_MODE_WRITE)
- GST_ELEMENT_ERROR (element, RESOURCE, OPEN_WRITE,
- (_("Could not access device \"%s\", check its permissions."),
- c->dsp), GST_ERROR_SYSTEM);
- else
- GST_ELEMENT_ERROR (element, RESOURCE, OPEN_READ,
- (_("Could not access device \"%s\", check its permissions."),
- c->dsp), GST_ERROR_SYSTEM);
- break;
- case ENXIO:
- case ENODEV:
- case ENOENT:
- GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND,
- (_("Device \"%s\" does not exist."), c->dsp), GST_ERROR_SYSTEM);
- break;
- default:
- if (oss->mode == GST_OSS_MODE_WRITE)
- GST_ELEMENT_ERROR (element, RESOURCE, OPEN_WRITE,
- (_("Could not open device \"%s\" for writing."), c->dsp),
- GST_ERROR_SYSTEM);
- else
- GST_ELEMENT_ERROR (element, RESOURCE, OPEN_READ,
- (_("Could not open device \"%s\" for reading."), c->dsp),
- GST_ERROR_SYSTEM);
- break;
- }
- return FALSE;
- }
-
- /* we have it, set the default parameters and go have fun */
- /* set card state */
- ioctl (oss->fd, SNDCTL_DSP_GETCAPS, &caps);
-
- GST_INFO ("oss: Capabilities %08x", caps);
-
- if (caps & DSP_CAP_DUPLEX)
- GST_INFO ("oss: Full duplex");
- if (caps & DSP_CAP_REALTIME)
- GST_INFO ("oss: Realtime");
- if (caps & DSP_CAP_BATCH)
- GST_INFO ("oss: Batch");
- if (caps & DSP_CAP_COPROC)
- GST_INFO ("oss: Has coprocessor");
- if (caps & DSP_CAP_TRIGGER)
- GST_INFO ("oss: Trigger");
- if (caps & DSP_CAP_MMAP)
- GST_INFO ("oss: Direct access");
-
-#ifdef DSP_CAP_MULTI
- if (caps & DSP_CAP_MULTI)
- GST_INFO ("oss: Multiple open");
-#endif /* DSP_CAP_MULTI */
-
-#ifdef DSP_CAP_BIND
- if (caps & DSP_CAP_BIND)
- GST_INFO ("oss: Channel binding");
-#endif /* DSP_CAP_BIND */
-
- ioctl (oss->fd, SNDCTL_DSP_GETFMTS, &caps);
-
- GST_INFO ("oss: Formats %08x", caps);
- if (caps & AFMT_MU_LAW)
- GST_INFO ("oss: MU_LAW");
- if (caps & AFMT_A_LAW)
- GST_INFO ("oss: A_LAW");
- if (caps & AFMT_IMA_ADPCM)
- GST_INFO ("oss: IMA_ADPCM");
- if (caps & AFMT_U8)
- GST_INFO ("oss: U8");
- if (caps & AFMT_S16_LE)
- GST_INFO ("oss: S16_LE");
- if (caps & AFMT_S16_BE)
- GST_INFO ("oss: S16_BE");
- if (caps & AFMT_S8)
- GST_INFO ("oss: S8");
- if (caps & AFMT_U16_LE)
- GST_INFO ("oss: U16_LE");
- if (caps & AFMT_U16_BE)
- GST_INFO ("oss: U16_BE");
- if (caps & AFMT_MPEG)
- GST_INFO ("oss: MPEG");
-#ifdef AFMT_AC3
- if (caps & AFMT_AC3)
- GST_INFO ("oss: AC3");
-#endif
-
- GST_INFO ("oss: opened audio (%s) with fd=%d", c->dsp, oss->fd);
-
- oss->caps = caps;
-
-do_mixer:
- gst_ossmixer_build_list (c, oss);
-
- return TRUE;
-}
-
-void
-gst_oss_close (GstOssDevice * oss)
-{
- gst_ossmixer_free_list (oss);
-
- if (oss->probed_caps) {
- gst_caps_unref (oss->probed_caps);
- oss->probed_caps = NULL;
- }
-
- if (oss->fd < 0)
- return;
-
- close (oss->fd);
- oss->fd = -1;
-}
-
-gboolean
-gst_oss_convert (GstOssDevice * oss,
- GstFormat src_format,
- gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
-{
- gboolean res = TRUE;
-
- if (src_format == *dest_format) {
- *dest_value = src_value;
- return TRUE;
- }
-
- if (oss->bps == 0 || oss->channels == 0 || oss->width == 0)
- return FALSE;
-
- switch (src_format) {
- case GST_FORMAT_BYTES:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- *dest_value = src_value * GST_SECOND / oss->bps;
- break;
- case GST_FORMAT_DEFAULT:
- *dest_value = src_value / (oss->width * oss->channels / 8);
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- *dest_value = src_value * oss->bps / GST_SECOND;
- break;
- case GST_FORMAT_DEFAULT:
- *dest_value = src_value * oss->rate / GST_SECOND;
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_DEFAULT:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- *dest_value = src_value * GST_SECOND / oss->rate;
- break;
- case GST_FORMAT_BYTES:
- *dest_value = src_value * oss->width * oss->channels / 8;
- break;
- default:
- res = FALSE;
- }
- break;
- default:
- res = FALSE;
- }
-
- return res;
-}
-
-/* rate probing code */
-
-
#if 0
#ifdef HAVE_OSS_INCLUDE_IN_SYS
@@ -878,7 +62,7 @@ gst_oss_convert (GstOssDevice * oss,
#include <stdlib.h>
#include <sys/ioctl.h>
#include <glib.h>
-#endif
+#endif /* 0 */
typedef struct _GstOssProbe GstOssProbe;
struct _GstOssProbe
@@ -898,15 +82,16 @@ struct _GstOssRange
int max;
};
-static GstStructure *gst_oss_get_format_structure (unsigned int format_bit);
-static gboolean gst_oss_rate_probe_check (GstOssProbe * probe);
-static int gst_oss_rate_check_rate (GstOssProbe * probe, int irate);
-static void gst_oss_rate_add_range (GQueue * queue, int min, int max);
-static void gst_oss_rate_add_rate (GArray * array, int rate);
-static int gst_oss_rate_int_compare (gconstpointer a, gconstpointer b);
+static GstStructure *gst_oss_helper_get_format_structure (unsigned int
+ format_bit);
+static gboolean gst_oss_helper_rate_probe_check (GstOssProbe * probe);
+static int gst_oss_helper_rate_check_rate (GstOssProbe * probe, int irate);
+static void gst_oss_helper_rate_add_range (GQueue * queue, int min, int max);
+static void gst_oss_helper_rate_add_rate (GArray * array, int rate);
+static int gst_oss_helper_rate_int_compare (gconstpointer a, gconstpointer b);
-void
-gst_oss_probe_caps (GstOssDevice * oss)
+GstCaps *
+gst_oss_helper_probe_caps (gint fd)
{
GstOssProbe *probe;
int i;
@@ -916,31 +101,29 @@ gst_oss_probe_caps (GstOssDevice * oss)
unsigned int format_mask;
GstCaps *caps;
- if (oss->probed_caps != NULL)
- return;
- if (oss->fd == -1)
- return;
-
/* FIXME test make sure we're not currently playing */
/* FIXME test both mono and stereo */
- format_mask = AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_S8 |
- AFMT_U16_LE | AFMT_U16_BE;
- format_mask &= oss->caps;
+ format_mask = AFMT_U8 | AFMT_S8;
+
+ if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+ format_mask |= AFMT_S16_LE | AFMT_U16_LE;
+ else
+ format_mask |= AFMT_S16_BE | AFMT_U16_BE;
caps = gst_caps_new_empty ();
/* assume that the most significant bit of format_mask is 0 */
- for (format_bit = 1; format_bit <= format_mask; format_bit <<= 1) {
+ for (format_bit = 1 << 31; format_bit > 0; format_bit >>= 1) {
if (format_bit & format_mask) {
GValue rate_value = { 0 };
probe = g_new0 (GstOssProbe, 1);
- probe->fd = oss->fd;
+ probe->fd = fd;
probe->format = format_bit;
probe->n_channels = 2;
- ret = gst_oss_rate_probe_check (probe);
+ ret = gst_oss_helper_rate_probe_check (probe);
if (probe->min == -1 || probe->max == -1) {
g_array_free (probe->rates, TRUE);
g_free (probe);
@@ -950,7 +133,7 @@ gst_oss_probe_caps (GstOssDevice * oss)
if (ret) {
GValue value = { 0 };
- g_array_sort (probe->rates, gst_oss_rate_int_compare);
+ g_array_sort (probe->rates, gst_oss_helper_rate_int_compare);
g_value_init (&rate_value, GST_TYPE_LIST);
g_value_init (&value, G_TYPE_INT);
@@ -971,7 +154,7 @@ gst_oss_probe_caps (GstOssDevice * oss)
g_array_free (probe->rates, TRUE);
g_free (probe);
- structure = gst_oss_get_format_structure (format_bit);
+ structure = gst_oss_helper_get_format_structure (format_bit);
gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
gst_structure_set_value (structure, "rate", &rate_value);
g_value_unset (&rate_value);
@@ -980,17 +163,17 @@ gst_oss_probe_caps (GstOssDevice * oss)
}
}
- if (gst_caps_is_empty (caps)) {
- GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS,
- (_("Your OSS device could not be probed correctly")), (NULL));
- return;
- }
+ if (gst_caps_is_empty (caps))
+ /* fixme: make user-visible */
+ g_critical ("Your OSS device could not be probed correctly");
+
GST_DEBUG ("probed caps: %" GST_PTR_FORMAT, caps);
- oss->probed_caps = caps;
+
+ return caps;
}
static GstStructure *
-gst_oss_get_format_structure (unsigned int format_bit)
+gst_oss_helper_get_format_structure (unsigned int format_bit)
{
GstStructure *structure;
int endianness;
@@ -1045,7 +228,7 @@ gst_oss_get_format_structure (unsigned int format_bit)
}
static gboolean
-gst_oss_rate_probe_check (GstOssProbe * probe)
+gst_oss_helper_rate_probe_check (GstOssProbe * probe)
{
GstOssRange *range;
GQueue *ranges;
@@ -1058,14 +241,14 @@ gst_oss_rate_probe_check (GstOssProbe * probe)
probe->rates = g_array_new (FALSE, FALSE, sizeof (int));
- probe->min = gst_oss_rate_check_rate (probe, 1000);
+ probe->min = gst_oss_helper_rate_check_rate (probe, 1000);
n_checks++;
- probe->max = gst_oss_rate_check_rate (probe, 100000);
+ probe->max = gst_oss_helper_rate_check_rate (probe, 100000);
/* a little bug workaround */
{
int max;
- max = gst_oss_rate_check_rate (probe, 48000);
+ max = gst_oss_helper_rate_check_rate (probe, 48000);
if (max > probe->max) {
GST_ERROR
("Driver bug recognized (driver does not round rates correctly). Please file a bug report.");
@@ -1078,14 +261,14 @@ gst_oss_rate_probe_check (GstOssProbe * probe)
* error) for rates outside of [8000,48000]. If this fails, the
* driver is seriously buggy, and probably doesn't work with other
* media libraries/apps. */
- probe->min = gst_oss_rate_check_rate (probe, 8000);
- probe->max = gst_oss_rate_check_rate (probe, 48000);
+ probe->min = gst_oss_helper_rate_check_rate (probe, 8000);
+ probe->max = gst_oss_helper_rate_check_rate (probe, 48000);
}
if (probe->min == -1 || probe->max == -1) {
GST_DEBUG ("unexpected check_rate error");
return FALSE;
}
- gst_oss_rate_add_range (ranges, probe->min + 1, probe->max - 1);
+ gst_oss_helper_rate_add_range (ranges, probe->min + 1, probe->max - 1);
while ((range = g_queue_pop_head (ranges))) {
int min1;
@@ -1096,7 +279,7 @@ gst_oss_rate_probe_check (GstOssProbe * probe)
GST_DEBUG ("checking [%d,%d]", range->min, range->max);
mid = (range->min + range->max) / 2;
- mid_ret = gst_oss_rate_check_rate (probe, mid);
+ mid_ret = gst_oss_helper_rate_check_rate (probe, mid);
if (mid_ret == -1) {
/* FIXME ioctl returned an error. do something */
GST_DEBUG ("unexpected check_rate error");
@@ -1133,8 +316,8 @@ gst_oss_rate_probe_check (GstOssProbe * probe)
}
}
- gst_oss_rate_add_range (ranges, range->min, min1);
- gst_oss_rate_add_range (ranges, max1, range->max);
+ gst_oss_helper_rate_add_range (ranges, range->min, min1);
+ gst_oss_helper_rate_add_range (ranges, max1, range->max);
g_free (range);
}
@@ -1148,7 +331,7 @@ gst_oss_rate_probe_check (GstOssProbe * probe)
}
static void
-gst_oss_rate_add_range (GQueue * queue, int min, int max)
+gst_oss_helper_rate_add_range (GQueue * queue, int min, int max)
{
if (min <= max) {
GstOssRange *range = g_new0 (GstOssRange, 1);
@@ -1163,7 +346,7 @@ gst_oss_rate_add_range (GQueue * queue, int min, int max)
}
static int
-gst_oss_rate_check_rate (GstOssProbe * probe, int irate)
+gst_oss_helper_rate_check_rate (GstOssProbe * probe, int irate)
{
int rate;
int format;
@@ -1191,12 +374,12 @@ gst_oss_rate_check_rate (GstOssProbe * probe, int irate)
if (rate == irate - 1 || rate == irate + 1) {
rate = irate;
}
- gst_oss_rate_add_rate (probe->rates, rate);
+ gst_oss_helper_rate_add_rate (probe->rates, rate);
return rate;
}
static void
-gst_oss_rate_add_rate (GArray * array, int rate)
+gst_oss_helper_rate_add_rate (GArray * array, int rate)
{
int i;
int val;
@@ -1212,7 +395,7 @@ gst_oss_rate_add_rate (GArray * array, int rate)
}
static int
-gst_oss_rate_int_compare (gconstpointer a, gconstpointer b)
+gst_oss_helper_rate_int_compare (gconstpointer a, gconstpointer b)
{
const int *va = (const int *) a;
const int *vb = (const int *) b;
diff --git a/sys/oss/gstosshelper.h b/sys/oss/gstosshelper.h
index 9b7eebd5..1593fe39 100644
--- a/sys/oss/gstosshelper.h
+++ b/sys/oss/gstosshelper.h
@@ -2,11 +2,7 @@
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wim.taymans@chello.be>
*
- * gstosshelper.h: helper functions for OSS Device handling. This
- * set of functions takes care of device setting/getting,
- * opening/closing devices, parsing caps to OSS formats/settings
- * or the other way around, device probing, supported format
- * probing and mixer integration.
+ * gstosshelper.h: OSS helper routines.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,128 +20,24 @@
* Boston, MA 02111-1307, USA.
*/
+
#ifndef __GST_OSS_HELPER_H__
#define __GST_OSS_HELPER_H__
+
#include <gst/gst.h>
#include <sys/types.h>
-/* debugging category */
-GST_DEBUG_CATEGORY_EXTERN (oss_debug);
-#define GST_CAT_DEFAULT oss_debug
-
-G_BEGIN_DECLS
-
-enum {
- ARG_0,
- OSS_ARG_DEVICE,
- OSS_ARG_MIXER_DEVICE,
- OSS_ARG_DEVICE_NAME,
- OSS_ARG_0
-};
-
-typedef enum {
- GST_OSS_MODE_READ,
- GST_OSS_MODE_WRITE,
- GST_OSS_MODE_VOLUME,
- GST_OSS_MODE_MIXER
-} GstOssOpenMode;
-
-/*
- * Embed those two in whatever object you're creating.
- */
-
-typedef struct _GstOssDeviceCombination {
- gchar *dsp, *mixer;
- dev_t dev;
-} GstOssDeviceCombination;
-
-typedef struct _GstOssDevice {
- /* device state */
- int fd;
- int caps; /* the capabilities */
- gint format;
- gint fragment;
- guint64 fragment_time;
- gint fragment_size;
- GstOssOpenMode mode;
- GstCaps *probed_caps;
+#include "gstosshelper.h"
- /* stats bytes per *second* */
- guint bps;
- /* sample width in bytes */
- guint sample_width;
-
- /* parameters */
- gint law;
- gint endianness;
- gboolean sign;
- gint width;
- gint depth;
- gint channels;
- gint rate;
-
- /* mixer stuff */
- GList *tracklist;
- guint32 stereomask,
- recdevs,
- recmask,
- mixcaps;
- gint mixer_fd;
- gchar *device_name;
-} GstOssDevice;
-
-/*
- * class/type/interface handling for mixer/device handling.
- */
-void gst_oss_add_mixer_type (GType type);
-void gst_oss_add_device_properties (GstElementClass * klass);
-void gst_oss_set_device_property (GstElement * element,
- GstOssDeviceCombination * c,
- GstOssDevice * dev,
- guint prop_id,
- GParamSpec * pspec,
- const GValue * value);
-void gst_oss_get_device_property (GstElement * element,
- GstOssDeviceCombination * c,
- GstOssDevice * d,
- guint prop_id,
- GParamSpec * pspec,
- GValue * value);
-
-/*
- * device open/close.
- */
-void gst_oss_init (GObject * obj,
- GstOssDeviceCombination * c,
- GstOssDevice * dev,
- GstOssOpenMode mode);
-void gst_oss_dispose (GstOssDeviceCombination * c,
- GstOssDevice * dev);
-gboolean gst_oss_open (GstElement * element,
- GstOssDeviceCombination * c,
- GstOssDevice * dev);
-void gst_oss_close (GstOssDevice * dev);
+G_BEGIN_DECLS
-/*
- * caps parsing/probing.
- */
-gboolean gst_oss_parse_caps (GstOssDevice * dev,
- const GstCaps * caps);
-gboolean gst_oss_merge_fixed_caps (GstOssDevice * dev,
- GstCaps * caps);
-gboolean gst_oss_sync_parms (GstOssDevice * dev);
-void gst_oss_reset (GstOssDevice * dev);
+GstCaps* gst_oss_helper_probe_caps (gint fd);
-gboolean gst_oss_convert (GstOssDevice * dev,
- GstFormat src_format,
- gint64 src_value,
- GstFormat * dest_format,
- gint64 * dest_value);
-void gst_oss_probe_caps (GstOssDevice * dev);
G_END_DECLS
+
#endif /* __GST_OSS_HELPER_H__ */
diff --git a/sys/oss/gstossmixer.c b/sys/oss/gstossmixer.c
index 1d462908..1e972568 100644
--- a/sys/oss/gstossmixer.c
+++ b/sys/oss/gstossmixer.c
@@ -35,257 +35,186 @@
#include <gst/gst-i18n-plugin.h>
#include "gstossmixer.h"
+#include "gstossmixertrack.h"
#define MASK_BIT_IS_SET(mask, bit) \
(mask & (1 << bit))
-static void gst_ossmixer_track_class_init (GstOssMixerTrackClass * klass);
-static void gst_ossmixer_track_init (GstOssMixerTrack * track);
+static gboolean
+gst_ossmixer_open (GstOssMixer * mixer)
+{
+#ifdef SOUND_MIXER_INFO
+ struct mixer_info minfo;
+#endif
-static gboolean gst_ossmixer_supported (GstImplementsInterface * iface,
- GType iface_type);
-static const GList *gst_ossmixer_list_tracks (GstMixer * ossmixer);
+ g_return_val_if_fail (mixer->mixer_fd == -1, FALSE);
-static void gst_ossmixer_set_volume (GstMixer * ossmixer,
- GstMixerTrack * track, gint * volumes);
-static void gst_ossmixer_get_volume (GstMixer * ossmixer,
- GstMixerTrack * track, gint * volumes);
+ mixer->mixer_fd = open (mixer->device, O_RDWR);
+ if (mixer->mixer_fd == -1) {
+ /* this is valid. OSS devices don't need to expose a mixer */
+ GST_DEBUG ("Failed to open mixer device %s, mixing disabled: %s",
+ mixer->device, strerror (errno));
+ return FALSE;
+ }
-static void gst_ossmixer_set_record (GstMixer * ossmixer,
- GstMixerTrack * track, gboolean record);
-static void gst_ossmixer_set_mute (GstMixer * ossmixer,
- GstMixerTrack * track, gboolean mute);
+ /* get masks */
+ if (ioctl (mixer->mixer_fd, SOUND_MIXER_READ_RECMASK, &mixer->recmask) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_RECSRC, &mixer->recdevs) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_STEREODEVS,
+ &mixer->stereomask) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_DEVMASK, &mixer->devmask) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_CAPS, &mixer->mixcaps) < 0) {
+ GST_DEBUG ("Failed to get device masks");
+ close (mixer->mixer_fd);
+ mixer->mixer_fd = -1;
+ return FALSE;
+ }
-static const gchar **labels = NULL;
-static GstMixerTrackClass *parent_class = NULL;
+ /* get name */
+#ifdef SOUND_MIXER_INFO
+ if (ioctl (mixer->mixer_fd, SOUND_MIXER_INFO, &minfo) == 0) {
+ mixer->cardname = g_strdup (minfo.name);
+ }
+#else
+ oss->cardname = g_strdup ("Unknown");
+#endif
-/* three functions: firstly, OSS has the nasty habit of inserting
- * spaces in the labels, we want to get rid of them. Secondly,
- * i18n is impossible with OSS' way of providing us with mixer
- * labels, so we make a 'given' list of i18n'ed labels. Thirdly, I
- * personally don't like the "1337" names that OSS gives to their
- * labels ("Vol", "Mic", "Rec"), I'd rather see full names. */
+ return TRUE;
+}
static void
-fill_labels (void)
+gst_ossmixer_ensure_track_list (GstOssMixer * mixer)
{
- gint i, pos;
- gchar *origs[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
- struct
- {
- gchar *given, *wanted;
- }
- cases[] = {
- /* Note: this list is simply ripped from soundcard.h. For
- * some people, some values might be missing (3D surround,
- * etc.) - feel free to add them. That's the reason why
- * I'm doing this in such a horribly complicated way. */
- {
- "Vol ", _("Volume")}
- , {
- "Bass ", _("Bass")}
- , {
- "Trebl", _("Treble")}
- , {
- "Synth", _("Synth")}
- , {
- "Pcm ", _("PCM")}
- , {
- "Spkr ", _("Speaker")}
- , {
- "Line ", _("Line-in")}
- , {
- "Mic ", _("Microphone")}
- , {
- "CD ", _("CD")}
- , {
- "Mix ", _("Mixer")}
- , {
- "Pcm2 ", _("PCM-2")}
- , {
- "Rec ", _("Record")}
- , {
- "IGain", _("In-gain")}
- , {
- "OGain", _("Out-gain")}
- , {
- "Line1", _("Line-1")}
- , {
- "Line2", _("Line-2")}
- , {
- "Line3", _("Line-3")}
- , {
- "Digital1", _("Digital-1")}
- , {
- "Digital2", _("Digital-2")}
- , {
- "Digital3", _("Digital-3")}
- , {
- "PhoneIn", _("Phone-in")}
- , {
- "PhoneOut", _("Phone-out")}
- , {
- "Video", _("Video")}
- , {
- "Radio", _("Radio")}
- , {
- "Monitor", _("Monitor")}
- , {
- NULL, NULL}
- };
-
- labels = g_malloc (sizeof (gchar *) * SOUND_MIXER_NRDEVICES);
+ gint i, master = -1;
+
+ g_return_if_fail (mixer->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++) {
- for (pos = 0; cases[pos].given != NULL; pos++) {
- if (!strcmp (cases[pos].given, origs[i])) {
- labels[i] = g_strdup (cases[pos].wanted);
- break;
- }
+ 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 this 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->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);
}
- if (cases[pos].given == NULL)
- labels[i] = g_strdup (origs[i]);
}
}
-GType
-gst_ossmixer_track_get_type (void)
+GstOssMixer *
+gst_ossmixer_new (const char *device, GstOssMixerDirection dir)
{
- static GType gst_ossmixer_track_type = 0;
-
- if (!gst_ossmixer_track_type) {
- static const GTypeInfo ossmixer_track_info = {
- sizeof (GstOssMixerTrackClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_ossmixer_track_class_init,
- NULL,
- NULL,
- sizeof (GstOssMixerTrack),
- 0,
- (GInstanceInitFunc) gst_ossmixer_track_init,
- NULL
- };
-
- gst_ossmixer_track_type =
- g_type_register_static (GST_TYPE_MIXER_TRACK,
- "GstOssMixerTrack", &ossmixer_track_info, 0);
- }
+ GstOssMixer *ret = NULL;
- return gst_ossmixer_track_type;
-}
+ g_return_val_if_fail (device != NULL, NULL);
-static void
-gst_ossmixer_track_class_init (GstOssMixerTrackClass * klass)
-{
- parent_class = g_type_class_ref (GST_TYPE_MIXER_TRACK);
-}
+ ret = g_new0 (GstOssMixer, 1);
-static void
-gst_ossmixer_track_init (GstOssMixerTrack * track)
-{
- track->lvol = track->rvol = 0;
- track->track_num = 0;
-}
+ ret->device = g_strdup (device);
+ ret->dir = dir;
-GstMixerTrack *
-gst_ossmixer_track_new (GstOssDevice * oss,
- gint track_num, gint max_chans, gint flags)
-{
- GstOssMixerTrack *osstrack;
- GstMixerTrack *track;
- gint volume;
+ if (!gst_ossmixer_open (ret))
+ goto error;
- if (!labels)
- fill_labels ();
-
- osstrack = g_object_new (GST_TYPE_OSSMIXER_TRACK, NULL);
- track = GST_MIXER_TRACK (osstrack);
- track->label = g_strdup (labels[track_num]);
- track->num_channels = max_chans;
- track->flags = flags;
- track->min_volume = 0;
- track->max_volume = 100;
- osstrack->track_num = track_num;
-
- /* volume */
- if (ioctl (oss->mixer_fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
- g_warning ("Error getting device (%d) volume: %s",
- osstrack->track_num, strerror (errno));
- volume = 0;
- }
- osstrack->lvol = (volume & 0xff);
- if (track->num_channels == 2) {
- osstrack->rvol = ((volume >> 8) & 0xff);
- }
+ return ret;
- return track;
-}
+error:
+ if (ret)
+ gst_ossmixer_free (ret);
-void
-gst_oss_interface_init (GstImplementsInterfaceClass * klass)
-{
- /* default virtual functions */
- klass->supported = gst_ossmixer_supported;
+ return NULL;
}
void
-gst_ossmixer_interface_init (GstMixerClass * klass)
+gst_ossmixer_free (GstOssMixer * mixer)
{
- GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE;
-
- /* default virtual functions */
- klass->list_tracks = gst_ossmixer_list_tracks;
- klass->set_volume = gst_ossmixer_set_volume;
- klass->get_volume = gst_ossmixer_get_volume;
- klass->set_mute = gst_ossmixer_set_mute;
- klass->set_record = gst_ossmixer_set_record;
-}
+ g_return_if_fail (mixer != NULL);
-static gboolean
-gst_ossmixer_supported (GstImplementsInterface * iface, GType iface_type)
-{
- GstOssDevice *oss = g_object_get_data (G_OBJECT (iface), "oss-data");
+ if (mixer->device) {
+ g_free (mixer->device);
+ mixer->device = NULL;
+ }
+
+ if (mixer->cardname) {
+ g_free (mixer->cardname);
+ mixer->cardname = NULL;
+ }
+
+ if (mixer->tracklist) {
+ g_list_foreach (mixer->tracklist, (GFunc) g_object_unref, NULL);
+ g_list_free (mixer->tracklist);
+ mixer->tracklist = NULL;
+ }
- g_return_val_if_fail (oss != NULL, FALSE);
- g_assert (iface_type == GST_TYPE_MIXER);
+ if (mixer->mixer_fd != -1) {
+ close (mixer->mixer_fd);
+ mixer->mixer_fd = -1;
+ }
- return (oss->mixer_fd != -1);
+ g_free (mixer);
}
/* unused with G_DISABLE_* */
static G_GNUC_UNUSED gboolean
-gst_ossmixer_contains_track (GstOssDevice * oss, GstOssMixerTrack * osstrack)
+gst_ossmixer_contains_track (GstOssMixer * mixer, GstOssMixerTrack * osstrack)
{
const GList *item;
- for (item = oss->tracklist; item != NULL; item = item->next)
+ for (item = mixer->tracklist; item != NULL; item = item->next)
if (item->data == osstrack)
return TRUE;
return FALSE;
}
-static const GList *
-gst_ossmixer_list_tracks (GstMixer * mixer)
+const GList *
+gst_ossmixer_list_tracks (GstOssMixer * mixer)
{
- GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
+ gst_ossmixer_ensure_track_list (mixer);
- return (const GList *) oss->tracklist;
+ return (const GList *) mixer->tracklist;
}
-static void
-gst_ossmixer_get_volume (GstMixer * mixer,
+void
+gst_ossmixer_get_volume (GstOssMixer * mixer,
GstMixerTrack * track, gint * volumes)
{
gint volume;
- GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (oss != NULL);
- g_return_if_fail (oss->mixer_fd != -1);
- g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
if (track->flags & GST_MIXER_TRACK_MUTE) {
volumes[0] = osstrack->lvol;
@@ -294,7 +223,7 @@ gst_ossmixer_get_volume (GstMixer * mixer,
}
} else {
/* get */
- if (ioctl (oss->mixer_fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
+ if (ioctl (mixer->mixer_fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
g_warning ("Error getting recording device (%d) volume: %s",
osstrack->track_num, strerror (errno));
volume = 0;
@@ -307,18 +236,15 @@ gst_ossmixer_get_volume (GstMixer * mixer,
}
}
-static void
-gst_ossmixer_set_volume (GstMixer * mixer,
+void
+gst_ossmixer_set_volume (GstOssMixer * mixer,
GstMixerTrack * track, gint * volumes)
{
gint volume;
- GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (oss != NULL);
- g_return_if_fail (oss->mixer_fd != -1);
- g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
/* prepare the value for ioctl() */
if (!(track->flags & GST_MIXER_TRACK_MUTE)) {
@@ -328,7 +254,7 @@ gst_ossmixer_set_volume (GstMixer * mixer,
}
/* set */
- if (ioctl (oss->mixer_fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
+ if (ioctl (mixer->mixer_fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
g_warning ("Error setting recording device (%d) volume (0x%x): %s",
osstrack->track_num, volume, strerror (errno));
return;
@@ -341,28 +267,26 @@ gst_ossmixer_set_volume (GstMixer * mixer,
}
}
-static void
-gst_ossmixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
+void
+gst_ossmixer_set_mute (GstOssMixer * mixer, GstMixerTrack * track,
+ gboolean mute)
{
int volume;
- GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (oss != NULL);
- g_return_if_fail (oss->mixer_fd != -1);
- g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
+ g_return_if_fail (mixer->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 (oss->stereomask, osstrack->track_num)) {
+ if (MASK_BIT_IS_SET (mixer->stereomask, osstrack->track_num)) {
volume |= ((osstrack->rvol & 0xff) << 8);
}
}
- if (ioctl (oss->mixer_fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
+ if (ioctl (mixer->mixer_fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
g_warning ("Error setting mixer recording device volume (0x%x): %s",
volume, strerror (errno));
return;
@@ -375,17 +299,14 @@ gst_ossmixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
}
}
-static void
-gst_ossmixer_set_record (GstMixer * mixer,
+void
+gst_ossmixer_set_record (GstOssMixer * mixer,
GstMixerTrack * track, gboolean record)
{
- GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (oss != NULL);
- g_return_if_fail (oss->mixer_fd != -1);
- g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
/* if there's nothing to do... */
if ((record && GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) ||
@@ -393,28 +314,28 @@ gst_ossmixer_set_record (GstMixer * mixer,
return;
/* if we're exclusive, then we need to unset the current one(s) */
- if (oss->mixcaps & SOUND_CAP_EXCL_INPUT) {
+ if (mixer->mixcaps & SOUND_CAP_EXCL_INPUT) {
GList *track;
- for (track = oss->tracklist; track != NULL; track = track->next) {
+ for (track = mixer->tracklist; track != NULL; track = track->next) {
GstMixerTrack *turn = (GstMixerTrack *) track->data;
turn->flags &= ~GST_MIXER_TRACK_RECORD;
}
- oss->recdevs = 0;
+ mixer->recdevs = 0;
}
/* set new record bit, if needed */
if (record) {
- oss->recdevs |= (1 << osstrack->track_num);
+ mixer->recdevs |= (1 << osstrack->track_num);
} else {
- oss->recdevs &= ~(1 << osstrack->track_num);
+ mixer->recdevs &= ~(1 << osstrack->track_num);
}
/* set it to the device */
- if (ioctl (oss->mixer_fd, SOUND_MIXER_WRITE_RECSRC, &oss->recdevs) < 0) {
+ if (ioctl (mixer->mixer_fd, SOUND_MIXER_WRITE_RECSRC, &mixer->recdevs) < 0) {
g_warning ("Error setting mixer recording devices (0x%x): %s",
- oss->recdevs, strerror (errno));
+ mixer->recdevs, strerror (errno));
return;
}
@@ -424,101 +345,3 @@ gst_ossmixer_set_record (GstMixer * mixer,
track->flags &= ~GST_MIXER_TRACK_RECORD;
}
}
-
-void
-gst_ossmixer_build_list (GstOssDeviceCombination * c, GstOssDevice * oss)
-{
- gint i, devmask, master = -1;
-
-#ifdef SOUND_MIXER_INFO
- struct mixer_info minfo;
-#endif
-
- g_return_if_fail (oss->mixer_fd == -1);
-
- oss->mixer_fd = open (c->mixer, O_RDWR);
- if (oss->mixer_fd == -1) {
- /* this is valid. OSS devices don't need to expose a mixer */
- GST_DEBUG ("Failed to open mixer device %s, mixing disabled: %s",
- c->mixer, strerror (errno));
- return;
- }
-
- /* get masks */
- if (ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECMASK, &oss->recmask) < 0 ||
- ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECSRC, &oss->recdevs) < 0 ||
- ioctl (oss->mixer_fd, SOUND_MIXER_READ_STEREODEVS, &oss->stereomask) < 0
- || ioctl (oss->mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0
- || ioctl (oss->mixer_fd, SOUND_MIXER_READ_CAPS, &oss->mixcaps) < 0) {
- GST_DEBUG ("Failed to get device masks - disabling mixer");
- close (oss->mixer_fd);
- oss->mixer_fd = -1;
- return;
- }
-
- /* get name */
-#ifdef SOUND_MIXER_INFO
- if (ioctl (oss->mixer_fd, SOUND_MIXER_INFO, &minfo) == 0) {
- oss->device_name = g_strdup (minfo.name);
- }
-#else
- oss->device_name = g_strdup ("Unknown");
-#endif
-
- /* find master volume */
- if (devmask & SOUND_MASK_VOLUME)
- master = SOUND_MIXER_VOLUME;
- else if (devmask & SOUND_MASK_PCM)
- master = SOUND_MIXER_PCM;
- else if (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 (devmask & (1 << i)) {
- GstMixerTrack *track;
- gboolean input = FALSE, stereo = FALSE, record = FALSE;
-
- /* track exists, make up capabilities */
- if (MASK_BIT_IS_SET (oss->stereomask, i))
- stereo = TRUE;
- if (MASK_BIT_IS_SET (oss->recmask, i))
- input = TRUE;
- if (MASK_BIT_IS_SET (oss->recdevs, i))
- record = TRUE;
-
- /* do we want this in our list? */
- if ((oss->mode == GST_OSS_MODE_READ && input == FALSE) ||
- (oss->mode == GST_OSS_MODE_WRITE && i != SOUND_MIXER_PCM))
- continue;
-
- /* add track to list */
- track = gst_ossmixer_track_new (oss, 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));
- oss->tracklist = g_list_append (oss->tracklist, track);
- }
- }
-}
-
-void
-gst_ossmixer_free_list (GstOssDevice * oss)
-{
- if (oss->mixer_fd == -1)
- return;
-
- g_list_foreach (oss->tracklist, (GFunc) g_object_unref, NULL);
- g_list_free (oss->tracklist);
- oss->tracklist = NULL;
-
- if (oss->device_name) {
- g_free (oss->device_name);
- oss->device_name = NULL;
- }
-
- close (oss->mixer_fd);
- oss->mixer_fd = -1;
-}
diff --git a/sys/oss/gstossmixer.h b/sys/oss/gstossmixer.h
index 2eede0ed..c5a8f325 100644
--- a/sys/oss/gstossmixer.h
+++ b/sys/oss/gstossmixer.h
@@ -19,48 +19,153 @@
* Boston, MA 02111-1307, USA.
*/
+
#ifndef __GST_OSS_MIXER_H__
#define __GST_OSS_MIXER_H__
+
#include <gst/gst.h>
#include <gst/interfaces/mixer.h>
#include "gstosshelper.h"
+
G_BEGIN_DECLS
-#define GST_TYPE_OSSMIXER_TRACK \
- (gst_ossmixer_track_get_type ())
-#define GST_OSSMIXER_TRACK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OSSMIXER_TRACK, \
- GstOssMixerTrack))
-#define GST_OSSMIXER_TRACK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_OSSMIXER_TRACK, \
- GstOssMixerTrackClass))
-#define GST_IS_OSSMIXER_TRACK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OSSMIXER_TRACK))
-#define GST_IS_OSSMIXER_TRACK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_OSSMIXER_TRACK))
-
-typedef struct _GstOssMixerTrack {
- GstMixerTrack parent;
-
- gint lvol, rvol;
- gint track_num;
-} GstOssMixerTrack;
-
-typedef struct _GstOssMixerTrackClass {
- GstMixerTrackClass parent;
-} GstOssMixerTrackClass;
-
-GType gst_ossmixer_track_get_type (void);
-
-void gst_ossmixer_interface_init (GstMixerClass *klass);
-void gst_oss_interface_init (GstImplementsInterfaceClass *klass);
-void gst_ossmixer_build_list (GstOssDeviceCombination * c,
- GstOssDevice *oss);
-void gst_ossmixer_free_list (GstOssDevice *oss);
+
+#define GST_OSS_MIXER(obj) ((GstOssMixer*)(obj))
+
+
+typedef enum {
+ GST_OSS_MIXER_CAPTURE = 1<<0,
+ GST_OSS_MIXER_PLAYBACK = 1<<1,
+ GST_OSS_MIXER_ALL = GST_OSS_MIXER_CAPTURE | GST_OSS_MIXER_PLAYBACK
+} GstOssMixerDirection;
+
+
+typedef struct _GstOssMixer GstOssMixer;
+
+
+struct _GstOssMixer {
+ GList * tracklist; /* list of available tracks */
+
+ gint mixer_fd;
+
+ gchar * device;
+ gchar * cardname;
+
+ gint recmask;
+ gint recdevs;
+ gint stereomask;
+ gint devmask;
+ gint mixcaps;
+
+ GstOssMixerDirection dir;
+};
+
+
+GstOssMixer* gst_ossmixer_new (const gchar *device,
+ GstOssMixerDirection dir);
+void gst_ossmixer_free (GstOssMixer *mixer);
+
+const GList* gst_ossmixer_list_tracks (GstOssMixer * mixer);
+void gst_ossmixer_set_volume (GstOssMixer * mixer,
+ GstMixerTrack * track,
+ gint * volumes);
+void gst_ossmixer_get_volume (GstOssMixer * mixer,
+ GstMixerTrack * track,
+ gint * volumes);
+void gst_ossmixer_set_record (GstOssMixer * mixer,
+ GstMixerTrack * track,
+ gboolean record);
+void gst_ossmixer_set_mute (GstOssMixer * mixer,
+ GstMixerTrack * track,
+ gboolean mute);
+
+
+#define GST_IMPLEMENT_OSS_MIXER_METHODS(Type, interface_as_function) \
+static gboolean \
+interface_as_function ## _supported (Type *this, GType iface_type) \
+{ \
+ g_assert (iface_type == GST_TYPE_MIXER); \
+ \
+ return (this->mixer != NULL); \
+} \
+ \
+static const GList* \
+interface_as_function ## _list_tracks (GstMixer * mixer) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_val_if_fail (this != NULL, NULL); \
+ g_return_val_if_fail (this->mixer != NULL, NULL); \
+ \
+ return gst_ossmixer_list_tracks (this->mixer); \
+} \
+ \
+static void \
+interface_as_function ## _set_volume (GstMixer * mixer, GstMixerTrack * track, \
+ gint * volumes) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_ossmixer_set_volume (this->mixer, track, volumes); \
+} \
+ \
+static void \
+interface_as_function ## _get_volume (GstMixer * mixer, GstMixerTrack * track, \
+ gint * volumes) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_ossmixer_get_volume (this->mixer, track, volumes); \
+} \
+ \
+static void \
+interface_as_function ## _set_record (GstMixer * mixer, GstMixerTrack * track, \
+ gboolean record) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_ossmixer_set_record (this->mixer, track, record); \
+} \
+ \
+static void \
+interface_as_function ## _set_mute (GstMixer * mixer, GstMixerTrack * track, \
+ gboolean mute) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_ossmixer_set_mute (this->mixer, track, mute); \
+} \
+ \
+static void \
+interface_as_function ## _interface_init (GstMixerClass * klass) \
+{ \
+ GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE; \
+ \
+ /* set up the interface hooks */ \
+ klass->list_tracks = interface_as_function ## _list_tracks; \
+ klass->set_volume = interface_as_function ## _set_volume; \
+ klass->get_volume = interface_as_function ## _get_volume; \
+ klass->set_mute = interface_as_function ## _set_mute; \
+ klass->set_record = interface_as_function ## _set_record; \
+}
+
G_END_DECLS
+
#endif /* __GST_OSS_MIXER_H__ */
diff --git a/sys/oss/gstossmixertrack.c b/sys/oss/gstossmixertrack.c
new file mode 100644
index 00000000..48e4a9d6
--- /dev/null
+++ b/sys/oss/gstossmixertrack.c
@@ -0,0 +1,180 @@
+/* GStreamer OSS Mixer implementation
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * gstossmixer.c: mixer interface implementation for OSS
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+
+#include <gst/gst-i18n-plugin.h>
+
+#include "gstossmixertrack.h"
+
+#define MASK_BIT_IS_SET(mask, bit) \
+ (mask & (1 << bit))
+
+G_DEFINE_TYPE (GstOssMixerTrack, gst_ossmixer_track, GST_TYPE_MIXER_TRACK);
+
+static void
+gst_ossmixer_track_class_init (GstOssMixerTrackClass * klass)
+{
+ /* nop */
+}
+
+static void
+gst_ossmixer_track_init (GstOssMixerTrack * track)
+{
+ track->lvol = track->rvol = 0;
+ track->track_num = 0;
+}
+
+static const gchar **labels = NULL;
+
+/* three functions: firstly, OSS has the nasty habit of inserting
+ * spaces in the labels, we want to get rid of them. Secondly,
+ * i18n is impossible with OSS' way of providing us with mixer
+ * labels, so we make a 'given' list of i18n'ed labels. Thirdly, I
+ * personally don't like the "1337" names that OSS gives to their
+ * labels ("Vol", "Mic", "Rec"), I'd rather see full names. */
+
+static void
+fill_labels (void)
+{
+ gint i, pos;
+ gchar *origs[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
+ struct
+ {
+ gchar *given, *wanted;
+ }
+ cases[] = {
+ /* Note: this list is simply ripped from soundcard.h. For
+ * some people, some values might be missing (3D surround,
+ * etc.) - feel free to add them. That's the reason why
+ * I'm doing this in such a horribly complicated way. */
+ {
+ "Vol ", _("Volume")}
+ , {
+ "Bass ", _("Bass")}
+ , {
+ "Trebl", _("Treble")}
+ , {
+ "Synth", _("Synth")}
+ , {
+ "Pcm ", _("PCM")}
+ , {
+ "Spkr ", _("Speaker")}
+ , {
+ "Line ", _("Line-in")}
+ , {
+ "Mic ", _("Microphone")}
+ , {
+ "CD ", _("CD")}
+ , {
+ "Mix ", _("Mixer")}
+ , {
+ "Pcm2 ", _("PCM-2")}
+ , {
+ "Rec ", _("Record")}
+ , {
+ "IGain", _("In-gain")}
+ , {
+ "OGain", _("Out-gain")}
+ , {
+ "Line1", _("Line-1")}
+ , {
+ "Line2", _("Line-2")}
+ , {
+ "Line3", _("Line-3")}
+ , {
+ "Digital1", _("Digital-1")}
+ , {
+ "Digital2", _("Digital-2")}
+ , {
+ "Digital3", _("Digital-3")}
+ , {
+ "PhoneIn", _("Phone-in")}
+ , {
+ "PhoneOut", _("Phone-out")}
+ , {
+ "Video", _("Video")}
+ , {
+ "Radio", _("Radio")}
+ , {
+ "Monitor", _("Monitor")}
+ , {
+ NULL, NULL}
+ };
+
+ labels = g_malloc (sizeof (gchar *) * SOUND_MIXER_NRDEVICES);
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ for (pos = 0; cases[pos].given != NULL; pos++) {
+ if (!strcmp (cases[pos].given, origs[i])) {
+ labels[i] = g_strdup (cases[pos].wanted);
+ break;
+ }
+ }
+ if (cases[pos].given == NULL)
+ labels[i] = g_strdup (origs[i]);
+ }
+}
+
+GstMixerTrack *
+gst_ossmixer_track_new (gint mixer_fd,
+ gint track_num, gint max_chans, gint flags)
+{
+ GstOssMixerTrack *osstrack;
+ GstMixerTrack *track;
+ gint volume;
+
+ if (!labels)
+ fill_labels ();
+
+ osstrack = g_object_new (GST_TYPE_OSSMIXER_TRACK, NULL);
+ track = GST_MIXER_TRACK (osstrack);
+ track->label = g_strdup (labels[track_num]);
+ track->num_channels = max_chans;
+ track->flags = flags;
+ track->min_volume = 0;
+ track->max_volume = 100;
+ osstrack->track_num = track_num;
+
+ /* volume */
+ if (ioctl (mixer_fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
+ g_warning ("Error getting device (%d) volume: %s",
+ osstrack->track_num, strerror (errno));
+ volume = 0;
+ }
+ osstrack->lvol = (volume & 0xff);
+ if (track->num_channels == 2) {
+ osstrack->rvol = ((volume >> 8) & 0xff);
+ }
+
+ return track;
+}
diff --git a/sys/oss/gstossmixertrack.h b/sys/oss/gstossmixertrack.h
new file mode 100644
index 00000000..1350a026
--- /dev/null
+++ b/sys/oss/gstossmixertrack.h
@@ -0,0 +1,62 @@
+/* GStreamer OSS Mixer implementation
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * gstossmixertrack.h: OSS mixer tracks
+ *
+ * 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_OSS_MIXER_TRACK_H__
+#define __GST_OSS_MIXER_TRACK_H__
+
+#include <gst/gst.h>
+#include <gst/interfaces/mixer.h>
+
+#include "gstosshelper.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSSMIXER_TRACK \
+ (gst_ossmixer_track_get_type ())
+#define GST_OSSMIXER_TRACK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OSSMIXER_TRACK, \
+ GstOssMixerTrack))
+#define GST_OSSMIXER_TRACK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_OSSMIXER_TRACK, \
+ GstOssMixerTrackClass))
+#define GST_IS_OSSMIXER_TRACK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OSSMIXER_TRACK))
+#define GST_IS_OSSMIXER_TRACK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_OSSMIXER_TRACK))
+
+typedef struct _GstOssMixerTrack {
+ GstMixerTrack parent;
+
+ gint lvol, rvol;
+ gint track_num;
+} GstOssMixerTrack;
+
+typedef struct _GstOssMixerTrackClass {
+ GstMixerTrackClass parent;
+} GstOssMixerTrackClass;
+
+GType gst_ossmixer_track_get_type (void);
+GstMixerTrack* gst_ossmixer_track_new (gint mixer_fd,
+ gint track_num, gint max_chans, gint flags);
+
+G_END_DECLS
+
+#endif /* __GST_OSS_MIXER_TRACK_H__ */
diff --git a/sys/oss/gstosssink.c b/sys/oss/gstosssink.c
index efef1ba0..a98efab1 100644
--- a/sys/oss/gstosssink.c
+++ b/sys/oss/gstosssink.c
@@ -162,27 +162,22 @@ gst_oss_sink_init (GstOssSink * osssink)
{
GST_DEBUG ("initializing osssink");
- osssink->element = g_object_new (GST_TYPE_OSSELEMENT, NULL);
+ osssink->fd = -1;
}
static GstCaps *
gst_oss_sink_getcaps (GstBaseSink * bsink)
{
GstOssSink *osssink;
- GstOssElement *element;
GstCaps *caps;
osssink = GST_OSSSINK (bsink);
- element = osssink->element;
- gst_osselement_probe_caps (element);
-
- if (element->probed_caps == NULL) {
- caps =
- gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD
+ if (osssink->fd == -1) {
+ caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD
(bsink)));
} else {
- caps = gst_caps_ref (element->probed_caps);
+ caps = gst_oss_helper_probe_caps (osssink->fd);
}
return caps;
diff --git a/sys/oss/gstosssink.h b/sys/oss/gstosssink.h
index 7f488117..3cede595 100644
--- a/sys/oss/gstosssink.h
+++ b/sys/oss/gstosssink.h
@@ -28,7 +28,7 @@
#include <gst/gst.h>
#include <gst/audio/gstaudiosink.h>
-#include "gstosselement.h"
+#include "gstosshelper.h"
G_BEGIN_DECLS
@@ -44,8 +44,6 @@ typedef struct _GstOssSinkClass GstOssSinkClass;
struct _GstOssSink {
GstAudioSink sink;
- GstOssElement *element;
-
gint fd;
gint bytes_per_sample;
};
diff --git a/sys/oss/gstosssrc.c b/sys/oss/gstosssrc.c
index e7a5cda1..2c413657 100644
--- a/sys/oss/gstosssrc.c
+++ b/sys/oss/gstosssrc.c
@@ -192,27 +192,23 @@ gst_oss_src_init (GstOssSrc * osssrc)
{
GST_DEBUG ("initializing osssrc");
+ osssrc->fd = -1;
osssrc->device = g_strdup ("/dev/dsp");
- osssrc->element = g_object_new (GST_TYPE_OSSELEMENT, NULL);
}
static GstCaps *
gst_oss_src_getcaps (GstBaseSrc * bsrc)
{
GstOssSrc *osssrc;
- GstOssElement *element;
GstCaps *caps;
osssrc = GST_OSS_SRC (bsrc);
- element = osssrc->element;
- gst_osselement_probe_caps (element);
-
- if (element->probed_caps == NULL) {
- caps =
- gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (bsrc)));
+ if (osssrc->fd == -1) {
+ caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
+ (bsrc)));
} else {
- caps = gst_caps_ref (element->probed_caps);
+ caps = gst_oss_helper_probe_caps (osssrc->fd);
}
return caps;
diff --git a/sys/oss/gstosssrc.h b/sys/oss/gstosssrc.h
index f787524f..23f7c389 100644
--- a/sys/oss/gstosssrc.h
+++ b/sys/oss/gstosssrc.h
@@ -28,7 +28,7 @@
#include <gst/gst.h>
#include <gst/audio/gstaudiosrc.h>
-#include "gstosselement.h"
+#include "gstosshelper.h"
G_BEGIN_DECLS
@@ -44,8 +44,6 @@ typedef struct _GstOssSrcClass GstOssSrcClass;
struct _GstOssSrc {
GstAudioSrc src;
- GstOssElement *element;
-
gint fd;
gint bytes_per_sample;