Commit a5ff454e authored by Mark Nauwelaerts's avatar Mark Nauwelaerts
Browse files

oss4: port to 0.11

parent c4c3736e
......@@ -310,7 +310,6 @@ dnl Non ported plugins (non-dependant, then dependant)
dnl Make sure you have a space before and after all plugins
GST_PLUGINS_NONPORTED="deinterlace \
cairo cairo_gobject gdk_pixbuf \
oss4 \
osx_video osx_audio "
AC_SUBST(GST_PLUGINS_NONPORTED)
......
......@@ -191,7 +191,6 @@ EXTRA_HFILES = \
$(top_srcdir)/gst/wavparse/gstwavparse.h \
$(top_srcdir)/gst/y4m/gsty4mencode.h \
$(top_srcdir)/sys/directsound/gstdirectsoundsink.h \
$(top_srcdir)/sys/oss4/oss4-mixer.h \
$(top_srcdir)/sys/oss4/oss4-sink.h \
$(top_srcdir)/sys/oss4/oss4-source.h \
$(top_srcdir)/sys/oss/gstosssink.h \
......
......@@ -111,7 +111,6 @@
<xi:include href="xml/element-multipartmux.xml" />
<xi:include href="xml/element-multiudpsink.xml" />
<xi:include href="xml/element-optv.xml" />
<xi:include href="xml/element-oss4mixer.xml" />
<xi:include href="xml/element-oss4sink.xml" />
<xi:include href="xml/element-oss4src.xml" />
<xi:include href="xml/element-osssink.xml" />
......
......@@ -1396,30 +1396,6 @@ GST_IS_MULTIUDPSINK_CLASS
gst_multiudpsink_get_type
</SECTION>
<SECTION>
<FILE>element-oss4mixer</FILE>
<TITLE>oss4mixer</TITLE>
GstOss4Mixer
<SUBSECTION Standard>
GstOss4MixerClass
GST_OSS4_MIXER
GST_OSS4_MIXER_CLASS
GST_IS_OSS4_MIXER
GST_IS_OSS4_MIXER_CLASS
GST_TYPE_OSS4_MIXER
gst_oss4_mixer_get_type
GST_OSS4_MIXER_CAST
GST_OSS4_MIXER_IS_OPEN
MIXEXT_ENUM_IS_AVAILABLE
MIXEXT_HAS_DESCRIPTION
MIXEXT_IS_ROOT
MIXEXT_IS_SLIDER
gst_oss4_mixer_get_control_val
gst_oss4_mixer_set_control_val
gst_oss4_source_input_get_type
GstOss4MixerControl
</SECTION>
<SECTION>
<FILE>element-oss4sink</FILE>
<TITLE>oss4sink</TITLE>
......
......@@ -2,10 +2,6 @@ plugin_LTLIBRARIES = libgstoss4audio.la
libgstoss4audio_la_SOURCES = \
oss4-audio.c \
oss4-mixer.c \
oss4-mixer-enum.c \
oss4-mixer-slider.c \
oss4-mixer-switch.c \
oss4-property-probe.c \
oss4-sink.c \
oss4-source.c
......@@ -13,7 +9,6 @@ libgstoss4audio_la_SOURCES = \
libgstoss4audio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
libgstoss4audio_la_LIBADD = \
$(GST_PLUGINS_BASE_LIBS) \
-lgstinterfaces-$(GST_API_VERSION) \
-lgstaudio-$(GST_API_VERSION) \
$(GST_LIBS)
libgstoss4audio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
......@@ -21,13 +16,8 @@ libgstoss4audio_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = \
oss4-audio.h \
oss4-mixer.h \
oss4-mixer-enum.h \
oss4-mixer-slider.h \
oss4-mixer-switch.h \
oss4-property-probe.h \
oss4-sink.h \
oss4-soundcard.h \
oss4-source.h
......@@ -33,10 +33,9 @@
#include <string.h>
#include "gst/gst-i18n-plugin.h"
#include <gst/audio/multichannel.h>
#include <gst/audio/audio.h>
#include "oss4-audio.h"
#include "oss4-mixer.h"
#include "oss4-property-probe.h"
#include "oss4-sink.h"
#include "oss4-source.h"
......@@ -51,33 +50,42 @@ GST_DEBUG_CATEGORY (oss4_debug);
typedef struct
{
const GstBufferFormat gst_fmt;
const GstAudioRingBufferFormatType gst_rbfmt;
const GstAudioFormat gst_rfmt;
const gint oss_fmt;
const gchar name[16];
const gint depth;
const gint width;
const gint endianness;
const gboolean signedness;
} GstOss4AudioFormat;
/* *INDENT-OFF* */
static const GstOss4AudioFormat fmt_map[] = {
/* note: keep sorted by preference, prefered formats first */
{
GST_MU_LAW, AFMT_MU_LAW, "audio/x-mulaw", 0, 0, 0, FALSE}, {
GST_A_LAW, AFMT_A_LAW, "audio/x-alaw", 0, 0, 0, FALSE}, {
GST_S32_LE, AFMT_S32_LE, "audio/x-raw-int", 32, 32, G_LITTLE_ENDIAN, TRUE}, {
GST_S32_BE, AFMT_S32_BE, "audio/x-raw-int", 32, 32, G_BIG_ENDIAN, TRUE}, {
GST_S24_LE, AFMT_S24_LE, "audio/x-raw-int", 24, 32, G_LITTLE_ENDIAN, TRUE}, {
GST_S24_BE, AFMT_S24_BE, "audio/x-raw-int", 24, 32, G_BIG_ENDIAN, TRUE}, {
GST_S24_3LE, AFMT_S24_PACKED, "audio/x-raw-int", 24, 24, G_LITTLE_ENDIAN,
TRUE}, {
GST_S16_LE, AFMT_S16_LE, "audio/x-raw-int", 16, 16, G_LITTLE_ENDIAN, TRUE}, {
GST_S16_BE, AFMT_S16_BE, "audio/x-raw-int", 16, 16, G_BIG_ENDIAN, TRUE}, {
GST_U16_LE, AFMT_U16_LE, "audio/x-raw-int", 16, 16, G_LITTLE_ENDIAN, FALSE}, {
GST_U16_BE, AFMT_U16_BE, "audio/x-raw-int", 16, 16, G_BIG_ENDIAN, FALSE}, {
GST_S8, AFMT_S8, "audio/x-raw-int", 8, 8, 0, TRUE}, {
GST_U8, AFMT_U8, "audio/x-raw-int", 8, 8, 0, FALSE}
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW, 0,
AFMT_MU_LAW, "audio/x-mulaw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW, 0,
AFMT_A_LAW, "audio/x-alaw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S32LE,
AFMT_S32_LE, "audio/x-raw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S32BE,
AFMT_S32_BE, "audio/x-raw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S24_32LE,
AFMT_S24_LE, "audio/x-raw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S24_32BE,
AFMT_S24_BE, "audio/x-raw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S24LE,
AFMT_S24_PACKED, "audio/x-raw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S16LE,
AFMT_S16_LE, "audio/x-raw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S16BE,
AFMT_S16_BE, "audio/x-raw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_U16LE,
AFMT_U16_LE, "audio/x-raw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_U16BE,
AFMT_U16_BE, "audio/x-raw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_S8,
AFMT_S8, "audio/x-raw"}, {
GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, GST_AUDIO_FORMAT_U8,
AFMT_U8, "audio/x-raw"}
};
/* *INDENT-ON* */
......@@ -96,24 +104,23 @@ gst_oss4_append_format_to_caps (const GstOss4AudioFormat * fmt, GstCaps * caps)
{
GstStructure *s;
s = gst_structure_empty_new (fmt->name);
if (fmt->width != 0 && fmt->depth != 0) {
gst_structure_set (s, "width", G_TYPE_INT, fmt->width, "depth", G_TYPE_INT,
fmt->depth, "signed", G_TYPE_BOOLEAN, fmt->signedness, NULL);
}
if (fmt->endianness != 0) {
gst_structure_set (s, "endianness", G_TYPE_INT, fmt->endianness, NULL);
s = gst_structure_new_empty (fmt->name);
if (fmt->gst_rbfmt == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) {
gst_structure_set (s, "format", G_TYPE_STRING,
gst_audio_format_to_string (fmt->gst_rfmt),
"layout", G_TYPE_STRING, "interleaved", NULL);
}
gst_caps_append_structure (caps, s);
}
static gint
gst_oss4_audio_get_oss_format (GstBufferFormat fmt)
gst_oss4_audio_get_oss_format (GstAudioRingBufferFormatType fmt,
GstAudioFormat rfmt)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
if (fmt_map[i].gst_fmt == fmt)
if (fmt_map[i].gst_rbfmt == fmt && fmt_map[i].gst_rfmt == rfmt)
return fmt_map[i].oss_fmt;
}
return 0;
......@@ -200,15 +207,15 @@ gst_oss4_audio_detect_rates (GstObject * obj, oss_audioinfo * ai,
}
static void
gst_oss4_audio_add_channel_layout (GstObject * obj, guint64 layout,
guint num_channels, GstStructure * s)
gst_oss4_audio_get_channel_layout (GstObject * obj, guint64 layout,
guint num_channels, GstAudioChannelPosition * ch_layout)
{
const GstAudioChannelPosition pos_map[16] = {
GST_AUDIO_CHANNEL_POSITION_NONE, /* 0 = dunno */
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, /* 1 = left */
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, /* 2 = right */
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, /* 3 = center */
GST_AUDIO_CHANNEL_POSITION_LFE, /* 4 = lfe */
GST_AUDIO_CHANNEL_POSITION_LFE1, /* 4 = lfe */
GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, /* 5 = left surround */
GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, /* 6 = right surround */
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, /* 7 = left rear */
......@@ -221,12 +228,9 @@ gst_oss4_audio_add_channel_layout (GstObject * obj, guint64 layout,
GST_AUDIO_CHANNEL_POSITION_NONE,
GST_AUDIO_CHANNEL_POSITION_NONE
};
GstAudioChannelPosition ch_layout[8] = { 0, };
guint speaker_pos; /* speaker position as defined by OSS */
guint i;
g_return_if_fail (num_channels <= G_N_ELEMENTS (ch_layout));
for (i = 0; i < num_channels; ++i) {
/* layout contains up to 16 speaker positions, with each taking up 4 bits */
speaker_pos = (guint) ((layout >> (i * 4)) & 0x0f);
......@@ -238,7 +242,7 @@ gst_oss4_audio_add_channel_layout (GstObject * obj, guint64 layout,
ch_layout[i] = pos_map[speaker_pos];
}
gst_audio_set_channel_positions (s, ch_layout);
return;
no_layout:
......@@ -253,11 +257,64 @@ no_layout:
for (i = 0; i < num_channels; ++i) {
ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
}
gst_audio_set_channel_positions (s, ch_layout);
return;
}
}
static void
gst_oss4_audio_set_ringbuffer_channel_layout (GstObject * obj, gint fd,
GstAudioRingBufferSpec * spec)
{
guint num_channels;
guint64 layout = 0;
GstAudioRingBuffer *rb;
GstAudioChannelPosition ch_layout[8] = { 0, };
num_channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
if (num_channels < 3 || num_channels > 9)
return;
if (spec->type != GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW)
return;
if (GST_IS_OSS4_SINK (obj)) {
rb = GST_AUDIO_BASE_SINK (obj)->ringbuffer;
} else if (GST_IS_OSS4_SOURCE (obj)) {
rb = GST_AUDIO_BASE_SRC (obj)->ringbuffer;
} else
g_assert_not_reached ();
/* -1 = get info for currently open device (fd). This will fail with
* OSS build <= 1013 because of a bug in OSS */
if (ioctl (fd, SNDCTL_DSP_GET_CHNORDER, &layout) == -1) {
GST_WARNING_OBJECT (obj, "couldn't query channel layout, assuming default");
layout = CHNORDER_NORMAL;
}
GST_DEBUG_OBJECT (obj, "channel layout: %08" G_GINT64_MODIFIER "x", layout);
gst_oss4_audio_get_channel_layout (obj, layout, num_channels, ch_layout);
gst_audio_ring_buffer_set_channel_positions (rb, ch_layout);
return;
}
static void
gst_oss4_audio_add_channel_layout (GstObject * obj, guint64 layout,
guint num_channels, GstStructure * s)
{
GstAudioChannelPosition ch_layout[8] = { 0, };
guint64 mask;
g_return_if_fail (num_channels <= G_N_ELEMENTS (ch_layout));
gst_oss4_audio_get_channel_layout (obj, layout, num_channels, ch_layout);
if (gst_audio_channel_positions_to_mask (ch_layout, num_channels, &mask))
gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK, mask, NULL);
return;
}
/* arbitrary max. limit */
#define GST_OSS4_MIN_CHANNELS 1
#define GST_OSS4_MAX_CHANNELS 4096
......@@ -403,8 +460,8 @@ done:
chan_s = gst_caps_get_structure (chan_caps, j);
if ((val = gst_structure_get_value (chan_s, "channels")))
gst_structure_set_value (s, "channels", val);
if ((val = gst_structure_get_value (chan_s, "channel-positions")))
gst_structure_set_value (s, "channel-positions", val);
if ((val = gst_structure_get_value (chan_s, "channel-mask")))
gst_structure_set_value (s, "channel-mask", val);
gst_caps_append_structure (out_caps, s);
s = NULL;
......@@ -458,7 +515,7 @@ gst_oss4_audio_probe_caps (GstObject * obj, int fd)
}
}
caps = gst_caps_do_simplify (caps);
caps = gst_caps_simplify (caps);
GST_LOG_OBJECT (obj, "formats: %" GST_PTR_FORMAT, caps);
if (!gst_oss4_audio_detect_rates (obj, &ai, caps))
......@@ -505,7 +562,7 @@ gst_oss4_audio_get_template_caps (void)
gst_oss4_append_format_to_caps (&fmt_map[i], caps);
}
caps = gst_caps_do_simplify (caps);
caps = gst_caps_simplify (caps);
for (i = 0; i < gst_caps_get_size (caps); ++i) {
GstStructure *s;
......@@ -521,17 +578,25 @@ gst_oss4_audio_get_template_caps (void)
/* called by gst_oss4_sink_prepare() and gst_oss4_source_prepare() */
gboolean
gst_oss4_audio_set_format (GstObject * obj, int fd, GstRingBufferSpec * spec)
gst_oss4_audio_set_format (GstObject * obj, int fd,
GstAudioRingBufferSpec * spec)
{
struct audio_buf_info info = { 0, };
int fmt, chans, rate;
int ofmt, fmt, chans, rate, width;
fmt = gst_oss4_audio_get_oss_format (spec->type,
GST_AUDIO_INFO_FORMAT (&spec->info));
fmt = gst_oss4_audio_get_oss_format (spec->format);
if (fmt == 0)
goto wrong_format;
if (spec->type == GST_BUFTYPE_LINEAR && spec->width != 32 &&
spec->width != 24 && spec->width != 16 && spec->width != 8) {
ofmt = fmt;
chans = GST_AUDIO_INFO_CHANNELS (&spec->info);
rate = GST_AUDIO_INFO_RATE (&spec->info);
width = GST_AUDIO_INFO_WIDTH (&spec->info);
if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW &&
width != 32 && width != 24 && width != 16 && width != 8) {
goto dodgy_width;
}
......@@ -541,14 +606,12 @@ gst_oss4_audio_set_format (GstObject * obj, int fd, GstRingBufferSpec * spec)
goto set_format_failed;
/* channels */
GST_LOG_OBJECT (obj, "setting channels: %d", spec->channels);
chans = spec->channels;
GST_LOG_OBJECT (obj, "setting channels: %d", chans);
if (ioctl (fd, SNDCTL_DSP_CHANNELS, &chans) == -1)
goto set_channels_failed;
/* rate */
GST_LOG_OBJECT (obj, "setting rate: %d", spec->rate);
rate = spec->rate;
GST_LOG_OBJECT (obj, "setting rate: %d", rate);
if (ioctl (fd, SNDCTL_DSP_SPEED, &rate) == -1)
goto set_rate_failed;
......@@ -557,8 +620,8 @@ gst_oss4_audio_set_format (GstObject * obj, int fd, GstRingBufferSpec * spec)
GST_DEBUG_OBJECT (obj, "effective rate : %d", rate);
/* make sure format, channels, and rate are the ones we requested */
if (fmt != gst_oss4_audio_get_oss_format (spec->format) ||
chans != spec->channels || rate != spec->rate) {
if (fmt != ofmt || chans != GST_AUDIO_INFO_CHANNELS (&spec->info) ||
rate != GST_AUDIO_INFO_RATE (&spec->info)) {
/* This shouldn't happen, but hey */
goto format_not_what_was_requested;
}
......@@ -579,24 +642,25 @@ gst_oss4_audio_set_format (GstObject * obj, int fd, GstRingBufferSpec * spec)
* being too large, and the buffer will wrap. */
spec->segtotal = info.fragstotal + 4;
spec->bytes_per_sample = (spec->width / 8) * spec->channels;
GST_DEBUG_OBJECT (obj, "got segsize: %d, segtotal: %d, value: %08x",
spec->segsize, spec->segtotal, info.fragsize);
gst_oss4_audio_set_ringbuffer_channel_layout (obj, fd, spec);
return TRUE;
/* ERRORS */
wrong_format:
{
GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
("Unable to get format %d", spec->format));
("Unable to get format (%d, %d)", spec->type,
GST_AUDIO_INFO_FORMAT (&spec->info)));
return FALSE;
}
dodgy_width:
{
GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
("unexpected width %d", spec->width));
("unexpected width %d", width));
return FALSE;
}
set_format_failed:
......@@ -664,8 +728,7 @@ gst_oss4_audio_find_device (GstObject * oss)
GValueArray *arr;
gchar *ret = NULL;
arr = gst_property_probe_probe_and_get_values_name (GST_PROPERTY_PROBE (oss),
"device");
arr = gst_oss4_property_probe_get_values (GST_OBJECT (oss), "device");
if (arr != NULL) {
if (arr->n_values > 0) {
......@@ -703,8 +766,7 @@ plugin_init (GstPlugin * plugin)
rank = GST_RANK_SECONDARY + 1;
if (!gst_element_register (plugin, "oss4sink", rank, GST_TYPE_OSS4_SINK) ||
!gst_element_register (plugin, "oss4src", rank, GST_TYPE_OSS4_SOURCE) ||
!gst_element_register (plugin, "oss4mixer", rank, GST_TYPE_OSS4_MIXER)) {
!gst_element_register (plugin, "oss4src", rank, GST_TYPE_OSS4_SOURCE)) {
return FALSE;
}
......
......@@ -21,7 +21,7 @@
#define GST_OSS4_AUDIO_H_
#include <gst/gst.h>
#include <gst/audio/gstringbuffer.h>
#include <gst/audio/gstaudioringbuffer.h>
/* This is the minimum version we require */
#define GST_MIN_OSS4_VERSION 0x040003
......@@ -32,7 +32,7 @@ gboolean gst_oss4_audio_check_version (GstObject * obj, int fd);
GstCaps * gst_oss4_audio_probe_caps (GstObject * obj, int fd);
gboolean gst_oss4_audio_set_format (GstObject * obj, int fd, GstRingBufferSpec * spec);
gboolean gst_oss4_audio_set_format (GstObject * obj, int fd, GstAudioRingBufferSpec * spec);
GstCaps * gst_oss4_audio_get_template_caps (void);
......
/* GStreamer OSS4 mixer enumeration control
* Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/* An 'enum' in gnome-volume-control / GstMixer is represented by a
* GstMixerOptions object
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst-i18n-plugin.h>
#define NO_LEGACY_MIXER
#include "oss4-mixer.h"
#include "oss4-mixer-enum.h"
#include "oss4-soundcard.h"
GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug);
#define GST_CAT_DEFAULT oss4mixer_debug
static GList *gst_oss4_mixer_enum_get_values (GstMixerOptions * options);
/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */
G_DEFINE_TYPE (GstOss4MixerEnum, gst_oss4_mixer_enum, GST_TYPE_MIXER_OPTIONS);
static void
gst_oss4_mixer_enum_init (GstOss4MixerEnum * e)
{
e->need_update = TRUE;
}
static void
gst_oss4_mixer_enum_dispose (GObject * obj)
{
GstMixerOptions *options = GST_MIXER_OPTIONS (obj);
/* our list is a flat list with constant strings, but the GstMixerOptions
* dispose will try to g_free the contained strings, so clean up the list
* before chaining up to GstMixerOptions */
g_list_free (options->values);
options->values = NULL;
G_OBJECT_CLASS (gst_oss4_mixer_enum_parent_class)->dispose (obj);
}
static void
gst_oss4_mixer_enum_class_init (GstOss4MixerEnumClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GstMixerOptionsClass *mixeroptions_class = (GstMixerOptionsClass *) klass;
gobject_class->dispose = gst_oss4_mixer_enum_dispose;
mixeroptions_class->get_values = gst_oss4_mixer_enum_get_values;
}
static GList *
gst_oss4_mixer_enum_get_values_locked (GstMixerOptions * options)
{
GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM_CAST (options);
GList *oldlist, *list = NULL;
int i;
/* if current list of values is empty, update/re-check in any case */
if (!e->need_update && options->values != NULL)
return options->values;
GST_LOG_OBJECT (e, "updating available values for %s", e->mc->mixext.extname);
for (i = 0; i < e->mc->mixext.maxvalue; ++i) {
const gchar *s;
s = g_quark_to_string (e->mc->enum_vals[i]);
if (MIXEXT_ENUM_IS_AVAILABLE (e->mc->mixext, i)) {
GST_LOG_OBJECT (e, "option '%s' is available", s);
list = g_list_prepend (list, (gpointer) s);
} else {
GST_LOG_OBJECT (e, "option '%s' is currently not available", s);
}
}
list = g_list_reverse (list);
/* this is not thread-safe, but then the entire GstMixer API isn't really,
* since we return foo->list and not a copy and don't take any locks, so
* not much we can do here but pray; we're usually either called from _new()
* or from within _get_values() though, so it should be okay. We could use
* atomic ops here, but I'm not sure how much more that really buys us.*/
oldlist = options->values; /* keep window small */
options->values = list;
g_list_free (oldlist);
e->need_update = FALSE;
return options->values;
}
static GList *
gst_oss4_mixer_enum_get_values (GstMixerOptions * options)
{
GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM (options);
GList *list;
/* we take the lock here mostly to serialise ioctls with the watch thread */
GST_OBJECT_LOCK (e->mixer);
list = gst_oss4_mixer_enum_get_values_locked (options);
GST_OBJECT_UNLOCK (e->mixer);
return list;
}
static const gchar *
gst_oss4_mixer_enum_get_current_value (GstOss4MixerEnum * e)
{
const gchar *cur_val = NULL;
if (e->mc->enum_vals != NULL && e->mc->last_val < e->mc->mixext.maxvalue) {
cur_val = g_quark_to_string (e->mc->enum_vals[e->mc->last_val]);
}
return cur_val;
}
static gboolean
gst_oss4_mixer_enum_update_current (GstOss4MixerEnum * e)
{
int cur = -1;
if (!gst_oss4_mixer_get_control_val (e->mixer, e->mc, &cur))
return FALSE;
if (cur < 0 || cur >= e->mc->mixext.maxvalue) {
GST_WARNING_OBJECT (e, "read value %d out of bounds [0-%d]", cur,
e->mc->mixext.maxvalue - 1);
e->mc->last_val = 0;
return FALSE;
}
return TRUE;
}
gboolean
gst_oss4_mixer_enum_set_option (GstOss4MixerEnum * e, const gchar * value)
{
GQuark q;
int i;
q = g_quark_try_string (value);
if (q == 0) {
GST_WARNING_OBJECT (e, "unknown option '%s'", value);
return FALSE;
}
for (i = 0; i < e->mc->mixext.maxvalue; ++i) {