[Xfce4-commits] <xfce4-mixer:gber/improvements> Improve the mixer widgets

Guido Berhoerster noreply at xfce.org
Fri Sep 21 17:18:34 CEST 2012


Updating branch refs/heads/gber/improvements
         to 504d1ac40d5dfc393510d9979f2df8761017a1ae (commit)
       from fc0f8d26f5bcd194a1e69118086b847ee55de251 (commit)

commit 504d1ac40d5dfc393510d9979f2df8761017a1ae
Author: Guido Berhoerster <guido+xfce at berhoerster.name>
Date:   Fri Sep 21 12:00:36 2012 +0200

    Improve the mixer widgets
    
    Separate labels from track and option widgets and align labels and option widgets horizontally.
    Reduce the distance between faders in track widgets and ensure it is always the same.
    Put the chain buttons above the mute and record buttons and add lines to the left and right of them.
    Default to unlocked state if the volume differs between the channels of a track.

 NEWS                            |    8 ++
 xfce4-mixer/xfce-mixer-option.c |   42 ++-----
 xfce4-mixer/xfce-mixer-switch.c |   39 +++----
 xfce4-mixer/xfce-mixer-track.c  |  251 ++++++++++++++++++++++++++++-----------
 xfce4-mixer/xfce-mixer.c        |   60 +++++++---
 5 files changed, 263 insertions(+), 137 deletions(-)

diff --git a/NEWS b/NEWS
index 0d0eb5b..9b0940e 100644
--- a/NEWS
+++ b/NEWS
@@ -48,6 +48,14 @@
   changed.
 - Handle options list changed messages which indicate that the available
   options of a track have changed.
+- Separate labels from track and option widgets and align labels and option
+  widgets horizontally.
+- Reduce the distance between faders in track widgets and ensure it is always
+  the same.
+- Put the chain buttons above the mute and record buttons and add lines to the
+  left and right of them.
+- Default to unlocked state if the volume differs between the channels of a
+  track.
 
 
 4.8.0
diff --git a/xfce4-mixer/xfce-mixer-option.c b/xfce4-mixer/xfce-mixer-option.c
index 8ad8682..c9a79b5 100644
--- a/xfce4-mixer/xfce-mixer-option.c
+++ b/xfce4-mixer/xfce-mixer-option.c
@@ -54,12 +54,12 @@ static void xfce_mixer_option_bus_message     (GstBus               *bus,
 
 struct _XfceMixerOptionClass
 {
-  GtkHBoxClass __parent__;
+  GtkComboBoxClass __parent__;
 };
 
 struct _XfceMixerOption
 {
-  GtkHBox __parent__;
+  GtkComboBox    __parent__;
 
   GtkListStore  *list_store;
 
@@ -67,8 +67,6 @@ struct _XfceMixerOption
   GstMixerTrack *track;
   guint          signal_handler_id;
 
-  GtkWidget     *combo;
-
   gboolean       ignore_signals;
 };
 
@@ -99,7 +97,7 @@ xfce_mixer_option_get_type (void)
           NULL,
         };
 
-      type = g_type_register_static (GTK_TYPE_HBOX, "XfceMixerOption", &info, 0);
+      type = g_type_register_static (GTK_TYPE_COMBO_BOX, "XfceMixerOption", &info, 0);
     }
   
   return type;
@@ -181,26 +179,13 @@ static void
 xfce_mixer_option_create_contents (XfceMixerOption *option)
 {
   GstMixerOptions *options;
-  GtkWidget       *label;
   GtkCellRenderer *renderer;
   const GList     *options_iter;
   GtkTreeIter      tree_iter;
   const gchar     *active_option;
-  const gchar     *track_label;
-  gchar           *title;
   gint             i;
   gint             active_index = 0;
 
-  gtk_box_set_homogeneous (GTK_BOX (option), FALSE);
-  gtk_box_set_spacing (GTK_BOX (option), 12);
-
-  track_label = xfce_mixer_get_track_label (option->track);
-  title = g_strdup_printf ("%s:", track_label);
-
-  label = gtk_label_new (title);
-  gtk_box_pack_start (GTK_BOX (option), label, FALSE, FALSE, 0);
-  gtk_widget_show (label);
-
   options = GST_MIXER_OPTIONS (option->track);
   active_option = gst_mixer_get_option (GST_MIXER (option->card), options);
 
@@ -215,21 +200,18 @@ xfce_mixer_option_create_contents (XfceMixerOption *option)
         active_index = i;
     }
 
-  option->combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (option->list_store));
-  gtk_box_pack_start (GTK_BOX (option), option->combo, FALSE, FALSE, 0);
+  gtk_combo_box_set_model (GTK_COMBO_BOX (option), GTK_TREE_MODEL (option->list_store));
   /* Make read-only options insensitive */
   if (GST_MIXER_TRACK_HAS_FLAG (option->track, GST_MIXER_TRACK_READONLY))
