diff -u -r gnome-media-2.26.0/gnome-volume-control/src/gvc-balance-bar.c hacked/gnome-volume-control/src/gvc-balance-bar.c
--- gnome-media-2.26.0/gnome-volume-control/src/gvc-balance-bar.c	2009-05-01 20:58:53.984379877 -0400
+++ hacked/gnome-volume-control/src/gvc-balance-bar.c	2009-05-01 20:52:24.735160934 -0400
@@ -38,6 +38,7 @@
 struct GvcBalanceBarPrivate
 {
         GvcChannelMap *channel_map;
+        GvcBalanceType btype;
         GtkWidget     *scale_box;
         GtkWidget     *start_box;
         GtkWidget     *end_box;
@@ -52,7 +53,8 @@
 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_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 @@
 
         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);
@@ -175,6 +191,53 @@
 }
 
 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.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);
+
+        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 +249,9 @@
         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 +308,19 @@
                                                               "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 +371,26 @@
                              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;
+        gdouble               *volume;
 
+        volume = gvc_channel_map_get_volume (bar->priv->channel_map);
         val = gtk_adjustment_get_value (adjustment);
 
         if (bar->priv->channel_map == NULL) {
                 return;
         }
+	if (bar->priv->btype == BALANCE_TYPE_RL)
+		volume[BALANCE] = val;
+	else
+		volume[FADE] = val;
 
-        left_v = 1.0;
-        right_v = 1.0;
-
-        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;
-                }
-        }
-
-        gvc_channel_map_gains_changed (bar->priv->channel_map);
+	gvc_channel_map_volume_changed (bar->priv->channel_map);
 }
 
 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 +413,12 @@
 }
 
 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 -u -r gnome-media-2.26.0/gnome-volume-control/src/gvc-balance-bar.h hacked/gnome-volume-control/src/gvc-balance-bar.h
--- gnome-media-2.26.0/gnome-volume-control/src/gvc-balance-bar.h	2008-12-14 10:59:37.000000000 -0500
+++ hacked/gnome-volume-control/src/gvc-balance-bar.h	2009-05-01 19:49:45.858378923 -0400
@@ -34,6 +34,11 @@
 #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 @@
 
 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 -u -r gnome-media-2.26.0/gnome-volume-control/src/gvc-channel-map.c hacked/gnome-volume-control/src/gvc-channel-map.c
--- gnome-media-2.26.0/gnome-volume-control/src/gvc-channel-map.c	2009-03-03 16:26:48.000000000 -0500
+++ hacked/gnome-volume-control/src/gvc-channel-map.c	2009-05-01 20:23:45.392379947 -0400
@@ -36,13 +36,14 @@
 struct GvcChannelMapPrivate
 {
         guint                 num_channels;
-        pa_channel_position_t positions[PA_CHANNELS_MAX];
-        gdouble               gains[PA_CHANNELS_MAX];
+        gdouble               volume[3]; /* volume, balance, fade */
         gboolean              can_balance;
+        gboolean              can_fade;
+        char                 *pa_map_str;
 };
 
 enum {
-        GAINS_CHANGED,
+        VOLUME_CHANGED,
         LAST_SIGNAL
 };
 
@@ -62,24 +63,58 @@
 }
 
 gdouble *
-gvc_channel_map_get_gains (GvcChannelMap *map)
+gvc_channel_map_get_volume (GvcChannelMap *map)
 {
         g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
-        return map->priv->gains;
+        return map->priv->volume;
 }
 
-pa_channel_position_t *
-gvc_channel_map_get_positions (GvcChannelMap *map)
+gboolean
+gvc_channel_map_can_balance (GvcChannelMap  *map)
 {
-        g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
-        return map->priv->positions;
+        g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
+        return map->priv->can_balance;
 }
 
 gboolean
-gvc_channel_map_can_balance (GvcChannelMap  *map)
+gvc_channel_map_can_fade (GvcChannelMap  *map)
 {
         g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
-        return map->priv->can_balance;
+
+        return map->priv->can_fade;
+}
+
+static pa_channel_map *
+gvc_channel_map_get_pa_channel_map (GvcChannelMap  *map)
+{
+        pa_channel_map *pa_map;
+
+        g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
+        pa_map = g_new0 (pa_channel_map, 1);
+        return pa_channel_map_parse (pa_map, map->priv->pa_map_str);
+}
+
+pa_cvolume *
+gvc_channel_map_get_cvolume_for_volumes (GvcChannelMap  *map,
+                                         guint           volume)
+{
+        pa_channel_map *pa_map;
+        pa_cvolume *cv;
+        gdouble *volumes;
+
+        pa_map = gvc_channel_map_get_pa_channel_map (map);
+        if (pa_map == NULL)
+                return NULL;
+
+        cv = g_new0 (pa_cvolume, 1);
+        volumes = map->priv->volume;
+        pa_cvolume_set (cv, map->priv->num_channels, (pa_volume_t) volume);
+        pa_cvolume_set_balance (cv, gvc_channel_map_get_pa_channel_map (map), volumes[BALANCE]);
+        pa_cvolume_set_fade (cv, gvc_channel_map_get_pa_channel_map (map), volumes[FADE]);
+
+        g_free (pa_map);
+
+        return cv;
 }
 
 static void
@@ -89,11 +124,11 @@
 
         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 +137,10 @@
 }
 
 void
-gvc_channel_map_gains_changed (GvcChannelMap *map)
+gvc_channel_map_volume_changed (GvcChannelMap *map)
 {
         g_return_if_fail (GVC_IS_CHANNEL_MAP (map));
-        g_signal_emit (map, signals[GAINS_CHANGED], 0);
+        g_signal_emit (map, signals[VOLUME_CHANGED], 0);
 }
 
 static void
