[gnome-media] Bug 568936 – Add fade slider
- From: Bastien Nocera <hadess src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-media] Bug 568936 – Add fade slider
- Date: Sat, 9 May 2009 20:53:17 -0400 (EDT)
commit e4c8d688709e54a8fabfb818664874d9d77ca42d
Author: Bastien Nocera <hadess hadess net>
Date: Sun May 10 01:46:33 2009 +0100
Bug 568936 â?? Add fade slider
With help from Lennart Poettering and Matthias Clasen.
- Add a new type of balance bar, the fade balance bar, to balance
volume between front and rear
- Don't update the UI when volume change operations are still pending
on the sink we're modifying
- Rework the internals to store pa_cvolume, like PA does internally,
instead of balance/fade/volume separately, as the value isn't
reversible to what we'd pass PA
---
gnome-volume-control/src/gvc-balance-bar.c | 228 +++++++++++++----------
gnome-volume-control/src/gvc-balance-bar.h | 8 +-
gnome-volume-control/src/gvc-channel-map.c | 102 ++++++++---
gnome-volume-control/src/gvc-channel-map.h | 19 ++-
gnome-volume-control/src/gvc-mixer-control.c | 17 ++-
gnome-volume-control/src/gvc-mixer-dialog.c | 21 ++-
gnome-volume-control/src/gvc-mixer-sink-input.c | 18 +--
gnome-volume-control/src/gvc-mixer-sink.c | 76 +++++---
gnome-volume-control/src/gvc-mixer-source.c | 25 +--
gnome-volume-control/src/gvc-mixer-stream.c | 20 ++-
gnome-volume-control/src/gvc-mixer-stream.h | 2 +
11 files changed, 336 insertions(+), 200 deletions(-)
diff --git a/gnome-volume-control/src/gvc-balance-bar.c b/gnome-volume-control/src/gvc-balance-bar.c
index 74d3b2a..c033902 100644
--- a/gnome-volume-control/src/gvc-balance-bar.c
+++ b/gnome-volume-control/src/gvc-balance-bar.c
@@ -38,6 +38,7 @@
struct GvcBalanceBarPrivate
{
GvcChannelMap *channel_map;
+ GvcBalanceType btype;
GtkWidget *scale_box;
GtkWidget *start_box;
GtkWidget *end_box;
@@ -52,7 +53,8 @@ struct GvcBalanceBarPrivate
enum
{
PROP_0,
- PROP_CHANNEL_MAP
+ PROP_CHANNEL_MAP,
+ PROP_BALANCE_TYPE,
};
static void gvc_balance_bar_class_init (GvcBalanceBarClass *klass);
@@ -68,6 +70,8 @@ static gboolean on_scale_button_release_event (GtkWidget *widget,
static gboolean on_scale_scroll_event (GtkWidget *widget,
GdkEventScroll *event,
GvcBalanceBar *bar);
+static void on_adjustment_value_changed (GtkAdjustment *adjustment,
+ GvcBalanceBar *bar);
G_DEFINE_TYPE (GvcBalanceBar, gvc_balance_bar, GTK_TYPE_HBOX)
@@ -98,15 +102,27 @@ _scale_box_new (GvcBalanceBar *bar)
gtk_box_pack_start (GTK_BOX (box), priv->scale, TRUE, TRUE, 0);
- str = g_strdup_printf ("<small>%s</small>", C_("balance", "Left"));
- gtk_scale_add_mark (GTK_SCALE (priv->scale), adjustment->lower ,
- GTK_POS_BOTTOM, str);
- g_free (str);
-
- str = g_strdup_printf ("<small>%s</small>", C_("balance", "Right"));
- gtk_scale_add_mark (GTK_SCALE (priv->scale), adjustment->upper,
- GTK_POS_BOTTOM, str);
- g_free (str);
+ if (bar->priv->btype == BALANCE_TYPE_RL) {
+ str = g_strdup_printf ("<small>%s</small>", C_("balance", "Left"));
+ gtk_scale_add_mark (GTK_SCALE (priv->scale), adjustment->lower,
+ GTK_POS_BOTTOM, str);
+ g_free (str);
+
+ str = g_strdup_printf ("<small>%s</small>", C_("balance", "Right"));
+ gtk_scale_add_mark (GTK_SCALE (priv->scale), adjustment->upper,
+ GTK_POS_BOTTOM, str);
+ g_free (str);
+ } else {
+ str = g_strdup_printf ("<small>%s</small>", C_("balance", "Front"));
+ gtk_scale_add_mark (GTK_SCALE (priv->scale), adjustment->lower,
+ GTK_POS_BOTTOM, str);
+ g_free (str);
+
+ str = g_strdup_printf ("<small>%s</small>", C_("balance", "Rear"));
+ gtk_scale_add_mark (GTK_SCALE (priv->scale), adjustment->upper,
+ GTK_POS_BOTTOM, str);
+ g_free (str);
+ }
gtk_scale_add_mark (GTK_SCALE (priv->scale), (adjustment->upper - adjustment->lower)/2 + adjustment->lower,
GTK_POS_BOTTOM, NULL);
@@ -161,6 +177,32 @@ gvc_balance_bar_set_size_group (GvcBalanceBar *bar,
}
static void
+update_level_from_map (GvcBalanceBar *bar,
+ GvcChannelMap *map)
+{
+ const gdouble *volumes;
+ gdouble val;
+
+ g_debug ("Volume changed (for %s bar)",
+ bar->priv->btype == BALANCE_TYPE_RL ? "Balance" : "Fade");
+
+ volumes = gvc_channel_map_get_volume (map);
+ if (bar->priv->btype == BALANCE_TYPE_RL)
+ val = volumes[BALANCE];
+ else
+ val = volumes[FADE];
+
+ gtk_adjustment_set_value (bar->priv->adjustment, val);
+}
+
+static void
+on_channel_map_volume_changed (GvcChannelMap *map,
+ GvcBalanceBar *bar)
+{
+ update_level_from_map (bar, map);
+}
+
+static void
gvc_balance_bar_set_channel_map (GvcBalanceBar *bar,
GvcChannelMap *map)
{
@@ -171,10 +213,61 @@ gvc_balance_bar_set_channel_map (GvcBalanceBar *bar,
}
bar->priv->channel_map = g_object_ref (map);
+ update_level_from_map (bar, map);
+
+ g_signal_connect (G_OBJECT (map), "volume-changed",
+ G_CALLBACK (on_channel_map_volume_changed), bar);
+
g_object_notify (G_OBJECT (bar), "channel-map");
}
static void
+gvc_balance_bar_set_balance_type (GvcBalanceBar *bar,
+ GvcBalanceType btype)
+{
+ GtkWidget *frame;
+
+ g_return_if_fail (GVC_BALANCE_BAR (bar));
+
+ bar->priv->btype = btype;
+ bar->priv->adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0,
+ -1.0,
+ 1.0,
+ 0.5,
+ 0.5,
+ 0.5));
+ g_object_ref_sink (bar->priv->adjustment);
+ g_signal_connect (bar->priv->adjustment,
+ "value-changed",
+ G_CALLBACK (on_adjustment_value_changed),
+ bar);
+
+ if (bar->priv->btype == BALANCE_TYPE_RL) {
+ bar->priv->label = gtk_label_new_with_mnemonic (_("_Balance:"));
+ } else {
+ bar->priv->label = gtk_label_new_with_mnemonic (_("_Fade:"));
+ }
+ gtk_misc_set_alignment (GTK_MISC (bar->priv->label),
+ 0.0,
+ 0.0);
+ /* frame */
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+ gtk_container_add (GTK_CONTAINER (bar), frame);
+
+ /* box with scale */
+ bar->priv->scale_box = _scale_box_new (bar);
+ gtk_container_add (GTK_CONTAINER (frame), bar->priv->scale_box);
+ gtk_widget_show_all (frame);
+
+ gtk_widget_set_direction (bar->priv->scale, GTK_TEXT_DIR_LTR);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (bar->priv->label),
+ bar->priv->scale);
+
+ g_object_notify (G_OBJECT (bar), "balance-type");
+}
+
+static void
gvc_balance_bar_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -186,6 +279,9 @@ gvc_balance_bar_set_property (GObject *object,
case PROP_CHANNEL_MAP:
gvc_balance_bar_set_channel_map (self, g_value_get_object (value));
break;
+ case PROP_BALANCE_TYPE:
+ gvc_balance_bar_set_balance_type (self, g_value_get_int (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -242,36 +338,19 @@ gvc_balance_bar_class_init (GvcBalanceBarClass *klass)
"The channel map",
GVC_TYPE_CHANNEL_MAP,
G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_BALANCE_TYPE,
+ g_param_spec_int ("balance-type",
+ "balance type",
+ "Whether the balance is right-left or front-rear",
+ BALANCE_TYPE_RL, BALANCE_TYPE_FR, BALANCE_TYPE_RL,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (klass, sizeof (GvcBalanceBarPrivate));
}
static gboolean
-on_left (pa_channel_position_t p)
-{
- return
- p == PA_CHANNEL_POSITION_FRONT_LEFT ||
- p == PA_CHANNEL_POSITION_REAR_LEFT ||
- p == PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER ||
- p == PA_CHANNEL_POSITION_SIDE_LEFT ||
- p == PA_CHANNEL_POSITION_TOP_FRONT_LEFT ||
- p == PA_CHANNEL_POSITION_TOP_REAR_LEFT;
-}
-
-static gboolean
-on_right (pa_channel_position_t p)
-{
- return
- p == PA_CHANNEL_POSITION_FRONT_RIGHT ||
- p == PA_CHANNEL_POSITION_REAR_RIGHT ||
- p == PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER ||
- p == PA_CHANNEL_POSITION_SIDE_RIGHT ||
- p == PA_CHANNEL_POSITION_TOP_FRONT_RIGHT ||
- p == PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
-}
-
-static gboolean
on_scale_button_press_event (GtkWidget *widget,
GdkEventButton *event,
GvcBalanceBar *bar)
@@ -322,83 +401,29 @@ on_adjustment_value_changed (GtkAdjustment *adjustment,
GvcBalanceBar *bar)
{
gdouble val;
- gdouble *gains;
- pa_channel_position_t *positions;
- guint num_channels;
- guint i;
- gdouble left_v;
- gdouble center_v;
- gdouble right_v;
+ pa_cvolume cv;
+ const pa_channel_map *pa_map;
- val = gtk_adjustment_get_value (adjustment);
-
- if (bar->priv->channel_map == NULL) {
+ if (bar->priv->channel_map == NULL)
return;
- }
- left_v = 1.0;
- right_v = 1.0;
+ cv = *gvc_channel_map_get_cvolume_for_volumes (bar->priv->channel_map, -1);
+ val = gtk_adjustment_get_value (adjustment);
- if (val > 0) {
- left_v = 1.0 - val;
- } else if (val < 0) {
- right_v = 1.0 - ABS(val);
- }
- center_v = (left_v + right_v) / 2.0;
-
- num_channels = gvc_channel_map_get_num_channels (bar->priv->channel_map);
- positions = gvc_channel_map_get_positions (bar->priv->channel_map);
- gains = gvc_channel_map_get_gains (bar->priv->channel_map);
-
- for (i = 0; i < num_channels; i++) {
- if (on_left (positions[i])) {
- gains[i] = left_v;
- } else if (on_right (positions[i])) {
- gains[i] = right_v;
- } else {
- gains[i] = center_v;
- }
- }
+ pa_map = gvc_channel_map_get_pa_channel_map (bar->priv->channel_map);
+
+ if (bar->priv->btype == BALANCE_TYPE_RL)
+ pa_cvolume_set_balance (&cv, pa_map, val);
+ else
+ pa_cvolume_set_fade (&cv, pa_map, val);
- gvc_channel_map_gains_changed (bar->priv->channel_map);
+ gvc_channel_map_volume_changed (bar->priv->channel_map, &cv);
}
static void
gvc_balance_bar_init (GvcBalanceBar *bar)
{
- GtkWidget *frame;
-
bar->priv = GVC_BALANCE_BAR_GET_PRIVATE (bar);
-
- bar->priv->adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0,
- -1.0,
- 1.0,
- 0.05,
- 0.1,
- 0.1));
- g_object_ref_sink (bar->priv->adjustment);
- g_signal_connect (bar->priv->adjustment,
- "value-changed",
- G_CALLBACK (on_adjustment_value_changed),
- bar);
-
- bar->priv->label = gtk_label_new_with_mnemonic (_("_Balance:"));
- gtk_misc_set_alignment (GTK_MISC (bar->priv->label),
- 0.0,
- 0.0);
- /* frame */
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
- gtk_container_add (GTK_CONTAINER (bar), frame);
-
- /* box with scale */
- bar->priv->scale_box = _scale_box_new (bar);
- gtk_container_add (GTK_CONTAINER (frame), bar->priv->scale_box);
- gtk_widget_show_all (frame);
-
- gtk_widget_set_direction (bar->priv->scale, GTK_TEXT_DIR_LTR);
- gtk_label_set_mnemonic_widget (GTK_LABEL (bar->priv->label),
- bar->priv->scale);
}
static void
@@ -421,11 +446,12 @@ gvc_balance_bar_finalize (GObject *object)
}
GtkWidget *
-gvc_balance_bar_new (GvcChannelMap *channel_map)
+gvc_balance_bar_new (GvcChannelMap *channel_map, GvcBalanceType btype)
{
GObject *bar;
bar = g_object_new (GVC_TYPE_BALANCE_BAR,
"channel-map", channel_map,
+ "balance-type", btype,
NULL);
return GTK_WIDGET (bar);
}
diff --git a/gnome-volume-control/src/gvc-balance-bar.h b/gnome-volume-control/src/gvc-balance-bar.h
index e684530..01b2f13 100644
--- a/gnome-volume-control/src/gvc-balance-bar.h
+++ b/gnome-volume-control/src/gvc-balance-bar.h
@@ -34,6 +34,11 @@ G_BEGIN_DECLS
#define GVC_IS_BALANCE_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_BALANCE_BAR))
#define GVC_BALANCE_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_BALANCE_BAR, GvcBalanceBarClass))
+typedef enum {
+ BALANCE_TYPE_RL,
+ BALANCE_TYPE_FR,
+} GvcBalanceType;
+
typedef struct GvcBalanceBarPrivate GvcBalanceBarPrivate;
typedef struct
@@ -49,7 +54,8 @@ typedef struct
GType gvc_balance_bar_get_type (void);
-GtkWidget * gvc_balance_bar_new (GvcChannelMap *map);
+GtkWidget * gvc_balance_bar_new (GvcChannelMap *map,
+ GvcBalanceType btype);
void gvc_balance_bar_set_size_group (GvcBalanceBar *bar,
GtkSizeGroup *group,
diff --git a/gnome-volume-control/src/gvc-channel-map.c b/gnome-volume-control/src/gvc-channel-map.c
index b8a0791..66a8ecf 100644
--- a/gnome-volume-control/src/gvc-channel-map.c
+++ b/gnome-volume-control/src/gvc-channel-map.c
@@ -35,14 +35,15 @@
struct GvcChannelMapPrivate
{
- guint num_channels;
- pa_channel_position_t positions[PA_CHANNELS_MAX];
- gdouble gains[PA_CHANNELS_MAX];
+ pa_channel_map pa_map;
+ pa_cvolume pa_volume;
+ gdouble extern_volume[3]; /* volume, balance, fade */
gboolean can_balance;
+ gboolean can_fade;
};
enum {
- GAINS_CHANGED,
+ VOLUME_CHANGED,
LAST_SIGNAL
};
@@ -58,30 +59,70 @@ guint
gvc_channel_map_get_num_channels (GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), 0);
- return map->priv->num_channels;
-}
-gdouble *
-gvc_channel_map_get_gains (GvcChannelMap *map)
-{
- g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
- return map->priv->gains;
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return 0;
+
+ return map->priv->pa_map.channels;
}
-pa_channel_position_t *
-gvc_channel_map_get_positions (GvcChannelMap *map)
+const gdouble *
+gvc_channel_map_get_volume (GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
- return map->priv->positions;
+
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return NULL;
+
+ map->priv->extern_volume[VOLUME] = (gdouble) pa_cvolume_max (&map->priv->pa_volume);
+ map->priv->extern_volume[BALANCE] = (gdouble) pa_cvolume_get_balance (&map->priv->pa_volume, &map->priv->pa_map);
+ map->priv->extern_volume[FADE] = (gdouble) pa_cvolume_get_fade (&map->priv->pa_volume, &map->priv->pa_map);
+
+ return map->priv->extern_volume;
}
gboolean
gvc_channel_map_can_balance (GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
+
return map->priv->can_balance;
}
+gboolean
+gvc_channel_map_can_fade (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
+
+ return map->priv->can_fade;
+}
+
+const pa_channel_map *
+gvc_channel_map_get_pa_channel_map (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
+
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return NULL;
+
+ return &map->priv->pa_map;
+}
+
+const pa_cvolume *
+gvc_channel_map_get_cvolume_for_volumes (GvcChannelMap *map,
+ gint volume)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
+
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return NULL;
+
+ if (volume >= 0)
+ pa_cvolume_scale (&map->priv->pa_volume, (pa_volume_t) volume);
+
+ return &map->priv->pa_volume;
+}
+
static void
gvc_channel_map_class_init (GvcChannelMapClass *klass)
{
@@ -89,11 +130,11 @@ gvc_channel_map_class_init (GvcChannelMapClass *klass)
gobject_class->finalize = gvc_channel_map_finalize;
- signals [GAINS_CHANGED] =
- g_signal_new ("gains-changed",
+ signals [VOLUME_CHANGED] =
+ g_signal_new ("volume-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GvcChannelMapClass, gains_changed),
+ G_STRUCT_OFFSET (GvcChannelMapClass, volume_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
@@ -102,10 +143,19 @@ gvc_channel_map_class_init (GvcChannelMapClass *klass)
}
void
-gvc_channel_map_gains_changed (GvcChannelMap *map)
+gvc_channel_map_volume_changed (GvcChannelMap *map,
+ const pa_cvolume *cv)
{
g_return_if_fail (GVC_IS_CHANNEL_MAP (map));
- g_signal_emit (map, signals[GAINS_CHANGED], 0);
+ g_return_if_fail (cv != NULL);
+ g_return_if_fail (pa_cvolume_compatible_with_channel_map(cv, &map->priv->pa_map));
+
+ if (pa_cvolume_equal(cv, &map->priv->pa_volume))
+ return;
+
+ map->priv->pa_volume = *cv;
+
+ g_signal_emit (map, signals[VOLUME_CHANGED], 0);
}
static void
@@ -141,18 +191,18 @@ static void
set_from_pa_map (GvcChannelMap *map,
const pa_channel_map *pa_map)
{
- guint i;
+ g_assert (pa_channel_map_valid(pa_map));
- map->priv->num_channels = pa_map->channels;
#ifdef HAVE_NEW_PULSE
map->priv->can_balance = pa_channel_map_can_balance (pa_map);
+ map->priv->can_fade = pa_channel_map_can_fade (pa_map);
#else
- map->priv->can_balance = TRUE;
+ map->priv->can_balance = TRUE;
+ map->priv->can_fade = FALSE;
#endif
- for (i = 0; i < pa_map->channels; i++) {
- map->priv->positions[i] = pa_map->map[i];
- map->priv->gains[i] = 1.0;
- }
+
+ map->priv->pa_map = *pa_map;
+ pa_cvolume_set(&map->priv->pa_volume, pa_map->channels, PA_VOLUME_NORM);
}
GvcChannelMap *
diff --git a/gnome-volume-control/src/gvc-channel-map.h b/gnome-volume-control/src/gvc-channel-map.h
index de5815a..b00895a 100644
--- a/gnome-volume-control/src/gvc-channel-map.h
+++ b/gnome-volume-control/src/gvc-channel-map.h
@@ -44,20 +44,31 @@ typedef struct
typedef struct
{
GObjectClass parent_class;
- void (*gains_changed) (GvcChannelMap *channel_map);
+ void (*volume_changed) (GvcChannelMap *channel_map);
} GvcChannelMapClass;
+enum {
+ VOLUME,
+ BALANCE,
+ FADE,
+};
+
GType gvc_channel_map_get_type (void);
GvcChannelMap * gvc_channel_map_new (void);
GvcChannelMap * gvc_channel_map_new_from_pa_channel_map (const pa_channel_map *map);
guint gvc_channel_map_get_num_channels (GvcChannelMap *map);
-pa_channel_position_t * gvc_channel_map_get_positions (GvcChannelMap *map);
-gdouble * gvc_channel_map_get_gains (GvcChannelMap *map);
+const gdouble * gvc_channel_map_get_volume (GvcChannelMap *map);
gboolean gvc_channel_map_can_balance (GvcChannelMap *map);
+gboolean gvc_channel_map_can_fade (GvcChannelMap *map);
-void gvc_channel_map_gains_changed (GvcChannelMap *map);
+void gvc_channel_map_volume_changed (GvcChannelMap *map,
+ const pa_cvolume *cv);
+/* private */
+const pa_cvolume * gvc_channel_map_get_cvolume_for_volumes (GvcChannelMap *map,
+ int volume);
+const pa_channel_map * gvc_channel_map_get_pa_channel_map (GvcChannelMap *map);
G_END_DECLS
#endif /* __GVC_CHANNEL_MAP_H */
diff --git a/gnome-volume-control/src/gvc-mixer-control.c b/gnome-volume-control/src/gvc-mixer-control.c
index 4ac2c6c..fd69fe8 100644
--- a/gnome-volume-control/src/gvc-mixer-control.c
+++ b/gnome-volume-control/src/gvc-mixer-control.c
@@ -221,11 +221,11 @@ gvc_stream_collate (GvcMixerStream *a,
nameb = gvc_mixer_stream_get_name (b);
if (nameb == NULL && namea == NULL)
- return 0;
+ return 0;
if (nameb == NULL)
- return 1;
+ return 1;
if (namea == NULL)
- return -1;
+ return -1;
return g_utf8_collate (namea, nameb);
}
@@ -502,6 +502,7 @@ update_sink (GvcMixerControl *control,
GvcMixerStream *stream;
gboolean is_new;
pa_volume_t max_volume;
+ GvcChannelMap *map;
char map_buff[PA_CHANNEL_MAP_SNPRINT_MAX];
pa_channel_map_snprint (map_buff, PA_CHANNEL_MAP_SNPRINT_MAX, &info->channel_map);
@@ -513,17 +514,21 @@ update_sink (GvcMixerControl *control,
map_buff);
#endif
+ map = NULL;
is_new = FALSE;
stream = g_hash_table_lookup (control->priv->sinks,
GUINT_TO_POINTER (info->index));
if (stream == NULL) {
- GvcChannelMap *map;
map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map);
stream = gvc_mixer_sink_new (control->priv->pa_context,
info->index,
map);
g_object_unref (map);
is_new = TRUE;
+ } else if (gvc_mixer_stream_is_running (stream)) {
+ /* Ignore events if volume changes are outstanding */
+ g_debug ("Ignoring event, volume changes are outstanding");
+ return;
}
max_volume = pa_cvolume_max (&info->volume);
@@ -551,6 +556,10 @@ update_sink (GvcMixerControl *control,
&& strcmp (control->priv->default_sink_name, info->name) == 0) {
_set_default_sink (control, stream);
}
+
+ if (map == NULL)
+ map = gvc_mixer_stream_get_channel_map (stream);
+ gvc_channel_map_volume_changed (map, &info->volume);
}
static void
diff --git a/gnome-volume-control/src/gvc-mixer-dialog.c b/gnome-volume-control/src/gvc-mixer-dialog.c
index c953ff3..036fe87 100644
--- a/gnome-volume-control/src/gvc-mixer-dialog.c
+++ b/gnome-volume-control/src/gvc-mixer-dialog.c
@@ -63,6 +63,7 @@ struct GvcMixerDialogPrivate
GtkWidget *output_treeview;
GtkWidget *output_settings_box;
GtkWidget *output_balance_bar;
+ GtkWidget *output_fade_bar;
GtkWidget *input_treeview;
GtkWidget *sound_theme_chooser;
GtkWidget *click_feedback_button;
@@ -150,6 +151,11 @@ update_output_settings (GvcMixerDialog *dialog)
dialog->priv->output_balance_bar);
dialog->priv->output_balance_bar = NULL;
}
+ if (dialog->priv->output_fade_bar != NULL) {
+ gtk_container_remove (GTK_CONTAINER (dialog->priv->output_settings_box),
+ dialog->priv->output_fade_bar);
+ dialog->priv->output_fade_bar = NULL;
+ }
stream = gvc_mixer_control_get_default_sink (dialog->priv->mixer_control);
if (stream == NULL) {
@@ -163,7 +169,7 @@ update_output_settings (GvcMixerDialog *dialog)
return;
}
- dialog->priv->output_balance_bar = gvc_balance_bar_new (map);
+ dialog->priv->output_balance_bar = gvc_balance_bar_new (map, BALANCE_TYPE_RL);
if (dialog->priv->size_group != NULL) {
gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (dialog->priv->output_balance_bar),
dialog->priv->size_group,
@@ -174,6 +180,19 @@ update_output_settings (GvcMixerDialog *dialog)
FALSE, FALSE, 12);
gtk_widget_show (dialog->priv->output_balance_bar);
+ if (gvc_channel_map_can_fade (map)) {
+ dialog->priv->output_fade_bar = gvc_balance_bar_new (map, BALANCE_TYPE_FR);
+ if (dialog->priv->size_group != NULL) {
+ gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (dialog->priv->output_fade_bar),
+ dialog->priv->size_group,
+ TRUE);
+ }
+ gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box),
+ dialog->priv->output_fade_bar,
+ FALSE, FALSE, 12);
+ gtk_widget_show (dialog->priv->output_fade_bar);
+ }
+
/* We could make this into a "No settings" label instead */
gtk_widget_set_sensitive (dialog->priv->output_balance_bar, gvc_channel_map_can_balance (map));
}
diff --git a/gnome-volume-control/src/gvc-mixer-sink-input.c b/gnome-volume-control/src/gvc-mixer-sink-input.c
index b2c7172..963229e 100644
--- a/gnome-volume-control/src/gvc-mixer-sink-input.c
+++ b/gnome-volume-control/src/gvc-mixer-sink-input.c
@@ -52,32 +52,22 @@ gvc_mixer_sink_input_change_volume (GvcMixerStream *stream,
guint index;
GvcChannelMap *map;
pa_context *context;
- pa_cvolume cv;
- guint i;
+ const pa_cvolume *cv;
guint num_channels;
- gdouble *gains;
index = gvc_mixer_stream_get_index (stream);
map = gvc_mixer_stream_get_channel_map (stream);
num_channels = gvc_channel_map_get_num_channels (map);
- gains = gvc_channel_map_get_gains (map);
- /* set all values to nominal level */
- pa_cvolume_set (&cv, num_channels, (pa_volume_t)volume);
-
- /* apply channel gain mapping */
- for (i = 0; i < num_channels; i++) {
- pa_volume_t v;
- v = (double) volume * gains[i];
- cv.values[i] = v;
- }
+ /* set the volume */
+ cv = gvc_channel_map_get_cvolume_for_volumes (map, volume);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_sink_input_volume (context,
index,
- &cv,
+ cv,
NULL,
NULL);
diff --git a/gnome-volume-control/src/gvc-mixer-sink.c b/gnome-volume-control/src/gvc-mixer-sink.c
index 76eb3d7..c242723 100644
--- a/gnome-volume-control/src/gvc-mixer-sink.c
+++ b/gnome-volume-control/src/gvc-mixer-sink.c
@@ -35,12 +35,13 @@
struct GvcMixerSinkPrivate
{
- gpointer dummy;
+ pa_operation *change_volume_op;
};
static void gvc_mixer_sink_class_init (GvcMixerSinkClass *klass);
static void gvc_mixer_sink_init (GvcMixerSink *mixer_sink);
-static void gvc_mixer_sink_finalize (GObject *object);
+static void gvc_mixer_sink_finalize (GObject *object);
+static void gvc_mixer_sink_dispose (GObject *object);
G_DEFINE_TYPE (GvcMixerSink, gvc_mixer_sink, GVC_TYPE_MIXER_STREAM)
@@ -52,45 +53,35 @@ gvc_mixer_sink_change_volume (GvcMixerStream *stream,
guint index;
GvcChannelMap *map;
pa_context *context;
- pa_cvolume cv;
- guint i;
- guint num_channels;
- gdouble *gains;
+ const pa_cvolume *cv;
+ GvcMixerSink *sink = GVC_MIXER_SINK (stream);
index = gvc_mixer_stream_get_index (stream);
-
map = gvc_mixer_stream_get_channel_map (stream);
- num_channels = gvc_channel_map_get_num_channels (map);
- gains = gvc_channel_map_get_gains (map);
-
- g_debug ("Changing volume for sink: n=%d vol=%u", num_channels, (guint)volume);
- /* set all values to nominal level */
- pa_cvolume_set (&cv, num_channels, (pa_volume_t)volume);
+ g_debug ("Changing volume for sink: vol=%u", (guint)volume);
- /* apply channel gain mapping */
- for (i = 0; i < num_channels; i++) {
- pa_volume_t v;
- v = (double) volume * gains[i];
- g_debug ("Channel %d v=%u", i, v);
- cv.values[i] = v;
- }
+ /* set the volume */
+ cv = gvc_channel_map_get_cvolume_for_volumes (map, volume);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_sink_volume_by_index (context,
index,
- &cv,
+ cv,
NULL,
NULL);
if (o == NULL) {
- g_warning ("pa_context_set_sink_volume_by_index() failed");
+ g_warning ("pa_context_set_sink_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
- pa_operation_unref(o);
+ if (sink->priv->change_volume_op != NULL)
+ pa_operation_unref (sink->priv->change_volume_op);
+
+ sink->priv->change_volume_op = o;
return TRUE;
}
@@ -113,7 +104,7 @@ gvc_mixer_sink_change_is_muted (GvcMixerStream *stream,
NULL);
if (o == NULL) {
- g_warning ("pa_context_set_sink_mute_by_index() failed");
+ g_warning ("pa_context_set_sink_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
@@ -122,6 +113,23 @@ gvc_mixer_sink_change_is_muted (GvcMixerStream *stream,
return TRUE;
}
+static gboolean
+gvc_mixer_sink_is_running (GvcMixerStream *stream)
+{
+ GvcMixerSink *sink = GVC_MIXER_SINK (stream);
+
+ if (sink->priv->change_volume_op == NULL)
+ return FALSE;
+
+ if ((pa_operation_get_state(sink->priv->change_volume_op) == PA_OPERATION_RUNNING))
+ return TRUE;
+
+ pa_operation_unref(sink->priv->change_volume_op);
+ sink->priv->change_volume_op = NULL;
+
+ return FALSE;
+}
+
static GObject *
gvc_mixer_sink_constructor (GType type,
guint n_construct_properties,
@@ -144,10 +152,12 @@ gvc_mixer_sink_class_init (GvcMixerSinkClass *klass)
GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
object_class->constructor = gvc_mixer_sink_constructor;
+ object_class->dispose = gvc_mixer_sink_dispose;
object_class->finalize = gvc_mixer_sink_finalize;
stream_class->change_volume = gvc_mixer_sink_change_volume;
stream_class->change_is_muted = gvc_mixer_sink_change_is_muted;
+ stream_class->is_running = gvc_mixer_sink_is_running;
g_type_class_add_private (klass, sizeof (GvcMixerSinkPrivate));
}
@@ -160,6 +170,24 @@ gvc_mixer_sink_init (GvcMixerSink *sink)
}
static void
+gvc_mixer_sink_dispose (GObject *object)
+{
+ GvcMixerSink *mixer_sink;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_SINK (object));
+
+ mixer_sink = GVC_MIXER_SINK (object);
+
+ if (mixer_sink->priv->change_volume_op) {
+ pa_operation_unref(mixer_sink->priv->change_volume_op);
+ mixer_sink->priv->change_volume_op = NULL;
+ }
+
+ G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->dispose (object);
+}
+
+static void
gvc_mixer_sink_finalize (GObject *object)
{
GvcMixerSink *mixer_sink;
diff --git a/gnome-volume-control/src/gvc-mixer-source.c b/gnome-volume-control/src/gvc-mixer-source.c
index de1b09e..6eeb107 100644
--- a/gnome-volume-control/src/gvc-mixer-source.c
+++ b/gnome-volume-control/src/gvc-mixer-source.c
@@ -52,38 +52,25 @@ gvc_mixer_source_change_volume (GvcMixerStream *stream,
guint index;
GvcChannelMap *map;
pa_context *context;
- pa_cvolume cv;
- guint num_channels;
- guint i;
- gdouble *gains;
+ const pa_cvolume *cv;
index = gvc_mixer_stream_get_index (stream);
map = gvc_mixer_stream_get_channel_map (stream);
- num_channels = gvc_channel_map_get_num_channels (map);
- gains = gvc_channel_map_get_gains (map);
- /* set all values to nominal level */
- pa_cvolume_set (&cv, num_channels, (pa_volume_t)volume);
-
-
- /* apply channel gain mapping */
- for (i = 0; i < num_channels; i++) {
- pa_volume_t v;
- v = (double) volume * gains[i];
- cv.values[i] = v;
- }
+ /* set the volume */
+ cv = gvc_channel_map_get_cvolume_for_volumes (map, volume);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_source_volume_by_index (context,
index,
- &cv,
+ cv,
NULL,
NULL);
if (o == NULL) {
- g_warning ("pa_context_set_source_volume_by_index() failed");
+ g_warning ("pa_context_set_source_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
@@ -110,7 +97,7 @@ gvc_mixer_source_change_is_muted (GvcMixerStream *stream,
NULL);
if (o == NULL) {
- g_warning ("pa_context_set_source_mute_by_index() failed");
+ g_warning ("pa_context_set_source_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
diff --git a/gnome-volume-control/src/gvc-mixer-stream.c b/gnome-volume-control/src/gvc-mixer-stream.c
index 2e9a5f7..4978c60 100644
--- a/gnome-volume-control/src/gvc-mixer-stream.c
+++ b/gnome-volume-control/src/gvc-mixer-stream.c
@@ -283,10 +283,10 @@ gvc_mixer_stream_set_application_id (GvcMixerStream *stream,
}
static void
-on_channel_map_gains_changed (GvcChannelMap *channel_map,
- GvcMixerStream *stream)
+on_channel_map_volume_changed (GvcChannelMap *channel_map,
+ GvcMixerStream *stream)
{
- g_debug ("Gains changed");
+ g_debug ("Volume changed");
gvc_mixer_stream_change_volume (stream, stream->priv->volume);
}
@@ -302,7 +302,7 @@ gvc_mixer_stream_set_channel_map (GvcMixerStream *stream,
if (stream->priv->channel_map != NULL) {
g_signal_handlers_disconnect_by_func (stream->priv->channel_map,
- on_channel_map_gains_changed,
+ on_channel_map_volume_changed,
stream);
g_object_unref (stream->priv->channel_map);
}
@@ -311,8 +311,8 @@ gvc_mixer_stream_set_channel_map (GvcMixerStream *stream,
if (stream->priv->channel_map != NULL) {
g_signal_connect (stream->priv->channel_map,
- "gains-changed",
- G_CALLBACK (on_channel_map_gains_changed),
+ "volume-changed",
+ G_CALLBACK (on_channel_map_volume_changed),
stream);
g_object_notify (G_OBJECT (stream), "channel-map");
@@ -500,6 +500,14 @@ gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
return ret;
}
+gboolean
+gvc_mixer_stream_is_running (GvcMixerStream *stream)
+{
+ if (GVC_MIXER_STREAM_GET_CLASS (stream)->is_running != NULL)
+ return GVC_MIXER_STREAM_GET_CLASS (stream)->is_running (stream);
+ return FALSE;
+}
+
static void
gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
{
diff --git a/gnome-volume-control/src/gvc-mixer-stream.h b/gnome-volume-control/src/gvc-mixer-stream.h
index 2848146..50cc8db 100644
--- a/gnome-volume-control/src/gvc-mixer-stream.h
+++ b/gnome-volume-control/src/gvc-mixer-stream.h
@@ -52,6 +52,7 @@ typedef struct
guint volume);
gboolean (*change_is_muted) (GvcMixerStream *stream,
gboolean is_muted);
+ gboolean (*is_running) (GvcMixerStream *stream);
} GvcMixerStreamClass;
GType gvc_mixer_stream_get_type (void);
@@ -70,6 +71,7 @@ gboolean gvc_mixer_stream_get_is_muted (GvcMixerStream *stream);
gboolean gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream);
gboolean gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
gboolean is_muted);
+gboolean gvc_mixer_stream_is_running (GvcMixerStream *stream);
const char * gvc_mixer_stream_get_name (GvcMixerStream *stream);
const char * gvc_mixer_stream_get_icon_name (GvcMixerStream *stream);
const char * gvc_mixer_stream_get_description (GvcMixerStream *stream);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]