diff options
author | Andy Wingo <wingo@pobox.com> | 2005-08-23 13:26:21 +0000 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2005-08-23 13:26:21 +0000 |
commit | d1d21600f86907f1dbd1fe4204be443eeda6cafc (patch) | |
tree | 52725fea0103ecd999811dd30868043a768640d8 /sys/oss/gstosshelper.c | |
parent | ffaaa7528a2348853c1a89963646012f2edba310 (diff) |
sys/oss/gstossmixer.*: Refactored to be more like alsamixer.
Original commit message from CVS:
2005-08-23 Andy Wingo <wingo@pobox.com>
* sys/oss/gstossmixer.h:
* sys/oss/gstossmixer.c: Refactored to be more like alsamixer.
* sys/oss/gstossmixertrack.h:
* sys/oss/gstossmixertrack.c: Split out from gstossmixer.[ch],
like gstalsamixer.
* sys/oss/gstosssrc.c:
* sys/oss/gstosssink.c: Where before we used a gstosselement
object as a helper library, now just call functions from
gstosshelper.
* sys/oss/gstosshelper.h:
* sys/oss/gstosshelper.c: Made a real library. Removed
propertyprobe for now, should add it back later.
* sys/oss/gstosselement.h:
* sys/oss/gstosselement.c: Removed, we don't have a shared base
class.
* sys/oss/gstosshelper.c (gst_oss_helper_probe_caps): Search
higher-to-lower, makes 16 bit appear earlier in the caps, which
makes it preferred.
Diffstat (limited to 'sys/oss/gstosshelper.c')
-rw-r--r-- | sys/oss/gstosshelper.c | 907 |
1 files changed, 45 insertions, 862 deletions
diff --git a/sys/oss/gstosshelper.c b/sys/oss/gstosshelper.c index dfd503e4..987047a9 100644 --- a/sys/oss/gstosshelper.c +++ b/sys/oss/gstosshelper.c @@ -2,8 +2,7 @@ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> * 2000 Wim Taymans <wim.taymans@chello.be> * - * gstosshelper.c: helper functions for easy OSS device handling. - * See gstosshelper.h for details. + * gstosshelper.c: OSS helper routines * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -33,6 +32,7 @@ #include <unistd.h> #include <errno.h> #include <string.h> + #include <sys/soundcard.h> #include <gst/interfaces/propertyprobe.h> @@ -40,822 +40,6 @@ #include "gstosshelper.h" #include "gstossmixer.h" -static void gst_ossprobe_interface_init (GstPropertyProbeInterface * iface); - -static GList *device_combinations = NULL; - -void -gst_oss_add_mixer_type (GType type) -{ - static const GInterfaceInfo ossiface_info = { - (GInterfaceInitFunc) gst_oss_interface_init, - NULL, - NULL - }; - static const GInterfaceInfo ossmixer_info = { - (GInterfaceInitFunc) gst_ossmixer_interface_init, - NULL, - NULL - }; - static const GInterfaceInfo ossprobe_info = { - (GInterfaceInitFunc) gst_ossprobe_interface_init, - NULL, - NULL - }; - - g_type_add_interface_static (type, - GST_TYPE_IMPLEMENTS_INTERFACE, &ossiface_info); - g_type_add_interface_static (type, GST_TYPE_MIXER, &ossmixer_info); - g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE, &ossprobe_info); -} - -void -gst_oss_add_device_properties (GstElementClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_object_class_install_property (gobject_class, OSS_ARG_DEVICE, - g_param_spec_string ("device", "Device", "OSS device (/dev/dspN usually)", - "default", G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, OSS_ARG_MIXER_DEVICE, - g_param_spec_string ("mixerdev", "Mixer device", - "OSS mixer device (/dev/mixerN usually)", - "default", G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, OSS_ARG_DEVICE_NAME, - g_param_spec_string ("device_name", "Device name", "Name of the device", - NULL, G_PARAM_READABLE)); -} - -void -gst_oss_set_device_property (GstElement * element, - GstOssDeviceCombination * c, GstOssDevice * oss, - guint prop_id, GParamSpec * pspec, const GValue * value) -{ - switch (prop_id) { - case OSS_ARG_DEVICE: - /* disallow changing the device while it is opened - get_property("device") should return the right one */ - if (oss->fd == -1) { - g_free (c->dsp); - c->dsp = g_strdup (g_value_get_string (value)); - - /* let's assume that if we have a device map for the mixer, - * we're allowed to do all that automagically here */ - if (device_combinations != NULL) { - GList *list = device_combinations; - - while (list) { - GstOssDeviceCombination *combi = list->data; - - if (!strcmp (combi->dsp, c->dsp)) { - g_free (c->mixer); - c->mixer = g_strdup (combi->mixer); - break; - } - - list = list->next; - } - } - } - break; - case OSS_ARG_MIXER_DEVICE: - /* disallow changing the device while it is opened - get_property("mixerdev") should return the right one */ - if (oss->fd == -1) { - g_free (c->mixer); - c->mixer = g_strdup (g_value_get_string (value)); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (element, prop_id, pspec); - break; - } -} - -void -gst_oss_get_device_property (GstElement * element, GstOssDeviceCombination * c, - GstOssDevice * oss, guint prop_id, GParamSpec * pspec, GValue * value) -{ - switch (prop_id) { - case OSS_ARG_DEVICE: - g_value_set_string (value, c->dsp); - break; - case OSS_ARG_MIXER_DEVICE: - g_value_set_string (value, c->mixer); - break; - case OSS_ARG_DEVICE_NAME: - g_value_set_string (value, oss->device_name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (element, prop_id, pspec); - break; - } -} - -static const GList * -gst_oss_probe_get_properties (GstPropertyProbe * probe) -{ - GObjectClass *klass = G_OBJECT_GET_CLASS (probe); - static GList *list = NULL; - - if (!list) { - list = g_list_append (NULL, g_object_class_find_property (klass, "device")); - } - - return list; -} - -/* OSS (without devfs) allows at max. 16 devices */ -#define MAX_OSS_DEVICES 16 - -static void -gst_oss_do_probe (gchar * device_base, - gint device_num, gchar ** name, dev_t * devno) -{ - gchar *device = NULL; - struct stat s; - - if ((name == NULL) || (devno == NULL)) { - goto end; - } - - *name = NULL; - *devno = 0; - - if (device_num == -1) - device = g_strdup (device_base); - else if ((device_num >= -1) && (device_num <= MAX_OSS_DEVICES)) { - device = g_strdup_printf ("%s%d", device_base, device_num); - } else { - goto end; - } - - if (stat (device, &s) || !S_ISCHR (s.st_mode)) - goto end; - - *name = device; - *devno = s.st_rdev; - return; - -end: - g_free (device); -} - -static GList * -device_combination_append (GList * device_combinations, - GstOssDeviceCombination * combi) -{ - GList *it; - - for (it = device_combinations; it != NULL; it = it->next) { - GstOssDeviceCombination *cur; - - cur = (GstOssDeviceCombination *) it->data; - if (cur->dev == combi->dev) { - return device_combinations; - } - } - - return g_list_append (device_combinations, combi); -} - -static gboolean -gst_oss_probe_devices (GstOssOpenMode mode, gboolean check) -{ - static gboolean init = FALSE; - gint openmode = (mode == GST_OSS_MODE_WRITE) ? O_WRONLY : O_RDONLY; - gboolean do_mixer = (mode == GST_OSS_MODE_VOLUME); - - if (!init && !check) { -#define MIXER 0 -#define DSP 1 - gchar *dev_base[][2] = { {"/dev/mixer", "/dev/dsp"} - , - {"/dev/sound/mixer", "/dev/sound/dsp"} - , - {NULL, NULL} - }; - gint n; - gint base; - - while (device_combinations) { - GList *item = device_combinations; - GstOssDeviceCombination *combi = item->data; - - device_combinations = g_list_remove (device_combinations, item); - - g_free (combi->dsp); - g_free (combi->mixer); - g_free (combi); - } - - /* probe for all /dev entries */ - for (base = 0; dev_base[base][DSP] != NULL; base++) { - gint fd; - - for (n = -1; n < MAX_OSS_DEVICES; n++) { - gchar *dsp = NULL; - gchar *mixer = NULL; - dev_t dsp_dev; - dev_t mixer_dev; - - gst_oss_do_probe (dev_base[base][DSP], n, &dsp, &dsp_dev); - if (dsp == NULL) { - continue; - } - gst_oss_do_probe (dev_base[base][MIXER], n, &mixer, &mixer_dev); - /* does the device exist (can we open them)? */ - - /* we just check the dsp. we assume the mixer always works. - * we don't need a mixer anyway (says OSS)... If we are a - * mixer element, we use the mixer anyway. */ - if ((fd = open (do_mixer ? mixer : - dsp, openmode | O_NONBLOCK)) > 0 || errno == EBUSY) { - GstOssDeviceCombination *combi; - - if (fd > 0) - close (fd); - - /* yay! \o/ */ - combi = g_new0 (GstOssDeviceCombination, 1); - combi->dsp = dsp; - combi->mixer = mixer; - combi->dev = do_mixer ? mixer_dev : dsp_dev; - device_combinations = device_combination_append (device_combinations, - combi); - } else { - g_free (dsp); - g_free (mixer); - } - } - } - - init = TRUE; - } - - return init; -} - -static GValueArray * -gst_oss_probe_list_devices (void) -{ - GValueArray *array; - GValue value = { 0 }; - GList *item; - - if (!device_combinations) - return NULL; - - array = g_value_array_new (g_list_length (device_combinations)); - item = device_combinations; - g_value_init (&value, G_TYPE_STRING); - while (item) { - GstOssDeviceCombination *combi = item->data; - - g_value_set_string (&value, combi->dsp); - g_value_array_append (array, &value); - - item = item->next; - } - g_value_unset (&value); - - return array; -} - -static void -gst_oss_probe_property (GstPropertyProbe * probe, - guint prop_id, const GParamSpec * pspec) -{ - GstOssDevice *oss = g_object_get_data (G_OBJECT (probe), "oss-data"); - - switch (prop_id) { - case OSS_ARG_DEVICE: - gst_oss_probe_devices (oss ? oss->mode : GST_OSS_MODE_READ, FALSE); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); - break; - } -} - -static gboolean -gst_oss_needs_probe (GstPropertyProbe * probe, - guint prop_id, const GParamSpec * pspec) -{ - GstOssDevice *oss = g_object_get_data (G_OBJECT (probe), "oss-data"); - gboolean ret = FALSE; - - switch (prop_id) { - case OSS_ARG_DEVICE: - ret = !gst_oss_probe_devices (oss ? oss->mode : GST_OSS_MODE_READ, TRUE); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); - break; - } - - return ret; -} - -static GValueArray * -gst_oss_probe_get_values (GstPropertyProbe * probe, - guint prop_id, const GParamSpec * pspec) -{ - GValueArray *array = NULL; - - switch (prop_id) { - case OSS_ARG_DEVICE: - array = gst_oss_probe_list_devices (); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); - break; - } - - return array; -} - -static void -gst_ossprobe_interface_init (GstPropertyProbeInterface * iface) -{ - iface->get_properties = gst_oss_probe_get_properties; - iface->probe_property = gst_oss_probe_property; - iface->needs_probe = gst_oss_needs_probe; - iface->get_values = gst_oss_probe_get_values; -} - -void -gst_oss_init (GObject * obj, GstOssDeviceCombination * c, GstOssDevice * oss, - GstOssOpenMode mode) -{ - g_object_set_data (obj, "oss-data", oss); - - c->dsp = g_strdup ("/dev/dsp"); - c->mixer = g_strdup ("/dev/mixer"); - - oss->fd = -1; - oss->mixer_fd = -1; - oss->mode = mode; - - gst_oss_reset (oss); -} - -void -gst_oss_dispose (GstOssDeviceCombination * c, GstOssDevice * oss) -{ - g_free (c->dsp); - c->dsp = NULL; - g_free (c->mixer); - c->mixer = NULL; -} - -void -gst_oss_reset (GstOssDevice * oss) -{ - oss->law = 0; - oss->endianness = G_BYTE_ORDER; - oss->sign = TRUE; - oss->width = 16; - oss->depth = 16; - oss->channels = 2; - oss->rate = 44100; - oss->fragment = 0; - oss->bps = 0; - oss->sample_width = 0; - -/* AFMT_*_BE not available on all OSS includes (e.g. FBSD) */ -#ifdef WORDS_BIGENDIAN - oss->format = AFMT_S16_BE; -#else - oss->format = AFMT_S16_LE; -#endif /* WORDS_BIGENDIAN */ -} - -static gboolean -gst_ossformat_get (gint law, gint endianness, gboolean sign, gint width, - gint depth, gint * format, gint * bps) -{ - if (width != depth) - return FALSE; - - *bps = 1; - - if (law == 0) { - if (width == 16) { - if (sign == TRUE) { - if (endianness == G_LITTLE_ENDIAN) { - *format = AFMT_S16_LE; - GST_DEBUG ("16 bit signed LE, no law (%d)", *format); - } else if (endianness == G_BIG_ENDIAN) { - *format = AFMT_S16_BE; - GST_DEBUG ("16 bit signed BE, no law (%d)", *format); - } - } else { - if (endianness == G_LITTLE_ENDIAN) { - *format = AFMT_U16_LE; - GST_DEBUG ("16 bit unsigned LE, no law (%d)", *format); - } else if (endianness == G_BIG_ENDIAN) { - *format = AFMT_U16_BE; - GST_DEBUG ("16 bit unsigned BE, no law (%d)", *format); - } - } - *bps = 2; - } else if (width == 8) { - if (sign == TRUE) { - *format = AFMT_S8; - GST_DEBUG ("8 bit signed, no law (%d)", *format); - } else { - *format = AFMT_U8; - GST_DEBUG ("8 bit unsigned, no law (%d)", *format); - } - *bps = 1; - } - } else if (law == 1) { - *format = AFMT_MU_LAW; - GST_DEBUG ("mu law (%d)", *format); - } else if (law == 2) { - *format = AFMT_A_LAW; - GST_DEBUG ("a law (%d)", *format); - } else { - g_critical ("unknown law"); - return FALSE; - } - - return TRUE; -} - -gboolean -gst_oss_parse_caps (GstOssDevice * oss, const GstCaps * caps) -{ - gint bps, format; - GstStructure *structure; - gboolean res; - - structure = gst_caps_get_structure (caps, 0); - - res = gst_structure_get_int (structure, "width", &oss->width); - res &= gst_structure_get_int (structure, "depth", &oss->depth); - - if (!res || oss->width != oss->depth) - return FALSE; - - res = gst_structure_get_int (structure, "law", &oss->law); - res &= gst_structure_get_int (structure, "endianness", &oss->endianness); - res &= gst_structure_get_boolean (structure, "signed", &oss->sign); - - if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign, - oss->width, oss->depth, &format, &bps)) { - GST_DEBUG ("could not get format"); - return FALSE; - } - - gst_structure_get_int (structure, "channels", &oss->channels); - gst_structure_get_int (structure, "rate", &oss->rate); - - oss->sample_width = bps * oss->channels; - oss->bps = bps * oss->channels * oss->rate; - oss->format = format; - - return TRUE; -} - -#define GET_FIXED_INT(caps, name, dest) \ -G_STMT_START { \ - if (gst_caps_has_fixed_property (caps, name)) \ - gst_structure_get_int (structure, name, dest); \ -} G_STMT_END -#define GET_FIXED_BOOLEAN(caps, name, dest) \ -G_STMT_START { \ - if (gst_caps_has_fixed_property (caps, name)) \ - gst_structure_get_boolean (structure, name, dest); \ -} G_STMT_END - -gboolean -gst_oss_merge_fixed_caps (GstOssDevice * oss, GstCaps * caps) -{ - gint bps, format; - GstStructure *structure; - - structure = gst_caps_get_structure (caps, 0); - - /* peel off fixed stuff from the caps */ - gst_structure_get_int (structure, "law", &oss->law); - gst_structure_get_int (structure, "endianness", &oss->endianness); - gst_structure_get_boolean (structure, "signed", &oss->sign); - gst_structure_get_int (structure, "width", &oss->width); - gst_structure_get_int (structure, "depth", &oss->depth); - - if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign, - oss->width, oss->depth, &format, &bps)) { - return FALSE; - } - - gst_structure_get_int (structure, "rate", &oss->rate); - gst_structure_get_int (structure, "channels", &oss->channels); - - oss->bps = bps * oss->channels * oss->rate; - oss->format = format; - - return TRUE; -} - -gboolean -gst_oss_sync_parms (GstOssDevice * oss) -{ - audio_buf_info space; - int frag; - gint target_format; - gint target_channels; - gint target_rate; - - /* gint fragscale, frag_ln; */ - - if (oss->fd == -1) - return FALSE; - - if ((oss->fragment & 0xFFFF) == 0) { - frag = 0; - } else if (oss->fragment >> 16) { - frag = oss->fragment; - } else { - frag = 0x7FFF0000 | oss->fragment; - } - - GST_INFO - ("oss: setting sound card to %dHz %d format %s (%08x fragment)", - oss->rate, oss->format, (oss->channels == 2) ? "stereo" : "mono", frag); - - if (frag) - ioctl (oss->fd, SNDCTL_DSP_SETFRAGMENT, &frag); - ioctl (oss->fd, SNDCTL_DSP_RESET, 0); - - target_format = oss->format; - target_channels = oss->channels; - target_rate = oss->rate; - - ioctl (oss->fd, SNDCTL_DSP_SETFMT, &oss->format); - ioctl (oss->fd, SNDCTL_DSP_CHANNELS, &oss->channels); - ioctl (oss->fd, SNDCTL_DSP_SPEED, &oss->rate); - - ioctl (oss->fd, SNDCTL_DSP_GETBLKSIZE, &oss->fragment_size); - - if (oss->mode == GST_OSS_MODE_WRITE) { - ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &space); - } else { - ioctl (oss->fd, SNDCTL_DSP_GETISPACE, &space); - } - -#if 0 - /* FIXME: make the current fragment info available somehow - * the current way overrides preset values and that sucks */ - /* calculate new fragment using a poor man's logarithm function */ - fragscale = 1; - frag_ln = 0; - while (fragscale < space.fragsize) { - fragscale <<= 1; - frag_ln++; - } - oss->fragment = space.fragstotal << 16 | frag_ln; -#endif - - GST_INFO ("oss: set sound card to %dHz, %d format, %s " - "(%d bytes buffer, %08x fragment)", - oss->rate, oss->format, - (oss->channels == 2) ? "stereo" : "mono", space.bytes, oss->fragment); - - oss->fragment_time = (GST_SECOND * oss->fragment_size) / oss->bps; - GST_INFO ("fragment time %u %" G_GUINT64_FORMAT, - oss->bps, oss->fragment_time); - - if (target_format != oss->format || - target_channels != oss->channels || target_rate != oss->rate) { - if (target_channels != oss->channels) - g_warning - ("couldn't set the right number of channels (wanted %d, got %d), enjoy the tone difference", - target_channels, oss->channels); - if (target_rate < oss->rate - 1 || target_rate > oss->rate + 1) - g_warning - ("couldn't set the right sample rate (wanted %d, got %d), enjoy the speed difference", - target_rate, oss->rate); - if (target_format != oss->format) - g_warning ("couldn't set requested OSS format, enjoy the noise :)"); - /* we could eventually return FALSE here, or just do some additional tests - * to see that the frequencies don't differ too much etc.. */ - } - return TRUE; -} - -gboolean -gst_oss_open (GstElement * element, - GstOssDeviceCombination * c, GstOssDevice * oss) -{ - gint caps; - - g_return_val_if_fail (oss->fd == -1, FALSE); - GST_INFO ("oss: attempting to open sound device"); - - /* first try to open the sound card */ - if (oss->mode == GST_OSS_MODE_VOLUME) { - goto do_mixer; - } else if (oss->mode == GST_OSS_MODE_WRITE) { - /* open non blocking first so that it returns immediatly with an error - * when we cannot get to the device */ - oss->fd = open (c->dsp, O_WRONLY | O_NONBLOCK); - - if (oss->fd >= 0) { - close (oss->fd); - - /* re-open the sound device in blocking mode */ - oss->fd = open (c->dsp, O_WRONLY); - } - } else { - oss->fd = open (c->dsp, O_RDONLY); - } - - if (oss->fd < 0) { - switch (errno) { - case EBUSY: - GST_ELEMENT_ERROR (element, RESOURCE, BUSY, - (_("OSS device \"%s\" is already in use by another program."), - c->dsp), (NULL)); - break; - case EACCES: - case ETXTBSY: - if (oss->mode == GST_OSS_MODE_WRITE) - GST_ELEMENT_ERROR (element, RESOURCE, OPEN_WRITE, - (_("Could not access device \"%s\", check its permissions."), - c->dsp), GST_ERROR_SYSTEM); - else - GST_ELEMENT_ERROR (element, RESOURCE, OPEN_READ, - (_("Could not access device \"%s\", check its permissions."), - c->dsp), GST_ERROR_SYSTEM); - break; - case ENXIO: - case ENODEV: - case ENOENT: - GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, - (_("Device \"%s\" does not exist."), c->dsp), GST_ERROR_SYSTEM); - break; - default: - if (oss->mode == GST_OSS_MODE_WRITE) - GST_ELEMENT_ERROR (element, RESOURCE, OPEN_WRITE, - (_("Could not open device \"%s\" for writing."), c->dsp), - GST_ERROR_SYSTEM); - else - GST_ELEMENT_ERROR (element, RESOURCE, OPEN_READ, - (_("Could not open device \"%s\" for reading."), c->dsp), - GST_ERROR_SYSTEM); - break; - } - return FALSE; - } - - /* we have it, set the default parameters and go have fun */ - /* set card state */ - ioctl (oss->fd, SNDCTL_DSP_GETCAPS, &caps); - - GST_INFO ("oss: Capabilities %08x", caps); - - if (caps & DSP_CAP_DUPLEX) - GST_INFO ("oss: Full duplex"); - if (caps & DSP_CAP_REALTIME) - GST_INFO ("oss: Realtime"); - if (caps & DSP_CAP_BATCH) - GST_INFO ("oss: Batch"); - if (caps & DSP_CAP_COPROC) - GST_INFO ("oss: Has coprocessor"); - if (caps & DSP_CAP_TRIGGER) - GST_INFO ("oss: Trigger"); - if (caps & DSP_CAP_MMAP) - GST_INFO ("oss: Direct access"); - -#ifdef DSP_CAP_MULTI - if (caps & DSP_CAP_MULTI) - GST_INFO ("oss: Multiple open"); -#endif /* DSP_CAP_MULTI */ - -#ifdef DSP_CAP_BIND - if (caps & DSP_CAP_BIND) - GST_INFO ("oss: Channel binding"); -#endif /* DSP_CAP_BIND */ - - ioctl (oss->fd, SNDCTL_DSP_GETFMTS, &caps); - - GST_INFO ("oss: Formats %08x", caps); - if (caps & AFMT_MU_LAW) - GST_INFO ("oss: MU_LAW"); - if (caps & AFMT_A_LAW) - GST_INFO ("oss: A_LAW"); - if (caps & AFMT_IMA_ADPCM) - GST_INFO ("oss: IMA_ADPCM"); - if (caps & AFMT_U8) - GST_INFO ("oss: U8"); - if (caps & AFMT_S16_LE) - GST_INFO ("oss: S16_LE"); - if (caps & AFMT_S16_BE) - GST_INFO ("oss: S16_BE"); - if (caps & AFMT_S8) - GST_INFO ("oss: S8"); - if (caps & AFMT_U16_LE) - GST_INFO ("oss: U16_LE"); - if (caps & AFMT_U16_BE) - GST_INFO ("oss: U16_BE"); - if (caps & AFMT_MPEG) - GST_INFO ("oss: MPEG"); -#ifdef AFMT_AC3 - if (caps & AFMT_AC3) - GST_INFO ("oss: AC3"); -#endif - - GST_INFO ("oss: opened audio (%s) with fd=%d", c->dsp, oss->fd); - - oss->caps = caps; - -do_mixer: - gst_ossmixer_build_list (c, oss); - - return TRUE; -} - -void -gst_oss_close (GstOssDevice * oss) -{ - gst_ossmixer_free_list (oss); - - if (oss->probed_caps) { - gst_caps_unref (oss->probed_caps); - oss->probed_caps = NULL; - } - - if (oss->fd < 0) - return; - - close (oss->fd); - oss->fd = -1; -} - -gboolean -gst_oss_convert (GstOssDevice * oss, - GstFormat src_format, - gint64 src_value, GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res = TRUE; - - if (src_format == *dest_format) { - *dest_value = src_value; - return TRUE; - } - - if (oss->bps == 0 || oss->channels == 0 || oss->width == 0) - return FALSE; - - switch (src_format) { - case GST_FORMAT_BYTES: - switch (*dest_format) { - case GST_FORMAT_TIME: - *dest_value = src_value * GST_SECOND / oss->bps; - break; - case GST_FORMAT_DEFAULT: - *dest_value = src_value / (oss->width * oss->channels / 8); - break; - default: - res = FALSE; - } - break; - case GST_FORMAT_TIME: - switch (*dest_format) { - case GST_FORMAT_BYTES: - *dest_value = src_value * oss->bps / GST_SECOND; - break; - case GST_FORMAT_DEFAULT: - *dest_value = src_value * oss->rate / GST_SECOND; - break; - default: - res = FALSE; - } - break; - case GST_FORMAT_DEFAULT: - switch (*dest_format) { - case GST_FORMAT_TIME: - *dest_value = src_value * GST_SECOND / oss->rate; - break; - case GST_FORMAT_BYTES: - *dest_value = src_value * oss->width * oss->channels / 8; - break; - default: - res = FALSE; - } - break; - default: - res = FALSE; - } - - return res; -} - -/* rate probing code */ - - #if 0 #ifdef HAVE_OSS_INCLUDE_IN_SYS @@ -878,7 +62,7 @@ gst_oss_convert (GstOssDevice * oss, #include <stdlib.h> #include <sys/ioctl.h> #include <glib.h> -#endif +#endif /* 0 */ typedef struct _GstOssProbe GstOssProbe; struct _GstOssProbe @@ -898,15 +82,16 @@ struct _GstOssRange int max; }; -static GstStructure *gst_oss_get_format_structure (unsigned int format_bit); -static gboolean gst_oss_rate_probe_check (GstOssProbe * probe); -static int gst_oss_rate_check_rate (GstOssProbe * probe, int irate); -static void gst_oss_rate_add_range (GQueue * queue, int min, int max); -static void gst_oss_rate_add_rate (GArray * array, int rate); -static int gst_oss_rate_int_compare (gconstpointer a, gconstpointer b); +static GstStructure *gst_oss_helper_get_format_structure (unsigned int + format_bit); +static gboolean gst_oss_helper_rate_probe_check (GstOssProbe * probe); +static int gst_oss_helper_rate_check_rate (GstOssProbe * probe, int irate); +static void gst_oss_helper_rate_add_range (GQueue * queue, int min, int max); +static void gst_oss_helper_rate_add_rate (GArray * array, int rate); +static int gst_oss_helper_rate_int_compare (gconstpointer a, gconstpointer b); -void -gst_oss_probe_caps (GstOssDevice * oss) +GstCaps * +gst_oss_helper_probe_caps (gint fd) { GstOssProbe *probe; int i; @@ -916,31 +101,29 @@ gst_oss_probe_caps (GstOssDevice * oss) unsigned int format_mask; GstCaps *caps; - if (oss->probed_caps != NULL) - return; - if (oss->fd == -1) - return; - /* FIXME test make sure we're not currently playing */ /* FIXME test both mono and stereo */ - format_mask = AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_S8 | - AFMT_U16_LE | AFMT_U16_BE; - format_mask &= oss->caps; + format_mask = AFMT_U8 | AFMT_S8; + + if (G_BYTE_ORDER == G_LITTLE_ENDIAN) + format_mask |= AFMT_S16_LE | AFMT_U16_LE; + else + format_mask |= AFMT_S16_BE | AFMT_U16_BE; caps = gst_caps_new_empty (); /* assume that the most significant bit of format_mask is 0 */ - for (format_bit = 1; format_bit <= format_mask; format_bit <<= 1) { + for (format_bit = 1 << 31; format_bit > 0; format_bit >>= 1) { if (format_bit & format_mask) { GValue rate_value = { 0 }; probe = g_new0 (GstOssProbe, 1); - probe->fd = oss->fd; + probe->fd = fd; probe->format = format_bit; probe->n_channels = 2; - ret = gst_oss_rate_probe_check (probe); + ret = gst_oss_helper_rate_probe_check (probe); if (probe->min == -1 || probe->max == -1) { g_array_free (probe->rates, TRUE); g_free (probe); @@ -950,7 +133,7 @@ gst_oss_probe_caps (GstOssDevice * oss) if (ret) { GValue value = { 0 }; - g_array_sort (probe->rates, gst_oss_rate_int_compare); + g_array_sort (probe->rates, gst_oss_helper_rate_int_compare); g_value_init (&rate_value, GST_TYPE_LIST); g_value_init (&value, G_TYPE_INT); @@ -971,7 +154,7 @@ gst_oss_probe_caps (GstOssDevice * oss) g_array_free (probe->rates, TRUE); g_free (probe); - structure = gst_oss_get_format_structure (format_bit); + structure = gst_oss_helper_get_format_structure (format_bit); gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_structure_set_value (structure, "rate", &rate_value); g_value_unset (&rate_value); @@ -980,17 +163,17 @@ gst_oss_probe_caps (GstOssDevice * oss) } } - if (gst_caps_is_empty (caps)) { - GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, - (_("Your OSS device could not be probed correctly")), (NULL)); - return; - } + if (gst_caps_is_empty (caps)) + /* fixme: make user-visible */ + g_critical ("Your OSS device could not be probed correctly"); + GST_DEBUG ("probed caps: %" GST_PTR_FORMAT, caps); - oss->probed_caps = caps; + + return caps; } static GstStructure * -gst_oss_get_format_structure (unsigned int format_bit) +gst_oss_helper_get_format_structure (unsigned int format_bit) { GstStructure *structure; int endianness; @@ -1045,7 +228,7 @@ gst_oss_get_format_structure (unsigned int format_bit) } static gboolean -gst_oss_rate_probe_check (GstOssProbe * probe) +gst_oss_helper_rate_probe_check (GstOssProbe * probe) { GstOssRange *range; GQueue *ranges; @@ -1058,14 +241,14 @@ gst_oss_rate_probe_check (GstOssProbe * probe) probe->rates = g_array_new (FALSE, FALSE, sizeof (int)); - probe->min = gst_oss_rate_check_rate (probe, 1000); + probe->min = gst_oss_helper_rate_check_rate (probe, 1000); n_checks++; - probe->max = gst_oss_rate_check_rate (probe, 100000); + probe->max = gst_oss_helper_rate_check_rate (probe, 100000); /* a little bug workaround */ { int max; - max = gst_oss_rate_check_rate (probe, 48000); + max = gst_oss_helper_rate_check_rate (probe, 48000); if (max > probe->max) { GST_ERROR ("Driver bug recognized (driver does not round rates correctly). Please file a bug report."); @@ -1078,14 +261,14 @@ gst_oss_rate_probe_check (GstOssProbe * probe) * error) for rates outside of [8000,48000]. If this fails, the * driver is seriously buggy, and probably doesn't work with other * media libraries/apps. */ - probe->min = gst_oss_rate_check_rate (probe, 8000); - probe->max = gst_oss_rate_check_rate (probe, 48000); + probe->min = gst_oss_helper_rate_check_rate (probe, 8000); + probe->max = gst_oss_helper_rate_check_rate (probe, 48000); } if (probe->min == -1 || probe->max == -1) { GST_DEBUG ("unexpected check_rate error"); return FALSE; } - gst_oss_rate_add_range (ranges, probe->min + 1, probe->max - 1); + gst_oss_helper_rate_add_range (ranges, probe->min + 1, probe->max - 1); while ((range = g_queue_pop_head (ranges))) { int min1; @@ -1096,7 +279,7 @@ gst_oss_rate_probe_check (GstOssProbe * probe) GST_DEBUG ("checking [%d,%d]", range->min, range->max); mid = (range->min + range->max) / 2; - mid_ret = gst_oss_rate_check_rate (probe, mid); + mid_ret = gst_oss_helper_rate_check_rate (probe, mid); if (mid_ret == -1) { /* FIXME ioctl returned an error. do something */ GST_DEBUG ("unexpected check_rate error"); @@ -1133,8 +316,8 @@ gst_oss_rate_probe_check (GstOssProbe * probe) } } - gst_oss_rate_add_range (ranges, range->min, min1); - gst_oss_rate_add_range (ranges, max1, range->max); + gst_oss_helper_rate_add_range (ranges, range->min, min1); + gst_oss_helper_rate_add_range (ranges, max1, range->max); g_free (range); } @@ -1148,7 +331,7 @@ gst_oss_rate_probe_check (GstOssProbe * probe) } static void -gst_oss_rate_add_range (GQueue * queue, int min, int max) +gst_oss_helper_rate_add_range (GQueue * queue, int min, int max) { if (min <= max) { GstOssRange *range = g_new0 (GstOssRange, 1); @@ -1163,7 +346,7 @@ gst_oss_rate_add_range (GQueue * queue, int min, int max) } static int -gst_oss_rate_check_rate (GstOssProbe * probe, int irate) +gst_oss_helper_rate_check_rate (GstOssProbe * probe, int irate) { int rate; int format; @@ -1191,12 +374,12 @@ gst_oss_rate_check_rate (GstOssProbe * probe, int irate) if (rate == irate - 1 || rate == irate + 1) { rate = irate; } - gst_oss_rate_add_rate (probe->rates, rate); + gst_oss_helper_rate_add_rate (probe->rates, rate); return rate; } static void -gst_oss_rate_add_rate (GArray * array, int rate) +gst_oss_helper_rate_add_rate (GArray * array, int rate) { int i; int val; @@ -1212,7 +395,7 @@ gst_oss_rate_add_rate (GArray * array, int rate) } static int -gst_oss_rate_int_compare (gconstpointer a, gconstpointer b) +gst_oss_helper_rate_int_compare (gconstpointer a, gconstpointer b) { const int *va = (const int *) a; const int *vb = (const int *) b; |