-    gtk_widget_set_sensitive (option->combo, FALSE);
-  gtk_combo_box_set_active (GTK_COMBO_BOX (option->combo), active_index);
-  gtk_widget_show (option->combo);
+    gtk_widget_set_sensitive (GTK_WIDGET (option), FALSE);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (option), active_index);
+  gtk_widget_show (GTK_WIDGET (option));
 
   renderer = gtk_cell_renderer_text_new ();
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (option->combo), renderer, TRUE);
-  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (option->combo), renderer, "text", OPTION_COLUMN);
-
-  g_signal_connect (option->combo, "changed", G_CALLBACK (xfce_mixer_option_changed), option);
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (option), renderer, TRUE);
+  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (option), renderer, "text", OPTION_COLUMN);
 
-  g_free (title);
+  g_signal_connect (option, "changed", G_CALLBACK (xfce_mixer_option_changed), option);
 }
 
 
@@ -278,7 +260,7 @@ xfce_mixer_option_update (XfceMixerOption *option)
       if (G_UNLIKELY (g_utf8_collate (current_option, active_option) == 0))
         {
           option->ignore_signals = TRUE;
-          gtk_combo_box_set_active_iter (GTK_COMBO_BOX (option->combo), &iter);
+          gtk_combo_box_set_active_iter (GTK_COMBO_BOX (option), &iter);
           option->ignore_signals = FALSE;
 
           g_free (current_option);
@@ -328,7 +310,7 @@ xfce_mixer_option_bus_message (GstBus          *bus,
               gtk_list_store_set (option->list_store, &tree_iter, OPTION_COLUMN, options_iter->data, -1);
 
               if (G_UNLIKELY (g_utf8_collate (active_option, options_iter->data) == 0))
-                gtk_combo_box_set_active (GTK_COMBO_BOX (option->combo), i);
+                gtk_combo_box_set_active (GTK_COMBO_BOX (option), i);
             }
         }
     }
diff --git a/xfce4-mixer/xfce-mixer-switch.c b/xfce4-mixer/xfce-mixer-switch.c
index 4babd6c..dd07d41 100644
--- a/xfce4-mixer/xfce-mixer-switch.c
+++ b/xfce4-mixer/xfce-mixer-switch.c
@@ -1,6 +1,7 @@
 /* vi:set expandtab sw=2 sts=2: */
 /*-
  * Copyright (c) 2008 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2012 Guido Berhoerster <guido+xfce at berhoerster.name>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -39,25 +40,22 @@ static void xfce_mixer_switch_init            (XfceMixerSwitch      *mixer_switc
 static void xfce_mixer_switch_dispose         (GObject              *object);
 static void xfce_mixer_switch_finalize        (GObject              *object);
 static void xfce_mixer_switch_create_contents (XfceMixerSwitch      *mixer_switch);
-static void xfce_mixer_switch_toggled         (GtkToggleButton      *button,
-                                               XfceMixerSwitch      *mixer_switch);
+static void xfce_mixer_switch_toggled         (GtkToggleButton      *button);
 
 
 
 struct _XfceMixerSwitchClass
 {
-  GtkHBoxClass __parent__;
+  GtkCheckButtonClass __parent__;
 };
 
 struct _XfceMixerSwitch
 {
-  GtkHBox __parent__;
+  GtkCheckButton  __parent__;
 
   GstElement    *card;
   GstMixerTrack *track;
 
-  GtkWidget     *check_button;
-
   gboolean       ignore_signals;
 };
 
@@ -88,7 +86,7 @@ xfce_mixer_switch_get_type (void)
           NULL,
         };
 
-      type = g_type_register_static (GTK_TYPE_HBOX, "XfceMixerSwitch", &info, 0);
+      type = g_type_register_static (GTK_TYPE_CHECK_BUTTON, "XfceMixerSwitch", &info, 0);
     }
   
   return type;
@@ -99,7 +97,8 @@ xfce_mixer_switch_get_type (void)
 static void
 xfce_mixer_switch_class_init (XfceMixerSwitchClass *klass)
 {
-  GObjectClass *gobject_class;
+  GObjectClass         *gobject_class;
+  GtkToggleButtonClass *gtk_toggle_button_class;
 
   /* Determine parent type class */
   xfce_mixer_switch_parent_class = g_type_class_peek_parent (klass);
@@ -107,6 +106,9 @@ xfce_mixer_switch_class_init (XfceMixerSwitchClass *klass)
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->dispose = xfce_mixer_switch_dispose;
   gobject_class->finalize = xfce_mixer_switch_finalize;
