Make GstMixerTrack a GObject. I also want to make it emit several signals, starting work is in here but it's not full...

Original commit message from CVS:
Make GstMixerTrack a GObject. I also want to make it emit several signals, starting work is in here but it's not fully implemented yet. for OSS, this will cause issues, but for ALSA, this is all automated.
This commit is contained in:
Ronald S. Bultje 2003-10-10 12:24:20 +00:00
parent c5c78205bc
commit 4506e60ea0
4 changed files with 171 additions and 56 deletions

View file

@ -40,6 +40,7 @@ enum {
ARG_0, ARG_0,
ARG_DEVICE, ARG_DEVICE,
ARG_MIXERDEV, ARG_MIXERDEV,
ARG_DEVICE_NAME,
}; };
/* elementfactory information */ /* elementfactory information */
@ -124,12 +125,15 @@ gst_osselement_class_init (GstOssElementClass *klass)
parent_class = g_type_class_ref (GST_TYPE_ELEMENT); parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE, g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE,
g_param_spec_string ("device", "device", "oss device (/dev/dspN usually)", g_param_spec_string ("device", "Device", "OSS device (/dev/dspN usually)",
"default", G_PARAM_READWRITE)); "default", G_PARAM_READWRITE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MIXERDEV, g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MIXERDEV,
g_param_spec_string ("mixerdev", "mixer device", g_param_spec_string ("mixerdev", "Mixer device",
"oss mixer device (/dev/mixerN usually)", "OSS mixer device (/dev/mixerN usually)",
"default", G_PARAM_READWRITE)); "default", G_PARAM_READWRITE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MIXERDEV,
g_param_spec_string ("device_name", "Device name", "Name of the device",
NULL, G_PARAM_READABLE));
gobject_class->set_property = gst_osselement_set_property; gobject_class->set_property = gst_osselement_set_property;
gobject_class->get_property = gst_osselement_get_property; gobject_class->get_property = gst_osselement_get_property;
@ -146,6 +150,7 @@ gst_osselement_init (GstOssElement *oss)
oss->fd = -1; oss->fd = -1;
oss->mixer_fd = -1; oss->mixer_fd = -1;
oss->tracklist = NULL; oss->tracklist = NULL;
oss->device_name = NULL;
gst_osselement_reset (oss); gst_osselement_reset (oss);
} }
@ -632,6 +637,9 @@ gst_osselement_get_property (GObject *object,
case ARG_MIXERDEV: case ARG_MIXERDEV:
g_value_set_string (value, oss->mixer_dev); g_value_set_string (value, oss->mixer_dev);
break; break;
case ARG_DEVICE_NAME:
g_value_set_string (value, oss->device_name);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;

View file

@ -82,6 +82,7 @@ struct _GstOssElement
recmask, recmask,
mixcaps; mixcaps;
gint mixer_fd; gint mixer_fd;
gchar *device_name;
}; };
struct _GstOssElementClass { struct _GstOssElementClass {

View file

@ -1,7 +1,7 @@
/* GStreamer OSS Mixer implementation /* GStreamer OSS Mixer implementation
* Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
* *
* gstossmixer.h: mixer interface implementation for OSS * gstossmixer.c: mixer interface implementation for OSS
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -37,26 +37,72 @@
#define MASK_BIT_IS_SET(mask, bit) \ #define MASK_BIT_IS_SET(mask, bit) \
(mask & (1 << bit)) (mask & (1 << bit))
static gboolean gst_ossmixer_supported (GstInterface *iface, static void gst_ossmixer_track_class_init (GstOssMixerTrackClass *klass);
GType iface_type); static void gst_ossmixer_track_init (GstOssMixerTrack *track);
static const GList * gst_ossmixer_list_tracks (GstMixer *ossmixer); static gboolean gst_ossmixer_supported (GstInterface *iface,
GType iface_type);
static const GList *
gst_ossmixer_list_tracks (GstMixer *ossmixer);
static void gst_ossmixer_set_volume (GstMixer *ossmixer, static void gst_ossmixer_set_volume (GstMixer *ossmixer,
GstMixerTrack *track, GstMixerTrack *track,
gint *volumes); gint *volumes);
static void gst_ossmixer_get_volume (GstMixer *ossmixer, static void gst_ossmixer_get_volume (GstMixer *ossmixer,
GstMixerTrack *track, GstMixerTrack *track,
gint *volumes); gint *volumes);
static void gst_ossmixer_set_record (GstMixer *ossmixer, static void gst_ossmixer_set_record (GstMixer *ossmixer,
GstMixerTrack *track, GstMixerTrack *track,
gboolean record); gboolean record);
static void gst_ossmixer_set_mute (GstMixer *ossmixer, static void gst_ossmixer_set_mute (GstMixer *ossmixer,
GstMixerTrack *track, GstMixerTrack *track,
gboolean mute); gboolean mute);
static const gchar *labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS; static const gchar *labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
static GstMixerTrackClass *parent_class = NULL;
GType
gst_ossmixer_track_get_type (void)
{
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);
}
return gst_ossmixer_track_type;
}
static void
gst_ossmixer_track_class_init (GstOssMixerTrackClass *klass)
{
parent_class = g_type_class_ref (GST_TYPE_MIXER_TRACK);
}
static void
gst_ossmixer_track_init (GstOssMixerTrack *track)
{
track->lvol = track->rvol = 0;
track->track_num = 0;
}
GstMixerTrack * GstMixerTrack *
gst_ossmixer_track_new (GstOssElement *oss, gst_ossmixer_track_new (GstOssElement *oss,
@ -64,34 +110,28 @@ gst_ossmixer_track_new (GstOssElement *oss,
gint max_chans, gint max_chans,
gint flags) gint flags)
{ {
GstMixerTrack *track = (GstMixerTrack *) g_new (GstOssMixerTrack, 1); GstOssMixerTrack *osstrack;
GstMixerTrack *track;
gint volumes[2]; gint volumes[2];
osstrack = g_object_new (GST_TYPE_OSSMIXER_TRACK, NULL);
track = GST_MIXER_TRACK (osstrack);
track->label = g_strdup (labels[track_num]); track->label = g_strdup (labels[track_num]);
track->num_channels = max_chans; track->num_channels = max_chans;
track->flags = flags; track->flags = flags;
track->min_volume = 0; track->min_volume = 0;
track->max_volume = 100; track->max_volume = 100;
((GstOssMixerTrack *) track)->track_num = track_num; osstrack->track_num = track_num;
/* volume */ /* volume */
gst_ossmixer_get_volume (GST_MIXER (oss), track, volumes); gst_ossmixer_get_volume (GST_MIXER (oss), track, volumes);
if (max_chans == 1) { osstrack->lvol = volumes[0];
volumes[1] = 0; if (max_chans == 2)
} osstrack->rvol = volumes[1];
((GstOssMixerTrack *) track)->lvol = volumes[0];
((GstOssMixerTrack *) track)->rvol = volumes[1];
return track; return track;
} }
void
gst_ossmixer_track_free (GstMixerTrack *track)
{
g_free (track->label);
g_free (track);
}
void void
gst_oss_interface_init (GstInterfaceClass *klass) gst_oss_interface_init (GstInterfaceClass *klass)
{ {
@ -119,13 +159,22 @@ gst_ossmixer_supported (GstInterface *iface,
return (GST_OSSELEMENT (iface)->mixer_fd != -1); return (GST_OSSELEMENT (iface)->mixer_fd != -1);
} }
static gboolean
gst_ossmixer_contains_track (GstOssElement *oss,
GstOssMixerTrack *osstrack)
{
const GList *item;
for (item = oss->tracklist; item != NULL; item = item->next)
if (item->data == osstrack)
return TRUE;
return FALSE;
}
static const GList * static const GList *
gst_ossmixer_list_tracks (GstMixer *mixer) gst_ossmixer_list_tracks (GstMixer *mixer)
{ {
GstOssElement *oss = GST_OSSELEMENT (mixer);
g_return_val_if_fail (oss->mixer_fd != -1, NULL);
return (const GList *) GST_OSSELEMENT (mixer)->tracklist; return (const GList *) GST_OSSELEMENT (mixer)->tracklist;
} }
@ -136,9 +185,11 @@ gst_ossmixer_get_volume (GstMixer *mixer,
{ {
gint volume; gint volume;
GstOssElement *oss = GST_OSSELEMENT (mixer); GstOssElement *oss = GST_OSSELEMENT (mixer);
GstOssMixerTrack *osstrack = (GstOssMixerTrack *) track; GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
/* assert that we're opened and that we're using a known item */
g_return_if_fail (oss->mixer_fd != -1); g_return_if_fail (oss->mixer_fd != -1);
g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
if (track->flags & GST_MIXER_TRACK_MUTE) { if (track->flags & GST_MIXER_TRACK_MUTE) {
volumes[0] = osstrack->lvol; volumes[0] = osstrack->lvol;
@ -167,9 +218,11 @@ gst_ossmixer_set_volume (GstMixer *mixer,
{ {
gint volume; gint volume;
GstOssElement *oss = GST_OSSELEMENT (mixer); GstOssElement *oss = GST_OSSELEMENT (mixer);
GstOssMixerTrack *osstrack = (GstOssMixerTrack *) track; GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
/* assert that we're opened and that we're using a known item */
g_return_if_fail (oss->mixer_fd != -1); g_return_if_fail (oss->mixer_fd != -1);
g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
/* prepare the value for ioctl() */ /* prepare the value for ioctl() */
if (!(track->flags & GST_MIXER_TRACK_MUTE)) { if (!(track->flags & GST_MIXER_TRACK_MUTE)) {
@ -199,9 +252,11 @@ gst_ossmixer_set_mute (GstMixer *mixer,
{ {
int volume; int volume;
GstOssElement *oss = GST_OSSELEMENT (mixer); GstOssElement *oss = GST_OSSELEMENT (mixer);
GstOssMixerTrack *osstrack = (GstOssMixerTrack *) track; GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
/* assert that we're opened and that we're using a known item */
g_return_if_fail (oss->mixer_fd != -1); g_return_if_fail (oss->mixer_fd != -1);
g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
if (mute) { if (mute) {
volume = 0; volume = 0;
@ -231,9 +286,11 @@ gst_ossmixer_set_record (GstMixer *mixer,
gboolean record) gboolean record)
{ {
GstOssElement *oss = GST_OSSELEMENT (mixer); GstOssElement *oss = GST_OSSELEMENT (mixer);
GstOssMixerTrack *osstrack = (GstOssMixerTrack *) track; GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
/* assert that we're opened and that we're using a known item */
g_return_if_fail (oss->mixer_fd != -1); g_return_if_fail (oss->mixer_fd != -1);
g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
/* if we're exclusive, then we need to unset the current one(s) */ /* if we're exclusive, then we need to unset the current one(s) */
if (oss->mixcaps & SOUND_CAP_EXCL_INPUT) { if (oss->mixcaps & SOUND_CAP_EXCL_INPUT) {
@ -270,22 +327,40 @@ void
gst_ossmixer_build_list (GstOssElement *oss) gst_ossmixer_build_list (GstOssElement *oss)
{ {
gint i, devmask; gint i, devmask;
const GList *pads = gst_element_get_pad_list (GST_ELEMENT (oss));
GstPadDirection dir = GST_PAD_UNKNOWN;
struct mixer_info minfo;
g_return_if_fail (oss->mixer_fd == -1); g_return_if_fail (oss->mixer_fd == -1);
oss->mixer_fd = open (oss->mixer_dev, O_RDWR); oss->mixer_fd = open (oss->mixer_dev, O_RDWR);
if (oss->mixer_fd == -1) { if (oss->mixer_fd == -1) {
g_warning ("Failed to open mixer device %s, mixing disabled: %s", /* this is valid. OSS devices don't need to expose a mixer */
GST_DEBUG ("Failed to open mixer device %s, mixing disabled: %s",
oss->mixer_dev, strerror (errno)); oss->mixer_dev, strerror (errno));
return; return;
} }
/* get direction */
if (pads && g_list_length ((GList *) pads) == 1)
dir = GST_PAD_DIRECTION (GST_PAD (pads->data));
/* get masks */ /* get masks */
ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECMASK, &oss->recmask); if (ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECMASK, &oss->recmask) < 0 ||
ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECSRC, &oss->recdevs); ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECSRC, &oss->recdevs) < 0 ||
ioctl (oss->mixer_fd, SOUND_MIXER_READ_STEREODEVS, &oss->stereomask); ioctl (oss->mixer_fd, SOUND_MIXER_READ_STEREODEVS, &oss->stereomask) < 0 ||
ioctl (oss->mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask); ioctl (oss->mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0 ||
ioctl (oss->mixer_fd, SOUND_MIXER_READ_CAPS, &oss->mixcaps); 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 */
if (ioctl (oss->mixer_fd, SOUND_MIXER_INFO, &minfo) == 0) {
oss->device_name = g_strdup (minfo.name);
}
/* build track list */ /* build track list */
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
@ -301,11 +376,16 @@ gst_ossmixer_build_list (GstOssElement *oss)
if (MASK_BIT_IS_SET (oss->recdevs, i)) if (MASK_BIT_IS_SET (oss->recdevs, i))
record = TRUE; record = TRUE;
/* do we want this in our list? */
if ((dir == GST_PAD_SRC && input == FALSE) ||
(dir == GST_PAD_SINK && i == SOUND_MIXER_PCM))
continue;
/* add track to list */ /* add track to list */
track = gst_ossmixer_track_new (oss, i, stereo ? 2 : 1, track = gst_ossmixer_track_new (oss, i, stereo ? 2 : 1,
(record ? GST_MIXER_TRACK_RECORD : 0) | (record ? GST_MIXER_TRACK_RECORD : 0) |
(input ? GST_MIXER_TRACK_INPUT : (input ? GST_MIXER_TRACK_INPUT :
GST_MIXER_TRACK_OUTPUT)); GST_MIXER_TRACK_OUTPUT));
oss->tracklist = g_list_append (oss->tracklist, track); oss->tracklist = g_list_append (oss->tracklist, track);
} }
} }
@ -314,12 +394,18 @@ gst_ossmixer_build_list (GstOssElement *oss)
void void
gst_ossmixer_free_list (GstOssElement *oss) gst_ossmixer_free_list (GstOssElement *oss)
{ {
g_return_if_fail (oss->mixer_fd != -1); if (oss->mixer_fd == -1)
return;
g_list_foreach (oss->tracklist, (GFunc) gst_ossmixer_track_free, NULL); g_list_foreach (oss->tracklist, (GFunc) g_object_unref, NULL);
g_list_free (oss->tracklist); g_list_free (oss->tracklist);
oss->tracklist = NULL; oss->tracklist = NULL;
if (oss->device_name) {
g_free (oss->device_name);
oss->device_name = NULL;
}
close (oss->mixer_fd); close (oss->mixer_fd);
oss->mixer_fd = -1; oss->mixer_fd = -1;
} }

View file

@ -28,16 +28,36 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#define GST_TYPE_OSSMIXER_TRACK \
(gst_ossmixer_track_get_type ())
#define GST_OSSMIXER_TRACK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OSSMIXER_TRACK, \
GstOssMixerTrack))
#define GST_OSSMIXER_TRACK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_OSSMIXER_TRACK, \
GstOssMixerTrackClass))
#define GST_IS_OSSMIXER_TRACK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OSSMIXER_TRACK))
#define GST_IS_OSSMIXER_TRACK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_OSSMIXER_TRACK))
typedef struct _GstOssMixerTrack { typedef struct _GstOssMixerTrack {
GstMixerTrack parent; GstMixerTrack parent;
gint lvol, rvol; gint lvol, rvol;
gint track_num; gint track_num;
} GstOssMixerTrack; } GstOssMixerTrack;
void gst_ossmixer_interface_init (GstMixerClass *klass); typedef struct _GstOssMixerTrackClass {
void gst_oss_interface_init (GstInterfaceClass *klass); GstMixerTrackClass parent;
void gst_ossmixer_build_list (GstOssElement *oss); } GstOssMixerTrackClass;
void gst_ossmixer_free_list (GstOssElement *oss);
GType gst_ossmixer_track_get_type (void);
void gst_ossmixer_interface_init (GstMixerClass *klass);
void gst_oss_interface_init (GstInterfaceClass *klass);
void gst_ossmixer_build_list (GstOssElement *oss);
void gst_ossmixer_free_list (GstOssElement *oss);
G_END_DECLS G_END_DECLS