[gnome-flashback] sound applet finished



commit 6db6451585a2637f972edf23825e8d681491de92
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Fri Aug 29 20:32:52 2014 +0300

    sound applet finished

 .gitmodules                                       |    3 +
 autogen.sh                                        |    7 +
 configure.ac                                      |   11 +
 gnome-flashback/Makefile.am                       |    6 +-
 gnome-flashback/flashback-application.c           |   17 +
 gnome-flashback/libsound-applet/Makefile.am       |  134 +---
 gnome-flashback/libsound-applet/gvc               |    1 +
 gnome-flashback/libsound-applet/gvc-applet.c      |    2 +
 gnome-flashback/libsound-applet/gvc-channel-bar.c |  975 +++++++++++++++++++++
 gnome-flashback/libsound-applet/gvc-channel-bar.h |   86 ++
 gnome-flashback/libsound-applet/gvc-log.c         |   61 --
 gnome-flashback/libsound-applet/gvc-log.h         |   32 -
 po/POTFILES.in                                    |    4 +
 13 files changed, 1133 insertions(+), 206 deletions(-)
---
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..ebbfc19
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "gnome-flashback/libsound-applet/gvc"]
+       path = gnome-flashback/libsound-applet/gvc
+       url = git://git.gnome.org/libgnome-volume-control
diff --git a/autogen.sh b/autogen.sh
index db9a768..08b6c51 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -12,6 +12,13 @@ PKG_NAME="gnome-flashback"
     exit 1
 }
 
+if test ! -f gnome-flashback/libsound-applet/gvc/Makefile.am;
+then
+       echo "+ Setting up submodules"
+       git submodule init
+fi
+git submodule update
+
 which gnome-autogen.sh || {
     echo "You need to install gnome-common."
     exit 1
diff --git a/configure.ac b/configure.ac
index 556d9fd..fcf2ca0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,6 +29,8 @@ GLIB_GSETTINGS
 
 GTK_REQUIRED=3.10.0
 LIBGNOME_DESKTOP_REQUIRED=3.8.0
+CANBERRA_REQUIRED=0.13
+GLIB_REQUIRED=2.39.91
 
 PKG_CHECK_MODULES(GNOME_FLASHBACK, gtk+-3.0 >= $GTK_REQUIRED)
 AC_SUBST(GNOME_FLASHBACK_CFLAGS)
@@ -50,6 +52,13 @@ PKG_CHECK_MODULES(IDLE_MONITOR, gtk+-3.0 >= $GTK_REQUIRED)
 AC_SUBST(IDLE_MONITOR_CFLAGS)
 AC_SUBST(IDLE_MONITOR_LIBS)
 
+PKG_CHECK_MODULES(GVC, gobject-2.0 libpulse libpulse-mainloop-glib)
+AM_CONDITIONAL(HAVE_INTROSPECTION, false)
+
+PKG_CHECK_MODULES(SOUND_APPLET, gtk+-3.0 >= $GTK_REQUIRED libcanberra-gtk3 >= $CANBERRA_REQUIRED glib-2.0 >= 
$GLIB_REQUIRED)
+AC_SUBST(SOUND_APPLET_CFLAGS)
+AC_SUBST(SOUND_APPLET_LIBS)
+
 AC_CONFIG_FILES([
 Makefile
 gnome-flashback/Makefile
@@ -57,6 +66,8 @@ gnome-flashback/libdesktop-background/Makefile
 gnome-flashback/libdisplay-config/Makefile
 gnome-flashback/libend-session-dialog/Makefile
 gnome-flashback/libidle-monitor/Makefile
+gnome-flashback/libsound-applet/Makefile
+gnome-flashback/libsound-applet/gvc/Makefile
 po/Makefile.in
 sessions/Makefile
 ])
diff --git a/gnome-flashback/Makefile.am b/gnome-flashback/Makefile.am
index 56bc4a8..362a449 100644
--- a/gnome-flashback/Makefile.am
+++ b/gnome-flashback/Makefile.am
@@ -2,7 +2,8 @@ SUBDIRS = \
        libdesktop-background \
        libdisplay-config \
        libend-session-dialog \
-       libidle-monitor
+       libidle-monitor \
+       libsound-applet
 
 bin_PROGRAMS = \
        gnome-flashback
@@ -22,7 +23,8 @@ gnome_flashback_LDADD = \
        $(top_builddir)/gnome-flashback/libdesktop-background/libdesktop-background.la \
        $(top_builddir)/gnome-flashback/libdisplay-config/libdisplay-config.la \
        $(top_builddir)/gnome-flashback/libend-session-dialog/libend-session-dialog.la \
-       $(top_builddir)/gnome-flashback/libidle-monitor/libidle-monitor.la
+       $(top_builddir)/gnome-flashback/libidle-monitor/libidle-monitor.la \
+       $(top_builddir)/gnome-flashback/libsound-applet/libsound-applet.la
 
 desktopdir       = $(datadir)/applications
 desktop_in_files = gnome-flashback.desktop.in
diff --git a/gnome-flashback/flashback-application.c b/gnome-flashback/flashback-application.c
index ca14b5a..41ae468 100644
--- a/gnome-flashback/flashback-application.c
+++ b/gnome-flashback/flashback-application.c
@@ -23,6 +23,7 @@
 #include "libdisplay-config/flashback-display-config.h"
 #include "libend-session-dialog/flashback-end-session-dialog.h"
 #include "libidle-monitor/flashback-idle-monitor.h"
+#include "libsound-applet/gvc-applet.h"
 
 #define FLASHBACK_SCHEMA       "org.gnome.gnome-flashback"
 #define KEY_DESKTOP_BACKGROUND "desktop-background"
@@ -38,6 +39,7 @@ struct _FlashbackApplicationPrivate {
        FlashbackDisplayConfig     *config;
        FlashbackEndSessionDialog  *dialog;
        FlashbackIdleMonitor       *monitor;
+       GvcApplet                  *applet;
 };
 
 G_DEFINE_TYPE (FlashbackApplication, flashback_application, GTK_TYPE_APPLICATION);
@@ -100,6 +102,19 @@ flashback_application_settings_changed (GSettings   *settings,
                        }
                }
        }
+
+       if (key == NULL || g_strcmp0 (key, KEY_SOUND_APPLET) == 0) {
+               if (g_settings_get_boolean (settings, KEY_SOUND_APPLET)) {
+                       if (app->priv->applet == NULL) {
+                               app->priv->applet = gvc_applet_new ();
+                       }
+               } else {
+                       if (app->priv->applet) {
+                               g_object_unref (app->priv->applet);
+                               app->priv->applet = NULL;
+                       }
+               }
+       }
 }
 
 static void
@@ -152,6 +167,8 @@ flashback_application_shutdown (GApplication *application)
                app->priv->monitor = NULL;
        }
 