+
+  gtk_toggle_button_class = GTK_TOGGLE_BUTTON_CLASS (klass);
+  gtk_toggle_button_class->toggled = xfce_mixer_switch_toggled;
 }
 
 
@@ -160,14 +162,8 @@ xfce_mixer_switch_create_contents (XfceMixerSwitch *mixer_switch)
 {
   const gchar *label;
 
-  gtk_box_set_homogeneous (GTK_BOX (mixer_switch), FALSE);
-  gtk_box_set_spacing (GTK_BOX (mixer_switch), 12);
-
   label = xfce_mixer_get_track_label (mixer_switch->track);
-  mixer_switch->check_button = gtk_check_button_new_with_mnemonic (label);
-  gtk_box_pack_start (GTK_BOX (mixer_switch), mixer_switch->check_button, FALSE, FALSE, 0);
-  gtk_widget_show (mixer_switch->check_button);
-
+  gtk_button_set_label (GTK_BUTTON (mixer_switch), label);
   xfce_mixer_switch_update (mixer_switch);
 
   /* Make read-only switches insensitive */
@@ -177,17 +173,16 @@ xfce_mixer_switch_create_contents (XfceMixerSwitch *mixer_switch)
       (GST_MIXER_TRACK_HAS_FLAG (mixer_switch->track, GST_MIXER_TRACK_OUTPUT) &&
        (GST_MIXER_TRACK_HAS_FLAG (mixer_switch->track, GST_MIXER_TRACK_NO_MUTE) ||
         GST_MIXER_TRACK_HAS_FLAG (mixer_switch->track, GST_MIXER_TRACK_READONLY))))
-    gtk_widget_set_sensitive (GTK_WIDGET (mixer_switch->check_button), FALSE);
-
-  g_signal_connect (mixer_switch->check_button, "toggled", G_CALLBACK (xfce_mixer_switch_toggled), mixer_switch);
+    gtk_widget_set_sensitive (GTK_WIDGET (mixer_switch), FALSE);
 }
 
 
 
 static void 
-xfce_mixer_switch_toggled (GtkToggleButton *button,
-                           XfceMixerSwitch *mixer_switch)
+xfce_mixer_switch_toggled (GtkToggleButton *button)
 {
+  XfceMixerSwitch *mixer_switch = XFCE_MIXER_SWITCH (button);
+
   if (G_UNLIKELY (mixer_switch->ignore_signals))
     return;
 
@@ -207,10 +202,10 @@ xfce_mixer_switch_update (XfceMixerSwitch *mixer_switch)
   mixer_switch->ignore_signals = TRUE;
 
   if (G_LIKELY (GST_MIXER_TRACK_HAS_FLAG (mixer_switch->track, GST_MIXER_TRACK_INPUT)))
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mixer_switch->check_button), 
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mixer_switch),
                                   GST_MIXER_TRACK_HAS_FLAG (mixer_switch->track, GST_MIXER_TRACK_RECORD));
   else
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mixer_switch->check_button), 
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mixer_switch),
                                   !GST_MIXER_TRACK_HAS_FLAG (mixer_switch->track, GST_MIXER_TRACK_MUTE));
 
   mixer_switch->ignore_signals = FALSE;
diff --git a/xfce4-mixer/xfce-mixer-track.c b/xfce4-mixer/xfce-mixer-track.c
index 3c26195..13fa607 100644
--- a/xfce4-mixer/xfce-mixer-track.c
+++ b/xfce4-mixer/xfce-mixer-track.c
@@ -23,6 +23,10 @@
 #include <config.h>
 #endif
 
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+
 #include <gst/gst.h>
 #include <gst/interfaces/mixer.h>
 
@@ -39,30 +43,33 @@
 
 
 
