diff options
Diffstat (limited to 'backends/oss/oss-stream-control.c')
-rw-r--r-- | backends/oss/oss-stream-control.c | 527 |
1 files changed, 195 insertions, 332 deletions
diff --git a/backends/oss/oss-stream-control.c b/backends/oss/oss-stream-control.c index 0b1db26..5161528 100644 --- a/backends/oss/oss-stream-control.c +++ b/backends/oss/oss-stream-control.c @@ -15,14 +15,13 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ -#include <unistd.h> #include <errno.h> #include <glib.h> #include <glib/gstdio.h> #include <glib-object.h> -#include <libmatemixer/matemixer-port.h> -#include <libmatemixer/matemixer-stream-control.h> +#include <libmatemixer/matemixer.h> +#include <libmatemixer/matemixer-private.h> #include "oss-common.h" #include "oss-stream-control.h" @@ -30,437 +29,279 @@ struct _OssStreamControlPrivate { gint fd; - gint dev_number; - gchar *name; - gchar *description; + gint devnum; guint volume[2]; gfloat balance; gboolean stereo; - MateMixerPort *port; MateMixerStreamControlRole role; MateMixerStreamControlFlags flags; }; -enum { - PROP_0, - PROP_NAME, - PROP_DESCRIPTION, - PROP_FLAGS, - PROP_MUTE, - PROP_VOLUME, - PROP_BALANCE, - PROP_FADE, - PROP_FD, - PROP_DEV_NUMBER, - PROP_STEREO -}; - -static void mate_mixer_stream_control_interface_init (MateMixerStreamControlInterface *iface); - -static void oss_stream_control_class_init (OssStreamControlClass *klass); +static void oss_stream_control_class_init (OssStreamControlClass *klass); -static void oss_stream_control_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static void oss_stream_control_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); +static void oss_stream_control_init (OssStreamControl *control); +static void oss_stream_control_finalize (GObject *object); -static void oss_stream_control_init (OssStreamControl *octl); -static void oss_stream_control_finalize (GObject *object); +G_DEFINE_TYPE (OssStreamControl, oss_stream_control, MATE_MIXER_TYPE_STREAM_CONTROL) -G_DEFINE_TYPE_WITH_CODE (OssStreamControl, oss_stream_control, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (MATE_MIXER_TYPE_STREAM_CONTROL, - mate_mixer_stream_control_interface_init)) +static gboolean oss_stream_control_set_mute (MateMixerStreamControl *mmsc, + gboolean mute); -static const gchar * oss_stream_control_get_name (MateMixerStreamControl *ctl); -static const gchar * oss_stream_control_get_description (MateMixerStreamControl *ctl); +static guint oss_stream_control_get_num_channels (MateMixerStreamControl *mmsc); -static guint oss_stream_control_get_num_channels (MateMixerStreamControl *ctl); +static guint oss_stream_control_get_volume (MateMixerStreamControl *mmsc); -static gboolean oss_stream_control_set_volume (MateMixerStreamControl *ctl, +static gboolean oss_stream_control_set_volume (MateMixerStreamControl *mmsc, guint volume); -static guint oss_stream_control_get_channel_volume (MateMixerStreamControl *ctl, +static gboolean oss_stream_control_has_channel_position (MateMixerStreamControl *mmsc, + MateMixerChannelPosition position); +static MateMixerChannelPosition oss_stream_control_get_channel_position (MateMixerStreamControl *mmsc, guint channel); -static gboolean oss_stream_control_set_channel_volume (MateMixerStreamControl *ctl, - guint channel, - guint volume); -static MateMixerChannelPosition oss_stream_control_get_channel_position (MateMixerStreamControl *ctl, +static guint oss_stream_control_get_channel_volume (MateMixerStreamControl *mmsc, guint channel); -static gboolean oss_stream_control_has_channel_position (MateMixerStreamControl *ctl, - MateMixerChannelPosition position); +static gboolean oss_stream_control_set_channel_volume (MateMixerStreamControl *mmsc, + guint channel, + guint volume); -static gboolean oss_stream_control_set_balance (MateMixerStreamControl *ctl, +static gboolean oss_stream_control_set_balance (MateMixerStreamControl *mmsc, gfloat balance); -static guint oss_stream_control_get_min_volume (MateMixerStreamControl *ctl); -static guint oss_stream_control_get_max_volume (MateMixerStreamControl *ctl); -static guint oss_stream_control_get_normal_volume (MateMixerStreamControl *ctl); -static guint oss_stream_control_get_base_volume (MateMixerStreamControl *ctl); +static guint oss_stream_control_get_min_volume (MateMixerStreamControl *mmsc); +static guint oss_stream_control_get_max_volume (MateMixerStreamControl *mmsc); +static guint oss_stream_control_get_normal_volume (MateMixerStreamControl *mmsc); +static guint oss_stream_control_get_base_volume (MateMixerStreamControl *mmsc); -static void -mate_mixer_stream_control_interface_init (MateMixerStreamControlInterface *iface) -{ - iface->get_name = oss_stream_control_get_name; - iface->get_description = oss_stream_control_get_description; - iface->get_num_channels = oss_stream_control_get_num_channels; - iface->set_volume = oss_stream_control_set_volume; - iface->get_channel_volume = oss_stream_control_get_channel_volume; - iface->set_channel_volume = oss_stream_control_set_channel_volume; - iface->get_channel_position = oss_stream_control_get_channel_position; - iface->has_channel_position = oss_stream_control_has_channel_position; - iface->set_balance = oss_stream_control_set_balance; - iface->get_min_volume = oss_stream_control_get_min_volume; - iface->get_max_volume = oss_stream_control_get_max_volume; - iface->get_normal_volume = oss_stream_control_get_normal_volume; - iface->get_base_volume = oss_stream_control_get_base_volume; -} +static gboolean write_volume (OssStreamControl *control, + gint volume); static void oss_stream_control_class_init (OssStreamControlClass *klass) { - GObjectClass *object_class; + GObjectClass *object_class; + MateMixerStreamControlClass *control_class; object_class = G_OBJECT_CLASS (klass); - object_class->finalize = oss_stream_control_finalize; - object_class->get_property = oss_stream_control_get_property; - object_class->set_property = oss_stream_control_set_property; - - g_object_class_install_property (object_class, - PROP_FD, - g_param_spec_int ("fd", - "File descriptor", - "File descriptor of the device", - G_MININT, - G_MAXINT, - -1, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (object_class, - PROP_DEV_NUMBER, - g_param_spec_int ("dev-number", - "Dev number", - "OSS device number", - G_MININT, - G_MAXINT, - 0, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (object_class, - PROP_STEREO, - g_param_spec_boolean ("stereo", - "Stereo", - "Stereo", - FALSE, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_override_property (object_class, PROP_NAME, "name"); - g_object_class_override_property (object_class, PROP_DESCRIPTION, "description"); - g_object_class_override_property (object_class, PROP_FLAGS, "flags"); - g_object_class_override_property (object_class, PROP_MUTE, "mute"); - g_object_class_override_property (object_class, PROP_VOLUME, "volume"); - g_object_class_override_property (object_class, PROP_BALANCE, "balance"); - g_object_class_override_property (object_class, PROP_FADE, "fade"); + object_class->finalize = oss_stream_control_finalize; + + control_class = MATE_MIXER_STREAM_CONTROL_CLASS (klass); + control_class->set_mute = oss_stream_control_set_mute; + control_class->get_num_channels = oss_stream_control_get_num_channels; + control_class->get_volume = oss_stream_control_get_volume; + control_class->set_volume = oss_stream_control_set_volume; + control_class->get_channel_volume = oss_stream_control_get_channel_volume; + control_class->set_channel_volume = oss_stream_control_set_channel_volume; + control_class->get_channel_position = oss_stream_control_get_channel_position; + control_class->has_channel_position = oss_stream_control_has_channel_position; + control_class->set_balance = oss_stream_control_set_balance; + control_class->get_min_volume = oss_stream_control_get_min_volume; + control_class->get_max_volume = oss_stream_control_get_max_volume; + control_class->get_normal_volume = oss_stream_control_get_normal_volume; + control_class->get_base_volume = oss_stream_control_get_base_volume; g_type_class_add_private (object_class, sizeof (OssStreamControlPrivate)); } static void -oss_stream_control_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - OssStreamControl *octl; - - octl = OSS_STREAM_CONTROL (object); - - switch (param_id) { - case PROP_NAME: - g_value_set_string (value, octl->priv->name); - break; - case PROP_DESCRIPTION: - g_value_set_string (value, octl->priv->description); - break; - case PROP_FLAGS: - g_value_set_flags (value, octl->priv->flags); - break; - case PROP_MUTE: - /* Not supported */ - g_value_set_boolean (value, FALSE); - break; - case PROP_VOLUME: - g_value_set_uint (value, MAX (octl->priv->volume[0], octl->priv->volume[1])); - break; - case PROP_BALANCE: - g_value_set_float (value, octl->priv->balance); - break; - case PROP_FADE: - /* Not supported */ - g_value_set_float (value, 0.0f); - break; - case PROP_FD: - g_value_set_int (value, octl->priv->fd); - break; - case PROP_DEV_NUMBER: - g_value_set_int (value, octl->priv->dev_number); - break; - case PROP_STEREO: - g_value_set_boolean (value, octl->priv->stereo); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -oss_stream_control_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) +oss_stream_control_init (OssStreamControl *control) { - OssStreamControl *octl; - - octl = OSS_STREAM_CONTROL (object); - - switch (param_id) { - case PROP_FD: - octl->priv->fd = dup (g_value_get_int (value)); - break; - case PROP_DEV_NUMBER: - octl->priv->dev_number = g_value_get_int (value); - break; - case PROP_STEREO: - octl->priv->stereo = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -oss_stream_control_init (OssStreamControl *octl) -{ - octl->priv = G_TYPE_INSTANCE_GET_PRIVATE (octl, - OSS_TYPE_STREAM_CONTROL, - OssStreamControlPrivate); + control->priv = G_TYPE_INSTANCE_GET_PRIVATE (control, + OSS_TYPE_STREAM_CONTROL, + OssStreamControlPrivate); } static void oss_stream_control_finalize (GObject *object) { - OssStreamControl *octl; - - octl = OSS_STREAM_CONTROL (object); + OssStreamControl *control; - g_free (octl->priv->name); - g_free (octl->priv->description); + control = OSS_STREAM_CONTROL (object); - if (octl->priv->fd != -1) - g_close (octl->priv->fd, NULL); + close (control->priv->fd); G_OBJECT_CLASS (oss_stream_control_parent_class)->finalize (object); } OssStreamControl * -oss_stream_control_new (gint fd, - gint dev_number, - const gchar *name, - const gchar *description, - gboolean stereo) +oss_stream_control_new (const gchar *name, + const gchar *label, + MateMixerStreamControlRole role, + gint fd, + gint devnum, + gboolean stereo) { - OssStreamControl *ctl; - - ctl = g_object_new (OSS_TYPE_STREAM_CONTROL, - "fd", fd, - "dev-number", dev_number, - "stereo", stereo, - NULL); - - ctl->priv->name = g_strdup (name); - ctl->priv->description = g_strdup (description); + OssStreamControl *control; + MateMixerStreamControlFlags flags; - return ctl; + flags = MATE_MIXER_STREAM_CONTROL_HAS_VOLUME | + MATE_MIXER_STREAM_CONTROL_CAN_SET_VOLUME; + if (stereo == TRUE) + flags |= MATE_MIXER_STREAM_CONTROL_CAN_BALANCE; + + control = g_object_new (OSS_TYPE_STREAM_CONTROL, + "name", name, + "label", label, + "flags", flags, + NULL); + + control->priv->fd = fd; + control->priv->devnum = devnum; + control->priv->stereo = stereo; + return control; } gboolean -oss_stream_control_update (OssStreamControl *octl) +oss_stream_control_update (OssStreamControl *control) { gint v; gint ret; - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (octl), FALSE); + g_return_val_if_fail (OSS_IS_STREAM_CONTROL (control), FALSE); - ret = ioctl (octl->priv->fd, MIXER_READ (octl->priv->dev_number), &v); + ret = ioctl (control->priv->fd, MIXER_READ (control->priv->devnum), &v); if (ret < 0) { g_warning ("Failed to read volume: %s", g_strerror (errno)); return FALSE; } - octl->priv->volume[0] = v & 0xFF; + control->priv->volume[0] = v & 0xFF; - if (octl->priv->stereo == TRUE) - octl->priv->volume[1] = (v >> 8) & 0xFF; - - return TRUE; -} - -gboolean -oss_stream_control_set_port (OssStreamControl *octl, MateMixerPort *port) -{ - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (octl), FALSE); + if (control->priv->stereo == TRUE) { + gfloat balance; + guint left; + guint right; - // XXX provide property + control->priv->volume[1] = (v >> 8) & 0xFF; - if (octl->priv->port != NULL) - g_object_unref (octl->priv->port); + /* Calculate balance */ + left = control->priv->volume[0]; + right = control->priv->volume[1]; + if (left == right) + balance = 0.0f; + else if (left > right) + balance = -1.0f + ((gfloat) right / (gfloat) left); + else + balance = +1.0f - ((gfloat) left / (gfloat) right); - octl->priv->port = g_object_ref (port); + _mate_mixer_stream_control_set_balance (MATE_MIXER_STREAM_CONTROL (control), + balance); + } return TRUE; } -gboolean -oss_stream_control_set_role (OssStreamControl *octl, MateMixerStreamControlRole role) +static gboolean +oss_stream_control_set_mute (MateMixerStreamControl *mmsc, gboolean mute) { - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (octl), FALSE); + g_return_val_if_fail (OSS_IS_STREAM_CONTROL (mmsc), FALSE); - octl->priv->role = role; + // TODO return TRUE; } -static const gchar * -oss_stream_control_get_name (MateMixerStreamControl *ctl) +static guint +oss_stream_control_get_num_channels (MateMixerStreamControl *mmsc) { - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), NULL); + g_return_val_if_fail (OSS_IS_STREAM_CONTROL (mmsc), 0); - return OSS_STREAM_CONTROL (ctl)->priv->name; + return (OSS_STREAM_CONTROL (mmsc)->priv->stereo == TRUE) ? 2 : 1; } -static const gchar * -oss_stream_control_get_description (MateMixerStreamControl *ctl) +static guint +oss_stream_control_get_volume (MateMixerStreamControl *mmsc) { - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), NULL); + OssStreamControl *control; - return OSS_STREAM_CONTROL (ctl)->priv->description; -} + g_return_val_if_fail (OSS_IS_STREAM_CONTROL (mmsc), 0); -static guint -oss_stream_control_get_num_channels (MateMixerStreamControl *ctl) -{ - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), 0); + control = OSS_STREAM_CONTROL (mmsc); - if (OSS_STREAM_CONTROL (ctl)->priv->stereo == TRUE) - return 2; + if (control->priv->stereo == TRUE) + return MAX (control->priv->volume[0], control->priv->volume[1]); else - return 1; + return control->priv->volume[0]; } static gboolean -oss_stream_control_set_volume (MateMixerStreamControl *ctl, guint volume) +oss_stream_control_set_volume (MateMixerStreamControl *mmsc, guint volume) { - OssStreamControl *octl; - int v; - int ret; - - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), FALSE); + OssStreamControl *control; + gint v; - octl = OSS_STREAM_CONTROL (ctl); + g_return_val_if_fail (OSS_IS_STREAM_CONTROL (mmsc), FALSE); - /* Some backends may allow setting higher value than maximum, but not here */ - if (volume > 100) - volume = 100; + control = OSS_STREAM_CONTROL (mmsc); - v = volume; - if (octl->priv->stereo == TRUE) + v = CLAMP (volume, 0, 100); + if (control->priv->stereo == TRUE) v |= (volume & 0xFF) << 8; - ret = ioctl (octl->priv->fd, MIXER_WRITE (octl->priv->dev_number), &v); - if (ret < 0) { - g_warning ("Failed to set volume: %s", g_strerror (errno)); - return FALSE; - } - return TRUE; + return write_volume (control, v); } static guint -oss_stream_control_get_channel_volume (MateMixerStreamControl *ctl, guint channel) +oss_stream_control_get_channel_volume (MateMixerStreamControl *mmsc, guint channel) { - OssStreamControl *octl; + OssStreamControl *control; - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), 0); + g_return_val_if_fail (OSS_IS_STREAM_CONTROL (mmsc), 0); - octl = OSS_STREAM_CONTROL (ctl); + control = OSS_STREAM_CONTROL (mmsc); - if (channel > 1) - return 0; - - /* Right channel on mono stream will always have zero volume */ - return octl->priv->volume[channel]; + if (control->priv->stereo == TRUE) { + if (channel == 0 || channel == 1) + return control->priv->volume[channel]; + } else { + if (channel == 0) + return control->priv->volume[0]; + } + return 0; } static gboolean -oss_stream_control_set_channel_volume (MateMixerStreamControl *ctl, +oss_stream_control_set_channel_volume (MateMixerStreamControl *mmsc, guint channel, guint volume) { - OssStreamControl *octl; - int ret; - int v; + OssStreamControl *control; + gint v; - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), FALSE); + g_return_val_if_fail (OSS_IS_STREAM_CONTROL (mmsc), FALSE); - if (channel > 1) - return FALSE; - - octl = OSS_STREAM_CONTROL (ctl); - - /* Some backends may allow setting higher value than maximum, but not here */ - if (volume > 100) - volume = 100; - - if (channel == 0) - v = volume; - else - v = octl->priv->volume[0]; + control = OSS_STREAM_CONTROL (mmsc); + volume = CLAMP (volume, 0, 100); - if (channel == 1) { - if (octl->priv->stereo == FALSE) + if (control->priv->stereo == TRUE) { + if (channel > 1) return FALSE; - v |= volume << 8; - } else - v |= octl->priv->volume[1] << 8; + /* Stereo channel volume - left channel is in the lowest 8 bits and + * right channel is in the higher 8 bits */ + if (channel == 0) + v = volume | (control->priv->volume[1] << 8); + else + v = control->priv->volume[0] | (volume << 8); + } else { + if (channel > 0) + return FALSE; - ret = ioctl (octl->priv->fd, MIXER_WRITE (octl->priv->dev_number), &v); - if (ret < 0) { - g_warning ("Failed to set channel volume: %s", g_strerror (errno)); - return FALSE; + /* Single channel volume - only lowest 8 bits are used */ + v = volume; } - return TRUE; + + return write_volume (control, v); } static MateMixerChannelPosition -oss_stream_control_get_channel_position (MateMixerStreamControl *ctl, guint channel) +oss_stream_control_get_channel_position (MateMixerStreamControl *mmsc, guint channel) { - OssStreamControl *octl; + OssStreamControl *control; - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), MATE_MIXER_CHANNEL_UNKNOWN); + g_return_val_if_fail (OSS_IS_STREAM_CONTROL (mmsc), MATE_MIXER_CHANNEL_UNKNOWN); - octl = OSS_STREAM_CONTROL (ctl); + control = OSS_STREAM_CONTROL (mmsc); - if (octl->priv->stereo == TRUE) { + if (control->priv->stereo == TRUE) { if (channel == 0) return MATE_MIXER_CHANNEL_FRONT_LEFT; else if (channel == 1) @@ -473,57 +314,79 @@ oss_stream_control_get_channel_position (MateMixerStreamControl *ctl, guint chan } static gboolean -oss_stream_control_has_channel_position (MateMixerStreamControl *ctl, +oss_stream_control_has_channel_position (MateMixerStreamControl *mmsc, MateMixerChannelPosition position) { - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), FALSE); + g_return_val_if_fail (OSS_IS_STREAM_CONTROL (mmsc), FALSE); if (position == MATE_MIXER_CHANNEL_MONO) - return OSS_STREAM_CONTROL (ctl)->priv->stereo == FALSE; + return OSS_STREAM_CONTROL (mmsc)->priv->stereo == FALSE; if (position == MATE_MIXER_CHANNEL_FRONT_LEFT || position == MATE_MIXER_CHANNEL_FRONT_RIGHT) - return OSS_STREAM_CONTROL (ctl)->priv->stereo == TRUE; + return OSS_STREAM_CONTROL (mmsc)->priv->stereo == TRUE; return FALSE; } static gboolean -oss_stream_control_set_balance (MateMixerStreamControl *ctl, gfloat balance) +oss_stream_control_set_balance (MateMixerStreamControl *mmsc, gfloat balance) { - OssStreamControl *octl; + OssStreamControl *control; + guint max; + gint v; - g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), FALSE); + g_return_val_if_fail (OSS_IS_STREAM_CONTROL (mmsc), FALSE); - octl = OSS_STREAM_CONTROL (ctl); + control = OSS_STREAM_CONTROL (mmsc); - if (octl->priv->stereo == FALSE) - return FALSE; + max = MAX (control->priv->volume[0], control->priv->volume[1]); + if (balance <= 0) { + control->priv->volume[1] = (balance + 1.0f) * max; + control->priv->volume[0] = max; + } else { + control->priv->volume[0] = (1.0f - balance) * max; + control->priv->volume[1] = max; + } - // XXX - return TRUE; + v = control->priv->volume[0] | (control->priv->volume[1] << 8); + + return write_volume (control, v); } static guint -oss_stream_control_get_min_volume (MateMixerStreamControl *ctl) +oss_stream_control_get_min_volume (MateMixerStreamControl *mmsc) { return 0; } static guint -oss_stream_control_get_max_volume (MateMixerStreamControl *ctl) +oss_stream_control_get_max_volume (MateMixerStreamControl *mmsc) { return 100; } static guint -oss_stream_control_get_normal_volume (MateMixerStreamControl *ctl) +oss_stream_control_get_normal_volume (MateMixerStreamControl *mmsc) { return 100; } static guint -oss_stream_control_get_base_volume (MateMixerStreamControl *ctl) +oss_stream_control_get_base_volume (MateMixerStreamControl *mmsc) { return 100; } + +static gboolean +write_volume (OssStreamControl *control, gint volume) +{ + gint ret; + + ret = ioctl (control->priv->fd, MIXER_WRITE (control->priv->devnum), &volume); + if (ret < 0) { + g_warning ("Failed to set volume: %s", g_strerror (errno)); + return FALSE; + } + return TRUE; +} |