+       g_clear_object (&app->priv->applet);
+
        if (app->priv->settings) {
                g_object_unref (app->priv->settings);
                app->priv->settings = NULL;
diff --git a/gnome-flashback/libsound-applet/Makefile.am b/gnome-flashback/libsound-applet/Makefile.am
index 4f93246..6d58810 100644
--- a/gnome-flashback/libsound-applet/Makefile.am
+++ b/gnome-flashback/libsound-applet/Makefile.am
@@ -1,113 +1,25 @@
-SUBDIRS = data
-
-# This is used in PANEL_CFLAGS
-cappletname = sound
-NULL =
-
-ccpanelsdir = $(PANELS_DIR)
-ccpanels_LTLIBRARIES = libsound.la
-
-bin_PROGRAMS =                                 \
-       gnome-sound-applet                      \
-       $(NULL)
-
-AM_CPPFLAGS =                                  \
-       $(PANEL_CFLAGS)                         \
-       $(SOUND_PANEL_CFLAGS)                   \
-       -DLOCALE_DIR=\""$(datadir)/locale"\"    \
-       -DLIBEXECDIR=\"$(libexecdir)\"          \
-       -DGLADEDIR=\""$(pkgdatadir)"\"          \
-        -DSOUND_DATA_DIR="\"$(datadir)/sounds\""       \
-        -DSOUND_SET_DIR="\"$(pkgdatadir)/sounds\""     \
-       -DICON_DATA_DIR="\"$(pkgdatadir)/icons\"" \
-       $(NULL)
-
-noinst_LTLIBRARIES = libgnomevolumecontrol.la
-libgnomevolumecontrol_la_SOURCES =             \
-       gvc-mixer-card.h                        \
-       gvc-mixer-card.c                        \
-       gvc-mixer-card-private.h                \
-       gvc-mixer-stream.h                      \
-       gvc-mixer-stream.c                      \
-       gvc-mixer-stream-private.h              \
-       gvc-channel-map.h                       \
-       gvc-channel-map.c                       \
-       gvc-channel-map-private.h               \
-       gvc-mixer-ui-device.h                   \
-       gvc-mixer-ui-device.c                   \
-       gvc-mixer-sink.h                        \
-       gvc-mixer-sink.c                        \
-       gvc-mixer-source.h                      \
-       gvc-mixer-source.c                      \
-       gvc-mixer-sink-input.h                  \
-       gvc-mixer-sink-input.c                  \
-       gvc-mixer-source-output.h               \
-       gvc-mixer-source-output.c               \
-       gvc-mixer-event-role.h                  \
-       gvc-mixer-event-role.c                  \
-       gvc-mixer-control.h                     \
-       gvc-mixer-control.c                     \
-       gvc-mixer-control-private.h             \
-       gvc-channel-bar.h                       \
-       gvc-channel-bar.c                       \
-       gvc-pulseaudio-fake.h                   \
-       $(NULL)
-
-gnome_sound_applet_LDADD =                     \
-       -lm                                     \
-       libgnomevolumecontrol.la                \
-       $(SOUND_PANEL_LIBS)                     \
-       $(NULL)
-
-gnome_sound_applet_SOURCES =                   \
-       gvc-stream-status-icon.h                \
-       gvc-stream-status-icon.c                \
-       gvc-applet.h                            \
-       gvc-applet.c                            \
-       gvc-log.h                               \
-       gvc-log.c                               \
-       applet-main.c                           \
-       $(NULL)
-
-libsound_la_LIBADD =                           \
-       -lm                                     \
-       libgnomevolumecontrol.la                \
-       $(PANEL_LIBS)                           \
-       $(SOUND_PANEL_LIBS)                     \
-       $(NULL)
-
-libsound_la_LDFLAGS =                          \
-       $(PANEL_LDFLAGS)                        \
-       $(NULL)
-
-libsound_la_SOURCES =                          \
-       gvc-balance-bar.h                       \
-       gvc-balance-bar.c                       \
-       gvc-mixer-dialog.h                      \
-       gvc-mixer-dialog.c                      \
-       gvc-level-bar.h                         \
-       gvc-level-bar.c                         \
-       gvc-combo-box.h                         \
-       gvc-combo-box.c                         \
-       gvc-speaker-test.h                      \
-       gvc-speaker-test.c                      \
-       gvc-sound-theme-chooser.c               \
-       gvc-sound-theme-chooser.h               \
-       sound-theme-file-utils.c                \
-       sound-theme-file-utils.h                \
-       cc-sound-panel.c                        \
-       cc-sound-panel.h                        \
-       $(NULL)
-
-BUILT_SOURCES =                                \
-       $(NULL)
-
-CLEANFILES =                           \
-       $(BUILT_SOURCES)                \
-       $(NULL)
-
-MAINTAINERCLEANFILES =                  \
-        *~                              \
-        Makefile.in
+SUBDIRS = \
+       gvc
+
+noinst_LTLIBRARIES = \
+       libsound-applet.la
+
+AM_CPPFLAGS = \
+       $(SOUND_APPLET_CFLAGS) \
+       -I$(top_builddir)/gnome-flashback/libsound-applet \
+       -I$(srcdir)/gvc
+
+libsound_applet_la_SOURCES = \
+       gvc-applet.c \
+       gvc-applet.h \
+       gvc-channel-bar.c \
+       gvc-channel-bar.h \
+       gvc-stream-status-icon.c \
+       gvc-stream-status-icon.h
+
+libsound_applet_la_LIBADD = \
+       -lm \
+       $(SOUND_APPLET_LIBS) \
+       gvc/libgvc.la
 
 -include $(top_srcdir)/git.mk
diff --git a/gnome-flashback/libsound-applet/gvc b/gnome-flashback/libsound-applet/gvc
new file mode 160000
index 0000000..e14dbe8
--- /dev/null
+++ b/gnome-flashback/libsound-applet/gvc
@@ -0,0 +1 @@
+Subproject commit e14dbe8aa6dfaeea4a9f3405cf2f3e238e88623b
diff --git a/gnome-flashback/libsound-applet/gvc-applet.c b/gnome-flashback/libsound-applet/gvc-applet.c
index 702796e..3142472 100644
--- a/gnome-flashback/libsound-applet/gvc-applet.c
+++ b/gnome-flashback/libsound-applet/gvc-applet.c
@@ -298,5 +298,7 @@ gvc_applet_new (void)
 
         applet = g_object_new (GVC_TYPE_APPLET, NULL);
 
+        gvc_applet_start (GVC_APPLET (applet));
+
         return GVC_APPLET (applet);
 }