-static void xfce_mixer_track_class_init      (XfceMixerTrackClass *klass);
-static void xfce_mixer_track_init            (XfceMixerTrack      *track);
-static void xfce_mixer_track_dispose         (GObject             *object);
-static void xfce_mixer_track_finalize        (GObject             *object);
-static void xfce_mixer_track_create_contents (XfceMixerTrack      *track);
-static void xfce_mixer_track_fader_changed   (GtkRange            *range,
-                                              XfceMixerTrack      *track);
-static void xfce_mixer_track_mute_toggled    (GtkToggleButton     *button,
-                                              XfceMixerTrack      *track);
-static void xfce_mixer_track_lock_toggled    (GtkToggleButton     *button,
-                                              XfceMixerTrack      *track);
-static void xfce_mixer_track_record_toggled  (GtkToggleButton     *button,
-                                              XfceMixerTrack      *track);
+static void     xfce_mixer_track_class_init                    (XfceMixerTrackClass *klass);
+static void     xfce_mixer_track_init                          (XfceMixerTrack      *track);
+static void     xfce_mixer_track_dispose                       (GObject             *object);
+static void     xfce_mixer_track_finalize                      (GObject             *object);
+static gboolean xfce_mixer_track_lock_button_line_expose_event (GtkWidget           *widget,
+                                                                GdkEventExpose      *event,
+                                                                gpointer             user_data);
+static void     xfce_mixer_track_create_contents               (XfceMixerTrack      *track);
+static void     xfce_mixer_track_fader_changed                 (GtkRange            *range,
+                                                                XfceMixerTrack      *track);
+static void     xfce_mixer_track_mute_toggled                  (GtkToggleButton     *button,
+                                                                XfceMixerTrack      *track);
+static void     xfce_mixer_track_lock_toggled                  (GtkToggleButton     *button,
+                                                                XfceMixerTrack      *track);
+static void     xfce_mixer_track_record_toggled                (GtkToggleButton     *button,
+                                                                XfceMixerTrack      *track);
 
 
 
 struct _XfceMixerTrackClass
 {
-  GtkTableClass __parent__;
+  GtkVBoxClass __parent__;
 };
 
 struct _XfceMixerTrack
 {
-  GtkTable __parent__;
+  GtkVBox        __parent__;
 
   GtkWidget     *mute_button;
   GtkWidget     *lock_button;
@@ -103,7 +110,7 @@ xfce_mixer_track_get_type (void)
           NULL,
         };
 
-      type = g_type_register_static (GTK_TYPE_TABLE, "XfceMixerTrack", &info, 0);
+      type = g_type_register_static (GTK_TYPE_VBOX, "XfceMixerTrack", &info, 0);
     }
   
   return type;
