summaryrefslogtreecommitdiffstats
path: root/sys/oss/gstossmixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/oss/gstossmixer.c')
-rw-r--r--sys/oss/gstossmixer.c475
1 files changed, 149 insertions, 326 deletions
diff --git a/sys/oss/gstossmixer.c b/sys/oss/gstossmixer.c
index 1d462908..1e972568 100644
--- a/sys/oss/gstossmixer.c
+++ b/sys/oss/gstossmixer.c
@@ -35,257 +35,186 @@
#include <gst/gst-i18n-plugin.h>
#include "gstossmixer.h"
+#include "gstossmixertrack.h"
#define MASK_BIT_IS_SET(mask, bit) \
(mask & (1 << bit))
-static void gst_ossmixer_track_class_init (GstOssMixerTrackClass * klass);
-static void gst_ossmixer_track_init (GstOssMixerTrack * track);
+static gboolean
+gst_ossmixer_open (GstOssMixer * mixer)
+{
+#ifdef SOUND_MIXER_INFO
+ struct mixer_info minfo;
+#endif
-static gboolean gst_ossmixer_supported (GstImplementsInterface * iface,
- GType iface_type);
-static const GList *gst_ossmixer_list_tracks (GstMixer * ossmixer);
+ g_return_val_if_fail (mixer->mixer_fd == -1, FALSE);
-static void gst_ossmixer_set_volume (GstMixer * ossmixer,
- GstMixerTrack * track, gint * volumes);
-static void gst_ossmixer_get_volume (GstMixer * ossmixer,
- GstMixerTrack * track, gint * volumes);
+ mixer->mixer_fd = open (mixer->device, O_RDWR);
+ if (mixer->mixer_fd == -1) {
+ /* this is valid. OSS devices don't need to expose a mixer */
+ GST_DEBUG ("Failed to open mixer device %s, mixing disabled: %s",
+ mixer->device, strerror (errno));
+ return FALSE;
+ }
-static void gst_ossmixer_set_record (GstMixer * ossmixer,
- GstMixerTrack * track, gboolean record);
-static void gst_ossmixer_set_mute (GstMixer * ossmixer,
- GstMixerTrack * track, gboolean mute);
+ /* get masks */
+ if (ioctl (mixer->mixer_fd, SOUND_MIXER_READ_RECMASK, &mixer->recmask) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_RECSRC, &mixer->recdevs) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_STEREODEVS,
+ &mixer->stereomask) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_DEVMASK, &mixer->devmask) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_CAPS, &mixer->mixcaps) < 0) {
+ GST_DEBUG ("Failed to get device masks");
+ close (mixer->mixer_fd);
+ mixer->mixer_fd = -1;
+ return FALSE;
+ }
-static const gchar **labels = NULL;
-static GstMixerTrackClass *parent_class = NULL;
+ /* get name */
+#ifdef SOUND_MIXER_INFO
+ if (ioctl (mixer->mixer_fd, SOUND_MIXER_INFO, &minfo) == 0) {
+ mixer->cardname = g_strdup (minfo.name);
+ }
+#else
+ oss->cardname = g_strdup ("Unknown");
+#endif
-/* three functions: firstly, OSS has the nasty habit of inserting
- * spaces in the labels, we want to get rid of them. Secondly,
- * i18n is impossible with OSS' way of providing us with mixer
- * labels, so we make a 'given' list of i18n'ed labels. Thirdly, I
- * personally don't like the "1337" names that OSS gives to their
- * labels ("Vol", "Mic", "Rec"), I'd rather see full names. */
+ return TRUE;
+}
static void
-fill_labels (void)
+gst_ossmixer_ensure_track_list (GstOssMixer * mixer)
{
- gint i, pos;
- gchar *origs[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
- struct
- {
- gchar *given, *wanted;
- }
- cases[] = {
- /* Note: this list is simply ripped from soundcard.h. For
- * some people, some values might be missing (3D surround,
- * etc.) - feel free to add them. That's the reason why
- * I'm doing this in such a horribly complicated way. */
- {
- "Vol ", _("Volume")}
- , {
- "Bass ", _("Bass")}
- , {
- "Trebl", _("Treble")}
- , {
- "Synth", _("Synth")}
- , {
- "Pcm ", _("PCM")}
- , {
- "Spkr ", _("Speaker")}
- , {
- "Line ", _("Line-in")}
- , {
- "Mic ", _("Microphone")}
- , {
- "CD ", _("CD")}
- , {
- "Mix ", _("Mixer")}
- , {
- "Pcm2 ", _("PCM-2")}
- , {
- "Rec ", _("Record")}
- , {
- "IGain", _("In-gain")}
- , {
- "OGain", _("Out-gain")}
- , {
- "Line1", _("Line-1")}
- , {
- "Line2", _("Line-2")}
- , {
- "Line3", _("Line-3")}
- , {
- "Digital1", _("Digital-1")}
- , {
- "Digital2", _("Digital-2")}
- , {
- "Digital3", _("Digital-3")}
- , {
- "PhoneIn", _("Phone-in")}
- , {
- "PhoneOut", _("Phone-out")}
- , {
- "Video", _("Video")}
- , {
- "Radio", _("Radio")}
- , {
- "Monitor", _("Monitor")}
- , {
- NULL, NULL}
- };
-
- labels = g_malloc (sizeof (gchar *) * SOUND_MIXER_NRDEVICES);
+ gint i, master = -1;
+
+ g_return_if_fail (mixer->mixer_fd != -1);
+ if (mixer->tracklist)
+ return;
+
+ /* find master volume */
+ if (mixer->devmask & SOUND_MASK_VOLUME)
+ master = SOUND_MIXER_VOLUME;
+ else if (mixer->devmask & SOUND_MASK_PCM)
+ master = SOUND_MIXER_PCM;
+ else if (mixer->devmask & SOUND_MASK_SPEAKER)
+ master = SOUND_MIXER_SPEAKER; /* doubtful... */
+ /* else: no master, so we won't set any */
+
+ /* build track list */
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
- for (pos = 0; cases[pos].given != NULL; pos++) {
- if (!strcmp (cases[pos].given, origs[i])) {
- labels[i] = g_strdup (cases[pos].wanted);
- break;
- }
+ if (mixer->devmask & (1 << i)) {
+ GstMixerTrack *track;
+ gboolean input = FALSE, stereo = FALSE, record = FALSE;
+
+ /* track exists, make up capabilities */
+ if (MASK_BIT_IS_SET (mixer->stereomask, i))
+ stereo = TRUE;
+ if (MASK_BIT_IS_SET (mixer->recmask, i))
+ input = TRUE;
+ if (MASK_BIT_IS_SET (mixer->recdevs, i))
+ record = TRUE;
+
+ /* do we want this in our list? */
+ if (!((mixer->dir & GST_OSS_MIXER_CAPTURE && input == TRUE) ||
+ (mixer->dir & GST_OSS_MIXER_PLAYBACK && i != SOUND_MIXER_PCM)))
+ /* the PLAYBACK case seems hacky, but that's how 0.8 had it */
+ continue;
+
+ /* add track to list */
+ track = gst_ossmixer_track_new (mixer->mixer_fd, i, stereo ? 2 : 1,
+ (record ? GST_MIXER_TRACK_RECORD : 0) |
+ (input ? GST_MIXER_TRACK_INPUT :
+ GST_MIXER_TRACK_OUTPUT) |
+ ((master != i) ? 0 : GST_MIXER_TRACK_MASTER));
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
}
- if (cases[pos].given == NULL)
- labels[i] = g_strdup (origs[i]);
}
}
-GType
-gst_ossmixer_track_get_type (void)
+GstOssMixer *
+gst_ossmixer_new (const char *device, GstOssMixerDirection dir)
{
- static GType gst_ossmixer_track_type = 0;
-
- if (!gst_ossmixer_track_type) {
- static const GTypeInfo ossmixer_track_info = {
- sizeof (GstOssMixerTrackClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_ossmixer_track_class_init,
- NULL,
- NULL,
- sizeof (GstOssMixerTrack),
- 0,
- (GInstanceInitFunc) gst_ossmixer_track_init,
- NULL
- };
-
- gst_ossmixer_track_type =
- g_type_register_static (GST_TYPE_MIXER_TRACK,
- "GstOssMixerTrack", &ossmixer_track_info, 0);
- }
+ GstOssMixer *ret = NULL;
- return gst_ossmixer_track_type;
-}
+ g_return_val_if_fail (device != NULL, NULL);
-static void
-gst_ossmixer_track_class_init (GstOssMixerTrackClass * klass)
-{
- parent_class = g_type_class_ref (GST_TYPE_MIXER_TRACK);
-}
+ ret = g_new0 (GstOssMixer, 1);
-static void
-gst_ossmixer_track_init (GstOssMixerTrack * track)
-{
- track->lvol = track->rvol = 0;
- track->track_num = 0;
-}
+ ret->device = g_strdup (device);
+ ret->dir = dir;
-GstMixerTrack *
-gst_ossmixer_track_new (GstOssDevice * oss,
- gint track_num, gint max_chans, gint flags)
-{
- GstOssMixerTrack *osstrack;
- GstMixerTrack *track;
- gint volume;
+ if (!gst_ossmixer_open (ret))
+ goto error;
- if (!labels)
- fill_labels ();
-
- osstrack = g_object_new (GST_TYPE_OSSMIXER_TRACK, NULL);
- track = GST_MIXER_TRACK (osstrack);
- track->label = g_strdup (labels[track_num]);
- track->num_channels = max_chans;
- track->flags = flags;
- track->min_volume = 0;
- track->max_volume = 100;
- osstrack->track_num = track_num;
-
- /* volume */
- if (ioctl (oss->mixer_fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
- g_warning ("Error getting device (%d) volume: %s",
- osstrack->track_num, strerror (errno));
- volume = 0;
- }
- osstrack->lvol = (volume & 0xff);
- if (track->num_channels == 2) {
- osstrack->rvol = ((volume >> 8) & 0xff);
- }
+ return ret;
- return track;
-}
+error:
+ if (ret)
+ gst_ossmixer_free (ret);
-void
-gst_oss_interface_init (GstImplementsInterfaceClass * klass)
-{
- /* default virtual functions */
- klass->supported = gst_ossmixer_supported;
+ return NULL;
}
void
-gst_ossmixer_interface_init (GstMixerClass * klass)
+gst_ossmixer_free (GstOssMixer * mixer)
{
- GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE;
-
- /* default virtual functions */
- klass->list_tracks = gst_ossmixer_list_tracks;
- klass->set_volume = gst_ossmixer_set_volume;
- klass->get_volume = gst_ossmixer_get_volume;
- klass->set_mute = gst_ossmixer_set_mute;
- klass->set_record = gst_ossmixer_set_record;
-}
+ g_return_if_fail (mixer != NULL);
-static gboolean
-gst_ossmixer_supported (GstImplementsInterface * iface, GType iface_type)
-{
- GstOssDevice *oss = g_object_get_data (G_OBJECT (iface), "oss-data");
+ if (mixer->device) {
+ g_free (mixer->device);
+ mixer->device = NULL;
+ }
+
+ if (mixer->cardname) {
+ g_free (mixer->cardname);
+ mixer->cardname = NULL;
+ }
+
+ if (mixer->tracklist) {
+ g_list_foreach (mixer->tracklist, (GFunc) g_object_unref, NULL);
+ g_list_free (mixer->tracklist);
+ mixer->tracklist = NULL;
+ }
- g_return_val_if_fail (oss != NULL, FALSE);
- g_assert (iface_type == GST_TYPE_MIXER);
+ if (mixer->mixer_fd != -1) {
+ close (mixer->mixer_fd);
+ mixer->mixer_fd = -1;
+ }
- return (oss->mixer_fd != -1);
+ g_free (mixer);
}
/* unused with G_DISABLE_* */
static G_GNUC_UNUSED gboolean
-gst_ossmixer_contains_track (GstOssDevice * oss, GstOssMixerTrack * osstrack)
+gst_ossmixer_contains_track (GstOssMixer * mixer, GstOssMixerTrack * osstrack)
{
const GList *item;
- for (item = oss->tracklist; item != NULL; item = item->next)
+ for (item = mixer->tracklist; item != NULL; item = item->next)
if (item->data == osstrack)
return TRUE;
return FALSE;
}
-static const GList *
-gst_ossmixer_list_tracks (GstMixer * mixer)
+const GList *
+gst_ossmixer_list_tracks (GstOssMixer * mixer)
{
- GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
+ gst_ossmixer_ensure_track_list (mixer);
- return (const GList *) oss->tracklist;
+ return (const GList *) mixer->tracklist;
}
-static void
-gst_ossmixer_get_volume (GstMixer * mixer,
+void
+gst_ossmixer_get_volume (GstOssMixer * mixer,
GstMixerTrack * track, gint * volumes)
{
gint volume;
- GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (oss != NULL);
- g_return_if_fail (oss->mixer_fd != -1);
- g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
if (track->flags & GST_MIXER_TRACK_MUTE) {
volumes[0] = osstrack->lvol;
@@ -294,7 +223,7 @@ gst_ossmixer_get_volume (GstMixer * mixer,
}
} else {
/* get */
- if (ioctl (oss->mixer_fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
+ if (ioctl (mixer->mixer_fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
g_warning ("Error getting recording device (%d) volume: %s",
osstrack->track_num, strerror (errno));
volume = 0;
@@ -307,18 +236,15 @@ gst_ossmixer_get_volume (GstMixer * mixer,
}
}
-static void
-gst_ossmixer_set_volume (GstMixer * mixer,
+void
+gst_ossmixer_set_volume (GstOssMixer * mixer,
GstMixerTrack * track, gint * volumes)
{
gint volume;
- GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (oss != NULL);
- g_return_if_fail (oss->mixer_fd != -1);
- g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
/* prepare the value for ioctl() */
if (!(track->flags & GST_MIXER_TRACK_MUTE)) {
@@ -328,7 +254,7 @@ gst_ossmixer_set_volume (GstMixer * mixer,
}
/* set */
- if (ioctl (oss->mixer_fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
+ if (ioctl (mixer->mixer_fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
g_warning ("Error setting recording device (%d) volume (0x%x): %s",
osstrack->track_num, volume, strerror (errno));
return;
@@ -341,28 +267,26 @@ gst_ossmixer_set_volume (GstMixer * mixer,
}
}
-static void
-gst_ossmixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
+void
+gst_ossmixer_set_mute (GstOssMixer * mixer, GstMixerTrack * track,
+ gboolean mute)
{
int volume;
- GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (oss != NULL);
- g_return_if_fail (oss->mixer_fd != -1);
- g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
if (mute) {
volume = 0;
} else {
volume = (osstrack->lvol & 0xff);
- if (MASK_BIT_IS_SET (oss->stereomask, osstrack->track_num)) {
+ if (MASK_BIT_IS_SET (mixer->stereomask, osstrack->track_num)) {
volume |= ((osstrack->rvol & 0xff) << 8);
}
}
- if (ioctl (oss->mixer_fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
+ if (ioctl (mixer->mixer_fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
g_warning ("Error setting mixer recording device volume (0x%x): %s",
volume, strerror (errno));
return;
@@ -375,17 +299,14 @@ gst_ossmixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
}
}
-static void
-gst_ossmixer_set_record (GstMixer * mixer,
+void
+gst_ossmixer_set_record (GstOssMixer * mixer,
GstMixerTrack * track, gboolean record)
{
- GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (oss != NULL);
- g_return_if_fail (oss->mixer_fd != -1);
- g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
/* if there's nothing to do... */
if ((record && GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) ||
@@ -393,28 +314,28 @@ gst_ossmixer_set_record (GstMixer * mixer,
return;
/* if we're exclusive, then we need to unset the current one(s) */
- if (oss->mixcaps & SOUND_CAP_EXCL_INPUT) {
+ if (mixer->mixcaps & SOUND_CAP_EXCL_INPUT) {
GList *track;
- for (track = oss->tracklist; track != NULL; track = track->next) {
+ for (track = mixer->tracklist; track != NULL; track = track->next) {
GstMixerTrack *turn = (GstMixerTrack *) track->data;
turn->flags &= ~GST_MIXER_TRACK_RECORD;
}
- oss->recdevs = 0;
+ mixer->recdevs = 0;
}
/* set new record bit, if needed */
if (record) {
- oss->recdevs |= (1 << osstrack->track_num);
+ mixer->recdevs |= (1 << osstrack->track_num);
} else {
- oss->recdevs &= ~(1 << osstrack->track_num);
+ mixer->recdevs &= ~(1 << osstrack->track_num);
}
/* set it to the device */
- if (ioctl (oss->mixer_fd, SOUND_MIXER_WRITE_RECSRC, &oss->recdevs) < 0) {
+ if (ioctl (mixer->mixer_fd, SOUND_MIXER_WRITE_RECSRC, &mixer->recdevs) < 0) {
g_warning ("Error setting mixer recording devices (0x%x): %s",
- oss->recdevs, strerror (errno));
+ mixer->recdevs, strerror (errno));
return;
}
@@ -424,101 +345,3 @@ gst_ossmixer_set_record (GstMixer * mixer,
track->flags &= ~GST_MIXER_TRACK_RECORD;
}
}
-
-void
-gst_ossmixer_build_list (GstOssDeviceCombination * c, GstOssDevice * oss)
-{
- gint i, devmask, master = -1;
-
-#ifdef SOUND_MIXER_INFO
- struct mixer_info minfo;
-#endif
-
- g_return_if_fail (oss->mixer_fd == -1);
-
- oss->mixer_fd = open (c->mixer, O_RDWR);
- if (oss->mixer_fd == -1) {
- /* this is valid. OSS devices don't need to expose a mixer */
- GST_DEBUG ("Failed to open mixer device %s, mixing disabled: %s",
- c->mixer, strerror (errno));
- return;
- }
-
- /* get masks */
- if (ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECMASK, &oss->recmask) < 0 ||
- ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECSRC, &oss->recdevs) < 0 ||
- ioctl (oss->mixer_fd, SOUND_MIXER_READ_STEREODEVS, &oss->stereomask) < 0
- || ioctl (oss->mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0
- || ioctl (oss->mixer_fd, SOUND_MIXER_READ_CAPS, &oss->mixcaps) < 0) {
- GST_DEBUG ("Failed to get device masks - disabling mixer");
- close (oss->mixer_fd);
- oss->mixer_fd = -1;
- return;
- }
-
- /* get name */
-#ifdef SOUND_MIXER_INFO
- if (ioctl (oss->mixer_fd, SOUND_MIXER_INFO, &minfo) == 0) {
- oss->device_name = g_strdup (minfo.name);
- }
-#else
- oss->device_name = g_strdup ("Unknown");
-#endif
-
- /* find master volume */
- if (devmask & SOUND_MASK_VOLUME)
- master = SOUND_MIXER_VOLUME;
- else if (devmask & SOUND_MASK_PCM)
- master = SOUND_MIXER_PCM;
- else if (devmask & SOUND_MASK_SPEAKER)
- master = SOUND_MIXER_SPEAKER; /* doubtful... */
- /* else: no master, so we won't set any */
-
- /* build track list */
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
- if (devmask & (1 << i)) {
- GstMixerTrack *track;
- gboolean input = FALSE, stereo = FALSE, record = FALSE;
-
- /* track exists, make up capabilities */
- if (MASK_BIT_IS_SET (oss->stereomask, i))
- stereo = TRUE;
- if (MASK_BIT_IS_SET (oss->recmask, i))
- input = TRUE;
- if (MASK_BIT_IS_SET (oss->recdevs, i))
- record = TRUE;
-
- /* do we want this in our list? */
- if ((oss->mode == GST_OSS_MODE_READ && input == FALSE) ||
- (oss->mode == GST_OSS_MODE_WRITE && i != SOUND_MIXER_PCM))
- continue;
-
- /* add track to list */
- track = gst_ossmixer_track_new (oss, i, stereo ? 2 : 1,
- (record ? GST_MIXER_TRACK_RECORD : 0) |
- (input ? GST_MIXER_TRACK_INPUT :
- GST_MIXER_TRACK_OUTPUT) |
- ((master != i) ? 0 : GST_MIXER_TRACK_MASTER));
- oss->tracklist = g_list_append (oss->tracklist, track);
- }
- }
-}
-
-void
-gst_ossmixer_free_list (GstOssDevice * oss)
-{
- if (oss->mixer_fd == -1)
- return;
-
- g_list_foreach (oss->tracklist, (GFunc) g_object_unref, NULL);
- g_list_free (oss->tracklist);
- oss->tracklist = NULL;
-
- if (oss->device_name) {
- g_free (oss->device_name);
- oss->device_name = NULL;
- }
-
- close (oss->mixer_fd);
- oss->mixer_fd = -1;
-}