@@ -141,18 +176,30 @@
 set_from_pa_map (GvcChannelMap        *map,
                  const pa_channel_map *pa_map)
 {
-        guint i;
+	GString *s;
+        guint i = 0;
+
+        g_assert (pa_map->channels > 0);
 
         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_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->volume[VOLUME] = 1.0;
+	map->priv->volume[BALANCE] = 0.0;
+	map->priv->volume[FADE] = 0.0;
+
+	s = g_string_new (pa_channel_position_to_string (pa_map->map[i]));
+	for (i = 1; i < pa_map->channels; i++) {
+		g_string_append_printf (s, ",%s",
+					pa_channel_position_to_string (pa_map->map[i]));
+	}
+	map->priv->pa_map_str = g_string_free (s, FALSE);
 }
 
 GvcChannelMap *
diff -u -r gnome-media-2.26.0/gnome-volume-control/src/gvc-channel-map.h hacked/gnome-volume-control/src/gvc-channel-map.h
--- gnome-media-2.26.0/gnome-volume-control/src/gvc-channel-map.h	2009-03-03 16:26:48.000000000 -0500
+++ hacked/gnome-volume-control/src/gvc-channel-map.h	2009-05-01 19:49:45.845380281 -0400
@@ -44,19 +44,29 @@
 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);
+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_volume_changed          (GvcChannelMap  *map);
 
-void                    gvc_channel_map_gains_changed           (GvcChannelMap  *map);
+/* private */
+pa_cvolume *            gvc_channel_map_get_cvolume_for_volumes (GvcChannelMap  *map,
+                                                                 guint           volume);
 
 G_END_DECLS
 
diff -u -r gnome-media-2.26.0/gnome-volume-control/src/gvc-mixer-dialog.c hacked/gnome-volume-control/src/gvc-mixer-dialog.c
--- gnome-media-2.26.0/gnome-volume-control/src/gvc-mixer-dialog.c	2009-03-04 20:35:12.000000000 -0500
+++ hacked/gnome-volume-control/src/gvc-mixer-dialog.c	2009-05-01 19:49:45.851380337 -0400
@@ -62,6 +62,7 @@
         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;
@@ -149,6 +150,11 @@
                                       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) {
@@ -162,7 +168,7 @@
                 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,
@@ -173,6 +179,19 @@
                             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 -u -r gnome-media-2.26.0/gnome-volume-control/src/gvc-mixer-sink.c hacked/gnome-volume-control/src/gvc-mixer-sink.c
--- gnome-media-2.26.0/gnome-volume-control/src/gvc-mixer-sink.c	2008-12-14 10:59:37.000000000 -0500
+++ hacked/gnome-volume-control/src/gvc-mixer-sink.c	2009-05-01 19:49:45.844379934 -0400
@@ -52,36 +52,24 @@
         guint              index;
         GvcChannelMap     *map;
         pa_context        *context;
-        pa_cvolume         cv;
-        guint              i;
+        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);
 
         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);
-
-        /* 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);
 
@@ -92,6 +80,8 @@
 
         pa_operation_unref(o);
 
+        g_free (cv);
+
         return TRUE;
 }
 
diff -u -r gnome-media-2.26.0/gnome-volume-control/src/gvc-mixer-sink-input.c hacked/gnome-volume-control/src/gvc-mixer-sink-input.c
--- gnome-media-2.26.0/gnome-volume-control/src/gvc-mixer-sink-input.c	2009-03-04 20:35:12.000000000 -0500
+++ hacked/gnome-volume-control/src/gvc-mixer-sink-input.c	2009-05-01 19:49:45.854380329 -0400
@@ -52,26 +52,16 @@
         guint              index;
         GvcChannelMap     *map;
         pa_context        *context;
-        pa_cvolume         cv;
-        guint              i;
+        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);
 
@@ -88,6 +78,8 @@
 
         pa_operation_unref(o);
 
+        g_free (cv);
+
         return TRUE;
 }
 
diff -u -r gnome-media-2.26.0/gnome-volume-control/src/gvc-mixer-source.c hacked/gnome-volume-control/src/gvc-mixer-source.c
--- gnome-media-2.26.0/gnome-volume-control/src/gvc-mixer-source.c	2008-12-14 10:59:37.000000000 -0500
+++ hacked/gnome-volume-control/src/gvc-mixer-source.c	2009-05-01 19:49:45.852380544 -0400
@@ -52,33 +52,22 @@
         guint              index;
         GvcChannelMap     *map;
         pa_context        *context;
-        pa_cvolume         cv;
+        pa_cvolume        *cv;
         guint              num_channels;
-        guint              i;
-        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_source_volume_by_index (context,
                                                    index,
-                                                   &cv,
+                                                   cv,
                                                    NULL,
                                                    NULL);
 
@@ -89,6 +78,8 @@
 
         pa_operation_unref(o);
 
+        g_free (cv);
+
         return TRUE;
 }
 
diff -u -r gnome-media-2.26.0/gnome-volume-control/src/gvc-mixer-stream.c hacked/gnome-volume-control/src/gvc-mixer-stream.c
--- gnome-media-2.26.0/gnome-volume-control/src/gvc-mixer-stream.c	2009-03-04 20:35:12.000000000 -0500
+++ hacked/gnome-volume-control/src/gvc-mixer-stream.c	2009-05-01 19:49:45.860378569 -0400
@@ -283,10 +283,10 @@
 }
 
 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 @@
 
         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 @@
 
         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");