@@ -176,40 +183,108 @@ xfce_mixer_track_new (GstElement    *card,
 
 
 
+static gboolean
+xfce_mixer_track_lock_button_line_expose_event (GtkWidget       *widget,
+                                                GdkEventExpose  *event,
+                                                gpointer         user_data)
+{
+  GtkPositionType    position = GPOINTER_TO_INT (user_data);
+  GtkAllocation      allocation;
+  cairo_t           *cr;
+  GtkStyle          *style = gtk_widget_get_style (widget);
+  GdkPoint           points[3];
+  double             line_width = 2.0;
+
+  cr = gdk_cairo_create (gtk_widget_get_window (widget));
+
+  gtk_widget_get_allocation (widget, &allocation);
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+    position = (position == GTK_POS_LEFT) ? GTK_POS_RIGHT : GTK_POS_LEFT;
+
+  /* Only refresh regions where it is necessary */
+  gdk_cairo_region (cr, event->region);
+  cairo_clip (cr);
+
+  /*
+   * Draw an L-shaped line from the right/left center to the top middle of the
+   * allocation
+   */
+  gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]);
+  cairo_set_line_width(cr, line_width);
+  if (position == GTK_POS_RIGHT)
+    {
+      points[0].x = 0;
+      points[0].y = round ((allocation.height - line_width) / 2.0);
+      points[1].x = round ((allocation.width - line_width) / 2.0);
+      points[1].y = points[0].y;
+      points[2].x = points[1].x;
+      points[2].y = 0;
+    }
+  else
+    {
+      points[0].x = allocation.width;
+      points[0].y = round ((allocation.height - line_width) / 2.0);
+      points[1].x = round ((allocation.width + line_width) / 2.0);
+      points[1].y = points[0].y;
+      points[2].x = points[1].x;
+      points[2].y = 0;
+    }
+  cairo_move_to (cr, points[0].x, points[0].y);
+  cairo_line_to (cr, points[1].x, points[1].y);
+  cairo_line_to (cr, points[2].x, points[2].y);
+  cairo_stroke (cr);
+
+  cairo_destroy (cr);
+
+  return TRUE;
+}
+
+
+
 static void
 xfce_mixer_track_create_contents (XfceMixerTrack *track)
 {
-  GtkWidget   *label;
-  GtkWidget   *image;
-  GtkWidget   *button_box;
-  GtkWidget   *fader;
-  gdouble      step;
-  const gchar *track_label;
-  gchar       *tooltip_text;
-  gint         channel;
-  gint         columns;
-  gint        *volumes;
-  
-  /* Calculate the number of columns required for the GtkTable */
-  columns = MAX (track->gst_track->num_channels, 1);
+  gint            *volumes;
+  gboolean         volume_locked = TRUE;
+  gint             channel;
+  const gchar     *track_label;
+  gchar           *tooltip_text;
+  gdouble          step;
+  GtkWidget       *faders_alignment;
+  GtkWidget       *faders_vbox;
+  GtkWidget       *faders_hbox;
+  GtkWidget       *lock_button_hbox;
+  GtkWidget       *fader;
+  GtkWidget       *lock_button_line1;
+  GtkWidget       *lock_button_line2;
+  GtkWidget       *image;
+  GtkWidget       *buttons_alignment;
+  GtkWidget       *buttons_hbox;
+  GtkRequisition   lock_button_hbox_requisition;
 
   /* Get volumes of all channels of the track */
-  volumes = g_new (gint, track->gst_track->num_channels);
+  volumes = g_new0 (gint, track->gst_track->num_channels);
   gst_mixer_get_volume (GST_MIXER (track->card), track->gst_track, volumes);
 
-  /* Put some space between channel faders */
-  gtk_table_set_col_spacings (GTK_TABLE (track), 6);
-  gtk_table_set_row_spacings (GTK_TABLE (track), 6);
-
-  /* Put the name of the track on top of the other elements */
   track_label = xfce_mixer_get_track_label (track->gst_track);
-  label = gtk_label_new (track_label);
-  gtk_misc_set_alignment (GTK_MISC (label), 0.5f, 0.5f);
-  gtk_table_attach (GTK_TABLE (track), label, 0, columns, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0);
-  gtk_widget_show (label);
 
   step = (gdouble) (track->gst_track->max_volume - track->gst_track->min_volume) / (gdouble) 20;
 
+  gtk_box_set_spacing (GTK_BOX (track), 6);
+
+  /* Center and do not expand faders and lock button */
+  faders_alignment = gtk_alignment_new (0.5, 1.0, 0, 1.0);
+  gtk_box_pack_start (GTK_BOX (track), faders_alignment, TRUE, TRUE, 0);
+  gtk_widget_show (faders_alignment);
+
+  faders_vbox = gtk_vbox_new (FALSE, 6);
+  gtk_container_add (GTK_CONTAINER (faders_alignment), faders_vbox);
+  gtk_widget_show (faders_vbox);
+
+  faders_hbox = gtk_hbox_new (TRUE, 6);
+  gtk_box_pack_start (GTK_BOX (faders_vbox), faders_hbox, TRUE, TRUE, 0);
+  gtk_widget_show (faders_hbox);
+
   /* Create a fader for each channel */
   for (channel = 0; channel < track->gst_track->num_channels; ++channel)
     {
@@ -223,27 +298,83 @@ xfce_mixer_track_create_contents (XfceMixerTrack *track)
       /* Make read-only tracks insensitive */
       if (GST_MIXER_TRACK_HAS_FLAG (track->gst_track, GST_MIXER_TRACK_READONLY))
         gtk_widget_set_sensitive (fader, FALSE);
+      gtk_box_pack_start (GTK_BOX (faders_hbox), fader, TRUE, TRUE, 0);
       g_signal_connect (fader, "value-changed", G_CALLBACK (xfce_mixer_track_fader_changed), track);
-      gtk_table_attach (GTK_TABLE (track), fader, channel, channel + 1, 1, 2, GTK_SHRINK, GTK_FILL|GTK_EXPAND, 0, 0);
       gtk_widget_show (fader);
 
       track->channel_faders = g_list_append (track->channel_faders, fader);
 
+      /* Equal volume across all channels means the track is locked */
+      if (volume_locked && channel > 0 && volumes[channel] != volumes[channel - 1])
+        volume_locked = FALSE;
+
       g_free (tooltip_text);
     }
 
-  /* Create a horizontal for the control buttons */
-  button_box = gtk_hbox_new (TRUE, 6);
-  gtk_table_attach (GTK_TABLE (track), button_box, 0, columns, 2, 3, GTK_FILL, GTK_SHRINK, 0, 0);
-  gtk_widget_show (button_box);
+  /* Create lock button with lines */
+  lock_button_hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (faders_vbox), lock_button_hbox, FALSE, FALSE, 0);
+  gtk_widget_show (lock_button_hbox);
+
+  /* Left L-shaped line */
+  lock_button_line1 =  gtk_drawing_area_new ();
+  gtk_widget_set_size_request (lock_button_line1, 12, 8);
+  gtk_box_pack_start (GTK_BOX (lock_button_hbox), lock_button_line1, TRUE, TRUE, 0);
+  g_signal_connect (G_OBJECT (lock_button_line1), "expose-event", G_CALLBACK (xfce_mixer_track_lock_button_line_expose_event), GINT_TO_POINTER (GTK_POS_LEFT));
+  gtk_widget_show (lock_button_line1);
+
+  /* Lock button */
+  tooltip_text = g_strdup_printf (_("Lock channels for %s together"), track_label);
+  track->lock_button = gtk_toggle_button_new ();
+  image = gtk_image_new_from_file (DATADIR "/pixmaps/xfce4-mixer/chain.png");
+  gtk_button_set_image (GTK_BUTTON (track->lock_button), image);
+  gtk_widget_set_tooltip_text (track->lock_button, tooltip_text);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (track->lock_button), TRUE);
+  /* Make button insensitive for read-only tracks */
+  if (GST_MIXER_TRACK_HAS_FLAG (track->gst_track, GST_MIXER_TRACK_READONLY))
+    gtk_widget_set_sensitive (track->lock_button, FALSE);
+  g_signal_connect (track->lock_button, "toggled", G_CALLBACK (xfce_mixer_track_lock_toggled), track);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (track->lock_button), volume_locked);
+  gtk_box_pack_start (GTK_BOX (lock_button_hbox), track->lock_button, FALSE, FALSE, 0);
+  gtk_widget_show (track->lock_button);
+  g_free (tooltip_text);
+
+  /* Right L-shaped line */
+  lock_button_line2 =  gtk_drawing_area_new ();
+  gtk_widget_set_size_request (lock_button_line2, 12, 8);
+  gtk_box_pack_start (GTK_BOX (lock_button_hbox), lock_button_line2, TRUE, TRUE, 0);
+  g_signal_connect (G_OBJECT (lock_button_line2), "expose-event", G_CALLBACK (xfce_mixer_track_lock_button_line_expose_event), GINT_TO_POINTER (GTK_POS_RIGHT));
+  gtk_widget_show (lock_button_line2);
+
+  /*
+   * Destroy the chain button and lines and replace them with an equally sized
+   * placeholder if there is only one fader
+   */
+  if (track->gst_track->num_channels < 2)
+    {
+      gtk_widget_size_request (lock_button_hbox, &lock_button_hbox_requisition);
+      gtk_widget_destroy (lock_button_hbox);
+      lock_button_hbox = gtk_hbox_new (FALSE, 0);
+      gtk_widget_set_size_request (lock_button_hbox, lock_button_hbox_requisition.width, lock_button_hbox_requisition.height);
+      gtk_box_pack_start (GTK_BOX (faders_vbox), lock_button_hbox, FALSE, FALSE, 0);
+      gtk_widget_show (lock_button_hbox);
+    }
+
+  buttons_alignment = gtk_alignment_new (0.5, 1.0, 0, 0);
+  gtk_box_pack_start (GTK_BOX (track), buttons_alignment, FALSE, FALSE, 0);
+  gtk_widget_show (buttons_alignment);
 
