mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-19 16:21:17 +00:00
oss4: port to 0.11
This commit is contained in:
parent
c4c3736e1a
commit
a5ff454e6a
21 changed files with 208 additions and 3582 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -1,269 +0,0 @@
|
|||
/* GStreamer OSS4 mixer enumeration control
|
||||
* Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* An 'enum' in gnome-volume-control / GstMixer is represented by a
|
||||
* GstMixerOptions object
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
|
||||
#define NO_LEGACY_MIXER
|
||||
#include "oss4-mixer.h"
|
||||
#include "oss4-mixer-enum.h"
|
||||
#include "oss4-soundcard.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug);
|
||||
#define GST_CAT_DEFAULT oss4mixer_debug
|
||||
|
||||
static GList *gst_oss4_mixer_enum_get_values (GstMixerOptions * options);
|
||||
|
||||
/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */
|
||||
G_DEFINE_TYPE (GstOss4MixerEnum, gst_oss4_mixer_enum, GST_TYPE_MIXER_OPTIONS);
|
||||
|
||||
static void
|
||||
gst_oss4_mixer_enum_init (GstOss4MixerEnum * e)
|
||||
{
|
||||
e->need_update = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_mixer_enum_dispose (GObject * obj)
|
||||
{
|
||||
GstMixerOptions *options = GST_MIXER_OPTIONS (obj);
|
||||
|
||||
/* our list is a flat list with constant strings, but the GstMixerOptions
|
||||
* dispose will try to g_free the contained strings, so clean up the list
|
||||
* before chaining up to GstMixerOptions */
|
||||
g_list_free (options->values);
|
||||
options->values = NULL;
|
||||
|
||||
G_OBJECT_CLASS (gst_oss4_mixer_enum_parent_class)->dispose (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_mixer_enum_class_init (GstOss4MixerEnumClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstMixerOptionsClass *mixeroptions_class = (GstMixerOptionsClass *) klass;
|
||||
|
||||
gobject_class->dispose = gst_oss4_mixer_enum_dispose;
|
||||
mixeroptions_class->get_values = gst_oss4_mixer_enum_get_values;
|
||||
}
|
||||
|
||||
static GList *
|
||||
gst_oss4_mixer_enum_get_values_locked (GstMixerOptions * options)
|
||||
{
|
||||
GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM_CAST (options);
|
||||
GList *oldlist, *list = NULL;
|
||||
int i;
|
||||
|
||||
/* if current list of values is empty, update/re-check in any case */
|
||||
if (!e->need_update && options->values != NULL)
|
||||
return options->values;
|
||||
|
||||
GST_LOG_OBJECT (e, "updating available values for %s", e->mc->mixext.extname);
|
||||
|
||||
for (i = 0; i < e->mc->mixext.maxvalue; ++i) {
|
||||
const gchar *s;
|
||||
|
||||
s = g_quark_to_string (e->mc->enum_vals[i]);
|
||||
if (MIXEXT_ENUM_IS_AVAILABLE (e->mc->mixext, i)) {
|
||||
GST_LOG_OBJECT (e, "option '%s' is available", s);
|
||||
list = g_list_prepend (list, (gpointer) s);
|
||||
} else {
|
||||
GST_LOG_OBJECT (e, "option '%s' is currently not available", s);
|
||||
}
|
||||
}
|
||||
|
||||
list = g_list_reverse (list);
|
||||
|
||||
/* this is not thread-safe, but then the entire GstMixer API isn't really,
|
||||
* since we return foo->list and not a copy and don't take any locks, so
|
||||
* not much we can do here but pray; we're usually either called from _new()
|
||||
* or from within _get_values() though, so it should be okay. We could use
|
||||
* atomic ops here, but I'm not sure how much more that really buys us.*/
|
||||
oldlist = options->values; /* keep window small */
|
||||
options->values = list;
|
||||
g_list_free (oldlist);
|
||||
|
||||
e->need_update = FALSE;
|
||||
|
||||
return options->values;
|
||||
}
|
||||
|
||||
static GList *
|
||||
gst_oss4_mixer_enum_get_values (GstMixerOptions * options)
|
||||
{
|
||||
GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM (options);
|
||||
GList *list;
|
||||
|
||||
/* we take the lock here mostly to serialise ioctls with the watch thread */
|
||||
GST_OBJECT_LOCK (e->mixer);
|
||||
|
||||
list = gst_oss4_mixer_enum_get_values_locked (options);
|
||||
|
||||
GST_OBJECT_UNLOCK (e->mixer);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
gst_oss4_mixer_enum_get_current_value (GstOss4MixerEnum * e)
|
||||
{
|
||||
const gchar *cur_val = NULL;
|
||||
|
||||
if (e->mc->enum_vals != NULL && e->mc->last_val < e->mc->mixext.maxvalue) {
|
||||
cur_val = g_quark_to_string (e->mc->enum_vals[e->mc->last_val]);
|
||||
}
|
||||
|
||||
return cur_val;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_oss4_mixer_enum_update_current (GstOss4MixerEnum * e)
|
||||
{
|
||||
int cur = -1;
|
||||
|
||||
if (!gst_oss4_mixer_get_control_val (e->mixer, e->mc, &cur))
|
||||
return FALSE;
|
||||
|
||||
if (cur < 0 || cur >= e->mc->mixext.maxvalue) {
|
||||
GST_WARNING_OBJECT (e, "read value %d out of bounds [0-%d]", cur,
|
||||
e->mc->mixext.maxvalue - 1);
|
||||
e->mc->last_val = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_oss4_mixer_enum_set_option (GstOss4MixerEnum * e, const gchar * value)
|
||||
{
|
||||
GQuark q;
|
||||
int i;
|
||||
|
||||
q = g_quark_try_string (value);
|
||||
if (q == 0) {
|
||||
GST_WARNING_OBJECT (e, "unknown option '%s'", value);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < e->mc->mixext.maxvalue; ++i) {
|
||||
if (q == e->mc->enum_vals[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= e->mc->mixext.maxvalue) {
|
||||
GST_WARNING_OBJECT (e, "option '%s' is not valid for this control", value);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (e, "option '%s' = %d", value, i);
|
||||
|
||||
if (!MIXEXT_ENUM_IS_AVAILABLE (e->mc->mixext, i)) {
|
||||
GST_WARNING_OBJECT (e, "option '%s' is not selectable currently", value);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gst_oss4_mixer_set_control_val (e->mixer, e->mc, i)) {
|
||||
GST_WARNING_OBJECT (e, "could not set option '%s' (%d)", value, i);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* and re-read current value with sanity checks (or could just assign here) */
|
||||
gst_oss4_mixer_enum_update_current (e);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gst_oss4_mixer_enum_get_option (GstOss4MixerEnum * e)
|
||||
{
|
||||
const gchar *cur_str = NULL;
|
||||
|
||||
if (!gst_oss4_mixer_enum_update_current (e)) {
|
||||
GST_WARNING_OBJECT (e, "failed to read current value");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cur_str = gst_oss4_mixer_enum_get_current_value (e);
|
||||
GST_LOG_OBJECT (e, "%s (%d)", GST_STR_NULL (cur_str), e->mc->last_val);
|
||||
return cur_str;
|
||||
}
|
||||
|
||||
GstMixerTrack *
|
||||
gst_oss4_mixer_enum_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc)
|
||||
{
|
||||
GstOss4MixerEnum *e;
|
||||
GstMixerTrack *track;
|
||||
|
||||
e = g_object_new (GST_TYPE_OSS4_MIXER_ENUM, "untranslated-label",
|
||||
mc->mixext.extname, NULL);
|
||||
e->mixer = mixer;
|
||||
e->mc = mc;
|
||||
|
||||
track = GST_MIXER_TRACK (e);
|
||||
|
||||
/* caller will set track->label and track->flags */
|
||||
|
||||
track->num_channels = 0;
|
||||
track->min_volume = 0;
|
||||
track->max_volume = 0;
|
||||
|
||||
(void) gst_oss4_mixer_enum_get_values_locked (GST_MIXER_OPTIONS (track));
|
||||
|
||||
if (!gst_oss4_mixer_enum_update_current (e)) {
|
||||
GST_WARNING_OBJECT (track, "failed to read current value, returning NULL");
|
||||
g_object_unref (track);
|
||||
track = NULL;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (e, "current value: %d (%s)", e->mc->last_val,
|
||||
gst_oss4_mixer_enum_get_current_value (e));
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
/* This is called from the watch thread */
|
||||
void
|
||||
gst_oss4_mixer_enum_process_change_unlocked (GstMixerTrack * track)
|
||||
{
|
||||
GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM_CAST (track);
|
||||
|
||||
gchar *cur;
|
||||
|
||||
if (!e->mc->changed && !e->mc->list_changed)
|
||||
return;
|
||||
|
||||
if (e->mc->list_changed) {
|
||||
gst_mixer_options_list_changed (GST_MIXER (e->mixer),
|
||||
GST_MIXER_OPTIONS (e));
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (e->mixer);
|
||||
cur = (gchar *) gst_oss4_mixer_enum_get_current_value (e);
|
||||
GST_OBJECT_UNLOCK (e->mixer);
|
||||
|
||||
gst_mixer_option_changed (GST_MIXER (e->mixer), GST_MIXER_OPTIONS (e), cur);
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/* GStreamer OSS4 mixer on/off enum control
|
||||
* Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef GST_OSS4_MIXER_ENUM_H
|
||||
#define GST_OSS4_MIXER_ENUM_H
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/interfaces/mixer.h>
|
||||
|
||||
#include "oss4-mixer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_OSS4_MIXER_ENUM (gst_oss4_mixer_enum_get_type())
|
||||
#define GST_OSS4_MIXER_ENUM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER_ENUM,GstOss4MixerEnum))
|
||||
#define GST_OSS4_MIXER_ENUM_CAST(obj) ((GstOss4MixerEnum *)(obj))
|
||||
#define GST_OSS4_MIXER_ENUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER_ENUM,GstOss4MixerEnumClass))
|
||||
#define GST_IS_OSS4_MIXER_ENUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER_ENUM))
|
||||
#define GST_IS_OSS4_MIXER_ENUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER_ENUM))
|
||||
|
||||
typedef struct _GstOss4MixerEnum GstOss4MixerEnum;
|
||||
typedef struct _GstOss4MixerEnumClass GstOss4MixerEnumClass;
|
||||
|
||||
struct _GstOss4MixerEnum {
|
||||
GstMixerOptions mixer_option;
|
||||
|
||||
GstOss4MixerControl * mc;
|
||||
GstOss4Mixer * mixer; /* the mixer we belong to (no ref taken) */
|
||||
|
||||
gboolean need_update;
|
||||
};
|
||||
|
||||
struct _GstOss4MixerEnumClass {
|
||||
GstMixerOptionsClass mixer_option_class;
|
||||
};
|
||||
|
||||
GType gst_oss4_mixer_enum_get_type (void);
|
||||
|
||||
gboolean gst_oss4_mixer_enum_set_option (GstOss4MixerEnum * e, const gchar * value);
|
||||
|
||||
const gchar * gst_oss4_mixer_enum_get_option (GstOss4MixerEnum * e);
|
||||
|
||||
GstMixerTrack * gst_oss4_mixer_enum_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc);
|
||||
|
||||
void gst_oss4_mixer_enum_process_change_unlocked (GstMixerTrack * track);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GST_OSS4_MIXER_ENUM_H */
|
||||
|
||||
|
|
@ -1,311 +0,0 @@
|
|||
/* GStreamer OSS4 mixer slider control
|
||||
* Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* A 'slider' in gnome-volume-control / GstMixer is represented by a
|
||||
* GstMixerTrack with one or more channels.
|
||||
*
|
||||
* A slider should be either flagged as INPUT or OUTPUT (mostly because of
|
||||
* gnome-volume-control being littered with g_asserts for everything it doesn't
|
||||
* expect).
|
||||
*
|
||||
* From mixertrack.h:
|
||||
* "Input tracks can have 'recording' enabled, which means that any input will
|
||||
* be hearable into the speakers that are attached to the output. Mute is
|
||||
* obvious."
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
|
||||
#define NO_LEGACY_MIXER
|
||||
#include "oss4-mixer-slider.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug);
|
||||
#define GST_CAT_DEFAULT oss4mixer_debug
|
||||
|
||||
/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */
|
||||
G_DEFINE_TYPE (GstOss4MixerSlider, gst_oss4_mixer_slider, GST_TYPE_MIXER_TRACK);
|
||||
|
||||
static void
|
||||
gst_oss4_mixer_slider_class_init (GstOss4MixerSliderClass * klass)
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_mixer_slider_init (GstOss4MixerSlider * s)
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
|
||||
static int
|
||||
gst_oss4_mixer_slider_pack_volume (GstOss4MixerSlider * s, const gint * volumes)
|
||||
{
|
||||
int val = 0;
|
||||
|
||||
switch (s->mc->mixext.type) {
|
||||
case MIXT_MONOSLIDER:
|
||||
case MIXT_MONOSLIDER16:
|
||||
case MIXT_SLIDER:
|
||||
val = volumes[0];
|
||||
break;
|
||||
case MIXT_STEREOSLIDER:
|
||||
val = ((volumes[1] & 0xff) << 8) | (volumes[0] & 0xff);
|
||||
break;
|
||||
case MIXT_STEREOSLIDER16:
|
||||
val = ((volumes[1] & 0xffff) << 16) | (volumes[0] & 0xffff);
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (0);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_mixer_slider_unpack_volume (GstOss4MixerSlider * s, int v,
|
||||
gint * volumes)
|
||||
{
|
||||
guint32 val; /* use uint so bitshifting the highest bit works right */
|
||||
|
||||
val = (guint32) v;
|
||||
switch (s->mc->mixext.type) {
|
||||
case MIXT_SLIDER:
|
||||
volumes[0] = val;
|
||||
break;
|
||||
case MIXT_MONOSLIDER:
|
||||
/* oss repeats the value in the upper bits, as if it was stereo */
|
||||
volumes[0] = val & 0x00ff;
|
||||
break;
|
||||
case MIXT_MONOSLIDER16:
|
||||
/* oss repeats the value in the upper bits, as if it was stereo */
|
||||
volumes[0] = val & 0x0000ffff;
|
||||
break;
|
||||
case MIXT_STEREOSLIDER:
|
||||
volumes[0] = (val & 0x00ff);
|
||||
volumes[1] = (val & 0xff00) >> 8;
|
||||
break;
|
||||
case MIXT_STEREOSLIDER16:
|
||||
volumes[0] = (val & 0x0000ffff);
|
||||
volumes[1] = (val & 0xffff0000) >> 16;
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_oss4_mixer_slider_get_volume (GstOss4MixerSlider * s, gint * volumes)
|
||||
{
|
||||
GstMixerTrack *track = GST_MIXER_TRACK (s);
|
||||
int v = 0;
|
||||
|
||||
/* if we're supposed to be muted, and don't have an actual mute control
|
||||
* (ie. 'simulate' the mute), then just return the volume as saved, not
|
||||
* the actually set volume which is most likely 0 */
|
||||
if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE) && !s->mc->mute) {
|
||||
volumes[0] = s->volumes[0];
|
||||
if (track->num_channels == 2)
|
||||
volumes[1] = s->volumes[1];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!gst_oss4_mixer_get_control_val (s->mixer, s->mc, &v))
|
||||
return FALSE;
|
||||
|
||||
gst_oss4_mixer_slider_unpack_volume (s, v, volumes);
|
||||
|
||||
if (track->num_channels > 1) {
|
||||
GST_LOG_OBJECT (s, "volume: left=%d, right=%d", volumes[0], volumes[1]);
|
||||
} else {
|
||||
GST_LOG_OBJECT (s, "volume: mono=%d", volumes[0]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_oss4_mixer_slider_set_volume (GstOss4MixerSlider * s, const gint * volumes)
|
||||
{
|
||||
GstMixerTrack *track = GST_MIXER_TRACK (s);
|
||||
int val = 0;
|
||||
|
||||
/* if we're supposed to be muted, and are 'simulating' the mute because
|
||||
* we don't have a mute control, don't actually change the volume, just
|
||||
* save it as the new desired volume for later when we get unmuted again */
|
||||
if (!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_NO_MUTE)) {
|
||||
if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE) && !s->mc->mute)
|
||||
goto done;
|
||||
}
|
||||
|
||||
val = gst_oss4_mixer_slider_pack_volume (s, volumes);
|
||||
|
||||
if (track->num_channels > 1) {
|
||||
GST_LOG_OBJECT (s, "left=%d, right=%d", volumes[0], volumes[1]);
|
||||
} else {
|
||||
GST_LOG_OBJECT (s, "mono=%d", volumes[0]);
|
||||
}
|
||||
|
||||
if (!gst_oss4_mixer_set_control_val (s->mixer, s->mc, val))
|
||||
return FALSE;
|
||||
|
||||
done:
|
||||
|
||||
s->volumes[0] = volumes[0];
|
||||
if (track->num_channels == 2)
|
||||
s->volumes[1] = volumes[1];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_oss4_mixer_slider_set_record (GstOss4MixerSlider * s, gboolean record)
|
||||
{
|
||||
/* There doesn't seem to be a way to do this using the OSS4 mixer API, so
|
||||
* just do nothing here for now. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_oss4_mixer_slider_set_mute (GstOss4MixerSlider * s, gboolean mute)
|
||||
{
|
||||
GstMixerTrack *track = GST_MIXER_TRACK (s);
|
||||
gboolean ret;
|
||||
|
||||
/* if the control does not support muting, then do not do anything */
|
||||
if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_NO_MUTE)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* If we do not have a mute control, simulate mute (which is a bit broken,
|
||||
* since we can not differentiate between capture/playback volume etc., so
|
||||
* we just assume that setting the volume to 0 would be the same as muting
|
||||
* this control) */
|
||||
if (s->mc->mute == NULL) {
|
||||
int volume;
|
||||
|
||||
if (mute) {
|
||||
/* make sure the current volume values get saved. */
|
||||
gst_oss4_mixer_slider_get_volume (s, s->volumes);
|
||||
volume = 0;
|
||||
} else {
|
||||
volume = gst_oss4_mixer_slider_pack_volume (s, s->volumes);
|
||||
}
|
||||
ret = gst_oss4_mixer_set_control_val (s->mixer, s->mc, volume);
|
||||
} else {
|
||||
ret = gst_oss4_mixer_set_control_val (s->mixer, s->mc->mute, !!mute);
|
||||
}
|
||||
|
||||
if (mute) {
|
||||
track->flags |= GST_MIXER_TRACK_MUTE;
|
||||
} else {
|
||||
track->flags &= ~GST_MIXER_TRACK_MUTE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GstMixerTrack *
|
||||
gst_oss4_mixer_slider_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc)
|
||||
{
|
||||
GstOss4MixerSlider *s;
|
||||
GstMixerTrack *track;
|
||||
gint volumes[2] = { 0, };
|
||||
|
||||
s = g_object_new (GST_TYPE_OSS4_MIXER_SLIDER, "untranslated-label",
|
||||
mc->mixext.extname, NULL);
|
||||
|
||||
track = GST_MIXER_TRACK (s);
|
||||
|
||||
/* caller will set track->label and track->flags */
|
||||
|
||||
s->mc = mc;
|
||||
s->mixer = mixer;
|
||||
|
||||
/* we don't do value scaling but just present a scale of 0-maxvalue */
|
||||
track->min_volume = 0;
|
||||
track->max_volume = mc->mixext.maxvalue;
|
||||
|
||||
switch (mc->mixext.type) {
|
||||
case MIXT_MONOSLIDER:
|
||||
case MIXT_MONOSLIDER16:
|
||||
case MIXT_SLIDER:
|
||||
track->num_channels = 1;
|
||||
break;
|
||||
case MIXT_STEREOSLIDER:
|
||||
case MIXT_STEREOSLIDER16:
|
||||
track->num_channels = 2;
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (track, "min=%d, max=%d, channels=%d", track->min_volume,
|
||||
track->max_volume, track->num_channels);
|
||||
|
||||
if (!gst_oss4_mixer_slider_get_volume (s, volumes)) {
|
||||
GST_WARNING_OBJECT (track, "failed to read volume, returning NULL");
|
||||
g_object_unref (track);
|
||||
track = NULL;
|
||||
}
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
/* This is called from the watch thread */
|
||||
void
|
||||
gst_oss4_mixer_slider_process_change_unlocked (GstMixerTrack * track)
|
||||
{
|
||||
GstOss4MixerSlider *s = GST_OSS4_MIXER_SLIDER_CAST (track);
|
||||
|
||||
if (s->mc->mute != NULL && s->mc->mute->changed) {
|
||||
gst_mixer_mute_toggled (GST_MIXER (s->mixer), track,
|
||||
!!s->mc->mute->last_val);
|
||||
} else {
|
||||
/* nothing to do here, since we don't/can't easily implement the record
|
||||
* flag */
|
||||
}
|
||||
|
||||
if (s->mc->changed) {
|
||||
gint volumes[2] = { 0, 0 };
|
||||
|
||||
gst_oss4_mixer_slider_unpack_volume (s, s->mc->last_val, volumes);
|
||||
|
||||
/* if we 'simulate' the mute, update flag when the volume changes */
|
||||
if (s->mc->mute == NULL) {
|
||||
if (volumes[0] == 0 && volumes[1] == 0) {
|
||||
track->flags |= GST_MIXER_TRACK_MUTE;
|
||||
} else {
|
||||
track->flags &= ~GST_MIXER_TRACK_MUTE;
|
||||
}
|
||||
}
|
||||
|
||||
gst_mixer_volume_changed (GST_MIXER (s->mixer), track, volumes);
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/* GStreamer OSS4 mixer slider control
|
||||
* Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef GST_OSS4_MIXER_SLIDER_H
|
||||
#define GST_OSS4_MIXER_SLIDER_H
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/interfaces/mixer.h>
|
||||
|
||||
#include "oss4-mixer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_OSS4_MIXER_SLIDER (gst_oss4_mixer_slider_get_type())
|
||||
#define GST_OSS4_MIXER_SLIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER_SLIDER,GstOss4MixerSlider))
|
||||
#define GST_OSS4_MIXER_SLIDER_CAST(obj) ((GstOss4MixerSlider *)(obj))
|
||||
#define GST_OSS4_MIXER_SLIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER_SLIDER,GstOss4MixerSliderClass))
|
||||
#define GST_IS_OSS4_MIXER_SLIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER_SLIDER))
|
||||
#define GST_IS_OSS4_MIXER_SLIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER_SLIDER))
|
||||
|
||||
typedef struct _GstOss4MixerSlider GstOss4MixerSlider;
|
||||
typedef struct _GstOss4MixerSliderClass GstOss4MixerSliderClass;
|
||||
|
||||
struct _GstOss4MixerSlider {
|
||||
GstMixerTrack mixer_track;
|
||||
|
||||
GstOss4MixerControl * mc;
|
||||
GstOss4Mixer * mixer; /* the mixer we belong to (no ref taken) */
|
||||
gint volumes[2]; /* left/mono, right */
|
||||
};
|
||||
|
||||
struct _GstOss4MixerSliderClass {
|
||||
GstMixerTrackClass mixer_track_class;
|
||||
};
|
||||
|
||||
GType gst_oss4_mixer_slider_get_type (void);
|
||||
|
||||
GstMixerTrack * gst_oss4_mixer_slider_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc);
|
||||
|
||||
gboolean gst_oss4_mixer_slider_get_volume (GstOss4MixerSlider * s, gint * volumes);
|
||||
|
||||
gboolean gst_oss4_mixer_slider_set_volume (GstOss4MixerSlider * s, const gint * volumes);
|
||||
|
||||
gboolean gst_oss4_mixer_slider_set_record (GstOss4MixerSlider * s, gboolean record);
|
||||
|
||||
gboolean gst_oss4_mixer_slider_set_mute (GstOss4MixerSlider * s, gboolean mute);
|
||||
|
||||
void gst_oss4_mixer_slider_process_change_unlocked (GstMixerTrack * track);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GST_OSS4_MIXER_SLIDER_H */
|
||||
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
/* GStreamer OSS4 mixer on/off switch control
|
||||
* Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* A simple ON/OFF 'switch' in gnome-volume-control / GstMixer is represented
|
||||
* by a GstMixerTrack with no channels.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
|
||||
#define NO_LEGACY_MIXER
|
||||
#include "oss4-mixer-switch.h"
|
||||
#include "oss4-soundcard.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug);
|
||||
#define GST_CAT_DEFAULT oss4mixer_debug
|
||||
|
||||
/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */
|
||||
G_DEFINE_TYPE (GstOss4MixerSwitch, gst_oss4_mixer_switch, GST_TYPE_MIXER_TRACK);
|
||||
|
||||
static void
|
||||
gst_oss4_mixer_switch_class_init (GstOss4MixerSwitchClass * klass)
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_mixer_switch_init (GstOss4MixerSwitch * s)
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_oss4_mixer_switch_set (GstOss4MixerSwitch * s, gboolean disabled)
|
||||
{
|
||||
GstMixerTrack *track;
|
||||
int newval;
|
||||
|
||||
track = GST_MIXER_TRACK (s);
|
||||
|
||||
newval = disabled ? GST_MIXER_TRACK_MUTE : 0;
|
||||
|
||||
if (newval == (track->flags & GST_MIXER_TRACK_MUTE)) {
|
||||
GST_LOG_OBJECT (s, "switch is already %d, doing nothing", newval);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!gst_oss4_mixer_set_control_val (s->mixer, s->mc, !disabled)) {
|
||||
GST_WARNING_OBJECT (s, "could not set switch to %d", !disabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
track->flags |= GST_MIXER_TRACK_MUTE;
|
||||
} else {
|
||||
track->flags &= ~GST_MIXER_TRACK_MUTE;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (s, "set switch to %d", newval);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_oss4_mixer_switch_get (GstOss4MixerSwitch * s, gboolean * disabled)
|
||||
{
|
||||
GstMixerTrack *track;
|
||||
int enabled = -1;
|
||||
|
||||
track = GST_MIXER_TRACK (s);
|
||||
|
||||
if (!gst_oss4_mixer_get_control_val (s->mixer, s->mc, &enabled)
|
||||
|| (enabled < 0)) {
|
||||
GST_WARNING_OBJECT (s, "could not get switch state");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
track->flags &= ~GST_MIXER_TRACK_MUTE;
|
||||
} else {
|
||||
track->flags |= GST_MIXER_TRACK_MUTE;
|
||||
}
|
||||
*disabled = (enabled == 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GstMixerTrack *
|
||||
gst_oss4_mixer_switch_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc)
|
||||
{
|
||||
GstOss4MixerSwitch *s;
|
||||
GstMixerTrack *track;
|
||||
int cur = -1;
|
||||
|
||||
s = g_object_new (GST_TYPE_OSS4_MIXER_SWITCH, "untranslated-label",
|
||||
mc->mixext.extname, NULL);
|
||||
|
||||
s->mixer = mixer;
|
||||
s->mc = mc;
|
||||
|
||||
track = GST_MIXER_TRACK (s);
|
||||
|
||||
/* caller will set track->label and track->flags */
|
||||
|
||||
track->num_channels = 0;
|
||||
track->min_volume = 0;
|
||||
track->max_volume = 0;
|
||||
|
||||
if (!gst_oss4_mixer_get_control_val (s->mixer, s->mc, &cur) || cur < 0)
|
||||
return NULL;
|
||||
|
||||
if (cur) {
|
||||
track->flags &= ~GST_MIXER_TRACK_MUTE;
|
||||
} else {
|
||||
track->flags |= GST_MIXER_TRACK_MUTE;
|
||||
}
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
/* This is called from the watch thread */
|
||||
void
|
||||
gst_oss4_mixer_switch_process_change_unlocked (GstMixerTrack * track)
|
||||
{
|
||||
GstOss4MixerSwitch *s = GST_OSS4_MIXER_SWITCH_CAST (track);
|
||||
|
||||
if (!s->mc->changed)
|
||||
return;
|
||||
|
||||
gst_mixer_mute_toggled (GST_MIXER (s->mixer), track, !s->mc->last_val);
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/* GStreamer OSS4 mixer on/off switch control
|
||||
* Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef GST_OSS4_MIXER_SWITCH_H
|
||||
#define GST_OSS4_MIXER_SWITCH_H
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/interfaces/mixer.h>
|
||||
|
||||
#include "oss4-mixer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_OSS4_MIXER_SWITCH (gst_oss4_mixer_switch_get_type())
|
||||
#define GST_OSS4_MIXER_SWITCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER_SWITCH,GstOss4MixerSwitch))
|
||||
#define GST_OSS4_MIXER_SWITCH_CAST(obj) ((GstOss4MixerSwitch *)(obj))
|
||||
#define GST_OSS4_MIXER_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER_SWITCH,GstOss4MixerSwitchClass))
|
||||
#define GST_IS_OSS4_MIXER_SWITCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER_SWITCH))
|
||||
#define GST_IS_OSS4_MIXER_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER_SWITCH))
|
||||
|
||||
typedef struct _GstOss4MixerSwitch GstOss4MixerSwitch;
|
||||
typedef struct _GstOss4MixerSwitchClass GstOss4MixerSwitchClass;
|
||||
|
||||
struct _GstOss4MixerSwitch {
|
||||
GstMixerTrack mixer_track;
|
||||
|
||||
GstOss4MixerControl * mc;
|
||||
GstOss4Mixer * mixer; /* the mixer we belong to (no ref taken) */
|
||||
};
|
||||
|
||||
struct _GstOss4MixerSwitchClass {
|
||||
GstMixerTrackClass mixer_track_class;
|
||||
};
|
||||
|
||||
GType gst_oss4_mixer_switch_get_type (void);
|
||||
|
||||
gboolean gst_oss4_mixer_switch_set (GstOss4MixerSwitch * s, gboolean enabled);
|
||||
|
||||
gboolean gst_oss4_mixer_switch_get (GstOss4MixerSwitch * s, gboolean * enabled);
|
||||
|
||||
GstMixerTrack * gst_oss4_mixer_switch_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc);
|
||||
|
||||
void gst_oss4_mixer_switch_process_change_unlocked (GstMixerTrack * track);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GST_OSS4_MIXER_SWITCH_H */
|
||||
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,128 +0,0 @@
|
|||
/* GStreamer OSS4 mixer implementation
|
||||
* Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef OSS4_MIXER_H
|
||||
#define OSS4_MIXER_H
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "oss4-soundcard.h"
|
||||
|
||||
#define GST_OSS4_MIXER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER,GstOss4Mixer))
|
||||
#define GST_OSS4_MIXER_CAST(obj) ((GstOss4Mixer *)(obj))
|
||||
#define GST_OSS4_MIXER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER,GstOss4MixerClass))
|
||||
#define GST_IS_OSS4_MIXER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER))
|
||||
#define GST_IS_OSS4_MIXER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER))
|
||||
#define GST_TYPE_OSS4_MIXER (gst_oss4_mixer_get_type())
|
||||
|
||||
#define GST_OSS4_MIXER_IS_OPEN(obj) (GST_OSS4_MIXER(obj)->fd != -1)
|
||||
|
||||
typedef struct _GstOss4Mixer GstOss4Mixer;
|
||||
typedef struct _GstOss4MixerClass GstOss4MixerClass;
|
||||
|
||||
struct _GstOss4Mixer {
|
||||
GstElement element;
|
||||
|
||||
/*< private >*/
|
||||
|
||||
/* element bits'n'bops */
|
||||
gchar * device;
|
||||
|
||||
/* mixer details */
|
||||
gint fd; /* file descriptor if open, or -1 */
|
||||
gchar * device_name; /* device description, or NULL */
|
||||
gchar * open_device; /* the device we opened */
|
||||
|
||||
GList * tracks; /* list of available tracks */
|
||||
GList * controls; /* list of available controls */
|
||||
gboolean need_update; /* re-read list of available tracks? */
|
||||
|
||||
oss_mixext last_mixext; /* we keep this around so we can
|
||||
* easily check if the mixer
|
||||
* interface has changed */
|
||||
|
||||
GThread * watch_thread; /* thread watching for value changes */
|
||||
GCond * watch_cond;
|
||||
gint watch_shutdown;
|
||||
gint modify_counter; /* from MIXERINFO */
|
||||
|
||||
/* for property probe interface */
|
||||
GList * property_probe_list;
|
||||
};
|
||||
|
||||
struct _GstOss4MixerClass {
|
||||
GstElementClass element_class;
|
||||
};
|
||||
|
||||
/* helper struct holding info about one control */
|
||||
typedef struct _GstOss4MixerControl GstOss4MixerControl;
|
||||
|
||||
struct _GstOss4MixerControl {
|
||||
oss_mixext mixext;
|
||||
GstOss4MixerControl *parent; /* NULL if root */
|
||||
GstOss4MixerControl *mute; /* sibling with mute function, or NULL */
|
||||
GList *mute_group; /* group of mute controls, or NULL */
|
||||
GList *children; /* GstOss4MixerControls (no ownership) */
|
||||
|
||||
GQuark *enum_vals; /* 0-terminated array of values or NULL */
|
||||
int enum_version; /* 0 = list won't change */
|
||||
|
||||
int last_val; /* last value seen */
|
||||
|
||||
gboolean is_virtual : 1; /* is a vmix control with dynamic label */
|
||||
gboolean is_master : 1;
|
||||
gboolean is_slider : 1; /* represent as slider */
|
||||
gboolean is_switch : 1; /* represent as switch */
|
||||
gboolean is_enum : 1; /* represent as combo/enumeration */
|
||||
gboolean no_list : 1; /* enumeration with no list available */
|
||||
gboolean is_input : 1; /* is an input-related control */
|
||||
gboolean is_output : 1; /* is an output-related control */
|
||||
gboolean used : 1; /* whether we know what to do with this */
|
||||
|
||||
gboolean changed : 1; /* transient flag used by watch thread */
|
||||
gboolean list_changed : 1; /* transient flag used by watch thread */
|
||||
};
|
||||
|
||||
/* header says parent=-1 means root, but it can also be parent=ctrl */
|
||||
#define MIXEXT_IS_ROOT(me) ((me).parent == -1 || (me).parent == (me).ctrl)
|
||||
|
||||
#define MIXEXT_IS_SLIDER(me) ((me).type == MIXT_MONOSLIDER || \
|
||||
(me).type == MIXT_STEREOSLIDER || (me).type == MIXT_MONOSLIDER16 || \
|
||||
(me).type == MIXT_STEREOSLIDER16 || (me).type == MIXT_SLIDER)
|
||||
|
||||
#define MIXEXT_HAS_DESCRIPTION(me) (((me).flags & MIXF_DESCR) != 0)
|
||||
|
||||
#define MIXEXT_ENUM_IS_AVAILABLE(me,num) \
|
||||
(((me).enum_present[num/8]) & (1 << (num % 8)))
|
||||
|
||||
|
||||
GType gst_oss4_mixer_get_type (void);
|
||||
|
||||
gboolean gst_oss4_mixer_get_control_val (GstOss4Mixer * mixer,
|
||||
GstOss4MixerControl * mc,
|
||||
int * val);
|
||||
|
||||
gboolean gst_oss4_mixer_set_control_val (GstOss4Mixer * mixer,
|
||||
GstOss4MixerControl * mc,
|
||||
int val);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* OSS4_MIXER_H */
|
||||
|
|
@ -27,9 +27,9 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
|
||||
|
||||
#define NO_LEGACY_MIXER
|
||||
#include "oss4-audio.h"
|
||||
#include "oss4-mixer.h"
|
||||
#include "oss4-sink.h"
|
||||
#include "oss4-source.h"
|
||||
#include "oss4-soundcard.h"
|
||||
|
@ -43,6 +43,8 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#if 0
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (oss4_debug);
|
||||
#define GST_CAT_DEFAULT oss4_debug
|
||||
|
||||
|
@ -110,6 +112,8 @@ gst_oss4_property_probe_needs_probe (GstPropertyProbe * probe,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static gint
|
||||
oss4_mixerinfo_priority_cmp (struct oss_mixerinfo *mi1,
|
||||
struct oss_mixerinfo *mi2)
|
||||
|
@ -282,9 +286,8 @@ gst_oss4_property_probe_get_audio_devices (GstObject * obj, int fd,
|
|||
return g_list_reverse (devices);
|
||||
}
|
||||
|
||||
static GValueArray *
|
||||
gst_oss4_property_probe_get_values (GstPropertyProbe * probe,
|
||||
guint prop_id, const GParamSpec * pspec)
|
||||
GValueArray *
|
||||
gst_oss4_property_probe_get_values (GstObject * probe, const gchar * pname)
|
||||
{
|
||||
struct oss_sysinfo si = { {0,}, };
|
||||
GValueArray *array = NULL;
|
||||
|
@ -292,8 +295,8 @@ gst_oss4_property_probe_get_values (GstPropertyProbe * probe,
|
|||
GList *devices, *l;
|
||||
int cap_mask, fd = -1;
|
||||
|
||||
if (!g_str_equal (pspec->name, "device")) {
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
|
||||
if (!g_str_equal (pname, "device")) {
|
||||
GST_WARNING_OBJECT (probe, "invalid property");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -310,9 +313,6 @@ gst_oss4_property_probe_get_values (GstPropertyProbe * probe,
|
|||
GST_DEBUG_OBJECT (probe, "probing available input devices");
|
||||
cap_mask = PCM_CAP_INPUT;
|
||||
fd = GST_OSS4_SOURCE (probe)->fd;
|
||||
} else if (GST_IS_OSS4_MIXER (probe)) {
|
||||
fd = GST_OSS4_MIXER (probe)->fd;
|
||||
cap_mask = 0;
|
||||
} else {
|
||||
GST_OBJECT_UNLOCK (obj);
|
||||
g_return_val_if_reached (NULL);
|
||||
|
@ -393,6 +393,7 @@ no_sysinfo:
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
gst_oss4_property_probe_interface_init (GstPropertyProbeInterface * iface)
|
||||
{
|
||||
|
@ -414,3 +415,4 @@ gst_oss4_add_property_probe_interface (GType type)
|
|||
g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
|
||||
&probe_iface_info);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -20,10 +20,14 @@
|
|||
#ifndef GST_OSS4_PROPERTY_PROBE_H
|
||||
#define GST_OSS4_PROPERTY_PROBE_H
|
||||
|
||||
#if 0
|
||||
|
||||
#include <gst/interfaces/propertyprobe.h>
|
||||
|
||||
void gst_oss4_add_property_probe_interface (GType type);
|
||||
|
||||
#endif
|
||||
|
||||
gboolean gst_oss4_property_probe_find_device_name (GstObject * obj,
|
||||
int fd,
|
||||
const gchar * device_handle,
|
||||
|
@ -33,6 +37,9 @@ gboolean gst_oss4_property_probe_find_device_name_nofd (GstObject * obj,
|
|||
const gchar * device_handle,
|
||||
gchar ** device_name);
|
||||
|
||||
GValueArray *gst_oss4_property_probe_get_values (GstObject * obj, const gchar * pname);
|
||||
|
||||
|
||||
#endif /* GST_OSS4_PROPERTY_PROBE_H */
|
||||
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
#include <gst/interfaces/streamvolume.h>
|
||||
#include <gst/audio/streamvolume.h>
|
||||
|
||||
#define NO_LEGACY_MIXER
|
||||
#include "oss4-audio.h"
|
||||
|
@ -66,7 +66,6 @@
|
|||
GST_DEBUG_CATEGORY_EXTERN (oss4sink_debug);
|
||||
#define GST_CAT_DEFAULT oss4sink_debug
|
||||
|
||||
static void gst_oss4_sink_init_interfaces (GType type);
|
||||
static void gst_oss4_sink_dispose (GObject * object);
|
||||
static void gst_oss4_sink_finalize (GObject * object);
|
||||
|
||||
|
@ -75,15 +74,15 @@ static void gst_oss4_sink_get_property (GObject * object, guint prop_id,
|
|||
static void gst_oss4_sink_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstCaps *gst_oss4_sink_getcaps (GstBaseSink * bsink);
|
||||
static GstCaps *gst_oss4_sink_getcaps (GstBaseSink * bsink, GstCaps * filter);
|
||||
static gboolean gst_oss4_sink_open (GstAudioSink * asink,
|
||||
gboolean silent_errors);
|
||||
static gboolean gst_oss4_sink_open_func (GstAudioSink * asink);
|
||||
static gboolean gst_oss4_sink_close (GstAudioSink * asink);
|
||||
static gboolean gst_oss4_sink_prepare (GstAudioSink * asink,
|
||||
GstRingBufferSpec * spec);
|
||||
GstAudioRingBufferSpec * spec);
|
||||
static gboolean gst_oss4_sink_unprepare (GstAudioSink * asink);
|
||||
static guint gst_oss4_sink_write (GstAudioSink * asink, gpointer data,
|
||||
static gint gst_oss4_sink_write (GstAudioSink * asink, gpointer data,
|
||||
guint length);
|
||||
static guint gst_oss4_sink_delay (GstAudioSink * asink);
|
||||
static void gst_oss4_sink_reset (GstAudioSink * asink);
|
||||
|
@ -104,8 +103,9 @@ enum
|
|||
PROP_LAST
|
||||
};
|
||||
|
||||
GST_BOILERPLATE_FULL (GstOss4Sink, gst_oss4_sink, GstAudioSink,
|
||||
GST_TYPE_AUDIO_SINK, gst_oss4_sink_init_interfaces);
|
||||
#define gst_oss4_sink_parent_class parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (GstOss4Sink, gst_oss4_sink,
|
||||
GST_TYPE_AUDIO_SINK, G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL));
|
||||
|
||||
static void
|
||||
gst_oss4_sink_dispose (GObject * object)
|
||||
|
@ -120,28 +120,14 @@ gst_oss4_sink_dispose (GObject * object)
|
|||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_sink_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
GstPadTemplate *templ;
|
||||
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"OSS v4 Audio Sink", "Sink/Audio",
|
||||
"Output to a sound card via OSS version 4",
|
||||
"Tim-Philipp Müller <tim centricular net>");
|
||||
|
||||
templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||
gst_oss4_audio_get_template_caps ());
|
||||
gst_element_class_add_pad_template (element_class, templ);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_sink_class_init (GstOss4SinkClass * klass)
|
||||
{
|
||||
GstAudioSinkClass *audiosink_class = (GstAudioSinkClass *) klass;
|
||||
GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
|
||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstPadTemplate *templ;
|
||||
|
||||
gobject_class->dispose = gst_oss4_sink_dispose;
|
||||
gobject_class->finalize = gst_oss4_sink_finalize;
|
||||
|
@ -180,10 +166,19 @@ gst_oss4_sink_class_init (GstOss4SinkClass * klass)
|
|||
audiosink_class->write = GST_DEBUG_FUNCPTR (gst_oss4_sink_write);
|
||||
audiosink_class->delay = GST_DEBUG_FUNCPTR (gst_oss4_sink_delay);
|
||||
audiosink_class->reset = GST_DEBUG_FUNCPTR (gst_oss4_sink_reset);
|
||||
|
||||
gst_element_class_set_static_metadata (gstelement_class,
|
||||
"OSS v4 Audio Sink", "Sink/Audio",
|
||||
"Output to a sound card via OSS version 4",
|
||||
"Tim-Philipp Müller <tim centricular net>");
|
||||
|
||||
templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||
gst_oss4_audio_get_template_caps ());
|
||||
gst_element_class_add_pad_template (gstelement_class, templ);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_sink_init (GstOss4Sink * osssink, GstOss4SinkClass * klass)
|
||||
gst_oss4_sink_init (GstOss4Sink * osssink)
|
||||
{
|
||||
const gchar *device;
|
||||
|
||||
|
@ -206,9 +201,6 @@ gst_oss4_sink_finalize (GObject * object)
|
|||
g_free (osssink->device);
|
||||
osssink->device = NULL;
|
||||
|
||||
g_list_free (osssink->property_probe_list);
|
||||
osssink->property_probe_list = NULL;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
@ -383,7 +375,7 @@ gst_oss4_sink_get_property (GObject * object, guint prop_id,
|
|||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_oss4_sink_getcaps (GstBaseSink * bsink)
|
||||
gst_oss4_sink_getcaps (GstBaseSink * bsink, GstCaps * filter)
|
||||
{
|
||||
GstOss4Sink *oss;
|
||||
GstCaps *caps;
|
||||
|
@ -401,7 +393,16 @@ gst_oss4_sink_getcaps (GstBaseSink * bsink)
|
|||
}
|
||||
}
|
||||
|
||||
return caps;
|
||||
if (filter && caps) {
|
||||
GstCaps *intersection;
|
||||
|
||||
intersection =
|
||||
gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
|
||||
gst_caps_unref (caps);
|
||||
return intersection;
|
||||
} else {
|
||||
return caps;
|
||||
}
|
||||
}
|
||||
|
||||
/* note: we must not take the object lock here unless we fix up get_property */
|
||||
|
@ -576,7 +577,7 @@ gst_oss4_sink_close (GstAudioSink * asink)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_oss4_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
|
||||
gst_oss4_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec)
|
||||
{
|
||||
GstOss4Sink *oss;
|
||||
|
||||
|
@ -588,7 +589,8 @@ gst_oss4_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
oss->bytes_per_sample = spec->bytes_per_sample;
|
||||
oss->bytes_per_sample = GST_AUDIO_INFO_BPF (&spec->info);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -619,7 +621,7 @@ couldnt_reopen:
|
|||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
static gint
|
||||
gst_oss4_sink_write (GstAudioSink * asink, gpointer data, guint length)
|
||||
{
|
||||
GstOss4Sink *oss;
|
||||
|
@ -681,15 +683,3 @@ gst_oss4_sink_reset (GstAudioSink * asink)
|
|||
* same device/fd from multiple threads and might deadlock or blow up in
|
||||
* other ways if we try an ioctl SNDCTL_DSP_HALT or similar */
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_sink_init_interfaces (GType type)
|
||||
{
|
||||
static const GInterfaceInfo svol_iface_info = {
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_iface_info);
|
||||
|
||||
gst_oss4_add_property_probe_interface (type);
|
||||
}
|
||||
|
|
|
@ -47,8 +47,6 @@ struct _GstOss4Sink {
|
|||
gint mute_volume;
|
||||
|
||||
GstCaps * probed_caps;
|
||||
|
||||
GList * property_probe_list;
|
||||
};
|
||||
|
||||
struct _GstOss4SinkClass {
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gst/interfaces/mixer.h>
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
|
||||
#define NO_LEGACY_MIXER
|
||||
|
@ -74,10 +73,8 @@ enum
|
|||
PROP_DEVICE_NAME
|
||||
};
|
||||
|
||||
static void gst_oss4_source_init_interfaces (GType type);
|
||||
|
||||
GST_BOILERPLATE_FULL (GstOss4Source, gst_oss4_source, GstAudioSrc,
|
||||
GST_TYPE_AUDIO_SRC, gst_oss4_source_init_interfaces);
|
||||
#define gst_oss4_source_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstOss4Source, gst_oss4_source, GST_TYPE_AUDIO_SRC);
|
||||
|
||||
static void gst_oss4_source_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
@ -87,44 +84,31 @@ static void gst_oss4_source_set_property (GObject * object, guint prop_id,
|
|||
static void gst_oss4_source_dispose (GObject * object);
|
||||
static void gst_oss4_source_finalize (GstOss4Source * osssrc);
|
||||
|
||||
static GstCaps *gst_oss4_source_getcaps (GstBaseSrc * bsrc);
|
||||
static GstCaps *gst_oss4_source_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
|
||||
|
||||
static gboolean gst_oss4_source_open (GstAudioSrc * asrc,
|
||||
gboolean silent_errors);
|
||||
static gboolean gst_oss4_source_open_func (GstAudioSrc * asrc);
|
||||
static gboolean gst_oss4_source_close (GstAudioSrc * asrc);
|
||||
static gboolean gst_oss4_source_prepare (GstAudioSrc * asrc,
|
||||
GstRingBufferSpec * spec);
|
||||
GstAudioRingBufferSpec * spec);
|
||||
static gboolean gst_oss4_source_unprepare (GstAudioSrc * asrc);
|
||||
static guint gst_oss4_source_read (GstAudioSrc * asrc, gpointer data,
|
||||
guint length);
|
||||
static guint gst_oss4_source_delay (GstAudioSrc * asrc);
|
||||
static void gst_oss4_source_reset (GstAudioSrc * asrc);
|
||||
|
||||
static void
|
||||
gst_oss4_source_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
GstPadTemplate *templ;
|
||||
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"OSS v4 Audio Source", "Source/Audio",
|
||||
"Capture from a sound card via OSS version 4",
|
||||
"Tim-Philipp Müller <tim centricular net>");
|
||||
|
||||
templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
gst_oss4_audio_get_template_caps ());
|
||||
gst_element_class_add_pad_template (element_class, templ);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_class_init (GstOss4SourceClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
GstBaseSrcClass *gstbasesrc_class;
|
||||
GstAudioSrcClass *gstaudiosrc_class;
|
||||
GstPadTemplate *templ;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
gstbasesrc_class = (GstBaseSrcClass *) klass;
|
||||
gstaudiosrc_class = (GstAudioSrcClass *) klass;
|
||||
|
||||
|
@ -153,10 +137,19 @@ gst_oss4_source_class_init (GstOss4SourceClass * klass)
|
|||
g_param_spec_string ("device-name", "Device name",
|
||||
"Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gst_element_class_set_static_metadata (gstelement_class,
|
||||
"OSS v4 Audio Source", "Source/Audio",
|
||||
"Capture from a sound card via OSS version 4",
|
||||
"Tim-Philipp Müller <tim centricular net>");
|
||||
|
||||
templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
gst_oss4_audio_get_template_caps ());
|
||||
gst_element_class_add_pad_template (gstelement_class, templ);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_init (GstOss4Source * osssrc, GstOss4SourceClass * g_class)
|
||||
gst_oss4_source_init (GstOss4Source * osssrc)
|
||||
{
|
||||
const gchar *device;
|
||||
|
||||
|
@ -176,9 +169,6 @@ gst_oss4_source_finalize (GstOss4Source * oss)
|
|||
g_free (oss->device);
|
||||
oss->device = NULL;
|
||||
|
||||
g_list_free (oss->property_probe_list);
|
||||
oss->property_probe_list = NULL;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (oss));
|
||||
}
|
||||
|
||||
|
@ -265,7 +255,7 @@ gst_oss4_source_get_property (GObject * object, guint prop_id,
|
|||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_oss4_source_getcaps (GstBaseSrc * bsrc)
|
||||
gst_oss4_source_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
|
||||
{
|
||||
GstOss4Source *oss;
|
||||
GstCaps *caps;
|
||||
|
@ -283,7 +273,16 @@ gst_oss4_source_getcaps (GstBaseSrc * bsrc)
|
|||
}
|
||||
}
|
||||
|
||||
return caps;
|
||||
if (filter && caps) {
|
||||
GstCaps *intersection;
|
||||
|
||||
intersection =
|
||||
gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
|
||||
gst_caps_unref (caps);
|
||||
return intersection;
|
||||
} else {
|
||||
return caps;
|
||||
}
|
||||
}
|
||||
|
||||
/* note: we must not take the object lock here unless we fix up get_property */
|
||||
|
@ -414,14 +413,6 @@ gst_oss4_source_open_func (GstAudioSrc * asrc)
|
|||
return gst_oss4_source_open (asrc, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_free_mixer_tracks (GstOss4Source * oss)
|
||||
{
|
||||
g_list_foreach (oss->tracks, (GFunc) g_object_unref, NULL);
|
||||
g_list_free (oss->tracks);
|
||||
oss->tracks = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_oss4_source_close (GstAudioSrc * asrc)
|
||||
{
|
||||
|
@ -445,13 +436,11 @@ gst_oss4_source_close (GstAudioSrc * asrc)
|
|||
g_free (oss->device_name);
|
||||
oss->device_name = NULL;
|
||||
|
||||
gst_oss4_source_free_mixer_tracks (oss);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_oss4_source_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
|
||||
gst_oss4_source_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
|
||||
{
|
||||
GstOss4Source *oss;
|
||||
|
||||
|
@ -463,7 +452,8 @@ gst_oss4_source_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
oss->bytes_per_sample = spec->bytes_per_sample;
|
||||
oss->bytes_per_sample = GST_AUDIO_INFO_BPF (&spec->info);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -555,442 +545,3 @@ gst_oss4_source_reset (GstAudioSrc * asrc)
|
|||
* same device/fd from multiple threads and might deadlock or blow up in
|
||||
* other ways if we try an ioctl SNDCTL_DSP_HALT or similar */
|
||||
}
|
||||
|
||||
/* GstMixer interface, which we abuse here for input selection, because we
|
||||
* don't have a proper interface for that and because that's what
|
||||
* gnome-sound-recorder does. */
|
||||
|
||||
/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */
|
||||
G_DEFINE_TYPE (GstOss4SourceInput, gst_oss4_source_input, GST_TYPE_MIXER_TRACK);
|
||||
|
||||
static void
|
||||
gst_oss4_source_input_class_init (GstOss4SourceInputClass * klass)
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_input_init (GstOss4SourceInput * i)
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static void
|
||||
gst_ossmixer_ensure_track_list (GstOssMixer * mixer)
|
||||
{
|
||||
gint i, master = -1;
|
||||
|
||||
g_return_if_fail (mixer->fd != -1);
|
||||
|
||||
if (mixer->tracklist)
|
||||
return;
|
||||
|
||||
/* find master volume */
|
||||
if (mixer->devmask & SOUND_MASK_VOLUME)
|
||||
master = SOUND_MIXER_VOLUME;
|
||||
else if (mixer->devmask & SOUND_MASK_PCM)
|
||||
master = SOUND_MIXER_PCM;
|
||||
else if (mixer->devmask & SOUND_MASK_SPEAKER)
|
||||
master = SOUND_MIXER_SPEAKER; /* doubtful... */
|
||||
/* else: no master, so we won't set any */
|
||||
|
||||
/* build track list */
|
||||
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
|
||||
if (mixer->devmask & (1 << i)) {
|
||||
GstMixerTrack *track;
|
||||
gboolean input = FALSE, stereo = FALSE, record = FALSE;
|
||||
|
||||
/* track exists, make up capabilities */
|
||||
if (MASK_BIT_IS_SET (mixer->stereomask, i))
|
||||
stereo = TRUE;
|
||||
if (MASK_BIT_IS_SET (mixer->recmask, i))
|
||||
input = TRUE;
|
||||
if (MASK_BIT_IS_SET (mixer->recdevs, i))
|
||||
record = TRUE;
|
||||
|
||||
/* do we want mixer in our list? */
|
||||
if (!((mixer->dir & GST_OSS_MIXER_CAPTURE && input == TRUE) ||
|
||||
(mixer->dir & GST_OSS_MIXER_PLAYBACK && i != SOUND_MIXER_PCM)))
|
||||
/* the PLAYBACK case seems hacky, but that's how 0.8 had it */
|
||||
continue;
|
||||
|
||||
/* add track to list */
|
||||
track = gst_ossmixer_track_new (mixer->fd, i, stereo ? 2 : 1,
|
||||
(record ? GST_MIXER_TRACK_RECORD : 0) |
|
||||
(input ? GST_MIXER_TRACK_INPUT :
|
||||
GST_MIXER_TRACK_OUTPUT) |
|
||||
((master != i) ? 0 : GST_MIXER_TRACK_MASTER));
|
||||
mixer->tracklist = g_list_append (mixer->tracklist, track);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* unused with G_DISABLE_* */
|
||||
static G_GNUC_UNUSED gboolean
|
||||
gst_ossmixer_contains_track (GstOssMixer * mixer, GstOssMixerTrack * osstrack)
|
||||
{
|
||||
const GList *item;
|
||||
|
||||
for (item = mixer->tracklist; item != NULL; item = item->next)
|
||||
if (item->data == osstrack)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const GList *
|
||||
gst_ossmixer_list_tracks (GstOssMixer * mixer)
|
||||
{
|
||||
gst_ossmixer_ensure_track_list (mixer);
|
||||
|
||||
return (const GList *) mixer->tracklist;
|
||||
}
|
||||
|
||||
void
|
||||
gst_ossmixer_get_volume (GstOssMixer * mixer,
|
||||
GstMixerTrack * track, gint * volumes)
|
||||
{
|
||||
gint volume;
|
||||
GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
|
||||
|
||||
g_return_if_fail (mixer->fd != -1);
|
||||
g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
|
||||
|
||||
if (track->flags & GST_MIXER_TRACK_MUTE) {
|
||||
volumes[0] = osstrack->lvol;
|
||||
if (track->num_channels == 2) {
|
||||
volumes[1] = osstrack->rvol;
|
||||
}
|
||||
} else {
|
||||
/* get */
|
||||
if (ioctl (mixer->fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
|
||||
g_warning ("Error getting recording device (%d) volume: %s",
|
||||
osstrack->track_num, g_strerror (errno));
|
||||
volume = 0;
|
||||
}
|
||||
|
||||
osstrack->lvol = volumes[0] = (volume & 0xff);
|
||||
if (track->num_channels == 2) {
|
||||
osstrack->rvol = volumes[1] = ((volume >> 8) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gst_ossmixer_set_mute (GstOssMixer * mixer, GstMixerTrack * track,
|
||||
gboolean mute)
|
||||
{
|
||||
int volume;
|
||||
GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
|
||||
|
||||
g_return_if_fail (mixer->fd != -1);
|
||||
g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
|
||||
|
||||
if (mute) {
|
||||
volume = 0;
|
||||
} else {
|
||||
volume = (osstrack->lvol & 0xff);
|
||||
if (MASK_BIT_IS_SET (mixer->stereomask, osstrack->track_num)) {
|
||||
volume |= ((osstrack->rvol & 0xff) << 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl (mixer->fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
|
||||
g_warning ("Error setting mixer recording device volume (0x%x): %s",
|
||||
volume, g_strerror (errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mute) {
|
||||
track->flags |= GST_MIXER_TRACK_MUTE;
|
||||
} else {
|
||||
track->flags &= ~GST_MIXER_TRACK_MUTE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static gint
|
||||
gst_oss4_source_mixer_get_current_input (GstOss4Source * oss)
|
||||
{
|
||||
int cur = -1;
|
||||
|
||||
if (ioctl (oss->fd, SNDCTL_DSP_GET_RECSRC, &cur) == -1 || cur < 0)
|
||||
return -1;
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
gst_oss4_source_mixer_update_record_flags (GstOss4Source * oss, gint cur_route)
|
||||
{
|
||||
const gchar *cur_name = "";
|
||||
GList *t;
|
||||
|
||||
for (t = oss->tracks; t != NULL; t = t->next) {
|
||||
GstMixerTrack *track = t->data;
|
||||
|
||||
if (GST_OSS4_SOURCE_INPUT (track)->route == cur_route) {
|
||||
if (!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) {
|
||||
track->flags |= GST_MIXER_TRACK_RECORD;
|
||||
/* no point in sending a mixer-record-changes message here */
|
||||
}
|
||||
cur_name = track->label;
|
||||
} else {
|
||||
if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) {
|
||||
track->flags &= ~GST_MIXER_TRACK_RECORD;
|
||||
/* no point in sending a mixer-record-changes message here */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cur_name;
|
||||
}
|
||||
|
||||
static const GList *
|
||||
gst_oss4_source_mixer_list_tracks (GstMixer * mixer)
|
||||
{
|
||||
oss_mixer_enuminfo names = { 0, };
|
||||
GstOss4Source *oss;
|
||||
const gchar *cur_name;
|
||||
GList *tracks = NULL;
|
||||
gint i, cur;
|
||||
|
||||
g_return_val_if_fail (mixer != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_OSS4_SOURCE (mixer), NULL);
|
||||
g_return_val_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer), NULL);
|
||||
|
||||
oss = GST_OSS4_SOURCE (mixer);
|
||||
|
||||
if (oss->tracks != NULL && oss->tracks_static)
|
||||
goto done;
|
||||
|
||||
if (ioctl (oss->fd, SNDCTL_DSP_GET_RECSRC_NAMES, &names) == -1)
|
||||
goto get_recsrc_names_error;
|
||||
|
||||
oss->tracks_static = (names.version == 0);
|
||||
|
||||
GST_INFO_OBJECT (oss, "%d inputs (list is static: %s):", names.nvalues,
|
||||
(oss->tracks_static) ? "yes" : "no");
|
||||
|
||||
for (i = 0; i < MIN (names.nvalues, OSS_ENUM_MAXVALUE + 1); ++i) {
|
||||
GstMixerTrack *track;
|
||||
|
||||
track = g_object_new (GST_TYPE_OSS4_SOURCE_INPUT, NULL);
|
||||
track->label = g_strdup (&names.strings[names.strindex[i]]);
|
||||
track->flags = GST_MIXER_TRACK_INPUT;
|
||||
track->num_channels = 2;
|
||||
track->min_volume = 0;
|
||||
track->max_volume = 100;
|
||||
GST_OSS4_SOURCE_INPUT (track)->route = i;
|
||||
|
||||
GST_INFO_OBJECT (oss, " [%d] %s", i, track->label);
|
||||
tracks = g_list_append (tracks, track);
|
||||
}
|
||||
|
||||
gst_oss4_source_free_mixer_tracks (oss);
|
||||
oss->tracks = tracks;
|
||||
|
||||
done:
|
||||
|
||||
/* update RECORD flags */
|
||||
cur = gst_oss4_source_mixer_get_current_input (oss);
|
||||
cur_name = gst_oss4_source_mixer_update_record_flags (oss, cur);
|
||||
GST_DEBUG_OBJECT (oss, "current input route: %d (%s)", cur, cur_name);
|
||||
|
||||
return (const GList *) oss->tracks;
|
||||
|
||||
/* ERRORS */
|
||||
get_recsrc_names_error:
|
||||
{
|
||||
GST_WARNING_OBJECT (oss, "GET_RECSRC_NAMES failed: %s", g_strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_mixer_set_volume (GstMixer * mixer, GstMixerTrack * track,
|
||||
gint * volumes)
|
||||
{
|
||||
GstOss4Source *oss;
|
||||
int new_vol, cur;
|
||||
|
||||
g_return_if_fail (mixer != NULL);
|
||||
g_return_if_fail (track != NULL);
|
||||
g_return_if_fail (GST_IS_MIXER_TRACK (track));
|
||||
g_return_if_fail (GST_IS_OSS4_SOURCE (mixer));
|
||||
g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer));
|
||||
|
||||
oss = GST_OSS4_SOURCE (mixer);
|
||||
|
||||
cur = gst_oss4_source_mixer_get_current_input (oss);
|
||||
if (cur != GST_OSS4_SOURCE_INPUT (track)->route) {
|
||||
GST_DEBUG_OBJECT (oss, "track not selected input route, ignoring request");
|
||||
return;
|
||||
}
|
||||
|
||||
new_vol = (volumes[1] << 8) | volumes[0];
|
||||
if (ioctl (oss->fd, SNDCTL_DSP_SETRECVOL, &new_vol) == -1) {
|
||||
GST_WARNING_OBJECT (oss, "SETRECVOL failed: %s", g_strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_mixer_get_volume (GstMixer * mixer, GstMixerTrack * track,
|
||||
gint * volumes)
|
||||
{
|
||||
GstOss4Source *oss;
|
||||
int cur;
|
||||
|
||||
g_return_if_fail (mixer != NULL);
|
||||
g_return_if_fail (GST_IS_OSS4_SOURCE (mixer));
|
||||
g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer));
|
||||
|
||||
oss = GST_OSS4_SOURCE (mixer);
|
||||
|
||||
cur = gst_oss4_source_mixer_get_current_input (oss);
|
||||
if (cur != GST_OSS4_SOURCE_INPUT (track)->route) {
|
||||
volumes[0] = 0;
|
||||
volumes[1] = 0;
|
||||
} else {
|
||||
int vol = -1;
|
||||
|
||||
if (ioctl (oss->fd, SNDCTL_DSP_GETRECVOL, &vol) == -1 || vol < 0) {
|
||||
GST_WARNING_OBJECT (oss, "GETRECVOL failed: %s", g_strerror (errno));
|
||||
volumes[0] = 100;
|
||||
volumes[1] = 100;
|
||||
} else {
|
||||
volumes[0] = MIN (100, vol & 0xff);
|
||||
volumes[1] = MIN (100, (vol >> 8) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_mixer_set_record (GstMixer * mixer, GstMixerTrack * track,
|
||||
gboolean record)
|
||||
{
|
||||
GstOss4Source *oss;
|
||||
const gchar *cur_name;
|
||||
gint cur;
|
||||
|
||||
g_return_if_fail (mixer != NULL);
|
||||
g_return_if_fail (track != NULL);
|
||||
g_return_if_fail (GST_IS_MIXER_TRACK (track));
|
||||
g_return_if_fail (GST_IS_OSS4_SOURCE (mixer));
|
||||
g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer));
|
||||
|
||||
oss = GST_OSS4_SOURCE (mixer);
|
||||
|
||||
cur = gst_oss4_source_mixer_get_current_input (oss);
|
||||
|
||||
/* stop recording for an input that's not selected anyway => nothing to do */
|
||||
if (!record && cur != GST_OSS4_SOURCE_INPUT (track)->route)
|
||||
goto done;
|
||||
|
||||
/* select recording for an input that's already selected => nothing to do
|
||||
* (or should we mess with the recording volume in this case maybe?) */
|
||||
if (record && cur == GST_OSS4_SOURCE_INPUT (track)->route)
|
||||
goto done;
|
||||
|
||||
/* make current input stop recording: we can't really make an input stop
|
||||
* recording, we can only select an input FOR recording, so we'll just ignore
|
||||
* all requests to stop for now */
|
||||
if (!record) {
|
||||
GST_WARNING_OBJECT (oss, "Can't un-select an input as such, only switch "
|
||||
"to a different input source");
|
||||
/* FIXME: set recording volume to 0 maybe? */
|
||||
} else {
|
||||
int new_route = GST_OSS4_SOURCE_INPUT (track)->route;
|
||||
|
||||
/* select this input for recording */
|
||||
|
||||
if (ioctl (oss->fd, SNDCTL_DSP_SET_RECSRC, &new_route) == -1) {
|
||||
GST_WARNING_OBJECT (oss, "Could not select input %d for recording: %s",
|
||||
new_route, g_strerror (errno));
|
||||
} else {
|
||||
cur = new_route;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
cur_name = gst_oss4_source_mixer_update_record_flags (oss, cur);
|
||||
GST_DEBUG_OBJECT (oss, "active input route: %d (%s)", cur, cur_name);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track,
|
||||
gboolean mute)
|
||||
{
|
||||
g_return_if_fail (mixer != NULL);
|
||||
g_return_if_fail (track != NULL);
|
||||
g_return_if_fail (GST_IS_MIXER_TRACK (track));
|
||||
g_return_if_fail (GST_IS_OSS4_SOURCE (mixer));
|
||||
g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer));
|
||||
|
||||
/* FIXME: implement gst_oss4_source_mixer_set_mute() - what to do here? */
|
||||
/* oss4_mixer_set_mute (mixer->mixer, track, mute); */
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_mixer_interface_init (GstMixerInterface * iface)
|
||||
{
|
||||
GST_MIXER_TYPE (iface) = GST_MIXER_HARDWARE;
|
||||
|
||||
iface->list_tracks = gst_oss4_source_mixer_list_tracks;
|
||||
iface->set_volume = gst_oss4_source_mixer_set_volume;
|
||||
iface->get_volume = gst_oss4_source_mixer_get_volume;
|
||||
iface->set_mute = gst_oss4_source_mixer_set_mute;
|
||||
iface->set_record = gst_oss4_source_mixer_set_record;
|
||||
}
|
||||
|
||||
/* Implement the horror that is GstImplementsInterface */
|
||||
|
||||
static gboolean
|
||||
gst_oss4_source_mixer_supported (GstImplementsInterface * iface,
|
||||
GType iface_type)
|
||||
{
|
||||
GstOss4Source *oss;
|
||||
gboolean is_open;
|
||||
|
||||
g_return_val_if_fail (GST_IS_OSS4_SOURCE (iface), FALSE);
|
||||
g_return_val_if_fail (iface_type == GST_TYPE_MIXER, FALSE);
|
||||
|
||||
oss = GST_OSS4_SOURCE (iface);
|
||||
|
||||
GST_OBJECT_LOCK (oss);
|
||||
is_open = GST_OSS4_SOURCE_IS_OPEN (iface);
|
||||
GST_OBJECT_UNLOCK (oss);
|
||||
|
||||
return is_open;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_mixer_implements_interface_init (GstImplementsInterfaceClass *
|
||||
klass)
|
||||
{
|
||||
klass->supported = gst_oss4_source_mixer_supported;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_oss4_source_init_interfaces (GType type)
|
||||
{
|
||||
static const GInterfaceInfo implements_iface_info = {
|
||||
(GInterfaceInitFunc) gst_oss4_source_mixer_implements_interface_init,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
static const GInterfaceInfo mixer_iface_info = {
|
||||
(GInterfaceInitFunc) gst_oss4_source_mixer_interface_init,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
|
||||
&implements_iface_info);
|
||||
g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
|
||||
|
||||
gst_oss4_add_property_probe_interface (type);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/audio/gstaudiosrc.h>
|
||||
#include <gst/interfaces/mixertrack.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -46,13 +45,6 @@ struct _GstOss4Source {
|
|||
gint bytes_per_sample;
|
||||
|
||||
GstCaps * probed_caps;
|
||||
|
||||
/* property probe interface */
|
||||
GList * property_probe_list;
|
||||
|
||||
/* mixer interface */
|
||||
GList * tracks;
|
||||
gboolean tracks_static; /* FALSE if the list of inputs may change */
|
||||
};
|
||||
|
||||
struct _GstOss4SourceClass {
|
||||
|
@ -61,28 +53,6 @@ struct _GstOss4SourceClass {
|
|||
|
||||
GType gst_oss4_source_get_type (void);
|
||||
|
||||
/* our mixer track for input selection */
|
||||
#define GST_TYPE_OSS4_SOURCE_INPUT (gst_oss4_source_input_get_type())
|
||||
#define GST_OSS4_SOURCE_INPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_SOURCE_INPUT,GstOss4SourceInput))
|
||||
#define GST_OSS4_SOURCE_INPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_SOURCE_INPUT,GstOss4SourceInputClass))
|
||||
#define GST_IS_OSS4_SOURCE_INPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_SOURCE_INPUT))
|
||||
#define GST_IS_OSS4_SOURCE_INPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_SOURCE_INPUT))
|
||||
|
||||
typedef struct _GstOss4SourceInput GstOss4SourceInput;
|
||||
typedef struct _GstOss4SourceInputClass GstOss4SourceInputClass;
|
||||
|
||||
struct _GstOss4SourceInput {
|
||||
GstMixerTrack mixer_track;
|
||||
|
||||
int route; /* number for SNDCTL_DSP_SET_RECSRC etc. */
|
||||
};
|
||||
|
||||
struct _GstOss4SourceInputClass {
|
||||
GstMixerTrackClass mixer_track_class;
|
||||
};
|
||||
|
||||
GType gst_oss4_source_input_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GST_OSS4_SOURCE_H */
|
||||
|
|
Loading…
Reference in a new issue