Merge lp:~diwic/gnome-control-center/sound-nua-rebase into lp:~ubuntu-desktop/gnome-control-center/ubuntu

Proposed by David Henningsson on 2012-11-13
Status: Merged
Merged at revision: 509
Proposed branch: lp:~diwic/gnome-control-center/sound-nua-rebase
Merge into: lp:~ubuntu-desktop/gnome-control-center/ubuntu
Diff against target: 3334 lines (+3310/-1)
3 files modified
debian/changelog (+4/-1)
debian/patches/series (+1/-0)
debian/patches/sound_nua_panel.patch (+3305/-0)
To merge this branch: bzr merge lp:~diwic/gnome-control-center/sound-nua-rebase
Reviewer Review Type Date Requested Status
Sebastien Bacher 2012-11-13 Approve on 2012-11-14
David Henningsson (community) Approve on 2012-11-13
Review via email: mp+134134@code.launchpad.net

Description of the change

Rebase sound-nua against Gnome 3.6 code. Most of the code is now upstreamed, but Gnome wanted to keep their old design, so therefore we still keep the UI pieces as a patch.

The patch is reduced by about 75% compared to the previous size.

To post a comment you must log in.
David Henningsson (diwic) :
review: Needs Fixing
513. By David Henningsson on 2012-11-13

changed the version number back again

514. By David Henningsson on 2012-11-13

Updated patch comment

David Henningsson (diwic) :
review: Approve
Sebastien Bacher (seb128) wrote :