-  /* Create mute button for playback tracks */
-  if (G_LIKELY (xfce_mixer_track_type_new (track->gst_track) == XFCE_MIXER_TRACK_TYPE_PLAYBACK))
+  buttons_hbox = gtk_hbox_new (FALSE, 12);
+  gtk_container_add (GTK_CONTAINER (buttons_alignment), buttons_hbox);
+  gtk_widget_show (buttons_hbox);
+
+  /* Mute button for playback tracks */
+  if (xfce_mixer_track_type_new (track->gst_track) == XFCE_MIXER_TRACK_TYPE_PLAYBACK)
     {
       tooltip_text = g_strdup_printf (_("Mute/unmute %s"), track_label);
 
       track->mute_button = gtk_toggle_button_new ();
-      image = gtk_image_new_from_icon_name ("audio-volume-high", XFCE_MIXER_ICON_SIZE); 
+      image = gtk_image_new_from_icon_name ("audio-volume-high", XFCE_MIXER_ICON_SIZE);
       gtk_button_set_image (GTK_BUTTON (track->mute_button), image);
       gtk_widget_set_tooltip_text (track->mute_button, tooltip_text);
       /* Make button insensitive for tracks without mute or read-only tracks */
@@ -251,33 +382,13 @@ xfce_mixer_track_create_contents (XfceMixerTrack *track)
           GST_MIXER_TRACK_HAS_FLAG (track->gst_track, GST_MIXER_TRACK_NO_MUTE))
         gtk_widget_set_sensitive (track->mute_button, FALSE);
       g_signal_connect (track->mute_button, "toggled", G_CALLBACK (xfce_mixer_track_mute_toggled), track);
-      gtk_box_pack_start (GTK_BOX (button_box), track->mute_button, FALSE, FALSE, 0);
+      gtk_box_pack_start (GTK_BOX (buttons_hbox), track->mute_button, FALSE, FALSE, 0);
       gtk_widget_show (track->mute_button);
 
       g_free (tooltip_text);
     }
 