diff --git a/gnome-flashback/libsound-applet/gvc-channel-bar.c 
b/gnome-flashback/libsound-applet/gvc-channel-bar.c
new file mode 100644
index 0000000..429b335
--- /dev/null
+++ b/gnome-flashback/libsound-applet/gvc-channel-bar.c
@@ -0,0 +1,975 @@
+/*
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <pulse/pulseaudio.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+
+#include "gvc-channel-bar.h"
+#include "gvc-mixer-control.h"
+
+#define SCALE_SIZE 128
+#define ADJUSTMENT_MAX_NORMAL gvc_mixer_control_get_vol_max_norm(NULL)
+#define ADJUSTMENT_MAX_AMPLIFIED gvc_mixer_control_get_vol_max_amplified(NULL)
+#define ADJUSTMENT_MAX (bar->priv->is_amplified ? ADJUSTMENT_MAX_AMPLIFIED : ADJUSTMENT_MAX_NORMAL)
+#define SCROLLSTEP (ADJUSTMENT_MAX / 100.0 * 5.0)
+
+#define GVC_CHANNEL_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_CHANNEL_BAR, 
GvcChannelBarPrivate))
+
+struct GvcChannelBarPrivate
+{
+        GtkOrientation orientation;
+        GtkWidget     *scale_box;
+        GtkWidget     *start_box;
+        GtkWidget     *end_box;
+        GtkWidget     *image;
+        GtkWidget     *label;
+        GtkWidget     *low_image;
+        GtkWidget     *scale;
+        GtkWidget     *high_image;
+        GtkWidget     *mute_box;
+        GtkWidget     *mute_switch;
+        GtkAdjustment *adjustment;
+        GtkAdjustment *zero_adjustment;
+        gboolean       show_mute;
+        gboolean       is_muted;
+        char          *name;
+        char          *icon_name;
+        char          *low_icon_name;
+        char          *high_icon_name;
+        GtkSizeGroup  *size_group;
+        gboolean       symmetric;
+        gboolean       click_lock;
+        gboolean       is_amplified;
+        guint32        base_volume;
+};
+
+enum
+{
+        PROP_0,
+        PROP_ORIENTATION,
+        PROP_SHOW_MUTE,
+        PROP_IS_MUTED,
+        PROP_ADJUSTMENT,
+        PROP_NAME,
+        PROP_ICON_NAME,
+        PROP_LOW_ICON_NAME,
+        PROP_HIGH_ICON_NAME,
+        PROP_IS_AMPLIFIED,
+        PROP_ELLIPSIZE
+};
+
+static void     gvc_channel_bar_class_init    (GvcChannelBarClass *klass);
+static void     gvc_channel_bar_init          (GvcChannelBar      *channel_bar);
+static void     gvc_channel_bar_finalize      (GObject            *object);
+
+static gboolean on_scale_button_press_event   (GtkWidget      *widget,
+                                               GdkEventButton *event,
+                                               GvcChannelBar  *bar);
+static gboolean on_scale_button_release_event (GtkWidget      *widget,
+                                               GdkEventButton *event,
+                                               GvcChannelBar  *bar);
+static gboolean on_scale_scroll_event         (GtkWidget      *widget,
+                                               GdkEventScroll *event,
+                                               GvcChannelBar  *bar);
+
+G_DEFINE_TYPE (GvcChannelBar, gvc_channel_bar, GTK_TYPE_BOX)
+
+static GtkWidget *
+_scale_box_new (GvcChannelBar *bar)
+{
+        GvcChannelBarPrivate *priv = bar->priv;
+        GtkWidget            *box;
+        GtkWidget            *sbox;
+        GtkWidget            *ebox;
+
+        if (priv->orientation == GTK_ORIENTATION_VERTICAL) {
+                bar->priv->scale_box = box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+
+                priv->scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, priv->adjustment);
+
+                gtk_widget_set_size_request (priv->scale, -1, SCALE_SIZE);
+                gtk_range_set_inverted (GTK_RANGE (priv->scale), TRUE);
+
+                bar->priv->start_box = sbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+                gtk_box_pack_start (GTK_BOX (box), sbox, FALSE, FALSE, 0);
+
+                gtk_box_pack_start (GTK_BOX (sbox), priv->image, FALSE, FALSE, 0);
+                gtk_box_pack_start (GTK_BOX (sbox), priv->label, FALSE, FALSE, 0);
+
+                gtk_box_pack_start (GTK_BOX (sbox), priv->high_image, FALSE, FALSE, 0);
+                gtk_widget_hide (priv->high_image);
+                gtk_box_pack_start (GTK_BOX (box), priv->scale, TRUE, TRUE, 0);
+
+                bar->priv->end_box = ebox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+                gtk_box_pack_start (GTK_BOX (box), ebox, FALSE, FALSE, 0);
+
+                gtk_box_pack_start (GTK_BOX (ebox), priv->low_image, FALSE, FALSE, 0);
+                gtk_widget_hide (priv->low_image);
+
+                gtk_box_pack_start (GTK_BOX (ebox), priv->mute_box, FALSE, FALSE, 0);
+        } else {
+                bar->priv->scale_box = box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+                gtk_box_pack_start (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
+
+                priv->scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, priv->adjustment);
+
+                gtk_widget_set_size_request (priv->scale, SCALE_SIZE, -1);
+
+                bar->priv->start_box = sbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+                gtk_box_pack_start (GTK_BOX (box), sbox, FALSE, FALSE, 0);
+
+                gtk_box_pack_end (GTK_BOX (sbox), priv->low_image, FALSE, FALSE, 0);
+                gtk_widget_show (priv->low_image);
+
+                gtk_box_pack_start (GTK_BOX (sbox), priv->label, TRUE, TRUE, 0);
+                gtk_box_pack_start (GTK_BOX (box), priv->scale, TRUE, TRUE, 0);
+
+                bar->priv->end_box = ebox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+                gtk_box_pack_start (GTK_BOX (box), ebox, FALSE, FALSE, 0);
+
+                gtk_box_pack_start (GTK_BOX (ebox), priv->high_image, FALSE, FALSE, 0);
+                gtk_widget_show (priv->high_image);
+                gtk_box_pack_start (GTK_BOX (ebox), priv->mute_box, FALSE, FALSE, 0);
+        }
+
+        ca_gtk_widget_disable_sounds (bar->priv->scale, FALSE);
+        gtk_widget_add_events (bar->priv->scale, GDK_SCROLL_MASK);
+
+        g_signal_connect (G_OBJECT (bar->priv->scale), "button-press-event",
+                          G_CALLBACK (on_scale_button_press_event), bar);
+        g_signal_connect (G_OBJECT (bar->priv->scale), "button-release-event",
+                          G_CALLBACK (on_scale_button_release_event), bar);
+        g_signal_connect (G_OBJECT (bar->priv->scale), "scroll-event",
+                          G_CALLBACK (on_scale_scroll_event), bar);
+
+        if (bar->priv->size_group != NULL) {
+                gtk_size_group_add_widget (bar->priv->size_group, sbox);
+
+                if (bar->priv->symmetric) {
+                        gtk_size_group_add_widget (bar->priv->size_group, ebox);
+                }
+        }
+
+        gtk_scale_set_draw_value (GTK_SCALE (priv->scale), FALSE);
+
+        return box;
+}
+
+static void
+update_image (GvcChannelBar *bar)
+{
+        gtk_image_set_from_icon_name (GTK_IMAGE (bar->priv->image),
+                                      bar->priv->icon_name,
+                                      GTK_ICON_SIZE_DIALOG);
+
+        if (bar->priv->icon_name != NULL) {
+                gtk_widget_show (bar->priv->image);
+        } else {
+                gtk_widget_hide (bar->priv->image);
+        }
+}
+
+static void
+update_label (GvcChannelBar *bar)
+{
+        if (bar->priv->name != NULL) {
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (bar->priv->label),
+                                                  bar->priv->name);
+                gtk_label_set_mnemonic_widget (GTK_LABEL (bar->priv->label),
+                                               bar->priv->scale);
+                gtk_widget_show (bar->priv->label);
+        } else {
+                gtk_label_set_text (GTK_LABEL (bar->priv->label), NULL);
+                gtk_widget_hide (bar->priv->label);
+        }
+}
+
+static void
+update_layout (GvcChannelBar *bar)
+{
+        GtkWidget *box;
+        GtkWidget *frame;
+
+        if (bar->priv->scale == NULL) {
+                return;
+        }
+
+        box = bar->priv->scale_box;
+        frame = gtk_widget_get_parent (box);
+
+        g_object_ref (bar->priv->image);
+        g_object_ref (bar->priv->label);
+        g_object_ref (bar->priv->mute_box);
+        g_object_ref (bar->priv->low_image);
+        g_object_ref (bar->priv->high_image);
+
+        gtk_container_remove (GTK_CONTAINER (bar->priv->start_box), bar->priv->image);
+        gtk_container_remove (GTK_CONTAINER (bar->priv->start_box), bar->priv->label);
+        gtk_container_remove (GTK_CONTAINER (bar->priv->end_box), bar->priv->mute_box);
+
+        if (bar->priv->orientation == GTK_ORIENTATION_VERTICAL) {
+                gtk_container_remove (GTK_CONTAINER (bar->priv->start_box), bar->priv->low_image);
+                gtk_container_remove (GTK_CONTAINER (bar->priv->end_box), bar->priv->high_image);
+        } else {
+                gtk_container_remove (GTK_CONTAINER (bar->priv->end_box), bar->priv->low_image);
+                gtk_container_remove (GTK_CONTAINER (bar->priv->start_box), bar->priv->high_image);
+        }
+
+        gtk_container_remove (GTK_CONTAINER (box), bar->priv->start_box);
+        gtk_container_remove (GTK_CONTAINER (box), bar->priv->scale);
+        gtk_container_remove (GTK_CONTAINER (box), bar->priv->end_box);
+        gtk_container_remove (GTK_CONTAINER (frame), box);
+
+        bar->priv->scale_box = _scale_box_new (bar);
+        gtk_container_add (GTK_CONTAINER (frame), bar->priv->scale_box);
+
+        g_object_unref (bar->priv->image);
+        g_object_unref (bar->priv->label);
+        g_object_unref (bar->priv->mute_box);
+        g_object_unref (bar->priv->low_image);
+        g_object_unref (bar->priv->high_image);
+
+        gtk_widget_show_all (frame);
+}
+
+void
+gvc_channel_bar_set_size_group (GvcChannelBar *bar,
+                                GtkSizeGroup  *group,
+                                gboolean       symmetric)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        bar->priv->size_group = group;
+        bar->priv->symmetric = symmetric;
+
+        if (bar->priv->size_group != NULL) {
+                gtk_size_group_add_widget (bar->priv->size_group,
+                                           bar->priv->start_box);
+
+                if (bar->priv->symmetric) {
+                        gtk_size_group_add_widget (bar->priv->size_group,
+                                                   bar->priv->end_box);
+                }
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (bar));
+}
+
+void
+gvc_channel_bar_set_name (GvcChannelBar  *bar,
+                          const char     *name)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        g_free (bar->priv->name);
+        bar->priv->name = g_strdup (name);
+        update_label (bar);
+        g_object_notify (G_OBJECT (bar), "name");
+}
+
+void
+gvc_channel_bar_set_icon_name (GvcChannelBar  *bar,
+                               const char     *name)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        g_free (bar->priv->icon_name);
+        bar->priv->icon_name = g_strdup (name);
+        update_image (bar);
+        g_object_notify (G_OBJECT (bar), "icon-name");
+}
+
+void
+gvc_channel_bar_set_low_icon_name   (GvcChannelBar *bar,
+                                     const char    *name)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        if (name != NULL && strcmp (bar->priv->low_icon_name, name) != 0) {
+                g_free (bar->priv->low_icon_name);
+                bar->priv->low_icon_name = g_strdup (name);
+                gtk_image_set_from_icon_name (GTK_IMAGE (bar->priv->low_image),
+                                              bar->priv->low_icon_name,
+                                              GTK_ICON_SIZE_MENU);
+                g_object_notify (G_OBJECT (bar), "low-icon-name");
+        }
+}
+
+void
+gvc_channel_bar_set_high_icon_name  (GvcChannelBar *bar,
+                                     const char    *name)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        if (name != NULL && strcmp (bar->priv->high_icon_name, name) != 0) {
+                g_free (bar->priv->high_icon_name);
+                bar->priv->high_icon_name = g_strdup (name);
+                gtk_image_set_from_icon_name (GTK_IMAGE (bar->priv->high_image),
+                                              bar->priv->high_icon_name,
+                                              GTK_ICON_SIZE_MENU);
+                g_object_notify (G_OBJECT (bar), "high-icon-name");
+        }
+}
+
+void
+gvc_channel_bar_set_orientation (GvcChannelBar  *bar,
+                                 GtkOrientation  orientation)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        if (orientation != bar->priv->orientation) {
+                bar->priv->orientation = orientation;
+                update_layout (bar);
+                g_object_notify (G_OBJECT (bar), "orientation");
+        }
+}
+
+static void
+gvc_channel_bar_set_adjustment (GvcChannelBar *bar,
+                                GtkAdjustment *adjustment)
+{
+        g_return_if_fail (GVC_CHANNEL_BAR (bar));
+        g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+
+        if (bar->priv->adjustment != NULL) {
+                g_object_unref (bar->priv->adjustment);
+        }
+        bar->priv->adjustment = g_object_ref_sink (adjustment);
+
+        if (bar->priv->scale != NULL) {
+                gtk_range_set_adjustment (GTK_RANGE (bar->priv->scale), adjustment);
+        }
+
+        g_object_notify (G_OBJECT (bar), "adjustment");
+}
+
+GtkAdjustment *
+gvc_channel_bar_get_adjustment (GvcChannelBar *bar)
+{
+        g_return_val_if_fail (GVC_IS_CHANNEL_BAR (bar), NULL);
+
+        return bar->priv->adjustment;
+}
+
+static gboolean
+on_scale_button_press_event (GtkWidget      *widget,
+                             GdkEventButton *event,
+                             GvcChannelBar  *bar)
+{
+        bar->priv->click_lock = TRUE;
+
+        return FALSE;
+}
+
+static gboolean
+on_scale_button_release_event (GtkWidget      *widget,
+                               GdkEventButton *event,
+                               GvcChannelBar  *bar)
+{
+        GtkAdjustment *adj;
+        gdouble value;
+
+        bar->priv->click_lock = FALSE;
+
+        adj = gtk_range_get_adjustment (GTK_RANGE (widget));
+
+        value = gtk_adjustment_get_value (adj);
+
+        /* this means the adjustment moved away from zero and
+         * therefore we should unmute and set the volume. */
+        gvc_channel_bar_set_is_muted (bar, (value == 0.0));
+
+        /* Play a sound! */
+        ca_gtk_play_for_widget (GTK_WIDGET (bar), 0,
+                                CA_PROP_EVENT_ID, "audio-volume-change",
+                                CA_PROP_EVENT_DESCRIPTION, "foobar event happened",
+                                CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl",
+                                NULL);
+
+        return FALSE;
+}
+
+gboolean
+gvc_channel_bar_scroll (GvcChannelBar *bar, GdkEventScroll *event)
+{
+        GtkAdjustment *adj;
+        gdouble value;
+        GdkScrollDirection direction;
+        gdouble dx, dy;
+
+        g_return_val_if_fail (bar != NULL, FALSE);
+        g_return_val_if_fail (GVC_IS_CHANNEL_BAR (bar), FALSE);
+
+        direction = event->direction;
+
+        if (bar->priv->orientation == GTK_ORIENTATION_VERTICAL) {
+                if (direction == GDK_SCROLL_LEFT || direction == GDK_SCROLL_RIGHT)
+                        return FALSE;
+        } else {
+                /* Switch direction for RTL */
+                if (gtk_widget_get_direction (GTK_WIDGET (bar)) == GTK_TEXT_DIR_RTL) {
+                        if (direction == GDK_SCROLL_RIGHT)
+                                direction = GDK_SCROLL_LEFT;
+                        else if (direction == GDK_SCROLL_LEFT)
+                                direction = GDK_SCROLL_RIGHT;
+                }
+                /* Switch side scroll to vertical */
+                if (direction == GDK_SCROLL_RIGHT)
+                        direction = GDK_SCROLL_UP;
+                else if (direction == GDK_SCROLL_LEFT)
+                        direction = GDK_SCROLL_DOWN;
+        }
+
+       if (!gdk_event_get_scroll_deltas ((GdkEvent*)event, &dx, &dy)) {
+               dx = 0.0;
+               dy = 0.0;
+
+               switch (direction) {
+               case GDK_SCROLL_UP:
+               case GDK_SCROLL_LEFT:
+                       dy = 1.0;
+                       break;
+               case GDK_SCROLL_DOWN:
+               case GDK_SCROLL_RIGHT:
+                       dy = -1.0;
+                       break;
+               default:
+                       ;
+               }
+       }
+
+        adj = gtk_range_get_adjustment (GTK_RANGE (bar->priv->scale));
+        if (adj == bar->priv->zero_adjustment) {
+                if (dy > 0)
+                        gvc_channel_bar_set_is_muted (bar, FALSE);
+                return TRUE;
+        }
+
+        value = gtk_adjustment_get_value (adj);
+
+        if (dy > 0) {
+                if (value + dy * SCROLLSTEP > ADJUSTMENT_MAX)
+                        value = ADJUSTMENT_MAX;
+                else
+                        value = value + dy * SCROLLSTEP;
+        } else if (dy < 0) {
+                if (value + dy * SCROLLSTEP < 0)
+                        value = 0.0;
+                else
+                        value = value + dy * SCROLLSTEP;
+        }
+
+        gvc_channel_bar_set_is_muted (bar, (value == 0.0));
+        adj = gtk_range_get_adjustment (GTK_RANGE (bar->priv->scale));
+        gtk_adjustment_set_value (adj, value);
+
+        return TRUE;
+}
+
+static gboolean
+on_scale_scroll_event (GtkWidget      *widget,
+                       GdkEventScroll *event,
+                       GvcChannelBar  *bar)
+{
+        return gvc_channel_bar_scroll (bar, event);
+}
+
+static void
+on_zero_adjustment_value_changed (GtkAdjustment *adjustment,
+                                  GvcChannelBar *bar)
+{
+        gdouble value;
+
+        if (bar->priv->click_lock != FALSE) {
+                return;
+        }
+
+        value = gtk_adjustment_get_value (bar->priv->zero_adjustment);
+        gtk_adjustment_set_value (bar->priv->adjustment, value);
+
+
+        if (bar->priv->show_mute == FALSE) {
+                /* this means the adjustment moved away from zero and
+                 * therefore we should unmute and set the volume. */
+                gvc_channel_bar_set_is_muted (bar, value > 0.0);
+        }
+}
+
+static void
+update_mute_switch (GvcChannelBar *bar)
+{
+        if (bar->priv->show_mute) {
+                gtk_widget_show (bar->priv->mute_switch);
+                gtk_switch_set_active (GTK_SWITCH (bar->priv->mute_switch),
+                                       !bar->priv->is_muted);
+        } else {
+                gtk_widget_hide (bar->priv->mute_switch);
+        }
+
+        if (bar->priv->is_muted) {
+                /* If we aren't showing the mute button then
+                 * move slider to the zero.  But we don't want to
+                 * change the adjustment.  */
+                g_signal_handlers_block_by_func (bar->priv->zero_adjustment,
+                                                 on_zero_adjustment_value_changed,
+                                                 bar);
+                gtk_adjustment_set_value (bar->priv->zero_adjustment, 0);
+                g_signal_handlers_unblock_by_func (bar->priv->zero_adjustment,
+                                                   on_zero_adjustment_value_changed,
+                                                   bar);
+                gtk_range_set_adjustment (GTK_RANGE (bar->priv->scale),
+                                          bar->priv->zero_adjustment);
+        } else {
+                /* no longer muted so restore the original adjustment
+                 * and tell the front-end that the value changed */
+                gtk_range_set_adjustment (GTK_RANGE (bar->priv->scale),
+                                          bar->priv->adjustment);
+                gtk_adjustment_value_changed (bar->priv->adjustment);
+        }
+}
+
+void
+gvc_channel_bar_set_is_muted (GvcChannelBar *bar,
+                              gboolean       is_muted)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        if (is_muted != bar->priv->is_muted) {
+                /* Update our internal state before telling the
+                 * front-end about our changes */
+                bar->priv->is_muted = is_muted;
+                update_mute_switch (bar);
+                g_object_notify (G_OBJECT (bar), "is-muted");
+        }
+}
+
+gboolean
+gvc_channel_bar_get_is_muted  (GvcChannelBar *bar)
+{
+        g_return_val_if_fail (GVC_IS_CHANNEL_BAR (bar), FALSE);
+        return bar->priv->is_muted;
+}
+
+void
+gvc_channel_bar_set_show_mute (GvcChannelBar *bar,
+                               gboolean       show_mute)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        if (show_mute != bar->priv->show_mute) {
+                bar->priv->show_mute = show_mute;
+                g_object_notify (G_OBJECT (bar), "show-mute");
+                update_mute_switch (bar);
+        }
+}
+
+gboolean
+gvc_channel_bar_get_show_mute (GvcChannelBar *bar)
+{
+        g_return_val_if_fail (GVC_IS_CHANNEL_BAR (bar), FALSE);
+        return bar->priv->show_mute;
+}
+
+void
+gvc_channel_bar_set_is_amplified (GvcChannelBar *bar, gboolean amplified)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        bar->priv->is_amplified = amplified;
+        gtk_adjustment_set_upper (bar->priv->adjustment, ADJUSTMENT_MAX);
+        gtk_adjustment_set_upper (bar->priv->zero_adjustment, ADJUSTMENT_MAX);
+        gtk_scale_clear_marks (GTK_SCALE (bar->priv->scale));
+
+        if (amplified) {
+                char *str;
+
+                if (bar->priv->base_volume == ADJUSTMENT_MAX_NORMAL) {
+                        str = g_strdup_printf ("<small>%s</small>", C_("volume", "100%"));
+                        gtk_scale_add_mark (GTK_SCALE (bar->priv->scale), ADJUSTMENT_MAX_NORMAL,
+                                            GTK_POS_BOTTOM, str);
+                } else {
+                        str = g_strdup_printf ("<small>%s</small>", C_("volume", "Unamplified"));
+                        gtk_scale_add_mark (GTK_SCALE (bar->priv->scale), bar->priv->base_volume,
+                                            GTK_POS_BOTTOM, str);
+                        /* Only show 100% if it's higher than the base volume */
+                        if (bar->priv->base_volume < ADJUSTMENT_MAX_NORMAL) {
+                                str = g_strdup_printf ("<small>%s</small>", C_("volume", "100%"));
+                                gtk_scale_add_mark (GTK_SCALE (bar->priv->scale), ADJUSTMENT_MAX_NORMAL,
+                                                    GTK_POS_BOTTOM, str);
+                        }
+                }
+
+                g_free (str);
+                gtk_alignment_set (GTK_ALIGNMENT (bar->priv->mute_box), 0.5, 0, 0, 0);
+                gtk_misc_set_alignment (GTK_MISC (bar->priv->low_image), 0.5, 0.15);
+                gtk_misc_set_alignment (GTK_MISC (bar->priv->high_image), 0.5, 0.15);
+                gtk_misc_set_alignment (GTK_MISC (bar->priv->label), 0, 0);
+        } else {
+                gtk_alignment_set (GTK_ALIGNMENT (bar->priv->mute_box), 0.5, 0.5, 0, 0);
+                gtk_misc_set_alignment (GTK_MISC (bar->priv->low_image), 0.5, 0.5);
+                gtk_misc_set_alignment (GTK_MISC (bar->priv->high_image), 0.5, 0.5);
+                gtk_misc_set_alignment (GTK_MISC (bar->priv->label), 0, 0.5);
+        }
+}
+
+gboolean
+gvc_channel_bar_get_ellipsize (GvcChannelBar *bar)
+{
+        g_return_val_if_fail (GVC_IS_CHANNEL_BAR (bar), FALSE);
+
+        return gtk_label_get_ellipsize (GTK_LABEL (bar->priv->label)) != PANGO_ELLIPSIZE_NONE;
+}
+
+void
+gvc_channel_bar_set_ellipsize (GvcChannelBar *bar,
+                               gboolean       ellipsized)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        if (ellipsized)
+                gtk_label_set_ellipsize (GTK_LABEL (bar->priv->label), PANGO_ELLIPSIZE_END);
+       else
+                gtk_label_set_ellipsize (GTK_LABEL (bar->priv->label), PANGO_ELLIPSIZE_NONE);
+}
+
+void
+gvc_channel_bar_set_base_volume (GvcChannelBar *bar,
+                                 pa_volume_t    base_volume)
+{
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (bar));
+
+        if (base_volume == 0) {
+                bar->priv->base_volume = ADJUSTMENT_MAX_NORMAL;
+                return;
+        }
+
+        /* Note that you need to call _is_amplified() afterwards to update the marks */
+        bar->priv->base_volume = base_volume;
+}
+
+static void
+gvc_channel_bar_set_property (GObject       *object,
+                              guint          prop_id,
+                              const GValue  *value,
+                              GParamSpec    *pspec)
+{
+        GvcChannelBar *self = GVC_CHANNEL_BAR (object);
+
+        switch (prop_id) {
+        case PROP_ORIENTATION:
+                gvc_channel_bar_set_orientation (self, g_value_get_enum (value));
+                break;
+        case PROP_IS_MUTED:
+                gvc_channel_bar_set_is_muted (self, g_value_get_boolean (value));
+                break;
+        case PROP_SHOW_MUTE:
+                gvc_channel_bar_set_show_mute (self, g_value_get_boolean (value));
+                break;
+        case PROP_NAME:
+                gvc_channel_bar_set_name (self, g_value_get_string (value));
+                break;
+        case PROP_ICON_NAME:
+                gvc_channel_bar_set_icon_name (self, g_value_get_string (value));
+                break;
+        case PROP_LOW_ICON_NAME:
+                gvc_channel_bar_set_low_icon_name (self, g_value_get_string (value));
+                break;
+        case PROP_HIGH_ICON_NAME:
+                gvc_channel_bar_set_high_icon_name (self, g_value_get_string (value));
+                break;
+        case PROP_ADJUSTMENT:
+                gvc_channel_bar_set_adjustment (self, g_value_get_object (value));
+                break;
+        case PROP_IS_AMPLIFIED:
+                gvc_channel_bar_set_is_amplified (self, g_value_get_boolean (value));
+                break;
+        case PROP_ELLIPSIZE:
+                gvc_channel_bar_set_ellipsize (self, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_channel_bar_get_property (GObject     *object,
+                              guint        prop_id,
+                              GValue      *value,
+                              GParamSpec  *pspec)
+{
+        GvcChannelBar *self = GVC_CHANNEL_BAR (object);
+        GvcChannelBarPrivate *priv = self->priv;
+
+        switch (prop_id) {
+        case PROP_ORIENTATION:
+                g_value_set_enum (value, priv->orientation);
+                break;
+        case PROP_IS_MUTED:
+                g_value_set_boolean (value, priv->is_muted);
+                break;
+        case PROP_SHOW_MUTE:
+                g_value_set_boolean (value, priv->show_mute);
+                break;
+        case PROP_NAME:
+                g_value_set_string (value, priv->name);
+                break;
+        case PROP_ICON_NAME:
+                g_value_set_string (value, priv->icon_name);
+                break;
+        case PROP_LOW_ICON_NAME:
+                g_value_set_string (value, priv->low_icon_name);
+                break;
+        case PROP_HIGH_ICON_NAME:
+                g_value_set_string (value, priv->high_icon_name);
+                break;
+        case PROP_ADJUSTMENT:
+                g_value_set_object (value, gvc_channel_bar_get_adjustment (self));
+                break;
+        case PROP_IS_AMPLIFIED:
+                g_value_set_boolean (value, priv->is_amplified);
+                break;
+        case PROP_ELLIPSIZE:
+                g_value_set_boolean (value, gvc_channel_bar_get_ellipsize (self));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static GObject *
+gvc_channel_bar_constructor (GType                  type,
+                             guint                  n_construct_properties,
+                             GObjectConstructParam *construct_params)
+{
+        GObject       *object;
+        GvcChannelBar *self;
+
+        object = G_OBJECT_CLASS (gvc_channel_bar_parent_class)->constructor (type, n_construct_properties, 
construct_params);
+
+        self = GVC_CHANNEL_BAR (object);
+
+        update_mute_switch (self);
+
+        return object;
+}
+
+static void
+gvc_channel_bar_class_init (GvcChannelBarClass *klass)
+{
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->constructor = gvc_channel_bar_constructor;
+        object_class->finalize = gvc_channel_bar_finalize;
+        object_class->set_property = gvc_channel_bar_set_property;
+        object_class->get_property = gvc_channel_bar_get_property;
+
+        g_object_class_install_property (object_class,
+                                         PROP_ORIENTATION,
+                                         g_param_spec_enum ("orientation",
+                                                            "Orientation",
+                                                            "The orientation of the scale",
+                                                            GTK_TYPE_ORIENTATION,
+                                                            GTK_ORIENTATION_VERTICAL,
+                                                            G_PARAM_READWRITE));
+        g_object_class_install_property (object_class,
+                                         PROP_IS_MUTED,
+                                         g_param_spec_boolean ("is-muted",
+                                                               "is muted",
+                                                               "Whether stream is muted",
+                                                               FALSE,
+                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+        g_object_class_install_property (object_class,
+                                         PROP_SHOW_MUTE,
+                                         g_param_spec_boolean ("show-mute",
+                                                               "show mute",
+                                                               "Whether stream is muted",
+                                                               FALSE,
+                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+
+        g_object_class_install_property (object_class,
+                                         PROP_ADJUSTMENT,
+                                         g_param_spec_object ("adjustment",
+                                                              "Adjustment",
+                                                              "The GtkAdjustment that contains the current 
value of this scale button object",
+                                                              GTK_TYPE_ADJUSTMENT,
+                                                              G_PARAM_READWRITE));
+        g_object_class_install_property (object_class,
+                                         PROP_NAME,
+                                         g_param_spec_string ("name",
+                                                              "Name",
+                                                              "Name to display for this stream",
+                                                              NULL,
+                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+        g_object_class_install_property (object_class,
+                                         PROP_ICON_NAME,
+                                         g_param_spec_string ("icon-name",
+                                                              "Icon Name",
+                                                              "Name of icon to display for this stream",
+                                                              NULL,
+                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+        g_object_class_install_property (object_class,
+                                         PROP_LOW_ICON_NAME,
+                                         g_param_spec_string ("low-icon-name",
+                                                              "Icon Name",
+                                                              "Name of icon to display for this stream",
+                                                              "audio-volume-low-symbolic",
+                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+        g_object_class_install_property (object_class,
+                                         PROP_HIGH_ICON_NAME,
+                                         g_param_spec_string ("high-icon-name",
+                                                              "Icon Name",
+                                                              "Name of icon to display for this stream",
+                                                              "audio-volume-high-symbolic",
+                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+        g_object_class_install_property (object_class,
+                                         PROP_IS_AMPLIFIED,
+                                         g_param_spec_boolean ("is-amplified",
+                                                               "Is amplified",
+                                                               "Whether the stream is digitally amplified",
+                                                               FALSE,
+                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+        g_object_class_install_property (object_class,
+                                         PROP_ELLIPSIZE,
+                                         g_param_spec_boolean ("ellipsize",
+                                                               "Label is ellipsized",
+                                                               "Whether the label is ellipsized",
+                                                               FALSE,
+                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+        g_type_class_add_private (klass, sizeof (GvcChannelBarPrivate));
+}
+
+static void
+on_mute_switch_toggled (GtkSwitch     *sw,
+                        GParamSpec *pspec,
+                        GvcChannelBar *bar)
+{
+        gboolean is_muted;
+        is_muted = gtk_switch_get_active (sw);
+        gvc_channel_bar_set_is_muted (bar, !is_muted);
+}
+
+static void
+gvc_channel_bar_init (GvcChannelBar *bar)
+{
+        GtkWidget *frame;
+
+        bar->priv = GVC_CHANNEL_BAR_GET_PRIVATE (bar);
+
+        bar->priv->base_volume = ADJUSTMENT_MAX_NORMAL;
+        bar->priv->low_icon_name = g_strdup ("audio-volume-low-symbolic");
+        bar->priv->high_icon_name = g_strdup ("audio-volume-high-symbolic");
+
+        bar->priv->orientation = GTK_ORIENTATION_VERTICAL;
+        bar->priv->adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0,
+                                                                    0.0,
+                                                                    ADJUSTMENT_MAX_NORMAL,
+                                                                    ADJUSTMENT_MAX_NORMAL/100.0,
+                                                                    ADJUSTMENT_MAX_NORMAL/10.0,
+                                                                    0.0));
+        g_object_ref_sink (bar->priv->adjustment);
+
+        bar->priv->zero_adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0,
+                                                                         0.0,
+                                                                         ADJUSTMENT_MAX_NORMAL,
+                                                                         ADJUSTMENT_MAX_NORMAL/100.0,
+                                                                         ADJUSTMENT_MAX_NORMAL/10.0,
+                                                                         0.0));
+        g_object_ref_sink (bar->priv->zero_adjustment);
+
+        g_signal_connect (bar->priv->zero_adjustment,
+                          "value-changed",
+                          G_CALLBACK (on_zero_adjustment_value_changed),
+                          bar);
+
+        bar->priv->mute_switch = gtk_switch_new ();
+        gtk_widget_set_no_show_all (bar->priv->mute_switch, TRUE);
+        g_signal_connect (bar->priv->mute_switch,
+                          "notify::active",
+                          G_CALLBACK (on_mute_switch_toggled),
+                          bar);
+        bar->priv->mute_box = gtk_alignment_new (0.5, 0.5, 0, 0);
+        gtk_container_add (GTK_CONTAINER (bar->priv->mute_box), bar->priv->mute_switch);
+
+        bar->priv->low_image = gtk_image_new_from_icon_name ("audio-volume-low-symbolic",
+                                                             GTK_ICON_SIZE_MENU);
+        gtk_style_context_add_class (gtk_widget_get_style_context (bar->priv->low_image), "dim-label");
+        gtk_widget_set_no_show_all (bar->priv->low_image, TRUE);
+        bar->priv->high_image = gtk_image_new_from_icon_name ("audio-volume-high-symbolic",
+                                                              GTK_ICON_SIZE_MENU);
+        gtk_style_context_add_class (gtk_widget_get_style_context (bar->priv->high_image), "dim-label");
+        gtk_widget_set_no_show_all (bar->priv->high_image, TRUE);
+
+        bar->priv->image = gtk_image_new ();
+        gtk_widget_set_no_show_all (bar->priv->image, TRUE);
+
+        bar->priv->label = gtk_label_new (NULL);
+        gtk_misc_set_alignment (GTK_MISC (bar->priv->label), 0.0, 0.5);
+        gtk_widget_set_no_show_all (bar->priv->label, TRUE);
+
+        /* frame */
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+        gtk_box_pack_start (GTK_BOX (bar), frame, TRUE, TRUE, 0);
+        gtk_widget_show_all (frame);
+
+        /* box with scale */
+        bar->priv->scale_box = _scale_box_new (bar);
+
+        gtk_container_add (GTK_CONTAINER (frame), bar->priv->scale_box);
+}
+
+static void
+gvc_channel_bar_finalize (GObject *object)
+{
+        GvcChannelBar *channel_bar;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GVC_IS_CHANNEL_BAR (object));
+
+        channel_bar = GVC_CHANNEL_BAR (object);
+
+        g_return_if_fail (channel_bar->priv != NULL);
+
+        g_free (channel_bar->priv->name);
+        g_free (channel_bar->priv->icon_name);
+        g_free (channel_bar->priv->low_icon_name);
+        g_free (channel_bar->priv->high_icon_name);
+
+        G_OBJECT_CLASS (gvc_channel_bar_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_channel_bar_new (void)
+{
+        GObject *bar;
+        bar = g_object_new (GVC_TYPE_CHANNEL_BAR,
+                            "orientation", GTK_ORIENTATION_HORIZONTAL,
+                            NULL);
+        return GTK_WIDGET (bar);
+}
diff --git a/gnome-flashback/libsound-applet/gvc-channel-bar.h 
b/gnome-flashback/libsound-applet/gvc-channel-bar.h
new file mode 100644
index 0000000..f644abd
--- /dev/null
+++ b/gnome-flashback/libsound-applet/gvc-channel-bar.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GVC_CHANNEL_BAR_H
+#define __GVC_CHANNEL_BAR_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GVC_TYPE_CHANNEL_BAR         (gvc_channel_bar_get_type ())
+#define GVC_CHANNEL_BAR(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_CHANNEL_BAR, GvcChannelBar))
+#define GVC_CHANNEL_BAR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_CHANNEL_BAR, GvcChannelBarClass))
+#define GVC_IS_CHANNEL_BAR(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_CHANNEL_BAR))
+#define GVC_IS_CHANNEL_BAR_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_CHANNEL_BAR))
+#define GVC_CHANNEL_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_CHANNEL_BAR, 
GvcChannelBarClass))
+
+typedef struct GvcChannelBarPrivate GvcChannelBarPrivate;
+
+typedef struct
+{
+        GtkBox                parent;
+        GvcChannelBarPrivate *priv;
+} GvcChannelBar;
+
+typedef struct
+{
+        GtkBoxClass           parent_class;
+} GvcChannelBarClass;
+
+GType               gvc_channel_bar_get_type            (void);
+
+GtkWidget *         gvc_channel_bar_new                 (void);
+
+void                gvc_channel_bar_set_name            (GvcChannelBar *bar,
+                                                         const char    *name);
+void                gvc_channel_bar_set_icon_name       (GvcChannelBar *bar,
+                                                         const char    *icon_name);
+void                gvc_channel_bar_set_low_icon_name   (GvcChannelBar *bar,
+                                                         const char    *icon_name);
+void                gvc_channel_bar_set_high_icon_name  (GvcChannelBar *bar,
+                                                         const char    *icon_name);
+
+void                gvc_channel_bar_set_orientation     (GvcChannelBar *bar,
+                                                         GtkOrientation orientation);
+GtkOrientation      gvc_channel_bar_get_orientation     (GvcChannelBar *bar);
+
+GtkAdjustment *     gvc_channel_bar_get_adjustment      (GvcChannelBar *bar);
+
+gboolean            gvc_channel_bar_get_is_muted        (GvcChannelBar *bar);
+void                gvc_channel_bar_set_is_muted        (GvcChannelBar *bar,
+                                                         gboolean       is_muted);
+gboolean            gvc_channel_bar_get_show_mute       (GvcChannelBar *bar);
+void                gvc_channel_bar_set_show_mute       (GvcChannelBar *bar,
+                                                         gboolean       show_mute);
+void                gvc_channel_bar_set_size_group      (GvcChannelBar *bar,
+                                                         GtkSizeGroup  *group,
+                                                         gboolean       symmetric);
+void                gvc_channel_bar_set_is_amplified    (GvcChannelBar *bar,
+                                                         gboolean amplified);
+void                gvc_channel_bar_set_base_volume     (GvcChannelBar *bar,
+                                                         guint32        base_volume);
+gboolean            gvc_channel_bar_get_ellipsize       (GvcChannelBar *bar);
+void                gvc_channel_bar_set_ellipsize       (GvcChannelBar *bar,
+                                                         gboolean       ellipsized);
+
+gboolean            gvc_channel_bar_scroll              (GvcChannelBar  *bar,
+                                                         GdkEventScroll *event);
+
+G_END_DECLS
+
+#endif /* __GVC_CHANNEL_BAR_H */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index a1e0fc7..ea39d52 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,6 +4,10 @@
 gnome-flashback/gnome-flashback.desktop.in
 gnome-flashback/libend-session-dialog/flashback-inhibit-dialog.c
 [type: gettext/glade]gnome-flashback/libend-session-dialog/flashback-inhibit-dialog.ui
+gnome-flashback/libsound-applet/gvc-applet.c
+gnome-flashback/libsound-applet/gvc-channel-bar.c
+gnome-flashback/libsound-applet/gvc-stream-status-icon.c
+gnome-flashback/libsound-applet/gvc/gvc-mixer-control.c
 gnome-flashback/org.gnome.gnome-flashback.gschema.xml.in.in
 sessions/gnome-flashback-compiz.desktop.in.in
 sessions/gnome-flashback-compiz.session.in


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]