sys/oss/gstossmixer.*: Refactored to be more like alsamixer.
authorAndy Wingo <wingo@pobox.com>
Tue, 23 Aug 2005 13:26:21 +0000 (13:26 +0000)
committerAndy Wingo <wingo@pobox.com>
Tue, 23 Aug 2005 13:26:21 +0000 (13:26 +0000)
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.

15 files changed:
sys/oss/Makefile.am
sys/oss/gstossaudio.c
sys/oss/gstossdmabuffer.h
sys/oss/gstosselement.c [deleted file]
sys/oss/gstosselement.h [deleted file]
sys/oss/gstosshelper.c
sys/oss/gstosshelper.h
sys/oss/gstossmixer.c
sys/oss/gstossmixer.h
sys/oss/gstossmixertrack.c [new file with mode: 0644]
sys/oss/gstossmixertrack.h [new file with mode: 0644]
sys/oss/gstosssink.c
sys/oss/gstosssink.h
sys/oss/gstosssrc.c
sys/oss/gstosssrc.h

index d298b7c..d4fc239 100644 (file)
@@ -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
 
index 65cf703..219a036 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "gst/gst-i18n-plugin.h"
 
-#include "gstosselement.h"
 #include "gstosssink.h"
 #include "gstosssrc.h"
 
index 3a2c6ea..fef2492 100644 (file)
@@ -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 (file)
index 5b59bd7..0000000
+++ /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 (file)
index b895d42..0000000
+++ /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__ */
index dfd503e..987047a 100644 (file)
@@ -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>
 #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;
index 9b7eebd..1593fe3 100644 (file)
@@ -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
  * 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__ */
index 1d46290..1e97256 100644 (file)
 #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;
-}
index 2eede0e..c5a8f32 100644 (file)
  * 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 (file)
index 0000000..48e4a9d
--- /dev/null
@@ -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 (file)
index 0000000..1350a02
--- /dev/null
@@ -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__ */
index efef1ba..a98efab 100644 (file)
@@ -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;
index 7f48811..3cede59 100644 (file)
@@ -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;
 };
index e7a5cda..2c41365 100644 (file)
@@ -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;
index f787524..23f7c38 100644 (file)
@@ -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;