-  if (G_LIKELY (track->gst_track->num_channels >= 2))
-    {
-      tooltip_text = g_strdup_printf (_("Lock channels for %s together"), track_label);
-
-      track->lock_button = gtk_toggle_button_new ();
-      gtk_widget_set_size_request (GTK_WIDGET (track->lock_button), -1, XFCE_MIXER_ICON_SIZE);
-      image = gtk_image_new_from_file (DATADIR "/pixmaps/xfce4-mixer/chain.png");
-      gtk_button_set_image (GTK_BUTTON (track->lock_button), image);
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (track->lock_button), TRUE);
-      gtk_widget_set_tooltip_text (track->lock_button, tooltip_text);
-      /* Make button insensitive for read-only tracks */
-      if (GST_MIXER_TRACK_HAS_FLAG (track->gst_track, GST_MIXER_TRACK_READONLY))
-        gtk_widget_set_sensitive (track->lock_button, FALSE);
-      g_signal_connect (track->lock_button, "toggled", G_CALLBACK (xfce_mixer_track_lock_toggled), track);
-      gtk_box_pack_start (GTK_BOX (button_box), track->lock_button, FALSE, FALSE, 0);
-      gtk_widget_show (track->lock_button);
-
-      g_free (tooltip_text);
-    }
-
-  /* Create record button for capture tracks */
+  /* Record button for capture tracks */
   if (G_UNLIKELY (xfce_mixer_track_type_new (track->gst_track) == XFCE_MIXER_TRACK_TYPE_CAPTURE))
     {
       tooltip_text = g_strdup_printf (_("Enable/disable audible input from %s in output"), track_label);
@@ -291,7 +402,7 @@ xfce_mixer_track_create_contents (XfceMixerTrack *track)
           GST_MIXER_TRACK_HAS_FLAG (track->gst_track, GST_MIXER_TRACK_NO_RECORD))
         gtk_widget_set_sensitive (track->record_button, FALSE);
       g_signal_connect (track->record_button, "toggled", G_CALLBACK (xfce_mixer_track_record_toggled), track);
-      gtk_box_pack_start (GTK_BOX (button_box), track->record_button, FALSE, FALSE, 0);
+      gtk_box_pack_start (GTK_BOX (buttons_hbox), track->record_button, FALSE, FALSE, 0);
       gtk_widget_show (track->record_button);
 
       g_free (tooltip_text);
diff --git a/xfce4-mixer/xfce-mixer.c b/xfce4-mixer/xfce-mixer.c
index dd6f5f6..a39da96 100644
--- a/xfce4-mixer/xfce-mixer.c
+++ b/xfce4-mixer/xfce-mixer.c
@@ -248,7 +248,10 @@ xfce_mixer_create_contents (XfceMixer *mixer)
   GstMixerTrack        *track;
   const GList          *iter;
   const gchar          *titles[4] = { N_("Playback"), N_("Capture"), N_("Switches"), N_("Options") };
+  GtkWidget            *label_alignment;
+  GtkWidget            *option_alignment;
   GtkWidget            *track_widget;
+  GtkWidget            *track_label_widget;
   GtkWidget            *labels[4];
   GtkWidget            *scrollwins[4];
   GtkWidget            *views[4];
@@ -256,6 +259,7 @@ xfce_mixer_create_contents (XfceMixer *mixer)
   GtkWidget            *label1;
   GtkWidget            *label2;
   const gchar          *track_label;
+  gchar                *option_track_label;
   guint                 num_children[4] = { 0, 0, 0, 0 };
   gboolean              no_controls_visible = TRUE;
   gint                  i;
@@ -273,14 +277,13 @@ xfce_mixer_create_contents (XfceMixer *mixer)
       gtk_container_set_border_width (GTK_CONTAINER (scrollwins[i]), 6);
       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwins[i]), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
-      if (i < 2) 
-        {
-          views[i] = gtk_table_new (1, 1, FALSE);
-          gtk_table_set_col_spacings (GTK_TABLE (views[i]), 12);
-          gtk_table_set_row_spacings (GTK_TABLE (views[i]), 6);
-        }
+      if (i < 2)
+        views[i] = gtk_table_new (1, 2, FALSE);
       else
-        views[i] = gtk_vbox_new (FALSE, 6);
+        views[i] = gtk_table_new (2, 1, FALSE);
+
+      gtk_table_set_col_spacings (GTK_TABLE (views[i]), 12);
+      gtk_table_set_row_spacings (GTK_TABLE (views[i]), 6);
 
       gtk_container_set_border_width (GTK_CONTAINER (views[i]), 6);
       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrollwins[i]), views[i]);