Thanks David!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2012-11-06 04:32:05 +0000
3+++ debian/changelog 2012-11-13 15:56:18 +0000
4@@ -69,7 +69,10 @@
5 - Drop ubuntu-docs and gnome-user-guide from recommends to suggests
6 - Don't recommend indicators; let's leave that to Unity
7
8- -- Jeremy Bicha <jbicha@ubuntu.com> Mon, 05 Nov 2012 23:14:29 -0500
9+ [ David Henningsson ]
10+ * sound_nua_panel.patch: Rebase to gnome 3.6
11+
12+ -- David Henningsson <david.henningsson@canonical.com> Tue, 13 Nov 2012 15:59:40 +0100
13
14 gnome-control-center (1:3.4.2-0ubuntu20) quantal-proposed; urgency=low
15
16
17=== modified file 'debian/patches/series'
18--- debian/patches/series 2012-11-06 04:32:05 +0000
19+++ debian/patches/series 2012-11-13 15:56:18 +0000
20@@ -29,3 +29,4 @@
21 dont_download_local_image.patch
22 classic_use_sound_indicator.patch
23 accounts_fix_unsetting_icon.patch
24+sound_nua_panel.patch
25
26=== added file 'debian/patches/sound_nua_panel.patch'
27--- debian/patches/sound_nua_panel.patch 1970-01-01 00:00:00 +0000
28+++ debian/patches/sound_nua_panel.patch 2012-11-13 15:56:18 +0000
29@@ -0,0 +1,3305 @@
30+# Description: New design of the sound capplet
31+# Most of the code has now been upstreamed to Gnome, but they wanted
32+# to keep their old design, so about 25% of the original patch remains.
33+=== modified file 'configure.ac'
34+Index: gnome-control-center-3.6.2/configure.ac
35+===================================================================
36+--- gnome-control-center-3.6.2.orig/configure.ac 2012-11-13 16:25:40.665717988 +0100
37++++ gnome-control-center-3.6.2/configure.ac 2012-11-13 16:25:40.773717987 +0100
38+@@ -435,6 +435,9 @@
39+ panels/online-accounts/icons/32x32/Makefile
40+ panels/online-accounts/icons/48x48/Makefile
41+ panels/online-accounts/icons/256x256/Makefile
42++panels/sound-nua/Makefile
43++panels/sound-nua/data/Makefile
44++panels/sound-nua/data/gnome-sound-nua-panel.desktop.in
45+ panels/sound/Makefile
46+ panels/sound/data/Makefile
47+ panels/sound/data/gnome-sound-panel.desktop.in
48+Index: gnome-control-center-3.6.2/panels/Makefile.am
49+===================================================================
50+--- gnome-control-center-3.6.2.orig/panels/Makefile.am 2012-10-01 11:38:59.000000000 +0200
51++++ gnome-control-center-3.6.2/panels/Makefile.am 2012-11-13 16:25:40.777717988 +0100
52+@@ -10,6 +10,7 @@
53+ region \
54+ info \
55+ sound \
56++ sound-nua \
57+ keyboard \
58+ universal-access \
59+ user-accounts \
60+Index: gnome-control-center-3.6.2/panels/sound-nua/Makefile.am
61+===================================================================
62+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
63++++ gnome-control-center-3.6.2/panels/sound-nua/Makefile.am 2012-11-13 16:25:40.777717988 +0100
64+@@ -0,0 +1,63 @@
65++SUBDIRS = data
66++
67++# This is used in PANEL_CFLAGS
68++cappletname = sound
69++NULL =
70++
71++ccpanelsdir = $(PANELS_DIR)
72++ccpanels_LTLIBRARIES = libsoundnua.la
73++
74++AM_CPPFLAGS = \
75++ $(PANEL_CFLAGS) \
76++ $(SOUND_PANEL_CFLAGS) \
77++ -DLOCALE_DIR=\""$(datadir)/locale"\" \
78++ -DLIBEXECDIR=\"$(libexecdir)\" \
79++ -DGLADEDIR=\""$(pkgdatadir)"\" \
80++ -DSOUND_DATA_DIR="\"$(datadir)/sounds\"" \
81++ -DSOUND_SET_DIR="\"$(pkgdatadir)/sounds\"" \
82++ -DICON_DATA_DIR="\"$(pkgdatadir)/icons\"" \
83++ -I../sound \
84++ $(NULL)
85++
86++libsoundnua_la_LIBADD = \
87++ -lm \
88++ ../sound/libgnomevolumecontrol.la \
89++ $(PANEL_LIBS) \
90++ $(SOUND_PANEL_LIBS) \
91++ $(NULL)
92++
93++libsoundnua_la_LDFLAGS = \
94++ $(PANEL_LDFLAGS) \
95++ $(NULL)
96++
97++libsoundnua_la_SOURCES = \
98++ gvc-balance-bar.h \
99++ gvc-balance-bar.c \
100++ gvc-mixer-dialog.h \
101++ gvc-mixer-dialog.c \
102++ ../sound/gvc-level-bar.h \
103++ ../sound/gvc-level-bar.c \
104++ ../sound/gvc-combo-box.h \
105++ ../sound/gvc-combo-box.c \
106++ ../sound/gvc-speaker-test.h \
107++ ../sound/gvc-speaker-test.c \
108++ ../sound/gvc-sound-theme-chooser.c \
109++ ../sound/gvc-sound-theme-chooser.h \
110++ ../sound/sound-theme-file-utils.c \
111++ ../sound/sound-theme-file-utils.h \
112++ cc-sound-panel.c \
113++ cc-sound-panel.h \
114++ $(NULL)
115++
116++BUILT_SOURCES = \
117++ $(NULL)
118++
119++CLEANFILES = \
120++ $(BUILT_SOURCES) \
121++ $(NULL)
122++
123++MAINTAINERCLEANFILES = \
124++ *~ \
125++ Makefile.in
126++
127++-include $(top_srcdir)/git.mk
128+Index: gnome-control-center-3.6.2/panels/sound-nua/cc-sound-panel.c
129+===================================================================
130+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
131++++ gnome-control-center-3.6.2/panels/sound-nua/cc-sound-panel.c 2012-11-13 16:25:40.777717988 +0100
132+@@ -0,0 +1,141 @@
133++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
134++ *
135++ * Copyright (C) 2008 Red Hat, Inc.
136++ *
137++ * This program is free software; you can redistribute it and/or
138++ * modify it under the terms of the GNU General Public License as
139++ * published by the Free Software Foundation; either version 2 of the
140++ * License, or (at your option) any later version.
141++ *
142++ * This program is distributed in the hope that it will be useful, but
143++ * WITHOUT ANY WARRANTY; without even the implied warranty of
144++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
145++ * Lesser General Public License for more details.
146++ *
147++ * You should have received a copy of the GNU General Public License
148++ * along with this program; if not, write to the Free Software
149++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
150++ * 02111-1307, USA.
151++ */
152++
153++#include "config.h"
154++
155++#include <libintl.h>
156++#include <stdlib.h>
157++#include <string.h>
158++#include <unistd.h>
159++#include <errno.h>
160++
161++#include <glib/gi18n-lib.h>
162++#include <glib.h>
163++#include <gtk/gtk.h>
164++#include <pulse/pulseaudio.h>
165++
166++#include "cc-sound-panel.h"
167++#include "gvc-mixer-dialog.h"
168++
169++G_DEFINE_DYNAMIC_TYPE (CcSoundNuaPanel, cc_sound_panel, CC_TYPE_PANEL)
170++
171++enum {
172++ PROP_0,
173++ PROP_ARGV
174++};
175++
176++static void cc_sound_panel_finalize (GObject *object);
177++
178++static void
179++cc_sound_panel_set_property (GObject *object,
180++ guint property_id,
181++ const GValue *value,
182++ GParamSpec *pspec)
183++{
184++ CcSoundNuaPanel *self = CC_SOUND_PANEL (object);
185++
186++ switch (property_id) {
187++ case PROP_ARGV: {
188++ gchar **args;
189++
190++ args = g_value_get_boxed (value);
191++
192++ if (args && args[0]) {
193++ gvc_mixer_dialog_set_page (self->dialog, args[0]);
194++ }
195++ break;
196++ }
197++ default:
198++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
199++ }
200++}
201++
202++static void
203++cc_sound_panel_class_init (CcSoundNuaPanelClass *klass)
204++{
205++ GObjectClass *object_class = G_OBJECT_CLASS (klass);
206++
207++ object_class->finalize = cc_sound_panel_finalize;
208++ object_class->set_property = cc_sound_panel_set_property;
209++
210++ g_object_class_override_property (object_class, PROP_ARGV, "argv");
211++}
212++
213++static void
214++cc_sound_panel_class_finalize (CcSoundNuaPanelClass *klass)
215++{
216++}
217++
218++static void
219++cc_sound_panel_finalize (GObject *object)
220++{
221++ CcSoundNuaPanel *panel = CC_SOUND_PANEL (object);
222++
223++ if (panel->dialog != NULL)
224++ panel->dialog = NULL;
225++ if (panel->connecting_label != NULL)
226++ panel->connecting_label = NULL;
227++ if (panel->control != NULL) {
228++ g_object_unref (panel->control);
229++ panel->control = NULL;
230++ }
231++
232++ G_OBJECT_CLASS (cc_sound_panel_parent_class)->finalize (object);
233++}
234++
235++static void
236++cc_sound_panel_init (CcSoundNuaPanel *self)
237++{
238++ gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
239++ ICON_DATA_DIR);
240++ gtk_window_set_default_icon_name ("multimedia-volume-control");
241++
242++ self->control = gvc_mixer_control_new ("GNOME Volume Control Dialog");
243++ gvc_mixer_control_open (self->control);
244++ self->dialog = gvc_mixer_dialog_new (self->control);
245++ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->dialog));
246++ gtk_widget_show (GTK_WIDGET (self->dialog));
247++}
248++
249++void
250++cc_sound_panel_register (GIOModule *module)
251++{
252++ cc_sound_panel_register_type (G_TYPE_MODULE (module));
253++ g_io_extension_point_implement (CC_SHELL_PANEL_EXTENSION_POINT,
254++ CC_TYPE_SOUND_PANEL,
255++ "sound-nua", 0);
256++}
257++
258++/* GIO extension stuff */
259++void
260++g_io_module_load (GIOModule *module)
261++{
262++ bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
263++ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
264++
265++ /* register the panel */
266++ cc_sound_panel_register (module);
267++}
268++
269++void
270++g_io_module_unload (GIOModule *module)
271++{
272++}
273++
274+Index: gnome-control-center-3.6.2/panels/sound-nua/cc-sound-panel.h
275+===================================================================
276+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
277++++ gnome-control-center-3.6.2/panels/sound-nua/cc-sound-panel.h 2012-11-13 16:25:40.777717988 +0100
278+@@ -0,0 +1,60 @@
279++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
280++ *
281++ * Copyright (C) 2010 Red Hat, Inc.
282++ *
283++ * This program is free software; you can redistribute it and/or
284++ * modify it under the terms of the GNU General Public License as
285++ * published by the Free Software Foundation; either version 2 of the
286++ * License, or (at your option) any later version.
287++ *
288++ * This program is distributed in the hope that it will be useful, but
289++ * WITHOUT ANY WARRANTY; without even the implied warranty of
290++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
291++ * Lesser General Public License for more details.
292++ *
293++ * You should have received a copy of the GNU General Public License
294++ * along with this program; if not, write to the Free Software
295++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
296++ * 02111-1307, USA.
297++ */
298++
299++#ifndef _CC_SOUND_PANEL_H
300++#define _CC_SOUND_PANEL_H
301++
302++#include <shell/cc-panel.h>
303++#include "gvc-mixer-control.h"
304++#include "gvc-mixer-dialog.h"
305++
306++G_BEGIN_DECLS
307++
308++#define CC_TYPE_SOUND_PANEL cc_sound_panel_get_type()
309++#define CC_SOUND_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_TYPE_SOUND_PANEL, CcSoundNuaPanel))
310++#define CC_SOUND_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CC_TYPE_SOUND_PANEL, CcSoundNuaPanelClass))
311++#define CC_IS_SOUND_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CC_TYPE_SOUND_PANEL))
312++#define CC_IS_SOUND_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CC_TYPE_SOUND_PANEL))
313++#define CC_SOUND_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CC_TYPE_SOUND_PANEL, CcSoundNuaPanelClass))
314++
315++typedef struct _CcSoundNuaPanel CcSoundNuaPanel;
316++typedef struct _CcSoundNuaPanelClass CcSoundNuaPanelClass;
317++typedef struct _CcSoundNuaPanelPrivate CcSoundNuaPanelPrivate;
318++
319++struct _CcSoundNuaPanel {
320++ CcPanel parent;
321++
322++ GvcMixerControl *control;
323++ GvcMixerDialog *dialog;
324++ GtkWidget *connecting_label;
325++};
326++
327++struct _CcSoundNuaPanelClass {
328++ CcPanelClass parent_class;
329++};
330++
331++GType cc_sound_panel_get_type (void) G_GNUC_CONST;
332++
333++void cc_sound_panel_register (GIOModule *module);
334++
335++G_END_DECLS
336++
337++#endif /* _CC_SOUND_PANEL_H */
338++
339+Index: gnome-control-center-3.6.2/panels/sound-nua/data/Makefile.am
340+===================================================================
341+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
342++++ gnome-control-center-3.6.2/panels/sound-nua/data/Makefile.am 2012-11-13 16:25:40.777717988 +0100
343+@@ -0,0 +1,17 @@
344++NULL =
345++
346++@INTLTOOL_DESKTOP_RULE@
347++
348++appsdir = $(datadir)/applications
349++apps_in_files = gnome-sound-nua-panel.desktop.in
350++apps_DATA = $(apps_in_files:.desktop.in=.desktop)
351++
352++EXTRA_DIST = \
353++ gnome-sound-nua-panel.desktop.in.in \
354++ $(NULL)
355++
356++CLEANFILES = \
357++ gnome-sound-nua-panel.desktop \
358++ $(NULL)
359++
360++-include $(top_srcdir)/git.mk
361+Index: gnome-control-center-3.6.2/panels/sound-nua/data/gnome-sound-nua-panel.desktop.in.in
362+===================================================================
363+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
364++++ gnome-control-center-3.6.2/panels/sound-nua/data/gnome-sound-nua-panel.desktop.in.in 2012-11-13 16:25:40.781717988 +0100
365+@@ -0,0 +1,17 @@
366++[Desktop Entry]
367++_Name=Sound
368++_Comment=Change sound volume and sound events
369++Exec=gnome-control-center sound-nua
370++Icon=multimedia-volume-control
371++Terminal=false
372++Type=Application
373++StartupNotify=true
374++Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;
375++OnlyShowIn=Unity;
376++X-GNOME-Bugzilla-Bugzilla=GNOME
377++X-GNOME-Bugzilla-Product=gnome-control-center
378++X-GNOME-Bugzilla-Component=sound
379++X-GNOME-Bugzilla-Version=@VERSION@
380++X-GNOME-Settings-Panel=sound-nua
381++# Translators: those are keywords for the sound control-center panel
382++_Keywords=Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;
383+Index: gnome-control-center-3.6.2/panels/sound-nua/gvc-balance-bar.c
384+===================================================================
385+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
386++++ gnome-control-center-3.6.2/panels/sound-nua/gvc-balance-bar.c 2012-11-13 16:25:40.797717987 +0100
387+@@ -0,0 +1,575 @@
388++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
389++ *
390++ * Copyright (C) 2008 William Jon McCann
391++ *
392++ * This program is free software; you can redistribute it and/or modify
393++ * it under the terms of the GNU General Public License as published by
394++ * the Free Software Foundation; either version 2 of the License, or
395++ * (at your option) any later version.
396++ *
397++ * This program is distributed in the hope that it will be useful,
398++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
399++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
400++ * GNU General Public License for more details.
401++ *
402++ * You should have received a copy of the GNU General Public License
403++ * along with this program; if not, write to the Free Software
404++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
405++ *
406++ */
407++
408++#include "config.h"
409++
410++#include <stdlib.h>
411++#include <stdio.h>
412++#include <unistd.h>
413++
414++#include <glib.h>
415++#include <glib/gi18n-lib.h>
416++#include <gtk/gtk.h>
417++#include <canberra-gtk.h>
418++#include <pulse/pulseaudio.h>
419++
420++#include "gvc-balance-bar.h"
421++#include "gvc-channel-map-private.h"
422++
423++#define SCALE_SIZE 220
424++#define ADJUSTMENT_MAX_NORMAL 65536.0 /* PA_VOLUME_NORM */
425++
426++#define GVC_BALANCE_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_BALANCE_BAR, GvcBalanceBarPrivate))
427++
428++struct GvcBalanceBarPrivate
429++{
430++ GvcChannelMap *channel_map;
431++ GvcBalanceType btype;
432++ GtkWidget *scale_box;
433++ GtkWidget *start_box;
434++ GtkWidget *end_box;
435++ GtkWidget *label;
436++ GtkWidget *scale;
437++ GtkAdjustment *adjustment;
438++ GtkSizeGroup *size_group;
439++ gboolean symmetric;
440++ gboolean click_lock;
441++};
442++
443++enum
444++{
445++ PROP_0,
446++ PROP_CHANNEL_MAP,
447++ PROP_BALANCE_TYPE,
448++};
449++
450++static void gvc_balance_bar_class_init (GvcBalanceBarClass *klass);
451++static void gvc_balance_bar_init (GvcBalanceBar *balance_bar);
452++static void gvc_balance_bar_finalize (GObject *object);
453++
454++static gboolean on_scale_button_press_event (GtkWidget *widget,
455++ GdkEventButton *event,
456++ GvcBalanceBar *bar);
457++static gboolean on_scale_button_release_event (GtkWidget *widget,
458++ GdkEventButton *event,
459++ GvcBalanceBar *bar);
460++static gboolean on_scale_scroll_event (GtkWidget *widget,
461++ GdkEventScroll *event,
462++ GvcBalanceBar *bar);
463++static void on_adjustment_value_changed (GtkAdjustment *adjustment,
464++ GvcBalanceBar *bar);
465++
466++G_DEFINE_TYPE (GvcBalanceBar, gvc_balance_bar, GTK_TYPE_HBOX)
467++
468++static GtkWidget *
469++_scale_box_new (GvcBalanceBar *bar)
470++{
471++ GvcBalanceBarPrivate *priv = bar->priv;
472++ GtkWidget *box;
473++ GtkWidget *sbox;
474++ GtkWidget *ebox;
475++ GtkAdjustment *adjustment = bar->priv->adjustment;
476++ char *str_lower, *str_upper;
477++ gdouble lower, upper;
478++
479++ bar->priv->scale_box = box = gtk_box_new (FALSE, 6);
480++ priv->scale = gtk_hscale_new (priv->adjustment);
481++ gtk_widget_set_size_request (priv->scale, SCALE_SIZE, -1);
482++ gtk_scale_set_has_origin (GTK_SCALE (priv->scale), FALSE);
483++ gtk_widget_set_name (priv->scale, "balance-bar-scale");
484++ gtk_rc_parse_string ("style \"balance-bar-scale-style\" {\n"
485++ " GtkScale::trough-side-details = 0\n"
486++ "}\n"
487++ "widget \"*.balance-bar-scale\" style : rc \"balance-bar-scale-style\"\n");
488++
489++ bar->priv->start_box = sbox = gtk_box_new (FALSE, 6);
490++ gtk_box_pack_start (GTK_BOX (box), sbox, FALSE, FALSE, 0);
491++
492++ gtk_box_pack_start (GTK_BOX (sbox), priv->label, FALSE, FALSE, 0);
493++
494++ gtk_box_pack_start (GTK_BOX (box), priv->scale, TRUE, TRUE, 0);
495++
496++ switch (bar->priv->btype) {
497++ case BALANCE_TYPE_RL:
498++ str_lower = g_strdup_printf ("<small>%s</small>", C_("balance", "Left"));
499++ str_upper = g_strdup_printf ("<small>%s</small>", C_("balance", "Right"));
500++ break;
501++ case BALANCE_TYPE_FR:
502++ str_lower = g_strdup_printf ("<small>%s</small>", C_("balance", "Rear"));
503++ str_upper = g_strdup_printf ("<small>%s</small>", C_("balance", "Front"));
504++ break;
505++ case BALANCE_TYPE_LFE:
506++ str_lower = g_strdup_printf ("<small>%s</small>", C_("balance", "Minimum"));
507++ str_upper = g_strdup_printf ("<small>%s</small>", C_("balance", "Maximum"));
508++ break;
509++ default:
510++ g_assert_not_reached ();
511++ }
512++
513++ lower = gtk_adjustment_get_lower (adjustment);
514++ gtk_scale_add_mark (GTK_SCALE (priv->scale), lower,
515++ GTK_POS_BOTTOM, str_lower);
516++ g_free (str_lower);
517++ upper = gtk_adjustment_get_upper (adjustment);
518++ gtk_scale_add_mark (GTK_SCALE (priv->scale), upper,
519++ GTK_POS_BOTTOM, str_upper);
520++ g_free (str_upper);
521++
522++ if (bar->priv->btype != BALANCE_TYPE_LFE) {
523++ gtk_scale_add_mark (GTK_SCALE (priv->scale),
524++ (upper - lower)/2 + lower,
525++ GTK_POS_BOTTOM, NULL);
526++ }
527++
528++ bar->priv->end_box = ebox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
529++ gtk_box_pack_start (GTK_BOX (box), ebox, FALSE, FALSE, 0);
530++
531++ ca_gtk_widget_disable_sounds (bar->priv->scale, FALSE);
532++ gtk_widget_add_events (bar->priv->scale, GDK_SCROLL_MASK);
533++
534++ g_signal_connect (G_OBJECT (bar->priv->scale), "button-press-event",
535++ G_CALLBACK (on_scale_button_press_event), bar);
536++ g_signal_connect (G_OBJECT (bar->priv->scale), "button-release-event",
537++ G_CALLBACK (on_scale_button_release_event), bar);
538++ g_signal_connect (G_OBJECT (bar->priv->scale), "scroll-event",
539++ G_CALLBACK (on_scale_scroll_event), bar);
540++
541++ if (bar->priv->size_group != NULL) {
542++ gtk_size_group_add_widget (bar->priv->size_group, sbox);
543++
544++ if (bar->priv->symmetric) {
545++ gtk_size_group_add_widget (bar->priv->size_group, ebox);
546++ }
547++ }
548++
549++ gtk_scale_set_draw_value (GTK_SCALE (priv->scale), FALSE);
550++
551++ return box;
552++}
553++
554++void
555++gvc_balance_bar_set_size_group (GvcBalanceBar *bar,
556++ GtkSizeGroup *group,
557++ gboolean symmetric)
558++{
559++ g_return_if_fail (GVC_IS_BALANCE_BAR (bar));
560++
561++ bar->priv->size_group = group;
562++ bar->priv->symmetric = symmetric;
563++
564++ if (bar->priv->size_group != NULL) {
565++ gtk_size_group_add_widget (bar->priv->size_group,
566++ bar->priv->start_box);
567++
568++ if (bar->priv->symmetric) {
569++ gtk_size_group_add_widget (bar->priv->size_group,
570++ bar->priv->end_box);
571++ }
572++ }
573++ gtk_widget_queue_draw (GTK_WIDGET (bar));
574++}
575++
576++static const char *
577++btype_to_string (guint btype)
578++{
579++ switch (btype) {
580++ case BALANCE_TYPE_RL:
581++ return "Balance";
582++ case BALANCE_TYPE_FR:
583++ return "Fade";
584++ break;
585++ case BALANCE_TYPE_LFE:
586++ return "LFE";
587++ default:
588++ g_assert_not_reached ();
589++ }
590++ return NULL;
591++}
592++
593++static void
594++update_level_from_map (GvcBalanceBar *bar,
595++ GvcChannelMap *map)
596++{
597++ const gdouble *volumes;
598++ gdouble val;
599++
600++ g_debug ("Volume changed (for %s bar)", btype_to_string (bar->priv->btype));
601++
602++ volumes = gvc_channel_map_get_volume (map);
603++ switch (bar->priv->btype) {
604++ case BALANCE_TYPE_RL:
605++ val = volumes[BALANCE];
606++ break;
607++ case BALANCE_TYPE_FR:
608++ val = volumes[FADE];
609++ break;
610++ case BALANCE_TYPE_LFE:
611++ val = volumes[LFE];
612++ break;
613++ default:
614++ g_assert_not_reached ();
615++ }
616++
617++ gtk_adjustment_set_value (bar->priv->adjustment, val);
618++}
619++
620++static void
621++on_channel_map_volume_changed (GvcChannelMap *map,
622++ gboolean set,
623++ GvcBalanceBar *bar)
624++{
625++ update_level_from_map (bar, map);
626++}
627++
628++static void
629++gvc_balance_bar_set_channel_map (GvcBalanceBar *bar,
630++ GvcChannelMap *map)
631++{
632++ g_return_if_fail (GVC_BALANCE_BAR (bar));
633++
634++ if (bar->priv->channel_map != NULL) {
635++ g_signal_handlers_disconnect_by_func (G_OBJECT (bar->priv->channel_map),
636++ on_channel_map_volume_changed, bar);
637++ g_object_unref (bar->priv->channel_map);
638++ }
639++ bar->priv->channel_map = g_object_ref (map);
640++
641++ update_level_from_map (bar, map);
642++
643++ g_signal_connect (G_OBJECT (map), "volume-changed",
644++ G_CALLBACK (on_channel_map_volume_changed), bar);
645++
646++ g_object_notify (G_OBJECT (bar), "channel-map");
647++}
648++
649++static void
650++gvc_balance_bar_set_balance_type (GvcBalanceBar *bar,
651++ GvcBalanceType btype)
652++{
653++ GtkWidget *frame;
654++
655++ g_return_if_fail (GVC_BALANCE_BAR (bar));
656++
657++ bar->priv->btype = btype;
658++ if (bar->priv->btype != BALANCE_TYPE_LFE) {
659++ bar->priv->adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0,
660++ -1.0,
661++ 1.0,
662++ 0.5,
663++ 0.5,
664++ 0.0));
665++ } else {
666++ bar->priv->adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0,
667++ 0.0,
668++ ADJUSTMENT_MAX_NORMAL,
669++ ADJUSTMENT_MAX_NORMAL/100.0,
670++ ADJUSTMENT_MAX_NORMAL/10.0,
671++ 0.0));
672++ }
673++
674++ g_object_ref_sink (bar->priv->adjustment);
675++ g_signal_connect (bar->priv->adjustment,
676++ "value-changed",
677++ G_CALLBACK (on_adjustment_value_changed),
678++ bar);
679++
680++ switch (btype) {
681++ case BALANCE_TYPE_RL:
682++ bar->priv->label = gtk_label_new_with_mnemonic (_("_Balance:"));
683++ break;
684++ case BALANCE_TYPE_FR:
685++ bar->priv->label = gtk_label_new_with_mnemonic (_("_Fade:"));
686++ break;
687++ case BALANCE_TYPE_LFE:
688++ bar->priv->label = gtk_label_new_with_mnemonic (_("_Subwoofer:"));
689++ break;
690++ default:
691++ g_assert_not_reached ();
692++ }
693++ gtk_misc_set_alignment (GTK_MISC (bar->priv->label),
694++ 0.0,
695++ 0.0);
696++ /* frame */
697++ frame = gtk_frame_new (NULL);
698++ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
699++ gtk_container_add (GTK_CONTAINER (bar), frame);
700++
701++ /* box with scale */
702++ bar->priv->scale_box = _scale_box_new (bar);
703++ gtk_container_add (GTK_CONTAINER (frame), bar->priv->scale_box);
704++ gtk_widget_show_all (frame);
705++
706++ gtk_widget_set_direction (bar->priv->scale, GTK_TEXT_DIR_LTR);
707++ gtk_label_set_mnemonic_widget (GTK_LABEL (bar->priv->label),
708++ bar->priv->scale);
709++
710++ g_object_notify (G_OBJECT (bar), "balance-type");
711++}
712++
713++static void
714++gvc_balance_bar_set_property (GObject *object,
715++ guint prop_id,
716++ const GValue *value,
717++ GParamSpec *pspec)
718++{
719++ GvcBalanceBar *self = GVC_BALANCE_BAR (object);
720++
721++ switch (prop_id) {
722++ case PROP_CHANNEL_MAP:
723++ gvc_balance_bar_set_channel_map (self, g_value_get_object (value));
724++ break;
725++ case PROP_BALANCE_TYPE:
726++ gvc_balance_bar_set_balance_type (self, g_value_get_int (value));
727++ break;
728++ default:
729++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
730++ break;
731++ }
732++}
733++
734++static void
735++gvc_balance_bar_get_property (GObject *object,
736++ guint prop_id,
737++ GValue *value,
738++ GParamSpec *pspec)
739++{
740++ GvcBalanceBar *self = GVC_BALANCE_BAR (object);
741++
742++ switch (prop_id) {
743++ case PROP_CHANNEL_MAP:
744++ g_value_set_object (value, self->priv->channel_map);
745++ break;
746++ default:
747++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
748++ break;
749++ }
750++}
751++
752++static GObject *
753++gvc_balance_bar_constructor (GType type,
754++ guint n_construct_properties,
755++ GObjectConstructParam *construct_params)
756++{
757++ return G_OBJECT_CLASS (gvc_balance_bar_parent_class)->constructor (type, n_construct_properties, construct_params);
758++}
759++
760++static void
761++gvc_balance_bar_class_init (GvcBalanceBarClass *klass)
762++{
763++ GObjectClass *object_class = G_OBJECT_CLASS (klass);
764++
765++ object_class->constructor = gvc_balance_bar_constructor;
766++ object_class->finalize = gvc_balance_bar_finalize;
767++ object_class->set_property = gvc_balance_bar_set_property;
768++ object_class->get_property = gvc_balance_bar_get_property;
769++
770++ g_object_class_install_property (object_class,
771++ PROP_CHANNEL_MAP,
772++ g_param_spec_object ("channel-map",
773++ "channel map",
774++ "The channel map",
775++ GVC_TYPE_CHANNEL_MAP,
776++ G_PARAM_READWRITE));
777++ g_object_class_install_property (object_class,
778++ PROP_BALANCE_TYPE,
779++ g_param_spec_int ("balance-type",
780++ "balance type",
781++ "Whether the balance is right-left or front-rear",
782++ BALANCE_TYPE_RL, NUM_BALANCE_TYPES - 1, BALANCE_TYPE_RL,
783++ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
784++
785++ g_type_class_add_private (klass, sizeof (GvcBalanceBarPrivate));
786++}
787++
788++
789++static gboolean
790++on_scale_button_press_event (GtkWidget *widget,
791++ GdkEventButton *event,
792++ GvcBalanceBar *bar)
793++{
794++ bar->priv->click_lock = TRUE;
795++
796++ return FALSE;
797++}
798++
799++static gboolean
800++on_scale_button_release_event (GtkWidget *widget,
801++ GdkEventButton *event,
802++ GvcBalanceBar *bar)
803++{
804++ bar->priv->click_lock = FALSE;
805++
806++ return FALSE;
807++}
808++
809++static gboolean
810++on_scale_scroll_event (GtkWidget *widget,
811++ GdkEventScroll *event,
812++ GvcBalanceBar *bar)
813++{
814++ gdouble value;
815++ gdouble dx, dy;
816++
817++ value = gtk_adjustment_get_value (bar->priv->adjustment);
818++
819++ if (!gdk_event_get_scroll_deltas ((GdkEvent*)event, &dx, &dy)) {
820++ dx = 0.0;
821++ dy = 0.0;
822++
823++ switch (event->direction) {
824++ case GDK_SCROLL_UP:
825++ case GDK_SCROLL_RIGHT:
826++ dy = 1.0;
827++ break;
828++ case GDK_SCROLL_DOWN:
829++ case GDK_SCROLL_LEFT:
830++ dy = -1.0;
831++ break;
832++ default:
833++ ;
834++ }
835++ }
836++
837++ if (bar->priv->btype == BALANCE_TYPE_LFE) {
838++ if (dy > 0) {
839++ if (value + dy * ADJUSTMENT_MAX_NORMAL/100.0 > ADJUSTMENT_MAX_NORMAL)
840++ value = ADJUSTMENT_MAX_NORMAL;
841++ else
842++ value = value + dy * ADJUSTMENT_MAX_NORMAL/100.0;
843++ } else if (dy < 0) {
844++ if (value + dy * ADJUSTMENT_MAX_NORMAL/100.0 < 0)
845++ value = 0.0;
846++ else
847++ value = value + dy * ADJUSTMENT_MAX_NORMAL/100.0;
848++ }
849++ } else {
850++ if (dy > 0) {
851++ if (value + dy * 0.01 > 1.0)
852++ value = 1.0;
853++ else
854++ value = value + dy * 0.01;
855++ } else if (dy < 0) {
856++ if (value + dy * 0.01 < -1.0)
857++ value = -1.0;
858++ else
859++ value = value + dy * 0.01;
860++ }
861++ }
862++ gtk_adjustment_set_value (bar->priv->adjustment, value);
863++
864++ return TRUE;
865++}
866++
867++/* FIXME remove when we depend on a newer PA */
868++static pa_cvolume *
869++gvc_pa_cvolume_set_position (pa_cvolume *cv, const pa_channel_map *map, pa_channel_position_t t, pa_volume_t v) {
870++ unsigned c;
871++ gboolean good = FALSE;
872++
873++ g_assert(cv);
874++ g_assert(map);
875++
876++ g_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), NULL);
877++ g_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, NULL);
878++
879++ for (c = 0; c < map->channels; c++)
880++ if (map->map[c] == t) {
881++ cv->values[c] = v;
882++ good = TRUE;
883++ }
884++
885++ return good ? cv : NULL;
886++}
887++
888++static void
889++on_adjustment_value_changed (GtkAdjustment *adjustment,
890++ GvcBalanceBar *bar)
891++{
892++ gdouble val;
893++ pa_cvolume cv;
894++ const pa_channel_map *pa_map;
895++
896++ if (bar->priv->channel_map == NULL)
897++ return;
898++
899++ cv = *gvc_channel_map_get_cvolume (bar->priv->channel_map);
900++ val = gtk_adjustment_get_value (adjustment);
901++
902++ pa_map = gvc_channel_map_get_pa_channel_map (bar->priv->channel_map);
903++
904++ switch (bar->priv->btype) {
905++ case BALANCE_TYPE_RL:
906++ pa_cvolume_set_balance (&cv, pa_map, val);
907++ break;
908++ case BALANCE_TYPE_FR:
909++ pa_cvolume_set_fade (&cv, pa_map, val);
910++ break;
911++ case BALANCE_TYPE_LFE:
912++ gvc_pa_cvolume_set_position (&cv, pa_map, PA_CHANNEL_POSITION_LFE, val);
913++ break;
914++ }
915++
916++ gvc_channel_map_volume_changed (bar->priv->channel_map, &cv, TRUE);
917++}
918++
919++static void
920++gvc_balance_bar_init (GvcBalanceBar *bar)
921++{
922++ bar->priv = GVC_BALANCE_BAR_GET_PRIVATE (bar);
923++}
924++
925++static void
926++gvc_balance_bar_finalize (GObject *object)
927++{
928++ GvcBalanceBar *bar;
929++
930++ g_return_if_fail (object != NULL);
931++ g_return_if_fail (GVC_IS_BALANCE_BAR (object));
932++
933++ bar = GVC_BALANCE_BAR (object);
934++
935++ g_return_if_fail (bar->priv != NULL);
936++
937++ if (bar->priv->channel_map != NULL) {
938++ g_signal_handlers_disconnect_by_func (G_OBJECT (bar->priv->channel_map),
939++ on_channel_map_volume_changed, bar);
940++ g_object_unref (bar->priv->channel_map);
941++ }
942++
943++ G_OBJECT_CLASS (gvc_balance_bar_parent_class)->finalize (object);
944++}
945++
946++void
947++gvc_balance_bar_set_map (GvcBalanceBar* self,
948++ const GvcChannelMap *channel_map)
949++{
950++ g_object_set (G_OBJECT (self),
951++ "channel-map", channel_map, NULL);
952++}
953++
954++GtkWidget *
955++gvc_balance_bar_new (GvcBalanceType btype)
956++{
957++ GObject *bar;
958++ bar = g_object_new (GVC_TYPE_BALANCE_BAR,
959++ "balance-type", btype, NULL);
960++
961++ return GTK_WIDGET (bar);
962++}
963+Index: gnome-control-center-3.6.2/panels/sound-nua/gvc-balance-bar.h
964+===================================================================
965+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
966++++ gnome-control-center-3.6.2/panels/sound-nua/gvc-balance-bar.h 2012-11-13 16:25:40.873717987 +0100
967+@@ -0,0 +1,70 @@
968++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
969++ *
970++ * Copyright (C) 2008 Red Hat, Inc.
971++ *
972++ * This program is free software; you can redistribute it and/or modify
973++ * it under the terms of the GNU General Public License as published by
974++ * the Free Software Foundation; either version 2 of the License, or
975++ * (at your option) any later version.
976++ *
977++ * This program is distributed in the hope that it will be useful,
978++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
979++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
980++ * GNU General Public License for more details.
981++ *
982++ * You should have received a copy of the GNU General Public License
983++ * along with this program; if not, write to the Free Software
984++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
985++ *
986++ */
987++
988++#ifndef __GVC_BALANCE_BAR_H
989++#define __GVC_BALANCE_BAR_H
990++
991++#include <glib-object.h>
992++
993++#include "gvc-channel-map.h"
994++
995++G_BEGIN_DECLS
996++
997++#define GVC_TYPE_BALANCE_BAR (gvc_balance_bar_get_type ())
998++#define GVC_BALANCE_BAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_BALANCE_BAR, GvcBalanceBar))
999++#define GVC_BALANCE_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_BALANCE_BAR, GvcBalanceBarClass))
1000++#define GVC_IS_BALANCE_BAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_BALANCE_BAR))
1001++#define GVC_IS_BALANCE_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_BALANCE_BAR))
1002++#define GVC_BALANCE_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_BALANCE_BAR, GvcBalanceBarClass))
1003++
1004++typedef enum {
1005++ BALANCE_TYPE_RL,
1006++ BALANCE_TYPE_FR,
1007++ BALANCE_TYPE_LFE,
1008++} GvcBalanceType;
1009++
1010++#define NUM_BALANCE_TYPES BALANCE_TYPE_LFE + 1
1011++
1012++typedef struct GvcBalanceBarPrivate GvcBalanceBarPrivate;
1013++
1014++typedef struct
1015++{
1016++ GtkHBox parent;
1017++ GvcBalanceBarPrivate *priv;
1018++} GvcBalanceBar;
1019++
1020++typedef struct
1021++{
1022++ GtkHBoxClass parent_class;
1023++} GvcBalanceBarClass;
1024++
1025++GType gvc_balance_bar_get_type (void);
1026++GtkWidget * gvc_balance_bar_new (GvcBalanceType btype);
1027++
1028++void gvc_balance_bar_set_size_group (GvcBalanceBar *bar,
1029++ GtkSizeGroup *group,
1030++ gboolean symmetric);
1031++
1032++void gvc_balance_bar_set_map (GvcBalanceBar *self,
1033++ const GvcChannelMap *channel_map);
1034++
1035++G_END_DECLS
1036++
1037++#endif /* __GVC_BALANCE_BAR_H */
1038+Index: gnome-control-center-3.6.2/panels/sound-nua/gvc-mixer-dialog.c
1039+===================================================================
1040+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1041++++ gnome-control-center-3.6.2/panels/sound-nua/gvc-mixer-dialog.c 2012-11-13 16:26:26.245717312 +0100
1042+@@ -0,0 +1,2187 @@
1043++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
1044++ *
1045++ * Copyright (C) 2008 William Jon McCann
1046++ * Copyright (C) 2012 Conor Curran
1047++ *
1048++ * This program is free software; you can redistribute it and/or modify
1049++ * it under the terms of the GNU General Public License as published by
1050++ * the Free Software Foundation; either version 2 of the License, or
1051++ * (at your option) any later version.
1052++ *
1053++ * This program is distributed in the hope that it will be useful,
1054++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1055++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1056++ * GNU General Public License for more details.
1057++ *
1058++ * You should have received a copy of the GNU General Public License
1059++ * along with this program; if not, write to the Free Software
1060++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1061++ *
1062++ */
1063++
1064++#include "config.h"
1065++
1066++#include <stdlib.h>
1067++#include <stdio.h>
1068++#include <unistd.h>
1069++#include <math.h>
1070++
1071++#include <glib.h>
1072++#include <glib/gi18n-lib.h>
1073++#include <gdk/gdkkeysyms.h>
1074++#include <gtk/gtk.h>
1075++#include <pulse/pulseaudio.h>
1076++
1077++
1078++#include "gvc-channel-bar.h"
1079++#include "gvc-balance-bar.h"
1080++#include "gvc-combo-box.h"
1081++#include "gvc-mixer-control.h"
1082++#include "gvc-mixer-card.h"
1083++#include "gvc-mixer-ui-device.h"
1084++#include "gvc-mixer-sink.h"
1085++#include "gvc-mixer-source.h"
1086++#include "gvc-mixer-source-output.h"
1087++#include "gvc-mixer-dialog.h"
1088++#include "gvc-sound-theme-chooser.h"
1089++#include "gvc-level-bar.h"
1090++#include "gvc-speaker-test.h"
1091++#include "gvc-mixer-control-private.h"
1092++
1093++#define SCALE_SIZE 128
1094++
1095++#define GVC_MIXER_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_DIALOG, GvcMixerDialogPrivate))
1096++
1097++struct GvcMixerDialogPrivate
1098++{
1099++ GvcMixerControl *mixer_control;
1100++ GHashTable *bars;
1101++ GtkWidget *notebook;
1102++ GtkWidget *output_bar;
1103++ GtkWidget *input_bar;
1104++ GtkWidget *input_level_bar;
1105++ GtkWidget *effects_bar;
1106++ GtkWidget *output_stream_box;
1107++ GtkWidget *sound_effects_box;
1108++ GtkWidget *hw_box;
1109++ GtkWidget *hw_treeview;
1110++ GtkWidget *hw_settings_box;
1111++ GtkWidget *hw_profile_combo;
1112++ GtkWidget *input_box;
1113++ GtkWidget *output_box;
1114++ GtkWidget *applications_box;
1115++ GtkWidget *no_apps_label;
1116++ GtkWidget *output_treeview;
1117++ GtkWidget *output_settings_box;
1118++ GtkWidget *output_balance_bar;
1119++ GtkWidget *output_fade_bar;
1120++ GtkWidget *output_lfe_bar;
1121++ GtkWidget *output_profile_combo;
1122++ GtkWidget *input_profile_combo;
1123++ GtkWidget *input_treeview;
1124++ GtkWidget *input_settings_box;
1125++ GtkWidget *sound_theme_chooser;
1126++ GtkWidget *click_feedback_button;
1127++ GtkWidget *audible_bell_button;
1128++ GtkSizeGroup *size_group;
1129++ GtkWidget *selected_output_label;
1130++ GtkWidget *selected_input_label;
1131++ GtkWidget *test_output_button;
1132++ GSettings *indicator_settings;
1133++
1134++ gdouble last_input_peak;
1135++ guint num_apps;
1136++};
1137++
1138++enum {
1139++ NAME_COLUMN,
1140++ DEVICE_COLUMN,
1141++ ACTIVE_COLUMN,
1142++ ID_COLUMN,
1143++ SPEAKERS_COLUMN,
1144++ ICON_COLUMN,
1145++ NUM_COLUMNS
1146++};
1147++
1148++enum {
1149++ HW_ID_COLUMN,
1150++ HW_ICON_COLUMN,
1151++ HW_NAME_COLUMN,
1152++ HW_STATUS_COLUMN,
1153++ HW_PROFILE_COLUMN,
1154++ HW_PROFILE_HUMAN_COLUMN,
1155++ HW_SENSITIVE_COLUMN,
1156++ HW_NUM_COLUMNS
1157++};
1158++
1159++enum
1160++{
1161++ PROP_0,
1162++ PROP_MIXER_CONTROL
1163++};
1164++
1165++static void gvc_mixer_dialog_class_init (GvcMixerDialogClass *klass);
1166++static void gvc_mixer_dialog_init (GvcMixerDialog *mixer_dialog);
1167++static void gvc_mixer_dialog_finalize (GObject *object);
1168++
1169++static void bar_set_stream (GvcMixerDialog *dialog,
1170++ GtkWidget *bar,
1171++ GvcMixerStream *stream);
1172++
1173++static void on_adjustment_value_changed (GtkAdjustment *adjustment,
1174++ GvcMixerDialog *dialog);
1175++static void on_control_output_added (GvcMixerControl *control,
1176++ guint id,
1177++ GvcMixerDialog *dialog);
1178++static void on_control_active_output_update (GvcMixerControl *control,
1179++ guint id,
1180++ GvcMixerDialog *dialog);
1181++
1182++static void on_control_active_input_update (GvcMixerControl *control,
1183++ guint id,
1184++ GvcMixerDialog *dialog);
1185++
1186++G_DEFINE_TYPE (GvcMixerDialog, gvc_mixer_dialog, GTK_TYPE_VBOX)
1187++
1188++
1189++static void
1190++update_description (GvcMixerDialog *dialog,
1191++ guint column,
1192++ const char *value,
1193++ GvcMixerStream *stream)
1194++{
1195++ GtkTreeModel *model;
1196++ GtkTreeIter iter;
1197++ guint id;
1198++
1199++ if (GVC_IS_MIXER_SOURCE (stream))
1200++ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
1201++ else if (GVC_IS_MIXER_SINK (stream))
1202++ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
1203++ else
1204++ g_assert_not_reached ();
1205++
1206++ if (gtk_tree_model_get_iter_first (model, &iter) == FALSE){
1207++ g_warning ("The tree is empty => Cannot update the description");
1208++ return;
1209++ }
1210++
1211++ id = gvc_mixer_stream_get_id (stream);
1212++ do {
1213++ guint current_id;
1214++
1215++ gtk_tree_model_get (model, &iter,
1216++ ID_COLUMN, &current_id,
1217++ -1);
1218++ if (id != current_id)
1219++ continue;
1220++
1221++ gtk_list_store_set (GTK_LIST_STORE (model),
1222++ &iter,
1223++ column, value,
1224++ -1);
1225++ break;
1226++ } while (gtk_tree_model_iter_next (model, &iter));
1227++}
1228++
1229++static void
1230++profile_selection_changed (GvcComboBox *combo_box,
1231++ const char *profile,
1232++ GvcMixerDialog *dialog)
1233++{
1234++ g_debug ("profile_selection_changed - %s", profile);
1235++ GvcMixerUIDevice *out;
1236++ out = g_object_get_data (G_OBJECT (combo_box), "uidevice");
1237++
1238++ if (out == NULL) {
1239++ g_warning ("Could not find Output for profile combo box");
1240++ return;
1241++ }
1242++
1243++ g_debug (" \n on profile selection changed on output with \n description %s \n origin %s \n id %i \n \n",
1244++ gvc_mixer_ui_device_get_description (out),
1245++ gvc_mixer_ui_device_get_origin (out),
1246++ gvc_mixer_ui_device_get_id (out));
1247++
1248++ if (gvc_mixer_control_change_profile_on_selected_device (dialog->priv->mixer_control, out, profile) == FALSE) {
1249++ g_warning ("Could not change profile on device %s",
1250++ gvc_mixer_ui_device_get_description (out));
1251++ }
1252++}
1253++
1254++#define DECAY_STEP .15
1255++
1256++static void
1257++update_input_peak (GvcMixerDialog *dialog,
1258++ gdouble v)
1259++{
1260++ GtkAdjustment *adj;
1261++
1262++ if (dialog->priv->last_input_peak >= DECAY_STEP) {
1263++ if (v < dialog->priv->last_input_peak - DECAY_STEP) {
1264++ v = dialog->priv->last_input_peak - DECAY_STEP;
1265++ }
1266++ }
1267++
1268++ dialog->priv->last_input_peak = v;
1269++
1270++ adj = gvc_level_bar_get_peak_adjustment (GVC_LEVEL_BAR (dialog->priv->input_level_bar));
1271++ if (v >= 0) {
1272++ gtk_adjustment_set_value (adj, v);
1273++ } else {
1274++ gtk_adjustment_set_value (adj, 0.0);
1275++ }
1276++}
1277++
1278++static void
1279++update_input_meter (GvcMixerDialog *dialog,
1280++ uint32_t source_index,
1281++ uint32_t sink_input_idx,
1282++ double v)
1283++{
1284++ update_input_peak (dialog, v);
1285++}
1286++
1287++static void
1288++on_monitor_suspended_callback (pa_stream *s,
1289++ void *userdata)
1290++{
1291++ GvcMixerDialog *dialog;
1292++
1293++ dialog = userdata;
1294++
1295++ if (pa_stream_is_suspended (s)) {
1296++ g_debug ("Stream suspended");
1297++ update_input_meter (dialog,
1298++ pa_stream_get_device_index (s),
1299++ PA_INVALID_INDEX,
1300++ -1);
1301++ }
1302++}
1303++
1304++static void
1305++on_monitor_read_callback (pa_stream *s,
1306++ size_t length,
1307++ void *userdata)
1308++{
1309++ GvcMixerDialog *dialog;
1310++ const void *data;
1311++ double v;
1312++
1313++ dialog = userdata;
1314++
1315++ if (pa_stream_peek (s, &data, &length) < 0) {
1316++ g_warning ("Failed to read data from stream");
1317++ return;
1318++ }
1319++
1320++ assert (length > 0);
1321++ assert (length % sizeof (float) == 0);
1322++
1323++ v = ((const float *) data)[length / sizeof (float) -1];
1324++
1325++ pa_stream_drop (s);
1326++
1327++ if (v < 0) {
1328++ v = 0;
1329++ }
1330++ if (v > 1) {
1331++ v = 1;
1332++ }
1333++
1334++ update_input_meter (dialog,
1335++ pa_stream_get_device_index (s),
1336++ pa_stream_get_monitor_stream (s),
1337++ v);
1338++}
1339++
1340++static void
1341++create_monitor_stream_for_source (GvcMixerDialog *dialog,
1342++ GvcMixerStream *stream)
1343++{
1344++ pa_stream *s;
1345++ char t[16];
1346++ pa_buffer_attr attr;
1347++ pa_sample_spec ss;
1348++ pa_context *context;
1349++ int res;
1350++ pa_proplist *proplist;
1351++ gboolean has_monitor;
1352++
1353++ if (stream == NULL) {
1354++ g_debug ("\n create_monitor_stream_for_source - stream is null - returning\n");
1355++ return;
1356++ }
1357++ has_monitor = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (stream), "has-monitor"));
1358++ if (has_monitor != FALSE) {
1359++ g_debug ("\n create_monitor_stream_for_source, has monitor is not false - returning \n");
1360++ return;
1361++ }
1362++
1363++ g_debug ("Create monitor for %u",
1364++ gvc_mixer_stream_get_index (stream));
1365++
1366++ context = gvc_mixer_control_get_pa_context (dialog->priv->mixer_control);
1367++
1368++ if (pa_context_get_server_protocol_version (context) < 13) {
1369++ g_debug ("\n create_monitor_stream_for_source - protocol version is less 13 \n");
1370++ return;
1371++ }
1372++
1373++ ss.channels = 1;
1374++ ss.format = PA_SAMPLE_FLOAT32;
1375++ ss.rate = 25;
1376++
1377++ memset (&attr, 0, sizeof (attr));
1378++ attr.fragsize = sizeof (float);
1379++ attr.maxlength = (uint32_t) -1;
1380++
1381++ snprintf (t, sizeof (t), "%u", gvc_mixer_stream_get_index (stream));
1382++
1383++ proplist = pa_proplist_new ();
1384++ pa_proplist_sets (proplist, PA_PROP_APPLICATION_ID, "org.gnome.VolumeControl");
1385++ s = pa_stream_new_with_proplist (context, _("Peak detect"), &ss, NULL, proplist);
1386++ pa_proplist_free (proplist);
1387++ if (s == NULL) {
1388++ g_warning ("Failed to create monitoring stream");
1389++ return;
1390++ }
1391++
1392++ pa_stream_set_read_callback (s, on_monitor_read_callback, dialog);
1393++ pa_stream_set_suspended_callback (s, on_monitor_suspended_callback, dialog);
1394++
1395++ res = pa_stream_connect_record (s,
1396++ t,
1397++ &attr,
1398++ (pa_stream_flags_t) (PA_STREAM_DONT_MOVE
1399++ |PA_STREAM_PEAK_DETECT
1400++ |PA_STREAM_ADJUST_LATENCY));
1401++ if (res < 0) {
1402++ g_warning ("Failed to connect monitoring stream");
1403++ pa_stream_unref (s);
1404++ } else {
1405++ g_object_set_data (G_OBJECT (stream), "has-monitor", GINT_TO_POINTER (TRUE));
1406++ g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "pa_stream", s);
1407++ g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "stream", stream);
1408++ }
1409++}
1410++
1411++
1412++static void
1413++stop_monitor_stream_for_source (GvcMixerDialog *dialog)
1414++{
1415++ pa_stream *s;
1416++ pa_context *context;
1417++ int res = 0;
1418++ GvcMixerStream *stream;
1419++
1420++ stream = g_object_get_data (G_OBJECT (dialog->priv->input_level_bar), "stream");
1421++
1422++ if (stream == NULL){
1423++ g_debug ("\n stop_monitor_stream_for_source - gvcstream is null - returning \n");
1424++ return;
1425++ }
1426++ else{
1427++ g_debug ("\n stop_monitor_stream_for_source - gvcstream is not null - continue \n");
1428++ }
1429++
1430++ s = g_object_get_data (G_OBJECT (dialog->priv->input_level_bar), "pa_stream");
1431++
1432++ if (s != NULL){
1433++ res = pa_stream_disconnect (s);
1434++ if (res == 0) {
1435++ g_debug("stream has been disconnected");
1436++ pa_stream_unref (s);
1437++ }
1438++ g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "pa_stream", NULL);
1439++ }
1440++
1441++ context = gvc_mixer_control_get_pa_context (dialog->priv->mixer_control);
1442++
1443++ if (pa_context_get_server_protocol_version (context) < 13) {
1444++ return;
1445++ }
1446++ if (res == 0) {
1447++ g_object_set_data (G_OBJECT (stream), "has-monitor", GINT_TO_POINTER (FALSE));
1448++ }
1449++ g_debug ("Stopping monitor for %u", pa_stream_get_index (s));
1450++ g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "stream", NULL);
1451++}
1452++
1453++static void
1454++gvc_mixer_dialog_set_mixer_control (GvcMixerDialog *dialog,
1455++ GvcMixerControl *control)
1456++{
1457++ g_return_if_fail (GVC_MIXER_DIALOG (dialog));
1458++ g_return_if_fail (GVC_IS_MIXER_CONTROL (control));
1459++
1460++ g_object_ref (control);
1461++
1462++ if (dialog->priv->mixer_control != NULL) {
1463++ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
1464++ G_CALLBACK (on_control_active_output_update),
1465++ dialog);
1466++ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
1467++ G_CALLBACK (on_control_active_input_update),
1468++ dialog);
1469++ g_object_unref (dialog->priv->mixer_control);
1470++ }
1471++
1472++ dialog->priv->mixer_control = control;
1473++
1474++ g_signal_connect (dialog->priv->mixer_control,
1475++ "active-output-update",
1476++ G_CALLBACK (on_control_active_output_update),
1477++ dialog);
1478++ g_signal_connect (dialog->priv->mixer_control,
1479++ "active-input-update",
1480++ G_CALLBACK (on_control_active_input_update),
1481++ dialog);
1482++
1483++ g_object_notify (G_OBJECT (dialog), "mixer-control");
1484++}
1485++
1486++static GvcMixerControl *
1487++gvc_mixer_dialog_get_mixer_control (GvcMixerDialog *dialog)
1488++{
1489++ g_return_val_if_fail (GVC_IS_MIXER_DIALOG (dialog), NULL);
1490++
1491++ return dialog->priv->mixer_control;
1492++}
1493++
1494++static void
1495++gvc_mixer_dialog_set_property (GObject *object,
1496++ guint prop_id,
1497++ const GValue *value,
1498++ GParamSpec *pspec)
1499++{
1500++ GvcMixerDialog *self = GVC_MIXER_DIALOG (object);
1501++
1502++ switch (prop_id) {
1503++ case PROP_MIXER_CONTROL:
1504++ gvc_mixer_dialog_set_mixer_control (self, g_value_get_object (value));
1505++ break;
1506++ default:
1507++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1508++ break;
1509++ }
1510++}
1511++
1512++static void
1513++gvc_mixer_dialog_get_property (GObject *object,
1514++ guint prop_id,
1515++ GValue *value,
1516++ GParamSpec *pspec)
1517++{
1518++ GvcMixerDialog *self = GVC_MIXER_DIALOG (object);
1519++
1520++ switch (prop_id) {
1521++ case PROP_MIXER_CONTROL:
1522++ g_value_set_object (value, gvc_mixer_dialog_get_mixer_control (self));
1523++ break;
1524++ default:
1525++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1526++ break;
1527++ }
1528++}
1529++
1530++static void
1531++on_adjustment_value_changed (GtkAdjustment *adjustment,
1532++ GvcMixerDialog *dialog)
1533++{
1534++ GvcMixerStream *stream;
1535++
1536++ stream = g_object_get_data (G_OBJECT (adjustment), "gvc-mixer-dialog-stream");
1537++ if (stream != NULL) {
1538++ GObject *bar;
1539++ gdouble volume, rounded;
1540++ char *name;
1541++
1542++ volume = gtk_adjustment_get_value (adjustment);
1543++ rounded = round (volume);
1544++
1545++ bar = g_object_get_data (G_OBJECT (adjustment), "gvc-mixer-dialog-bar");
1546++ g_object_get (bar, "name", &name, NULL);
1547++ g_debug ("Setting stream volume %lf (rounded: %lf) for bar '%s'", volume, rounded, name);
1548++ g_free (name);
1549++
1550++ /* FIXME would need to do that in the balance bar really... */
1551++ /* Make sure we do not unmute muted streams, there's a button for that */
1552++ if (volume == 0.0)
1553++ gvc_mixer_stream_set_is_muted (stream, TRUE);
1554++ /* Only push the volume if it's actually changed */
1555++ if (gvc_mixer_stream_set_volume(stream, (pa_volume_t) rounded) != FALSE)
1556++ gvc_mixer_stream_push_volume (stream);
1557++ }
1558++}
1559++
1560++static void
1561++on_bar_is_muted_notify (GObject *object,
1562++ GParamSpec *pspec,
1563++ GvcMixerDialog *dialog)
1564++{
1565++ gboolean is_muted;
1566++ GvcMixerStream *stream;
1567++
1568++ is_muted = gvc_channel_bar_get_is_muted (GVC_CHANNEL_BAR (object));
1569++
1570++ stream = g_object_get_data (object, "gvc-mixer-dialog-stream");
1571++ if (stream != NULL) {
1572++ gvc_mixer_stream_change_is_muted (stream, is_muted);
1573++ } else {
1574++ char *name;
1575++ g_object_get (object, "name", &name, NULL);
1576++ g_warning ("Unable to find stream for bar '%s'", name);
1577++ g_free (name);
1578++ }
1579++}
1580++
1581++static GtkWidget *
1582++lookup_bar_for_stream (GvcMixerDialog *dialog,
1583++ GvcMixerStream *stream)
1584++{
1585++ GtkWidget *bar;
1586++
1587++ bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (stream)));
1588++
1589++ return bar;
1590++}
1591++
1592++// TODO
1593++// Do we need this ?
1594++// UI devices now pull description material mainly for the card ports.
1595++// Therefore the need for stream description dynamic changes more than ever seems unneccessary.
1596++static void
1597++on_stream_description_notify (GvcMixerStream *stream,
1598++ GParamSpec *pspec,
1599++ GvcMixerDialog *dialog)
1600++{
1601++ update_description (dialog, NAME_COLUMN,
1602++ gvc_mixer_stream_get_description (stream),
1603++ stream);
1604++}
1605++
1606++static void
1607++on_stream_volume_notify (GObject *object,
1608++ GParamSpec *pspec,
1609++ GvcMixerDialog *dialog)
1610++{
1611++ GvcMixerStream *stream;
1612++ GtkWidget *bar;
1613++ GtkAdjustment *adj;
1614++ stream = GVC_MIXER_STREAM (object);
1615++
1616++ bar = lookup_bar_for_stream (dialog, stream);
1617++
1618++ if (bar == NULL) {
1619++ if (stream == gvc_mixer_control_get_default_sink(dialog->priv->mixer_control)) {
1620++ bar = dialog->priv->output_bar;
1621++ }
1622++ else if(stream == gvc_mixer_control_get_default_source(dialog->priv->mixer_control)) {
1623++ bar = dialog->priv->input_bar;
1624++ }
1625++ else{
1626++ g_warning ("Unable to find bar for stream %s in on_stream_volume_notify()",
1627++ gvc_mixer_stream_get_name (stream));
1628++ return;
1629++ }
1630++ }
1631++
1632++ adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
1633++
1634++ g_signal_handlers_block_by_func (adj,
1635++ on_adjustment_value_changed,
1636++ dialog);
1637++
1638++ gtk_adjustment_set_value (adj,
1639++ gvc_mixer_stream_get_volume (stream));
1640++
1641++ g_signal_handlers_unblock_by_func (adj,
1642++ on_adjustment_value_changed,
1643++ dialog);
1644++}
1645++
1646++static void
1647++on_stream_is_muted_notify (GObject *object,
1648++ GParamSpec *pspec,
1649++ GvcMixerDialog *dialog)
1650++{
1651++ GvcMixerStream *stream;
1652++ GtkWidget *bar;
1653++ gboolean is_muted;
1654++
1655++ stream = GVC_MIXER_STREAM (object);
1656++
1657++ bar = lookup_bar_for_stream (dialog, stream);
1658++
1659++ if (bar == NULL) {
1660++ if (stream == gvc_mixer_control_get_default_sink(dialog->priv->mixer_control)) {
1661++ bar = dialog->priv->output_bar;
1662++ }
1663++ else if(stream == gvc_mixer_control_get_default_source(dialog->priv->mixer_control)) {
1664++ bar = dialog->priv->input_bar;
1665++ }
1666++ else{
1667++ g_warning ("Unable to find bar for stream %s in on_stream_muted_notify()",
1668++ gvc_mixer_stream_get_name (stream));
1669++ return;
1670++ }
1671++ }
1672++
1673++
1674++ is_muted = gvc_mixer_stream_get_is_muted (stream);
1675++ gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (bar),
1676++ is_muted);
1677++
1678++ if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) {
1679++ gtk_widget_set_sensitive (dialog->priv->applications_box,
1680++ !is_muted);
1681++ }
1682++
1683++}
1684++
1685++static void
1686++save_bar_for_stream (GvcMixerDialog *dialog,
1687++ GvcMixerStream *stream,
1688++ GtkWidget *bar)
1689++{
1690++ g_debug ("\n saving bar for stream %s",
1691++ gvc_mixer_stream_get_name (stream));
1692++ g_hash_table_insert (dialog->priv->bars,
1693++ GUINT_TO_POINTER (gvc_mixer_stream_get_id (stream)),
1694++ bar);
1695++}
1696++
1697++static GtkWidget *
1698++create_bar (GvcMixerDialog *dialog,
1699++ gboolean add_to_size_group,
1700++ gboolean symmetric)
1701++{
1702++ GtkWidget *bar;
1703++
1704++ bar = gvc_channel_bar_new ();
1705++ gtk_widget_set_sensitive (bar, FALSE);
1706++ if (add_to_size_group && dialog->priv->size_group != NULL) {
1707++ gvc_channel_bar_set_size_group (GVC_CHANNEL_BAR (bar),
1708++ dialog->priv->size_group,
1709++ symmetric);
1710++ }
1711++ gvc_channel_bar_set_orientation (GVC_CHANNEL_BAR (bar),
1712++ GTK_ORIENTATION_HORIZONTAL);
1713++ gvc_channel_bar_set_show_mute (GVC_CHANNEL_BAR (bar),
1714++ TRUE);
1715++ g_signal_connect (bar,
1716++ "notify::is-muted",
1717++ G_CALLBACK (on_bar_is_muted_notify),
1718++ dialog);
1719++ return bar;
1720++}
1721++
1722++static GtkWidget *
1723++create_app_bar (GvcMixerDialog *dialog,
1724++ const char *name,
1725++ const char *icon_name)
1726++{
1727++ GtkWidget *bar;
1728++
1729++ bar = create_bar (dialog, FALSE, FALSE);
1730++ gvc_channel_bar_set_ellipsize (GVC_CHANNEL_BAR (bar), TRUE);
1731++ gvc_channel_bar_set_icon_name (GVC_CHANNEL_BAR (bar), icon_name);
1732++ if (name == NULL || strchr (name, '_') == NULL) {
1733++ gvc_channel_bar_set_name (GVC_CHANNEL_BAR (bar), name);
1734++ } else {
1735++ char **tokens, *escaped;
1736++
1737++ tokens = g_strsplit (name, "_", -1);
1738++ escaped = g_strjoinv ("__", tokens);
1739++ g_strfreev (tokens);
1740++ gvc_channel_bar_set_name (GVC_CHANNEL_BAR (bar), escaped);
1741++ g_free (escaped);
1742++ }
1743++
1744++ return bar;
1745++}
1746++
1747++static gint test_it = 0;
1748++
1749++/* active_input_update
1750++ * Handle input update change from the backend (control).
1751++ * Trust the backend whole-heartedly to deliver the correct input
1752++ * i.e. keep it MVC.
1753++ */
1754++static void
1755++active_input_update (GvcMixerDialog *dialog,
1756++ GvcMixerUIDevice *active_input)
1757++{
1758++ g_debug ("\n active_input_update %s \n", gvc_mixer_ui_device_get_description (active_input));
1759++ // First make sure the correct UI device is selected.
1760++ GtkTreeModel *model;
1761++ GtkTreeIter iter;
1762++
1763++ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
1764++
1765++ if (gtk_tree_model_get_iter_first (model, &iter) == FALSE){
1766++ g_warning ("The tree is empty => we have no devices so cannot set the active input");
1767++ return;
1768++ }
1769++
1770++ do {
1771++ gboolean is_selected = FALSE;
1772++ gint id;
1773++
1774++ gtk_tree_model_get (model, &iter,
1775++ ID_COLUMN, &id,
1776++ -1);
1777++
1778++ is_selected = id == gvc_mixer_ui_device_get_id (active_input);
1779++
1780++ gtk_list_store_set (GTK_LIST_STORE (model),
1781++ &iter,
1782++ ACTIVE_COLUMN, is_selected,
1783++ -1);
1784++
1785++ if (is_selected) {
1786++ GtkTreeSelection *selection;
1787++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
1788++ gtk_tree_selection_select_iter (selection, &iter);
1789++ }
1790++
1791++ }while (gtk_tree_model_iter_next (model, &iter));
1792++
1793++
1794++ // Not ideal but for now destroy the combo and recreate below.
1795++ if (dialog->priv->input_profile_combo != NULL) {
1796++ gtk_container_remove (GTK_CONTAINER (dialog->priv->input_settings_box),
1797++ dialog->priv->input_profile_combo);
1798++ dialog->priv->input_profile_combo = NULL;
1799++ }
1800++
1801++ GvcMixerStream *stream;
1802++ GtkAdjustment *adj;
1803++
1804++ stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
1805++ active_input);
1806++ if (stream == NULL) {
1807++ g_warning ("active_input_update - couldn't find a stream from the supposed active input");
1808++ gtk_widget_set_sensitive (dialog->priv->input_bar,
1809++ FALSE);
1810++ return;
1811++ }
1812++
1813++ // Set the label accordingly
1814++ adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (dialog->priv->input_bar)));
1815++ g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
1816++
1817++ gtk_label_set_label (GTK_LABEL(dialog->priv->selected_input_label),
1818++ g_strdup_printf(_("Settings for %s"),
1819++ gvc_mixer_ui_device_get_description (active_input)));
1820++
1821++ gvc_channel_bar_set_base_volume (GVC_CHANNEL_BAR (dialog->priv->input_bar),
1822++ gvc_mixer_stream_get_base_volume (stream));
1823++ gvc_channel_bar_set_is_amplified (GVC_CHANNEL_BAR (dialog->priv->input_bar),
1824++ gvc_mixer_stream_get_can_decibel (stream));
1825++ /* Update the adjustment in case the previous bar wasn't decibel
1826++ * capable, and we clipped it */
1827++ adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (dialog->priv->input_bar)));
1828++ gtk_adjustment_set_value (adj,
1829++ gvc_mixer_stream_get_volume (stream));
1830++
1831++ stop_monitor_stream_for_source (dialog);
1832++ //if (test_it < 6){
1833++ create_monitor_stream_for_source (dialog, stream);
1834++ test_it += 1;
1835++ //}
1836++ bar_set_stream (dialog, dialog->priv->input_bar, stream);
1837++ // remove any previous stream that might have been pointed at
1838++ // the static input bar and connect new signals from new stream.
1839++
1840++ const GList* profiles = gvc_mixer_ui_device_get_profiles (active_input);
1841++
1842++ if (profiles != NULL && !gvc_mixer_ui_device_should_profiles_be_hidden (active_input)){
1843++ const gchar *active_profile;
1844++ dialog->priv->input_profile_combo = gvc_combo_box_new (_("Mode:"));
1845++ gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->input_profile_combo),
1846++ profiles);
1847++
1848++ active_profile = gvc_mixer_ui_device_get_active_profile (active_input);
1849++ if (active_profile)
1850++ gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->input_profile_combo), active_profile);
1851++
1852++ g_object_set_data (G_OBJECT (dialog->priv->input_profile_combo),
1853++ "uidevice",
1854++ active_input);
1855++
1856++ g_signal_connect (G_OBJECT (dialog->priv->input_profile_combo), "changed",
1857++ G_CALLBACK (profile_selection_changed), dialog);
1858++
1859++ gtk_box_pack_start (GTK_BOX (dialog->priv->input_settings_box),
1860++ dialog->priv->input_profile_combo,
1861++ TRUE, FALSE, 0);
1862++
1863++ if (dialog->priv->size_group != NULL) {
1864++ gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->input_profile_combo),
1865++ dialog->priv->size_group, FALSE);
1866++ }
1867++ gtk_widget_show (dialog->priv->input_profile_combo);
1868++ }
1869++}
1870++
1871++/* active_output_update
1872++ * Handle output update change from the backend (control).
1873++ * Trust the backend whole heartedly to deliver the correct output
1874++ * i.e. keep it MVC.
1875++ */
1876++static void
1877++active_output_update (GvcMixerDialog *dialog,
1878++ GvcMixerUIDevice *active_output)
1879++{
1880++ // First make sure the correct UI device is selected.
1881++ GtkTreeModel *model;
1882++ GtkTreeIter iter;
1883++ g_debug ("\n\n active output update - device id = %i \n\n",
1884++ gvc_mixer_ui_device_get_id (active_output));
1885++
1886++ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
1887++
1888++ if (gtk_tree_model_get_iter_first (model, &iter) == FALSE){
1889++ g_warning ("The tree is empty => we have no devices in the tree => cannot set the active output");
1890++ return;
1891++ }
1892++
1893++ do {
1894++ gboolean is_selected;
1895++ gint id;
1896++
1897++ gtk_tree_model_get (model, &iter,
1898++ ID_COLUMN, &id,
1899++ ACTIVE_COLUMN, &is_selected,
1900++ -1);
1901++
1902++ if (is_selected && id == gvc_mixer_ui_device_get_id (active_output)) {
1903++ g_debug ("\n\n unneccessary active output update unless it was a profile change on the same device ? \n\n");
1904++ }
1905++
1906++ is_selected = id == gvc_mixer_ui_device_get_id (active_output);
1907++
1908++ gtk_list_store_set (GTK_LIST_STORE (model),
1909++ &iter,
1910++ ACTIVE_COLUMN, is_selected,
1911++ -1);
1912++
1913++ if (is_selected) {
1914++ GtkTreeSelection *selection;
1915++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
1916++ gtk_tree_selection_select_iter (selection, &iter);
1917++ }
1918++
1919++ }while (gtk_tree_model_iter_next (model, &iter));
1920++
1921++ // Not ideal but for now destroy the combo and recreate below.
1922++ if (dialog->priv->output_profile_combo != NULL) {
1923++ gtk_container_remove (GTK_CONTAINER (dialog->priv->output_settings_box),
1924++ dialog->priv->output_profile_combo);
1925++ dialog->priv->output_profile_combo = NULL;
1926++ }
1927++
1928++ GvcMixerStream *stream;
1929++ const GvcChannelMap *map;
1930++ GtkAdjustment *adj;
1931++
1932++ stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
1933++ active_output);
1934++
1935++ if (stream == NULL) {
1936++ g_warning ("active_output_update - couldn't find a stream from the supposed active output");
1937++ return;
1938++ }
1939++
1940++ gboolean is_muted = gvc_mixer_stream_get_is_muted (stream);
1941++ gtk_widget_set_sensitive (dialog->priv->applications_box,
1942++ !is_muted);
1943++ adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (dialog->priv->output_bar)));
1944++ g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
1945++
1946++ bar_set_stream (dialog, dialog->priv->output_bar, stream);
1947++ gvc_channel_bar_set_base_volume (GVC_CHANNEL_BAR (dialog->priv->output_bar),
1948++ gvc_mixer_stream_get_base_volume (stream));
1949++ gvc_channel_bar_set_is_amplified (GVC_CHANNEL_BAR (dialog->priv->output_bar),
1950++ gvc_mixer_stream_get_can_decibel (stream));
1951++ /* Update the adjustment in case the previous bar wasn't decibel
1952++ * capable, and we clipped it */
1953++ adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (dialog->priv->output_bar)));
1954++ gtk_adjustment_set_value (adj,
1955++ gvc_mixer_stream_get_volume (stream));
1956++
1957++ map = gvc_mixer_stream_get_channel_map (stream);
1958++
1959++ if (map == NULL) {
1960++ g_warning ("Active output stream has no channel map");
1961++ gtk_widget_set_sensitive (dialog->priv->output_bar, FALSE);
1962++ gtk_widget_set_sensitive (dialog->priv->output_balance_bar, FALSE);
1963++ gtk_widget_set_sensitive (dialog->priv->output_lfe_bar, FALSE);
1964++ gtk_widget_set_sensitive (dialog->priv->output_fade_bar, FALSE);
1965++ return;
1966++ }
1967++
1968++
1969++ // Swap bars to the active map
1970++ gvc_balance_bar_set_map (GVC_BALANCE_BAR (dialog->priv->output_balance_bar),
1971++ map);
1972++ gvc_balance_bar_set_map (GVC_BALANCE_BAR (dialog->priv->output_fade_bar),
1973++ map);
1974++ gvc_balance_bar_set_map (GVC_BALANCE_BAR (dialog->priv->output_lfe_bar),
1975++ map);
1976++
1977++ // Set sensitivities accordingly.
1978++ gtk_widget_set_sensitive (dialog->priv->output_balance_bar,
1979++ gvc_channel_map_can_balance (map));
1980++ gtk_widget_set_sensitive (dialog->priv->output_fade_bar,
1981++ gvc_channel_map_can_fade (map));
1982++ gtk_widget_set_sensitive (dialog->priv->output_lfe_bar,
1983++ gvc_channel_map_has_lfe (map));
1984++ gtk_widget_set_sensitive (dialog->priv->output_bar,
1985++ TRUE);
1986++ // Set the label accordingly
1987++ gtk_label_set_label (GTK_LABEL(dialog->priv->selected_output_label),
1988++ g_strdup_printf(_("Settings for %s"),
1989++ gvc_mixer_ui_device_get_description (active_output)));
1990++ g_debug ("\n active_output_update %s \n", gvc_mixer_ui_device_get_description (active_output));
1991++
1992++ GList* profiles = gvc_mixer_ui_device_get_profiles (active_output);
1993++
1994++ if (profiles != NULL && !gvc_mixer_ui_device_should_profiles_be_hidden (active_output)) {
1995++ const gchar *active_profile;
1996++
1997++ dialog->priv->output_profile_combo = gvc_combo_box_new (_("Mode:"));
1998++ gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->output_profile_combo),
1999++ profiles);
2000++
2001++ gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box),
2002++ dialog->priv->output_profile_combo,
2003++ FALSE, FALSE, 3);
2004++
2005++ if (dialog->priv->size_group != NULL) {
2006++ gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->output_profile_combo),
2007++ dialog->priv->size_group, FALSE);
2008++ }
2009++
2010++ active_profile = gvc_mixer_ui_device_get_active_profile (active_output);
2011++ if (active_profile)
2012++ gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->output_profile_combo), active_profile);
2013++
2014++
2015++ g_object_set_data (G_OBJECT (dialog->priv->output_profile_combo),
2016++ "uidevice",
2017++ active_output);
2018++ g_signal_connect (G_OBJECT (dialog->priv->output_profile_combo), "changed",
2019++ G_CALLBACK (profile_selection_changed), dialog);
2020++
2021++ gtk_widget_show (dialog->priv->output_profile_combo);
2022++ }
2023++
2024++}
2025++
2026++static void
2027++bar_set_stream (GvcMixerDialog *dialog,
2028++ GtkWidget *bar,
2029++ GvcMixerStream *stream)
2030++{
2031++ GtkAdjustment *adj;
2032++
2033++ g_assert (bar != NULL);
2034++
2035++ gtk_widget_set_sensitive (bar, (stream != NULL));
2036++
2037++ adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
2038++
2039++ g_signal_handlers_disconnect_by_func (adj, on_adjustment_value_changed, dialog);
2040++
2041++ g_object_set_data (G_OBJECT (bar), "gvc-mixer-dialog-stream", stream);
2042++ g_object_set_data (G_OBJECT (adj), "gvc-mixer-dialog-stream", stream);
2043++ g_object_set_data (G_OBJECT (adj), "gvc-mixer-dialog-bar", bar);
2044++
2045++ if (stream != NULL) {
2046++ gboolean is_muted;
2047++
2048++ is_muted = gvc_mixer_stream_get_is_muted (stream);
2049++ gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (bar), is_muted);
2050++
2051++ gtk_adjustment_set_value (adj,
2052++ gvc_mixer_stream_get_volume (stream));
2053++ g_signal_connect (stream,
2054++ "notify::is-muted",
2055++ G_CALLBACK (on_stream_is_muted_notify),
2056++ dialog);
2057++ g_signal_connect (stream,
2058++ "notify::volume",
2059++ G_CALLBACK (on_stream_volume_notify),
2060++ dialog);
2061++ g_signal_connect (adj,
2062++ "value-changed",
2063++ G_CALLBACK (on_adjustment_value_changed),
2064++ dialog);
2065++ }
2066++}
2067++
2068++/**
2069++* This method handles all streams that are not an input or output
2070++* i.e. effects streams and application streams
2071++* TODO rename to truly reflect its usage.
2072++**/
2073++static void
2074++add_stream (GvcMixerDialog *dialog,
2075++ GvcMixerStream *stream)
2076++{
2077++
2078++ GtkWidget *bar;
2079++ bar = NULL;
2080++
2081++ if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control)) {
2082++ bar = dialog->priv->effects_bar;
2083++ g_debug ("Adding effects stream");
2084++ } else {
2085++ // Must be a sink/source input/output
2086++ const char *name;
2087++ name = gvc_mixer_stream_get_name (stream);
2088++ g_debug ("\n Add bar for application stream : %s",
2089++ name);
2090++
2091++ bar = create_app_bar (dialog, name,
2092++ gvc_mixer_stream_get_icon_name (stream));
2093++
2094++ gtk_box_pack_start (GTK_BOX (dialog->priv->applications_box), bar, FALSE, FALSE, 12);
2095++ dialog->priv->num_apps++;
2096++ gtk_widget_hide (dialog->priv->no_apps_label);
2097++ }
2098++ // We should have a bar by now.
2099++ g_assert (bar != NULL);
2100++ GvcMixerStream *old_stream;
2101++
2102++ if (bar != NULL) {
2103++ old_stream = g_object_get_data (G_OBJECT (bar), "gvc-mixer-dialog-stream");
2104++ if (old_stream != NULL) {
2105++ char *name;
2106++ g_object_get (bar, "name", &name, NULL);
2107++ g_debug ("Disconnecting old stream '%s' from bar '%s'",
2108++ gvc_mixer_stream_get_name (old_stream), name);
2109++ g_free (name);
2110++
2111++ g_signal_handlers_disconnect_by_func (old_stream, on_stream_is_muted_notify, dialog);
2112++ g_signal_handlers_disconnect_by_func (old_stream, on_stream_volume_notify, dialog);
2113++ g_print ("\n in add stream \n");
2114++ g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (old_stream)));
2115++ }
2116++ save_bar_for_stream (dialog, stream, bar);
2117++ bar_set_stream (dialog, bar, stream);
2118++ gtk_widget_show (bar);
2119++ }
2120++}
2121++
2122++static void
2123++remove_stream (GvcMixerDialog *dialog,
2124++ guint id)
2125++{
2126++ GtkWidget *bar;
2127++ bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
2128++ if (bar != NULL) {
2129++ g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (id));
2130++ gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (bar)),
2131++ bar);
2132++ dialog->priv->num_apps--;
2133++ if (dialog->priv->num_apps == 0) {
2134++ gtk_widget_show (dialog->priv->no_apps_label);
2135++ }
2136++ }
2137++
2138++}
2139++
2140++static void
2141++on_control_stream_added (GvcMixerControl *control,
2142++ guint id,
2143++ GvcMixerDialog *dialog)
2144++{
2145++ GvcMixerStream *stream;
2146++ stream = gvc_mixer_control_lookup_stream_id (control, id);
2147++
2148++ if (stream == NULL)
2149++ return;
2150++
2151++ const char *app_id;
2152++ app_id = gvc_mixer_stream_get_application_id (stream);
2153++
2154++ if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control) || (!GVC_IS_MIXER_SOURCE (stream) &&
2155++ !GVC_IS_MIXER_SINK (stream)
2156++ && !gvc_mixer_stream_is_virtual (stream)
2157++ && g_strcmp0 (app_id, "org.gnome.VolumeControl") != 0
2158++ && g_strcmp0 (app_id, "org.PulseAudio.pavucontrol") != 0)) {
2159++
2160++ GtkWidget *bar;
2161++
2162++ bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
2163++ if (bar != NULL) {
2164++ g_debug ("GvcMixerDialog: Stream %u already added", id);
2165++ return;
2166++ }
2167++ add_stream (dialog, stream);
2168++ }
2169++}
2170++
2171++static void
2172++on_control_stream_removed (GvcMixerControl *control,
2173++ guint id,
2174++ GvcMixerDialog *dialog)
2175++{
2176++ remove_stream (dialog, id);
2177++}
2178++
2179++static gboolean
2180++find_item_by_id (GtkTreeModel *model,
2181++ guint id,
2182++ guint column,
2183++ GtkTreeIter *iter)
2184++{
2185++ gboolean found_item;
2186++
2187++ found_item = FALSE;
2188++
2189++ if (!gtk_tree_model_get_iter_first (model, iter)) {
2190++ return FALSE;
2191++ }
2192++
2193++ do {
2194++ guint t_id;
2195++
2196++ gtk_tree_model_get (model, iter,
2197++ column, &t_id, -1);
2198++
2199++ if (id == t_id) {
2200++ found_item = TRUE;
2201++ }
2202++ } while (!found_item && gtk_tree_model_iter_next (model, iter));
2203++
2204++ return found_item;
2205++}
2206++
2207++static void
2208++add_input_ui_entry (GvcMixerDialog *dialog,
2209++ GvcMixerUIDevice *input)
2210++{
2211++ g_debug ("\n Add input ui entry with id : %u \n",
2212++ gvc_mixer_ui_device_get_id (input));
2213++
2214++ gchar *port_name;
2215++ gchar *origin;
2216++ gchar *description;
2217++ gboolean active;
2218++ gboolean available;
2219++ gint stream_id;
2220++ GvcMixerCard *card;
2221++
2222++ g_object_get (G_OBJECT (input),
2223++ "stream-id", &stream_id,
2224++ "card", &card,
2225++ "origin", &origin,
2226++ "description", &description,
2227++ "port-name", &port_name,
2228++ "port-available", &available,
2229++ NULL);
2230++ GtkTreeModel *model;
2231++ GtkTreeIter iter;
2232++ const GvcChannelMap *map;
2233++ GIcon *icon;
2234++
2235++ if (card == NULL) {
2236++ GvcMixerStream *stream;
2237++ g_debug ("just detected a network source");
2238++ stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, input);
2239++ if (stream == NULL) {
2240++ g_warning ("tried to add the network source but the stream was null - fail ?!");
2241++ g_free (port_name);
2242++ g_free (origin);
2243++ g_free (description);
2244++ return;
2245++ }
2246++ icon = gvc_mixer_stream_get_gicon (stream);
2247++ }
2248++ else
2249++ icon = gvc_mixer_card_get_gicon (card);
2250++
2251++ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
2252++ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
2253++
2254++ gtk_list_store_set (GTK_LIST_STORE (model),
2255++ &iter,
2256++ NAME_COLUMN, description,
2257++ DEVICE_COLUMN, origin,
2258++ ACTIVE_COLUMN, FALSE,
2259++ ICON_COLUMN, icon,
2260++ ID_COLUMN, gvc_mixer_ui_device_get_id (input),
2261++ SPEAKERS_COLUMN,origin,
2262++ -1);
2263++
2264++ if (icon != NULL)
2265++ g_object_unref (icon);
2266++
2267++ // TODO check this.
2268++ /*g_signal_connect (output,
2269++ "notify::description",
2270++ G_CALLBACK (on_output_description_notify),
2271++ dialog);*/
2272++
2273++ g_free (port_name);
2274++ g_free (origin);
2275++ g_free (description);
2276++}
2277++
2278++static void
2279++add_output_ui_entry (GvcMixerDialog *dialog,
2280++ GvcMixerUIDevice *output)
2281++{
2282++ g_debug ("\n Add output ui entry with id : %u \n",
2283++ gvc_mixer_ui_device_get_id (output));
2284++
2285++ gchar *sink_port_name;
2286++ gchar *origin;
2287++ gchar *description;
2288++ gboolean active;
2289++ gboolean available;
2290++ gint sink_stream_id;
2291++ GvcMixerCard *card;
2292++
2293++ g_object_get (G_OBJECT (output),
2294++ "stream-id", &sink_stream_id,
2295++ "card", &card,
2296++ "origin", &origin,
2297++ "description", &description,
2298++ "port-name", &sink_port_name,
2299++ "port-available", &available,
2300++ NULL);
2301++
2302++ GtkTreeModel *model;
2303++ GtkTreeIter iter;
2304++ const GvcChannelMap *map;
2305++ GIcon *icon;
2306++
2307++ if (card == NULL) {
2308++ g_debug ("just detected a network sink");
2309++
2310++ GvcMixerStream *stream;
2311++ stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, output);
2312++ if (stream == NULL) {
2313++ g_warning ("tried to add the network sink but the stream was null - fail ?!");
2314++ g_free (sink_port_name);
2315++ g_free (origin);
2316++ g_free (description);
2317++ return;
2318++ }
2319++ icon = gvc_mixer_stream_get_gicon (stream);
2320++ }
2321++ else
2322++ icon = gvc_mixer_card_get_gicon (card);
2323++
2324++
2325++ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
2326++ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
2327++
2328++ gtk_list_store_set (GTK_LIST_STORE (model),
2329++ &iter,
2330++ NAME_COLUMN, description,
2331++ DEVICE_COLUMN, origin,
2332++ ACTIVE_COLUMN, FALSE,
2333++ ICON_COLUMN, icon,
2334++ ID_COLUMN, gvc_mixer_ui_device_get_id (output),
2335++ SPEAKERS_COLUMN,origin,
2336++ -1);
2337++
2338++ if (icon != NULL)
2339++ g_object_unref (icon);
2340++
2341++ // TODO check this.
2342++ /*g_signal_connect (output,
2343++ "notify::description",
2344++ G_CALLBACK (on_output_description_notify),
2345++ dialog);*/
2346++
2347++ g_free (sink_port_name);
2348++ g_free (origin);
2349++ g_free (description);
2350++}
2351++
2352++static void
2353++on_control_output_added (GvcMixerControl *control,
2354++ guint id,
2355++ GvcMixerDialog *dialog)
2356++{
2357++ GvcMixerUIDevice* out = NULL;
2358++ out = gvc_mixer_control_lookup_output_id (control, id);
2359++
2360++ if (out == NULL) {
2361++ g_warning ("on_control_output_added - tried to fetch an output of id %u but got nothing", id);
2362++ return;
2363++ }
2364++
2365++ add_output_ui_entry (dialog, out);
2366++}
2367++
2368++static void
2369++on_control_active_output_update (GvcMixerControl *control,
2370++ guint id,
2371++ GvcMixerDialog *dialog)
2372++{
2373++ GvcMixerUIDevice* out = NULL;
2374++ out = gvc_mixer_control_lookup_output_id (control, id);
2375++
2376++ if (out == NULL) {
2377++ g_warning ("\n on_control_active_output_update - tried to fetch an output of id %u but got nothing", id);
2378++ return;
2379++ }
2380++ active_output_update (dialog, out);
2381++}
2382++
2383++static void
2384++on_control_active_input_update (GvcMixerControl *control,
2385++ guint id,
2386++ GvcMixerDialog *dialog)
2387++{
2388++ GvcMixerUIDevice* in = NULL;
2389++ in = gvc_mixer_control_lookup_input_id (control, id);
2390++
2391++ if (in == NULL) {
2392++ g_warning ("on_control_active_input_update - tried to fetch an input of id %u but got nothing", id);
2393++ return;
2394++ }
2395++ active_input_update (dialog, in);
2396++}
2397++
2398++static void
2399++on_control_input_added (GvcMixerControl *control,
2400++ guint id,
2401++ GvcMixerDialog *dialog)
2402++{
2403++ GvcMixerUIDevice* in = NULL;
2404++ in = gvc_mixer_control_lookup_input_id (control, id);
2405++
2406++ if (in == NULL) {
2407++ g_warning ("on_control_input_added - tried to fetch an input of id %u but got nothing", id);
2408++ return;
2409++ }
2410++ add_input_ui_entry (dialog, in);
2411++}
2412++
2413++static void
2414++on_control_output_removed (GvcMixerControl *control,
2415++ guint id,
2416++ GvcMixerDialog *dialog)
2417++{
2418++ GtkWidget *bar;
2419++ gboolean found;
2420++ GtkTreeIter iter;
2421++ GtkTreeModel *model;
2422++
2423++ GvcMixerUIDevice* out = NULL;
2424++ out = gvc_mixer_control_lookup_output_id (control, id);
2425++
2426++ gint sink_stream_id;
2427++
2428++ g_object_get (G_OBJECT (out),
2429++ "stream-id", &sink_stream_id,
2430++ NULL);
2431++
2432++ g_debug ("Remove output from dialog \n id : %u \n sink stream id : %i \n",
2433++ id,
2434++ sink_stream_id);
2435++
2436++ /* remove from any models */
2437++ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
2438++ found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
2439++ if (found) {
2440++ gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
2441++ }
2442++}
2443++
2444++
2445++
2446++static void
2447++on_control_input_removed (GvcMixerControl *control,
2448++ guint id,
2449++ GvcMixerDialog *dialog)
2450++{
2451++ GtkWidget *bar;
2452++ gboolean found;
2453++ GtkTreeIter iter;
2454++ GtkTreeModel *model;
2455++
2456++ GvcMixerUIDevice* in = NULL;
2457++ in = gvc_mixer_control_lookup_input_id (control, id);
2458++
2459++ gint stream_id;
2460++
2461++ g_object_get (G_OBJECT (in),
2462++ "stream-id", &stream_id,
2463++ NULL);
2464++
2465++ g_debug ("Remove input from dialog \n id : %u \n stream id : %i \n",
2466++ id,
2467++ stream_id);
2468++
2469++ /* remove from any models */
2470++ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
2471++ found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
2472++ if (found) {
2473++ gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
2474++ }
2475++}
2476++
2477++static void
2478++_gtk_label_make_bold (GtkLabel *label)
2479++{
2480++ PangoFontDescription *font_desc;
2481++
2482++ font_desc = pango_font_description_new ();
2483++
2484++ pango_font_description_set_weight (font_desc,
2485++ PANGO_WEIGHT_BOLD);
2486++
2487++ /* This will only affect the weight of the font, the rest is
2488++ * from the current state of the widget, which comes from the
2489++ * theme or user prefs, since the font desc only has the
2490++ * weight flag turned on.
2491++ */
2492++ gtk_widget_modify_font (GTK_WIDGET (label), font_desc);
2493++
2494++ pango_font_description_free (font_desc);
2495++}
2496++
2497++
2498++static void
2499++on_input_selection_changed (GtkTreeSelection *selection,
2500++ GvcMixerDialog *dialog)
2501++{
2502++ GtkTreeModel *model;
2503++ GtkTreeIter iter;
2504++ gboolean toggled;
2505++ guint id;
2506++
2507++ if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) {
2508++ g_debug ("Could not get default input from selection");
2509++ return;
2510++ }
2511++
2512++ gtk_tree_model_get (model, &iter,
2513++ ID_COLUMN, &id,
2514++ ACTIVE_COLUMN, &toggled,
2515++ -1);
2516++
2517++ toggled ^= 1;
2518++ GvcMixerUIDevice *input;
2519++ //g_debug ("on_input_selection_changed - try swap to input with id %u", id);
2520++ input = gvc_mixer_control_lookup_input_id (dialog->priv->mixer_control, id);
2521++
2522++ if (input == NULL) {
2523++ g_warning ("on_input_selection_changed - Unable to find input with id: %u", id);
2524++ return;
2525++ }
2526++
2527++ gvc_mixer_control_change_input (dialog->priv->mixer_control, input);
2528++}
2529++
2530++static void
2531++on_output_selection_changed (GtkTreeSelection *selection,
2532++ GvcMixerDialog *dialog)
2533++{
2534++ GtkTreeModel *model;
2535++ GtkTreeIter iter;
2536++ gboolean active;
2537++ guint id;
2538++
2539++ if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) {
2540++ g_debug ("Could not get default output from selection");
2541++ return;
2542++ }
2543++
2544++ gtk_tree_model_get (model, &iter,
2545++ ID_COLUMN, &id,
2546++ ACTIVE_COLUMN, &active,
2547++ -1);
2548++
2549++ g_debug ("\n\n on_output_selection_changed - active %i \n\n", active);
2550++ if (active){
2551++ return;
2552++ }
2553++
2554++ GvcMixerUIDevice *output;
2555++ g_debug ("\n on_output_selection_changed - try swap to output with id %u", id);
2556++ output = gvc_mixer_control_lookup_output_id (dialog->priv->mixer_control, id);
2557++
2558++ if (output == NULL) {
2559++ g_warning ("on_output_selection_changed - Unable to find output with id: %u", id);
2560++ return;
2561++ }
2562++
2563++ gvc_mixer_control_change_output (dialog->priv->mixer_control, output);
2564++}
2565++
2566++static void
2567++name_to_text (GtkTreeViewColumn *column,
2568++ GtkCellRenderer *cell,
2569++ GtkTreeModel *model,
2570++ GtkTreeIter *iter,
2571++ gpointer user_data)
2572++{
2573++ char *name, *mapping;
2574++
2575++ gtk_tree_model_get(model, iter,
2576++ NAME_COLUMN, &name,
2577++ SPEAKERS_COLUMN, &mapping,
2578++ -1);
2579++
2580++ if (mapping == NULL) {
2581++ g_object_set (cell, "text", name, NULL);
2582++ } else {
2583++ char *str;
2584++
2585++ str = g_strdup_printf ("%s\n<i>%s</i>",
2586++ name, mapping);
2587++ g_object_set (cell, "markup", str, NULL);
2588++ g_free (str);
2589++ }
2590++
2591++ g_free (name);
2592++ g_free (mapping);
2593++}
2594++
2595++static GtkWidget *
2596++create_stream_treeview (GvcMixerDialog *dialog,
2597++ GCallback on_selection_changed)
2598++{
2599++ GtkWidget *treeview;
2600++ GtkListStore *store;
2601++ GtkCellRenderer *renderer;
2602++ GtkTreeViewColumn *column;
2603++ GtkTreeSelection *selection;
2604++
2605++ treeview = gtk_tree_view_new ();
2606++ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
2607++
2608++ store = gtk_list_store_new (NUM_COLUMNS,
2609++ G_TYPE_STRING,
2610++ G_TYPE_STRING,
2611++ G_TYPE_BOOLEAN,
2612++ G_TYPE_UINT,
2613++ G_TYPE_STRING,
2614++ G_TYPE_ICON);
2615++ gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
2616++ GTK_TREE_MODEL (store));
2617++
2618++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
2619++ gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
2620++
2621++ column = gtk_tree_view_column_new ();
2622++ gtk_tree_view_column_set_title (column, _("Name"));
2623++ renderer = gtk_cell_renderer_pixbuf_new ();
2624++ gtk_tree_view_column_pack_start (column, renderer, FALSE);
2625++ g_object_set (G_OBJECT (renderer), "stock-size", GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
2626++ gtk_tree_view_column_set_attributes (column, renderer,
2627++ "gicon", ICON_COLUMN,
2628++ NULL);
2629++
2630++ renderer = gtk_cell_renderer_text_new ();
2631++ gtk_tree_view_column_pack_start (column, renderer, TRUE);
2632++ gtk_tree_view_column_set_cell_data_func (column, renderer,
2633++ name_to_text, NULL, NULL);
2634++ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
2635++
2636++ g_signal_connect ( selection, "changed",
2637++ on_selection_changed, dialog);
2638++#if 0
2639++ renderer = gtk_cell_renderer_text_new ();
2640++ column = gtk_tree_view_column_new_with_attributes (_("Device"),
2641++ renderer,
2642++ "text", DEVICE_COLUMN,
2643++ NULL);
2644++ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
2645++#endif
2646++ return treeview;
2647++}
2648++
2649++static void
2650++on_profile_changed (GvcComboBox *widget,
2651++ const char *profile,
2652++ gpointer user_data)
2653++{
2654++ GvcMixerCard *card;
2655++
2656++ card = g_object_get_data (G_OBJECT (widget), "card");
2657++ if (card == NULL) {
2658++ g_warning ("Could not find card for combobox");
2659++ return;
2660++ }
2661++
2662++ g_debug ("Profile changed to %s for card %s", profile,
2663++ gvc_mixer_card_get_name (card));
2664++
2665++ gvc_mixer_card_change_profile (card, profile);
2666++}
2667++
2668++static void
2669++on_test_speakers_clicked (GtkButton *widget,
2670++ gpointer user_data)
2671++{
2672++ GvcMixerDialog *dialog = GVC_MIXER_DIALOG (user_data);
2673++ GtkTreeModel *model;
2674++ GtkTreeIter iter;
2675++ gint active_output = GVC_MIXER_UI_DEVICE_INVALID;
2676++
2677++ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
2678++
2679++ if (gtk_tree_model_get_iter_first (model, &iter) == FALSE){
2680++ g_warning ("The tree is empty => we have no device to test speakers with return");
2681++ return;
2682++ }
2683++
2684++ do {
2685++ gboolean is_selected = FALSE ;
2686++ gint id;
2687++
2688++ gtk_tree_model_get (model, &iter,
2689++ ID_COLUMN, &id,
2690++ ACTIVE_COLUMN, &is_selected,
2691++ -1);
2692++
2693++ if (is_selected) {
2694++ active_output = id;
2695++ break;
2696++ }
2697++
2698++ }while (gtk_tree_model_iter_next (model, &iter));
2699++
2700++ if (active_output == GVC_MIXER_UI_DEVICE_INVALID) {
2701++ g_warning ("Cant find the active output from the UI");
2702++ return;
2703++ }
2704++
2705++ GvcMixerUIDevice *output;
2706++ output = gvc_mixer_control_lookup_output_id (dialog->priv->mixer_control, (guint)active_output);
2707++ gint stream_id = gvc_mixer_ui_device_get_stream_id(output);
2708++
2709++ if (stream_id == GVC_MIXER_UI_DEVICE_INVALID)
2710++ return;
2711++
2712++ g_debug ("Test the speakers on the %s", gvc_mixer_ui_device_get_description (output));
2713++
2714++ GvcMixerStream *stream;
2715++ GvcMixerCardProfile *profile;
2716++ GtkWidget *d, *speaker_test, *container;
2717++ char *title;
2718++
2719++ stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, stream_id);
2720++ if (stream == NULL) {
2721++ g_debug ("Stream/sink not found");
2722++ return;
2723++ }
2724++ title = g_strdup_printf (_("Speaker Testing for %s"), gvc_mixer_ui_device_get_description (output));
2725++ d = gtk_dialog_new_with_buttons (title,
2726++ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (widget))),
2727++ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
2728++ GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
2729++ NULL);
2730++ gtk_window_set_has_resize_grip (GTK_WINDOW (d), FALSE);
2731++
2732++ g_free (title);
2733++ speaker_test = gvc_speaker_test_new (dialog->priv->mixer_control,
2734++ stream);
2735++ gtk_widget_show (speaker_test);
2736++ container = gtk_dialog_get_content_area (GTK_DIALOG (d));
2737++ gtk_container_add (GTK_CONTAINER (container), speaker_test);
2738++
2739++ gtk_dialog_run (GTK_DIALOG (d));
2740++ gtk_widget_destroy (d);
2741++}
2742++
2743++static GObject *
2744++gvc_mixer_dialog_constructor (GType type,
2745++ guint n_construct_properties,
2746++ GObjectConstructParam *construct_params)
2747++{
2748++ GObject *object;
2749++ GvcMixerDialog *self;
2750++ GtkWidget *main_vbox;
2751++ GtkWidget *label;
2752++ GtkWidget *alignment;
2753++ GtkWidget *alignment_settings_box;
2754++ GtkWidget *settings_box;
2755++ GtkWidget *box;
2756++ GtkWidget *sbox;
2757++ GtkWidget *ebox;
2758++ GtkWidget *test_sound_box;
2759++ GSList *streams;
2760++ GSList *cards;
2761++ GSList *l;
2762++ GvcMixerStream *stream;
2763++ GvcMixerCard *card;
2764++ GtkTreeSelection *selection;
2765++
2766++ object = G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->constructor (type, n_construct_properties, construct_params);
2767++
2768++ self = GVC_MIXER_DIALOG (object);
2769++
2770++ main_vbox = GTK_WIDGET (self);
2771++ gtk_box_set_spacing (GTK_BOX (main_vbox), 2);
2772++
2773++ gtk_container_set_border_width (GTK_CONTAINER (self), 3);
2774++
2775++ self->priv->output_stream_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
2776++ alignment = gtk_alignment_new (0, 0, 1, 1);
2777++ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 0, 0);
2778++ gtk_container_add (GTK_CONTAINER (alignment), self->priv->output_stream_box);
2779++ gtk_box_pack_start (GTK_BOX (main_vbox),
2780++ alignment,
2781++ FALSE, FALSE, 0);
2782++
2783++ self->priv->notebook = gtk_notebook_new ();
2784++ gtk_box_pack_start (GTK_BOX (main_vbox),
2785++ self->priv->notebook,
2786++ TRUE, TRUE, 0);
2787++ gtk_container_set_border_width (GTK_CONTAINER (self->priv->notebook), 5);
2788++
2789++ /* Output page */
2790++ self->priv->output_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
2791++ gtk_container_set_border_width (GTK_CONTAINER (self->priv->output_box), 12);
2792++ label = gtk_label_new (_("Output"));
2793++ gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
2794++ self->priv->output_box,
2795++ label);
2796++
2797++ box = gtk_frame_new (_("Play sound through"));
2798++ gtk_widget_set_size_request (GTK_WIDGET (box), 310, -1);
2799++ label = gtk_frame_get_label_widget (GTK_FRAME (box));
2800++ _gtk_label_make_bold (GTK_LABEL (label));
2801++ gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
2802++ gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
2803++ gtk_box_pack_start (GTK_BOX (self->priv->output_box), box, FALSE, TRUE, 0);
2804++
2805++ alignment = gtk_alignment_new (0, 0, 1, 1);
2806++ gtk_container_add (GTK_CONTAINER (box), alignment);
2807++ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 10, 5, 0, 15);
2808++
2809++ self->priv->output_treeview = create_stream_treeview (self,
2810++ G_CALLBACK (on_output_selection_changed));
2811++ gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->output_treeview);
2812++
2813++ box = gtk_scrolled_window_new (NULL, NULL);
2814++ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (box),
2815++ GTK_POLICY_NEVER,
2816++ GTK_POLICY_AUTOMATIC);
2817++ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (box),
2818++ GTK_SHADOW_IN);
2819++ gtk_container_add (GTK_CONTAINER (box), self->priv->output_treeview);
2820++ gtk_container_add (GTK_CONTAINER (alignment), box);
2821++
2822++ self->priv->selected_output_label = gtk_label_new (_("Settings for the selected device"));
2823++ gtk_widget_set_halign (self->priv->selected_output_label, GTK_ALIGN_START);
2824++ gtk_widget_set_valign (self->priv->selected_output_label, GTK_ALIGN_START);
2825++ gtk_misc_set_padding (GTK_MISC (self->priv->selected_output_label), 0, 0);
2826++ _gtk_label_make_bold (GTK_LABEL (self->priv->selected_output_label));
2827++ settings_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2828++ alignment_settings_box = gtk_alignment_new (0, 0, 1, 1);
2829++ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment_settings_box), 7, 0, 0, 0);
2830++ self->priv->output_settings_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2831++ gtk_container_add (GTK_CONTAINER (alignment_settings_box), self->priv->output_settings_box);
2832++
2833++ gtk_box_pack_start (GTK_BOX (self->priv->output_box),
2834++ settings_box,
2835++ FALSE,
2836++ FALSE,
2837++ 0);
2838++ gtk_box_pack_start (GTK_BOX (settings_box),
2839++ self->priv->selected_output_label,
2840++ FALSE,
2841++ FALSE,
2842++ 0);
2843++ gtk_box_pack_start (GTK_BOX (settings_box),
2844++ alignment_settings_box,
2845++ FALSE,
2846++ FALSE,
2847++ 0);
2848++
2849++ self->priv->output_balance_bar = gvc_balance_bar_new (BALANCE_TYPE_RL);
2850++ if (self->priv->size_group != NULL) {
2851++ gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (self->priv->output_balance_bar),
2852++ self->priv->size_group,
2853++ FALSE);
2854++ }
2855++ gtk_box_pack_start (GTK_BOX (self->priv->output_settings_box),
2856++ self->priv->output_balance_bar,
2857++ FALSE, FALSE, 3);
2858++ gtk_widget_show (self->priv->output_balance_bar);
2859++
2860++ self->priv->output_fade_bar = gvc_balance_bar_new (BALANCE_TYPE_FR);
2861++ if (self->priv->size_group != NULL) {
2862++ gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (self->priv->output_fade_bar),
2863++ self->priv->size_group,
2864++ FALSE);
2865++ }
2866++ gtk_box_pack_start (GTK_BOX (self->priv->output_settings_box),
2867++ self->priv->output_fade_bar,
2868++ FALSE, FALSE, 3);
2869++ gtk_widget_show (self->priv->output_fade_bar);
2870++
2871++ self->priv->output_lfe_bar = gvc_balance_bar_new (BALANCE_TYPE_LFE);
2872++ if (self->priv->size_group != NULL) {
2873++ gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (self->priv->output_lfe_bar),
2874++ self->priv->size_group,
2875++ FALSE);
2876++ }
2877++ gtk_box_pack_start (GTK_BOX (self->priv->output_settings_box),
2878++ self->priv->output_lfe_bar,
2879++ FALSE, FALSE, 3);
2880++ gtk_widget_show (self->priv->output_lfe_bar);
2881++
2882++ /* Creating a box and try to deal using the same size group. */
2883++ test_sound_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2884++ gtk_box_pack_end (GTK_BOX (self->priv->output_settings_box),
2885++ test_sound_box,
2886++ FALSE,
2887++ FALSE,
2888++ 5);
2889++
2890++ sbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2891++ gtk_box_pack_start (GTK_BOX (test_sound_box),
2892++ sbox,
2893++ FALSE, FALSE, 0);
2894++
2895++ label = gtk_label_new (_("Test:"));
2896++ gtk_box_pack_start (GTK_BOX (sbox),
2897++ label,
2898++ FALSE, FALSE, 0);
2899++ if (self->priv->size_group != NULL)
2900++ gtk_size_group_add_widget (self->priv->size_group, sbox);
2901++
2902++ self->priv->test_output_button = gtk_button_new_with_label (_("Test Sound"));
2903++
2904++ /* FIXME: I am getting mental with all these hardcoded padding values,
2905++ * Here 8 works fine, not sure why. */
2906++ gtk_box_pack_start (GTK_BOX (test_sound_box),
2907++ self->priv->test_output_button,
2908++ TRUE, TRUE, 8);
2909++
2910++ /* Is this needed */
2911++ if (self->priv->size_group != NULL)
2912++ gtk_size_group_add_widget (self->priv->size_group, self->priv->test_output_button);
2913++
2914++ gtk_widget_show (test_sound_box);
2915++
2916++ //gtk_container_add (GTK_CONTAINER (box), self->priv->output_settings_box);
2917++ g_signal_connect (self->priv->test_output_button,
2918++ "released",
2919++ G_CALLBACK (on_test_speakers_clicked),
2920++ self);
2921++
2922++ /* Input page */
2923++ self->priv->input_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
2924++ gtk_container_set_border_width (GTK_CONTAINER (self->priv->input_box), 12);
2925++ label = gtk_label_new (_("Input"));
2926++ gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
2927++ self->priv->input_box,
2928++ label);
2929++ box = gtk_frame_new (_("Record sound from"));
2930++ gtk_widget_set_size_request (GTK_WIDGET (box), 310, -1);
2931++ label = gtk_frame_get_label_widget (GTK_FRAME (box));
2932++ _gtk_label_make_bold (GTK_LABEL (label));
2933++ gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
2934++ gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
2935++ gtk_box_pack_start (GTK_BOX (self->priv->input_box), box, FALSE, TRUE, 0);
2936++
2937++ alignment = gtk_alignment_new (0, 0, 1, 1);
2938++ gtk_container_add (GTK_CONTAINER (box), alignment);
2939++ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 10, 5, 0, 15);
2940++
2941++ self->priv->input_treeview = create_stream_treeview (self,
2942++ G_CALLBACK (on_input_selection_changed));
2943++ gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->input_treeview);
2944++
2945++ box = gtk_scrolled_window_new (NULL, NULL);
2946++ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (box),
2947++ GTK_POLICY_NEVER,
2948++ GTK_POLICY_AUTOMATIC);
2949++ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (box),
2950++ GTK_SHADOW_IN);
2951++ gtk_container_add (GTK_CONTAINER (box), self->priv->input_treeview);
2952++ gtk_container_add (GTK_CONTAINER (alignment), box);
2953++
2954++ self->priv->selected_input_label = gtk_label_new (_("Settings for the selected device"));
2955++ gtk_widget_set_halign (self->priv->selected_input_label, GTK_ALIGN_START);
2956++ _gtk_label_make_bold (GTK_LABEL (self->priv->selected_input_label));
2957++
2958++ self->priv->input_settings_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2959++ gtk_box_pack_start (GTK_BOX (self->priv->input_box),
2960++ self->priv->input_settings_box,
2961++ FALSE,
2962++ FALSE,
2963++ 0);
2964++ gtk_box_pack_start (GTK_BOX (self->priv->input_settings_box),
2965++ self->priv->selected_input_label,
2966++ FALSE,
2967++ FALSE,
2968++ 0);
2969++
2970++ self->priv->input_bar = create_bar (self, FALSE, TRUE);
2971++ gvc_channel_bar_set_name (GVC_CHANNEL_BAR (self->priv->input_bar),
2972++ _("_Input volume:"));
2973++ gvc_channel_bar_set_low_icon_name (GVC_CHANNEL_BAR (self->priv->input_bar),
2974++ "audio-input-microphone-low-symbolic");
2975++ gvc_channel_bar_set_high_icon_name (GVC_CHANNEL_BAR (self->priv->input_bar),
2976++ "audio-input-microphone-high-symbolic");
2977++ gtk_widget_set_sensitive (self->priv->input_bar, FALSE);
2978++
2979++ if (self->priv->size_group != NULL) {
2980++ gvc_channel_bar_set_size_group (GVC_CHANNEL_BAR (self->priv->input_bar),
2981++ self->priv->size_group,
2982++ FALSE);
2983++ }
2984++
2985++ gtk_box_pack_start (GTK_BOX (self->priv->input_settings_box),
2986++ self->priv->input_bar,
2987++ FALSE, FALSE, 15);
2988++ gtk_widget_show (self->priv->input_bar);
2989++
2990++
2991++ /* Creating a box and try to deal using the same size group. */
2992++ GtkWidget *input_level_box;
2993++ input_level_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2994++ gtk_box_pack_start (GTK_BOX (self->priv->input_settings_box),
2995++ input_level_box,
2996++ FALSE,
2997++ FALSE,
2998++ 5);
2999++
3000++ sbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
3001++ gtk_box_pack_start (GTK_BOX (input_level_box),
3002++ sbox,
3003++ FALSE, FALSE, 0);
3004++
3005++ label = gtk_label_new (_("Input level:"));
3006++ gtk_box_pack_start (GTK_BOX (sbox),
3007++ label,
3008++ FALSE, FALSE, 0);
3009++ if (self->priv->size_group != NULL)
3010++ gtk_size_group_add_widget (self->priv->size_group, sbox);
3011++
3012++
3013++ self->priv->input_level_bar = gvc_level_bar_new ();
3014++ gvc_level_bar_set_orientation (GVC_LEVEL_BAR (self->priv->input_level_bar),
3015++ GTK_ORIENTATION_HORIZONTAL);
3016++ gvc_level_bar_set_scale (GVC_LEVEL_BAR (self->priv->input_level_bar),
3017++ GVC_LEVEL_SCALE_LINEAR);
3018++
3019++ gtk_box_pack_start (GTK_BOX (input_level_box),
3020++ self->priv->input_level_bar,
3021++ TRUE, TRUE, 0);
3022++
3023++ /* Effects page */
3024++ self->priv->sound_effects_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
3025++ gtk_container_set_border_width (GTK_CONTAINER (self->priv->sound_effects_box), 12);
3026++ label = gtk_label_new (_("Sound Effects"));
3027++ gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
3028++ self->priv->sound_effects_box,
3029++ label);
3030++
3031++ self->priv->effects_bar = create_bar (self, FALSE, TRUE);
3032++ gvc_channel_bar_set_name (GVC_CHANNEL_BAR (self->priv->effects_bar),
3033++ _("_Alert volume:"));
3034++ gtk_widget_set_sensitive (self->priv->effects_bar, FALSE);
3035++ gtk_box_pack_start (GTK_BOX (self->priv->sound_effects_box),
3036++ self->priv->effects_bar, FALSE, FALSE, 0);
3037++
3038++ self->priv->sound_theme_chooser = gvc_sound_theme_chooser_new ();
3039++ gtk_box_pack_start (GTK_BOX (self->priv->sound_effects_box),
3040++ self->priv->sound_theme_chooser,
3041++ TRUE, TRUE, 6);
3042++
3043++ /* Applications */
3044++ self->priv->applications_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
3045++ gtk_container_set_border_width (GTK_CONTAINER (self->priv->applications_box), 12);
3046++ label = gtk_label_new (_("Applications"));
3047++ gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
3048++ self->priv->applications_box,
3049++ label);
3050++ self->priv->no_apps_label = gtk_label_new (_("No application is currently playing or recording audio."));
3051++ gtk_box_pack_start (GTK_BOX (self->priv->applications_box),
3052++ self->priv->no_apps_label,
3053++ TRUE, TRUE, 0);
3054++
3055++ self->priv->output_stream_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
3056++ alignment = gtk_alignment_new (0, 0, 1, 1);
3057++ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 0, 0, 0);
3058++ gtk_container_add (GTK_CONTAINER (alignment), self->priv->output_stream_box);
3059++ gtk_box_pack_start (GTK_BOX (main_vbox),
3060++ alignment,
3061++ FALSE, FALSE, 0);
3062++ // Output volume
3063++ self->priv->output_bar = create_bar (self, FALSE, TRUE);
3064++ gvc_channel_bar_set_name (GVC_CHANNEL_BAR (self->priv->output_bar),
3065++ _("_Output volume:"));
3066++ gtk_widget_set_sensitive (self->priv->output_bar, FALSE);
3067++ gtk_widget_set_size_request (self->priv->output_bar, 460, -1);
3068++
3069++ gtk_box_pack_start (GTK_BOX (self->priv->output_stream_box),
3070++ self->priv->output_bar, TRUE, FALSE, 12);
3071++
3072++ gtk_widget_show_all (main_vbox);
3073++
3074++ g_signal_connect (self->priv->mixer_control,
3075++ "stream-added",
3076++ G_CALLBACK (on_control_stream_added),
3077++ self);
3078++ g_signal_connect (self->priv->mixer_control,
3079++ "stream-removed",
3080++ G_CALLBACK (on_control_stream_removed),
3081++ self);
3082++ g_signal_connect (self->priv->mixer_control,
3083++ "output-added",
3084++ G_CALLBACK (on_control_output_added),
3085++ self);
3086++ g_signal_connect (self->priv->mixer_control,
3087++ "output-removed",
3088++ G_CALLBACK (on_control_output_removed),
3089++ self);
3090++ g_signal_connect (self->priv->mixer_control,
3091++ "input-added",
3092++ G_CALLBACK (on_control_input_added),
3093++ self);
3094++ g_signal_connect (self->priv->mixer_control,
3095++ "input-removed",
3096++ G_CALLBACK (on_control_input_removed),
3097++ self);
3098++ return object;
3099++}
3100++
3101++static void
3102++gvc_mixer_dialog_dispose (GObject *object)
3103++{
3104++ GvcMixerDialog *dialog = GVC_MIXER_DIALOG (object);
3105++
3106++ g_clear_object (&dialog->priv->indicator_settings);
3107++
3108++ if (dialog->priv->mixer_control != NULL) {
3109++ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
3110++ on_control_output_added,
3111++ dialog);
3112++ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
3113++ on_control_output_removed,
3114++ dialog);
3115++ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
3116++ on_control_active_input_update,
3117++ dialog);
3118++ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
3119++ on_control_active_output_update,
3120++ dialog);
3121++ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
3122++ on_control_input_added,
3123++ dialog);
3124++ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
3125++ on_control_input_removed,
3126++ dialog);
3127++ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
3128++ on_control_stream_added,
3129++ dialog);
3130++ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
3131++ on_control_stream_removed,
3132++ dialog);
3133++ g_object_unref (dialog->priv->mixer_control);
3134++ dialog->priv->mixer_control = NULL;
3135++ }
3136++
3137++ if (dialog->priv->bars != NULL) {
3138++ g_hash_table_destroy (dialog->priv->bars);
3139++ dialog->priv->bars = NULL;
3140++ }
3141++
3142++ G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->dispose (object);
3143++}
3144++
3145++static void
3146++gvc_mixer_dialog_class_init (GvcMixerDialogClass *klass)
3147++{
3148++ GObjectClass *object_class = G_OBJECT_CLASS (klass);
3149++
3150++ object_class->constructor = gvc_mixer_dialog_constructor;
3151++ object_class->dispose = gvc_mixer_dialog_dispose;
3152++ object_class->finalize = gvc_mixer_dialog_finalize;
3153++ object_class->set_property = gvc_mixer_dialog_set_property;
3154++ object_class->get_property = gvc_mixer_dialog_get_property;
3155++
3156++ g_object_class_install_property (object_class,
3157++ PROP_MIXER_CONTROL,
3158++ g_param_spec_object ("mixer-control",
3159++ "mixer control",
3160++ "mixer control",
3161++ GVC_TYPE_MIXER_CONTROL,
3162++ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
3163++
3164++ g_type_class_add_private (klass, sizeof (GvcMixerDialogPrivate));
3165++}
3166++
3167++
3168++static void
3169++gvc_mixer_dialog_init (GvcMixerDialog *dialog)
3170++{
3171++ dialog->priv = GVC_MIXER_DIALOG_GET_PRIVATE (dialog);
3172++ dialog->priv->bars = g_hash_table_new (NULL, NULL);
3173++ dialog->priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3174++}
3175++
3176++static void
3177++gvc_mixer_dialog_finalize (GObject *object)
3178++{
3179++ GvcMixerDialog *mixer_dialog;
3180++
3181++ g_return_if_fail (object != NULL);
3182++ g_return_if_fail (GVC_IS_MIXER_DIALOG (object));
3183++
3184++ mixer_dialog = GVC_MIXER_DIALOG (object);
3185++
3186++ g_return_if_fail (mixer_dialog->priv != NULL);
3187++ G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->finalize (object);
3188++}
3189++
3190++GvcMixerDialog *
3191++gvc_mixer_dialog_new (GvcMixerControl *control)
3192++{
3193++ GObject *dialog;
3194++ dialog = g_object_new (GVC_TYPE_MIXER_DIALOG,
3195++ "mixer-control", control,
3196++ NULL);
3197++ return GVC_MIXER_DIALOG (dialog);
3198++}
3199++
3200++enum {
3201++ PAGE_OUTPUT,
3202++ PAGE_INPUT,
3203++ PAGE_EVENTS,
3204++ PAGE_APPLICATIONS
3205++};
3206++
3207++gboolean
3208++gvc_mixer_dialog_set_page (GvcMixerDialog *self,
3209++ const char *page)
3210++{
3211++ guint num;
3212++
3213++ g_return_val_if_fail (self != NULL, FALSE);
3214++
3215++ num = PAGE_OUTPUT;
3216++
3217++ if (g_str_equal (page, "effects"))
3218++ num = PAGE_EVENTS;
3219++ else if (g_str_equal (page, "input"))
3220++ num = PAGE_INPUT;
3221++ else if (g_str_equal (page, "output"))
3222++ num = PAGE_OUTPUT;
3223++ else if (g_str_equal (page, "applications"))
3224++ num = PAGE_APPLICATIONS;
3225++
3226++ gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook), num);
3227++
3228++ return TRUE;
3229++}
3230+Index: gnome-control-center-3.6.2/panels/sound-nua/gvc-mixer-dialog.h
3231+===================================================================
3232+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
3233++++ gnome-control-center-3.6.2/panels/sound-nua/gvc-mixer-dialog.h 2012-11-13 16:25:40.893717986 +0100
3234+@@ -0,0 +1,56 @@
3235++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3236++ *
3237++ * Copyright (C) 2008 Red Hat, Inc.
3238++ *
3239++ * This program is free software; you can redistribute it and/or modify
3240++ * it under the terms of the GNU General Public License as published by
3241++ * the Free Software Foundation; either version 2 of the License, or
3242++ * (at your option) any later version.
3243++ *
3244++ * This program is distributed in the hope that it will be useful,
3245++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3246++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3247++ * GNU General Public License for more details.
3248++ *
3249++ * You should have received a copy of the GNU General Public License
3250++ * along with this program; if not, write to the Free Software
3251++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
3252++ *
3253++ */
3254++
3255++#ifndef __GVC_MIXER_DIALOG_H
3256++#define __GVC_MIXER_DIALOG_H
3257++
3258++#include <glib-object.h>
3259++#include "gvc-mixer-control.h"
3260++
3261++G_BEGIN_DECLS
3262++
3263++#define GVC_TYPE_MIXER_DIALOG (gvc_mixer_dialog_get_type ())
3264++#define GVC_MIXER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_DIALOG, GvcMixerDialog))
3265++#define GVC_MIXER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_DIALOG, GvcMixerDialogClass))
3266++#define GVC_IS_MIXER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_DIALOG))
3267++#define GVC_IS_MIXER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_DIALOG))
3268++#define GVC_MIXER_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_DIALOG, GvcMixerDialogClass))
3269++
3270++typedef struct GvcMixerDialogPrivate GvcMixerDialogPrivate;
3271++
3272++typedef struct
3273++{
3274++ GtkVBox parent;
3275++ GvcMixerDialogPrivate *priv;
3276++} GvcMixerDialog;
3277++
3278++typedef struct
3279++{
3280++ GtkVBoxClass parent_class;
3281++} GvcMixerDialogClass;
3282++
3283++GType gvc_mixer_dialog_get_type (void);
3284++
3285++GvcMixerDialog * gvc_mixer_dialog_new (GvcMixerControl *control);
3286++gboolean gvc_mixer_dialog_set_page (GvcMixerDialog *dialog, const gchar* page);
3287++
3288++G_END_DECLS
3289++
3290++#endif /* __GVC_MIXER_DIALOG_H */
3291+Index: gnome-control-center-3.6.2/panels/sound/data/gnome-sound-panel.desktop.in.in
3292+===================================================================
3293+--- gnome-control-center-3.6.2.orig/panels/sound/data/gnome-sound-panel.desktop.in.in 2012-10-01 11:39:00.000000000 +0200
3294++++ gnome-control-center-3.6.2/panels/sound/data/gnome-sound-panel.desktop.in.in 2012-11-13 16:25:40.897717987 +0100
3295+@@ -7,7 +7,7 @@
3296+ Type=Application
3297+ StartupNotify=true
3298+ Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;
3299+-OnlyShowIn=GNOME;Unity;
3300++OnlyShowIn=GNOME;
3301+ X-GNOME-Bugzilla-Bugzilla=GNOME
3302+ X-GNOME-Bugzilla-Product=gnome-control-center
3303+ X-GNOME-Bugzilla-Component=sound
3304+Index: gnome-control-center-3.6.2/panels/universal-access/cc-ua-panel.c
3305+===================================================================
3306+--- gnome-control-center-3.6.2.orig/panels/universal-access/cc-ua-panel.c 2012-11-13 16:25:40.341717994 +0100
3307++++ gnome-control-center-3.6.2/panels/universal-access/cc-ua-panel.c 2012-11-13 16:25:40.897717987 +0100
3308+@@ -492,7 +492,10 @@
3309+ CcShell *shell;
3310+
3311+ shell = cc_panel_get_shell (CC_PANEL (panel));
3312+- cc_shell_set_active_panel_from_id (shell, "sound", NULL, NULL);
3313++ if (g_strcmp0 (g_getenv ("XDG_CURRENT_DESKTOP"), "Unity") == 0)
3314++ cc_shell_set_active_panel_from_id (shell, "sound-nua", NULL, NULL);
3315++ else
3316++ cc_shell_set_active_panel_from_id (shell, "sound", NULL, NULL);
3317+
3318+ return TRUE;
3319+ }
3320+Index: gnome-control-center-3.6.2/shell/gnome-control-center.c
3321+===================================================================
3322+--- gnome-control-center-3.6.2.orig/shell/gnome-control-center.c 2012-11-13 16:25:40.669717988 +0100
3323++++ gnome-control-center-3.6.2/shell/gnome-control-center.c 2012-11-13 16:25:40.897717987 +0100
3324+@@ -984,6 +984,10 @@
3325+
3326+ g_clear_pointer (&priv->current_panel_id, g_free);
3327+
3328++ if (!g_strcmp0 (g_getenv ("XDG_CURRENT_DESKTOP"), "Unity") &&
3329++ !g_strcmp0(start_id, "sound"))
3330++ start_id = "sound-nua";
3331++
3332+ /* clear any custom widgets */
3333+ _shell_remove_all_custom_widgets (priv);
3334+

Subscribers

People subscribed via source and target branches