@@ -308,16 +311,20 @@ xfce_mixer_create_contents (XfceMixer *mixer)
             {
             case XFCE_MIXER_TRACK_TYPE_PLAYBACK:
               /* Create a regular volume control for this track */
+              track_label_widget = gtk_label_new (track_label);
+              gtk_table_attach (GTK_TABLE (views[0]), track_label_widget,
+                                num_children[0], num_children[0] + 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+              gtk_widget_show (track_label_widget);
               track_widget = xfce_mixer_track_new (mixer->card, track);
-              gtk_table_attach (GTK_TABLE (views[0]), track_widget, 
-                                num_children[0], num_children[0] + 1, 0, 1, GTK_SHRINK, GTK_FILL|GTK_EXPAND, 0, 0);
+              gtk_table_attach (GTK_TABLE (views[0]), track_widget,
+                                num_children[0], num_children[0] + 1, 1, 2, GTK_SHRINK, GTK_FILL|GTK_EXPAND, 0, 0);
               gtk_widget_show (track_widget);
               num_children[0]++;
 
               /* Append a separator. The last one will be destroyed later */
               last_separator[0] = gtk_vseparator_new ();
               gtk_table_attach (GTK_TABLE (views[0]), last_separator[0], 
-                                num_children[0], num_children[0] + 1, 0, 1, GTK_SHRINK, GTK_FILL|GTK_EXPAND, 0, 0);
+                                num_children[0], num_children[0] + 1, 0, 2, GTK_SHRINK, GTK_FILL|GTK_EXPAND, 0, 0);
               gtk_widget_show (last_separator[0]);
               num_children[0]++;
 
@@ -327,16 +334,20 @@ xfce_mixer_create_contents (XfceMixer *mixer)
 
             case XFCE_MIXER_TRACK_TYPE_CAPTURE:
               /* Create a regular volume control for this track */
+              track_label_widget = gtk_label_new (track_label);
+              gtk_table_attach (GTK_TABLE (views[1]), track_label_widget,
+                                num_children[1], num_children[1] + 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+              gtk_widget_show (track_label_widget);
               track_widget = xfce_mixer_track_new (mixer->card, track);
-              gtk_table_attach (GTK_TABLE (views[1]), track_widget, 
-                                num_children[1], num_children[1] + 1, 0, 1, GTK_SHRINK, GTK_FILL|GTK_EXPAND, 0, 0);
+              gtk_table_attach (GTK_TABLE (views[1]), track_widget,
+                                num_children[1], num_children[1] + 1, 1, 2, GTK_SHRINK, GTK_FILL|GTK_EXPAND, 0, 0);
               gtk_widget_show (track_widget);
               num_children[1]++;
 
               /* Append a separator. The last one will be destroyed later */
               last_separator[1] = gtk_vseparator_new ();
               gtk_table_attach (GTK_TABLE (views[1]), last_separator[1], 
-                                num_children[1], num_children[1] + 1, 0, 1, GTK_SHRINK, GTK_FILL|GTK_EXPAND, 0, 0);
+                                num_children[1], num_children[1] + 1, 0, 2, GTK_SHRINK, GTK_FILL|GTK_EXPAND, 0, 0);
               gtk_widget_show (last_separator[1]);
               num_children[1]++;
 
@@ -346,8 +357,10 @@ xfce_mixer_create_contents (XfceMixer *mixer)
 
             case XFCE_MIXER_TRACK_TYPE_SWITCH:
               track_widget = xfce_mixer_switch_new (mixer->card, track);
-              gtk_box_pack_start (GTK_BOX (views[2]), track_widget, FALSE, FALSE, 0);
+              gtk_table_attach (GTK_TABLE (views[2]), track_widget,
+                                0, 1, num_children[2], num_children[2] + 1, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0);
               gtk_widget_show (track_widget);
+
               num_children[2]++;
 
               /* Add the track to the hash table */
@@ -355,9 +368,26 @@ xfce_mixer_create_contents (XfceMixer *mixer)
               break;
 
             case XFCE_MIXER_TRACK_TYPE_OPTIONS:
+              label_alignment = gtk_alignment_new (0, 0, 0, 0);
+              gtk_table_attach (GTK_TABLE (views[3]), label_alignment,
+                                0, 1, num_children[3], num_children[3] + 1, GTK_FILL, GTK_SHRINK, 0, 0);
+              gtk_widget_show (label_alignment);
+
+              option_track_label = g_strdup_printf ("%s:", track_label);
+              track_label_widget = gtk_label_new (option_track_label);
+              gtk_container_add (GTK_CONTAINER (label_alignment), track_label_widget);
+              gtk_widget_show (track_label_widget);
+              g_free (option_track_label);
+
+              option_alignment = gtk_alignment_new (0, 0, 1.0f, 0);
+              gtk_table_attach (GTK_TABLE (views[3]), option_alignment,
+                                1, 2, num_children[3], num_children[3] + 1, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0);
+              gtk_widget_show (option_alignment);
+
               track_widget = xfce_mixer_option_new (mixer->card, track);
-              gtk_box_pack_start (GTK_BOX (views[3]), track_widget, FALSE, FALSE, 0);
+              gtk_container_add (GTK_CONTAINER (option_alignment), track_widget);
               gtk_widget_show (track_widget);
+
               num_children[3]++;
 
               /* Add the track to the hash table */


More information about the Xfce4-commits mailing list