Merge lp:~cjcurran/indicator-sound/one-big-refactor into lp:~indicator-applet-developers/indicator-sound/trunk_3

Proposed by Conor Curran
Status: Merged
Merged at revision: 116
Proposed branch: lp:~cjcurran/indicator-sound/one-big-refactor
Merge into: lp:~indicator-applet-developers/indicator-sound/trunk_3
Diff against target: 2787 lines (+1163/-1024)
23 files modified
src/Makefile.am (+6/-4)
src/common-defs.h (+21/-8)
src/dbus-menu-manager.c (+0/-234)
src/dbus-menu-manager.h (+0/-34)
src/dbus-shared-names.h (+3/-4)
src/indicator-sound.c (+159/-548)
src/indicator-sound.h (+0/-1)
src/metadata-widget.c (+0/-1)
src/mute-menu-item.c (+130/-0)
src/mute-menu-item.h (+59/-0)
src/pulse-manager.c (+29/-25)
src/pulse-manager.h (+0/-3)
src/slider-menu-item.c (+30/-20)
src/slider-menu-item.h (+6/-2)
src/sound-service-dbus.c (+239/-99)
src/sound-service-dbus.h (+11/-5)
src/sound-service.c (+5/-3)
src/sound-service.h (+0/-3)
src/sound-service.list (+0/-2)
src/sound-service.xml (+11/-25)
src/sound-state-manager.c (+388/-0)
src/sound-state-manager.h (+66/-0)
src/volume-widget.c (+0/-3)
To merge this branch: bzr merge lp:~cjcurran/indicator-sound/one-big-refactor
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+47584@code.launchpad.net

This proposal supersedes a proposal from 2011-01-26.

Description of the change

As the branch name suggests, this is a total overhaul of how the dbus communication and basic menuitems are handled. Code much tidier, encapsulated and sane. Indicator-sound.c is now very manageable.

The second part of this refactor will happen shortly and will focus on the pulsemanager.c

To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote : Posted in a previous version of this proposal

* In slider-menu-item.c the handle event function shouldn't need to ref and unref the variants. You have a dangling ref anyway, but just removing all ref/unref code will fix it.
* I'm unclear if set_root_menu_item does a ref on the menuitem or not. If it does, you need to unref it after calling the set function.
* sound_service_dbus_build_sound_menu leaks references to the items. That function needs to unref them. Probably should change DbusmenuMenuitem to initialially unowned, but that's too big of a change for now.

review: Needs Fixing
Revision history for this message
Ted Gould (ted) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/Makefile.am'
2--- src/Makefile.am 2011-01-11 10:41:33 +0000
3+++ src/Makefile.am 2011-01-26 20:58:59 +0000
4@@ -9,11 +9,13 @@
5 libsoundmenu_la_SOURCES = \
6 common-defs.h \
7 indicator-sound.h \
8+ indicator-sound.c \
9+ sound-state-manager.c \
10+ sound-state-manager.h \
11 transport-widget.c \
12 transport-widget.h \
13 metadata-widget.c \
14 metadata-widget.h \
15- indicator-sound.c \
16 title-widget.c \
17 title-widget.h \
18 volume-widget.c \
19@@ -87,15 +89,15 @@
20 common-defs.h \
21 sound-service.h \
22 sound-service.c \
23- dbus-menu-manager.c \
24- dbus-menu-manager.h \
25 pulse-manager.h \
26 pulse-manager.c \
27 sound-service-dbus.h \
28 sound-service-dbus.c \
29 slider-menu-item.h \
30 slider-menu-item.c \
31- gen-sound-service.xml.h \
32+ mute-menu-item.h \
33+ mute-menu-item.c \
34+ gen-sound-service.xml.h \
35 gen-sound-service.xml.c \
36 $(music_bridge_VALASOURCES:.vala=.c)
37
38
39=== modified file 'src/common-defs.h'
40--- src/common-defs.h 2010-12-09 11:36:33 +0000
41+++ src/common-defs.h 2011-01-26 20:58:59 +0000
42@@ -16,13 +16,21 @@
43 You should have received a copy of the GNU General Public License along
44 with this program. If not, see <http://www.gnu.org/licenses/>.
45 */
46-
47-
48-/* constants used for signals on the dbus. This file is shared between client and server implementation */
49-#define SIGNAL_SINK_INPUT_WHILE_MUTED "SinkInputWhileMuted"
50-#define SIGNAL_SINK_VOLUME_UPDATE "SinkVolumeUpdate"
51-#define SIGNAL_SINK_MUTE_UPDATE "SinkMuteUpdate"
52-#define SIGNAL_SINK_AVAILABLE_UPDATE "SinkAvailableUpdate"
53+#ifndef __COMMON_DEFS_H__
54+#define __COMMON_DEFS_H__
55+
56+
57+typedef enum {
58+ MUTED,
59+ ZERO_LEVEL,
60+ LOW_LEVEL,
61+ MEDIUM_LEVEL,
62+ HIGH_LEVEL,
63+ BLOCKED,
64+ UNAVAILABLE,
65+ AVAILABLE
66+}SoundState;
67+
68
69 #define DBUSMENU_PROPERTY_EMPTY -1
70
71@@ -30,6 +38,9 @@
72 #define DBUSMENU_VOLUME_MENUITEM_TYPE "x-canonical-ido-volume-type"
73 #define DBUSMENU_VOLUME_MENUITEM_LEVEL "x-canonical-ido-volume-level"
74
75+#define DBUSMENU_MUTE_MENUITEM_TYPE "x-canonical-sound-menu-mute-type"
76+#define DBUSMENU_MUTE_MENUITEM_VALUE "x-canonical-sound-menu-mute-value"
77+
78 #define DBUSMENU_TRANSPORT_MENUITEM_TYPE "x-canonical-sound-menu-player-transport-type"
79 #define DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE "x-canonical-sound-menu-player-transport-state"
80
81@@ -51,4 +62,6 @@
82
83 #define DBUSMENU_PLAYLISTS_MENUITEM_TYPE "x-canonical-sound-menu-player-playlists-type"
84 #define DBUSMENU_PLAYLISTS_MENUITEM_TITLE "x-canonical-sound-menu-player-playlists-title"
85-#define DBUSMENU_PLAYLISTS_MENUITEM_PLAYLISTS "x-canonical-sound-menu-player-playlists-playlists"
86\ No newline at end of file
87+#define DBUSMENU_PLAYLISTS_MENUITEM_PLAYLISTS "x-canonical-sound-menu-player-playlists-playlists"
88+
89+#endif
90
91=== removed file 'src/dbus-menu-manager.c'
92--- src/dbus-menu-manager.c 2011-01-11 16:30:56 +0000
93+++ src/dbus-menu-manager.c 1970-01-01 00:00:00 +0000
94@@ -1,234 +0,0 @@
95-/*
96-This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
97-Copyright 2010 Canonical Ltd.
98-
99-Authors:
100- Conor Curran <conor.curran@canonical.com>
101-
102-This program is free software: you can redistribute it and/or modify it
103-under the terms of the GNU General Public License version 3, as published
104-by the Free Software Foundation.
105-
106-This program is distributed in the hope that it will be useful, but
107-WITHOUT ANY WARRANTY; without even the implied warranties of
108-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
109-PURPOSE. See the GNU General Public License for more details.
110-
111-You should have received a copy of the GNU General Public License along
112-with this program. If not, see <http://www.gnu.org/licenses/>.
113-*/
114-
115-#include <unistd.h>
116-#include <glib/gi18n.h>
117-
118-#include <libdbusmenu-glib/server.h>
119-#include <libdbusmenu-glib/client.h>
120-
121-#include "dbus-menu-manager.h"
122-#include "sound-service-dbus.h"
123-#include "pulse-manager.h"
124-#include "slider-menu-item.h"
125-#include "common-defs.h"
126-
127-#include "dbus-shared-names.h"
128-
129-// DBUS items
130-static DbusmenuMenuitem *root_menuitem = NULL;
131-static DbusmenuMenuitem *mute_all_menuitem = NULL;
132-static SliderMenuItem *volume_slider_menuitem = NULL;
133-static SoundServiceDbus *dbus_interface = NULL;
134-
135-// PULSEAUDIO
136-static gboolean b_sink_available = FALSE;
137-static gboolean b_all_muted = FALSE;
138-static gboolean b_pulse_ready = FALSE;
139-static gboolean b_startup = TRUE;
140-static gdouble volume_percent = 0.0;
141-
142-static void set_global_mute_from_ui();
143-static gboolean idle_routine (gpointer data);
144-static void rebuild_sound_menu(DbusmenuMenuitem *root,
145- SoundServiceDbus *service);
146-static void refresh_menu();
147-
148-
149-/*-------------------------------------------------------------------------*/
150-// Public Methods
151-/*-------------------------------------------------------------------------*/
152-
153-/**
154-setup:
155-**/
156-DbusmenuMenuitem* dbus_menu_manager_setup()
157-{
158- root_menuitem = dbusmenu_menuitem_new();
159- g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem));
160-
161- g_idle_add(idle_routine, root_menuitem);
162-
163- dbus_interface = g_object_new(SOUND_SERVICE_DBUS_TYPE, NULL);
164-
165- DbusmenuServer *server = dbusmenu_server_new(INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH);
166- dbusmenu_server_set_root(server, root_menuitem);
167- establish_pulse_activities(dbus_interface);
168- return root_menuitem;
169-}
170-
171-void dbus_menu_manager_update_volume(gdouble volume)
172-{
173- GVariant* new_volume = g_variant_new_double(volume);
174- dbusmenu_menuitem_property_set_variant(DBUSMENU_MENUITEM(volume_slider_menuitem),
175- DBUSMENU_VOLUME_MENUITEM_LEVEL,
176- new_volume);
177-}
178-
179-
180-/**
181-update_pa_state:
182-**/
183-void dbus_menu_manager_update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_muted, gdouble percent)
184-{
185- b_sink_available = sink_available;
186- b_all_muted = sink_muted;
187- b_pulse_ready = pa_state;
188- volume_percent = percent;
189- g_debug("update pa state with state %i, availability of %i, mute value of %i and a volume percent is %f", pa_state, sink_available, sink_muted, volume_percent);
190- // Only rebuild the menu on start up...
191- if (b_startup == TRUE) {
192- rebuild_sound_menu(root_menuitem, dbus_interface);
193- b_startup = FALSE;
194- } else {
195- refresh_menu();
196- }
197- // Emit the signals after the menus are setup/torn down
198- // preserve ordering !
199- sound_service_dbus_update_sink_availability(dbus_interface, sink_available);
200- dbus_menu_manager_update_volume(percent);
201- sound_service_dbus_update_sink_mute(dbus_interface, sink_muted);
202- dbus_menu_manager_update_mute_ui(b_all_muted);
203-}
204-
205-/**
206-update_mute_ui:
207-'public' method allowing the pa manager to update the mute menu item.
208-**/
209-void dbus_menu_manager_update_mute_ui(gboolean incoming_mute_value)
210-{
211- b_all_muted = incoming_mute_value;
212- dbusmenu_menuitem_property_set(mute_all_menuitem,
213- DBUSMENU_MENUITEM_PROP_LABEL,
214- b_all_muted == FALSE ? _("Mute") : _("Unmute"));
215-}
216-
217-
218-/*-------------------------------------------------------------------------*/
219-// Private Methods
220-/*-------------------------------------------------------------------------*/
221-static void refresh_menu()
222-{
223- g_debug("in the refresh menu method");
224- if (b_sink_available == FALSE || b_pulse_ready == FALSE) {
225-
226- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem),
227- DBUSMENU_MENUITEM_PROP_ENABLED,
228- FALSE);
229- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem),
230- DBUSMENU_MENUITEM_PROP_VISIBLE,
231- FALSE);
232- dbusmenu_menuitem_property_set_bool(mute_all_menuitem,
233- DBUSMENU_MENUITEM_PROP_ENABLED,
234- FALSE);
235-
236- } else if (b_sink_available == TRUE && b_pulse_ready == TRUE) {
237-
238- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem),
239- DBUSMENU_MENUITEM_PROP_ENABLED,
240- TRUE);
241- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem),
242- DBUSMENU_MENUITEM_PROP_VISIBLE,
243- TRUE);
244- dbusmenu_menuitem_property_set_bool(mute_all_menuitem,
245- DBUSMENU_MENUITEM_PROP_ENABLED,
246- TRUE);
247- }
248-}
249-
250-
251-/**
252-idle_routine:
253-Something for glip mainloop to do when idle
254-**/
255-static gboolean idle_routine (gpointer data)
256-{
257- return FALSE;
258-}
259-
260-
261-
262-/**
263-show_sound_settings_dialog:
264-Bring up the gnome volume preferences dialog
265-**/
266-static void show_sound_settings_dialog (DbusmenuMenuitem *mi, gpointer user_data)
267-{
268- GError * error = NULL;
269- if (!g_spawn_command_line_async("gnome-volume-control --page=applications", &error) &&
270- !g_spawn_command_line_async("xfce4-mixer", &error))
271- {
272- g_warning("Unable to show dialog: %s", error->message);
273- g_error_free(error);
274- }
275-}
276-
277-/**
278-rebuild_sound_menu:
279-Build the DBus menu items, mute/unmute, slider, separator and sound preferences 'link'
280-**/
281-static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service)
282-{
283- // Mute button
284- mute_all_menuitem = dbusmenu_menuitem_new();
285- dbusmenu_menuitem_property_set(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, b_all_muted == FALSE ? _("Mute") : _("Unmute"));
286- g_signal_connect(G_OBJECT(mute_all_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(set_global_mute_from_ui), NULL);
287- dbusmenu_menuitem_property_set_bool(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, b_sink_available);
288-
289- // Slider
290- volume_slider_menuitem = slider_menu_item_new(b_sink_available, volume_percent);
291- dbusmenu_menuitem_child_append(root, mute_all_menuitem);
292- dbusmenu_menuitem_child_append(root, DBUSMENU_MENUITEM(volume_slider_menuitem));
293- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem),
294- DBUSMENU_MENUITEM_PROP_ENABLED,
295- b_sink_available && !b_all_muted);
296- g_debug("!!!!!!**in the rebuild sound menu - slider active = %i", b_sink_available && !b_all_muted);
297- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem),
298- DBUSMENU_MENUITEM_PROP_VISIBLE,
299- b_sink_available);
300- // Separator
301- DbusmenuMenuitem *separator = dbusmenu_menuitem_new();
302- dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
303- dbusmenu_menuitem_child_append(root, separator);
304-
305- // Sound preferences dialog
306- DbusmenuMenuitem *settings_mi = dbusmenu_menuitem_new();
307- dbusmenu_menuitem_property_set(settings_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Sound Preferences..."));
308-
309- //_("Sound Preferences..."));
310- dbusmenu_menuitem_child_append(root, settings_mi);
311- g_signal_connect(G_OBJECT(settings_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
312- G_CALLBACK(show_sound_settings_dialog), NULL);
313-}
314-
315-/**
316-set_global_mute_from_ui:
317-Callback for the dbusmenuitem button
318-**/
319-static void set_global_mute_from_ui()
320-{
321- b_all_muted = !b_all_muted;
322- toggle_global_mute(b_all_muted);
323- dbusmenu_menuitem_property_set(mute_all_menuitem,
324- DBUSMENU_MENUITEM_PROP_LABEL,
325- b_all_muted == FALSE ? _("Mute") : _("Unmute"));
326-}
327-
328-
329
330=== removed file 'src/dbus-menu-manager.h'
331--- src/dbus-menu-manager.h 2010-08-02 18:13:58 +0000
332+++ src/dbus-menu-manager.h 1970-01-01 00:00:00 +0000
333@@ -1,34 +0,0 @@
334-#ifndef __INCLUDE_DBUS_MENU_MANAGER_H__
335-#define __INCLUDE_DBUS_MENU_MANAGER_H__
336-
337-#include <libdbusmenu-glib/menuitem.h>
338-
339-/*
340-This handles the management of the dbusmeneu items.
341-Copyright 2010 Canonical Ltd.
342-
343-Authors:
344- Conor Curran <conor.curran@canonical.com>
345-
346-This program is free software: you can redistribute it and/or modify it
347-under the terms of the GNU General Public License version 3, as published
348-by the Free Software Foundation.
349-
350-This program is distributed in the hope that it will be useful, but
351-WITHOUT ANY WARRANTY; without even the implied warranties of
352-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
353-PURPOSE. See the GNU General Public License for more details.
354-
355-You should have received a copy of the GNU General Public License along
356-with this program. If not, see <http://www.gnu.org/licenses/>.
357-*/
358-
359-DbusmenuMenuitem* dbus_menu_manager_setup();
360-void dbus_menu_manager_teardown();
361-void dbus_menu_manager_update_volume(gdouble volume);
362-void dbus_menu_manager_update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_muted, gdouble current_vol);
363-// TODO update pa_state should incorporate the method below !
364-void dbus_menu_manager_update_mute_ui(gboolean incoming_mute_value);
365-
366-#endif
367-
368
369=== modified file 'src/dbus-shared-names.h'
370--- src/dbus-shared-names.h 2011-01-11 16:30:56 +0000
371+++ src/dbus-shared-names.h 2011-01-26 20:58:59 +0000
372@@ -23,16 +23,15 @@
373
374
375 #ifndef __DBUS_SHARED_NAMES_H__
376-#define __DBUS_SHARED_NAMES_H__ 1
377+#define __DBUS_SHARED_NAMES_H__
378
379 #define INDICATOR_SOUND_DBUS_NAME "com.canonical.indicators.sound"
380 #define INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH "/com/canonical/indicators/sound/menu"
381 #define INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH "/com/canonical/indicators/sound/service"
382 #define INDICATOR_SOUND_DBUS_INTERFACE "com.canonical.indicators.sound"
383 #define INDICATOR_SOUND_DBUS_VERSION 0
384-#define INDICATOR_SOUND_SIGNAL_SINK_INPUT_WHILE_MUTED "SinkInputWhileMuted"
385-#define INDICATOR_SOUND_SIGNAL_SINK_MUTE_UPDATE "SinkMuteUpdate"
386-#define INDICATOR_SOUND_SIGNAL_SINK_AVAILABLE_UPDATE "SinkAvailableUpdate"
387+
388+#define INDICATOR_SOUND_SIGNAL_STATE_UPDATE "SoundStateUpdate"
389
390
391 #endif /* __DBUS_SHARED_NAMES_H__ */
392
393=== modified file 'src/indicator-sound.c'
394--- src/indicator-sound.c 2011-01-11 23:18:47 +0000
395+++ src/indicator-sound.c 2011-01-26 20:58:59 +0000
396@@ -1,12 +1,8 @@
397 /*
398-A small wrapper utility to load indicators and put them as menu items
399-into the gnome-panel using it's applet interface.
400-
401 Copyright 2010 Canonical Ltd.
402
403 Authors:
404 Conor Curran <conor.curran@canonical.com>
405- Ted Gould <ted@canonical.com>
406
407 This program is free software: you can redistribute it and/or modify it
408 under the terms of the GNU General Public License version 3, as published
409@@ -20,6 +16,7 @@
410 You should have received a copy of the GNU General Public License along
411 with this program. If not, see <http://www.gnu.org/licenses/>.
412 */
413+
414 #include <math.h>
415 #include <glib.h>
416 #include <glib-object.h>
417@@ -40,6 +37,7 @@
418
419 #include "gen-sound-service.xml.h"
420 #include "common-defs.h"
421+#include "sound-state-manager.h"
422
423 typedef struct _IndicatorSoundPrivate IndicatorSoundPrivate;
424
425@@ -47,7 +45,8 @@
426 {
427 GtkWidget* volume_widget;
428 GList* transport_widgets_list;
429- GDBusProxy *dbus_proxy;
430+ GDBusProxy *dbus_proxy;
431+ SoundStateManager* state_manager;
432 };
433
434 #define INDICATOR_SOUND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_SOUND_TYPE, IndicatorSoundPrivate))
435@@ -67,18 +66,27 @@
436 static GtkLabel * get_label (IndicatorObject * io);
437 static GtkImage * get_icon (IndicatorObject * io);
438 static GtkMenu * get_menu (IndicatorObject * io);
439-static void indicator_sound_scroll (IndicatorObject* io, gint delta, IndicatorScrollDirection direction);
440+static void indicator_sound_scroll (IndicatorObject* io,
441+ gint delta,
442+ IndicatorScrollDirection direction);
443
444-//Slider related
445-static gboolean new_volume_slider_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
446+//key/moust event handlers
447 static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data);
448 static gboolean key_release_cb(GtkWidget* widget, GdkEventKey* event, gpointer data);
449-static void style_changed_cb(GtkWidget *widget, gpointer user_data);
450
451-//player widget realisation methods
452-static gboolean new_transport_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
453-static gboolean new_metadata_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
454-static gboolean new_title_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
455+//custom widget realisation methods
456+static gboolean new_volume_slider_widget (DbusmenuMenuitem * newitem,
457+ DbusmenuMenuitem * parent,
458+ DbusmenuClient * client);
459+static gboolean new_transport_widget (DbusmenuMenuitem * newitem,
460+ DbusmenuMenuitem * parent,
461+ DbusmenuClient * client);
462+static gboolean new_metadata_widget (DbusmenuMenuitem * newitem,
463+ DbusmenuMenuitem * parent,
464+ DbusmenuClient * client);
465+static gboolean new_title_widget (DbusmenuMenuitem * newitem,
466+ DbusmenuMenuitem * parent,
467+ DbusmenuClient * client);
468
469 // DBUS communication
470
471@@ -90,59 +98,6 @@
472 static void connection_changed (IndicatorServiceManager * sm,
473 gboolean connected,
474 gpointer userdata);
475-static void g_signal_cb ( GDBusProxy* proxy,
476- gchar* sender_name,
477- gchar* signal_name,
478- GVariant* parameters,
479- gpointer user_data);
480-
481-static void react_to_signal_sink_input_while_muted (gboolean value,
482- IndicatorSound* self);
483-static void react_to_signal_sink_mute_update (gboolean value,
484- IndicatorSound* self);
485-static void react_to_signal_sink_availability_update (gboolean value,
486- IndicatorSound* self);
487-static void fetch_state ( IndicatorSound* self );
488-
489-static void get_sink_mute_cb ( GObject *object,
490- GAsyncResult *res,
491- gpointer user_data );
492-
493-static void get_sink_availability_cb ( GObject *object,
494- GAsyncResult *res,
495- gpointer user_data );
496-
497-/****Volume States 'members' ***/
498-static void update_state(const gint state);
499-
500-static const gint STATE_MUTED = 0;
501-static const gint STATE_ZERO = 1;
502-static const gint STATE_LOW = 2;
503-static const gint STATE_MEDIUM = 3;
504-static const gint STATE_HIGH = 4;
505-static const gint STATE_MUTED_WHILE_INPUT = 5;
506-static const gint STATE_SINKS_NONE = 6;
507-
508-static GHashTable *volume_states = NULL;
509-static GtkImage *speaker_image = NULL;
510-static gint current_state = 0;
511-static gint previous_state = 0;
512-
513-static gboolean initial_mute ;
514-static gboolean device_available;
515-
516-static GtkIconSize design_team_size;
517-static gint blocked_id;
518-static gint animation_id;
519-
520-static GList * blocked_animation_list = NULL;
521-static GList * blocked_iter = NULL;
522-static void prepare_blocked_animation();
523-static gboolean fade_back_to_mute_image();
524-static gboolean start_animation();
525-static void reset_mute_blocking_animation();
526-static void free_the_animation_list();
527-
528
529 static void
530 indicator_sound_class_init (IndicatorSoundClass *klass)
531@@ -160,7 +115,6 @@
532 io_class->get_image = get_icon;
533 io_class->get_menu = get_menu;
534 io_class->scroll = indicator_sound_scroll;
535- design_team_size = gtk_icon_size_register("design-team-size", 22, 22);
536 }
537
538 static void
539@@ -169,39 +123,29 @@
540 self->service = NULL;
541 self->service = indicator_service_manager_new_version(INDICATOR_SOUND_DBUS_NAME,
542 INDICATOR_SOUND_DBUS_VERSION);
543-
544- prepare_state_machine();
545- prepare_blocked_animation();
546- animation_id = 0;
547- blocked_id = 0;
548- initial_mute = FALSE;
549- device_available = TRUE;
550
551 IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
552 priv->volume_widget = NULL;
553 priv->dbus_proxy = NULL;
554 GList* t_list = NULL;
555 priv->transport_widgets_list = t_list;
556+ priv->state_manager = g_object_new (SOUND_TYPE_STATE_MANAGER, NULL);
557
558- g_signal_connect(G_OBJECT(self->service),
559- INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE,
560- G_CALLBACK(connection_changed), self);
561+ g_signal_connect ( G_OBJECT(self->service),
562+ INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE,
563+ G_CALLBACK(connection_changed), self );
564 }
565
566 static void
567 indicator_sound_dispose (GObject *object)
568 {
569 IndicatorSound * self = INDICATOR_SOUND(object);
570+ IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
571
572 if (self->service != NULL) {
573 g_object_unref(G_OBJECT(self->service));
574 self->service = NULL;
575 }
576- g_hash_table_destroy(volume_states);
577-
578- free_the_animation_list();
579-
580- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (self));
581
582 g_list_free ( priv->transport_widgets_list );
583
584@@ -209,7 +153,6 @@
585 return;
586 }
587
588-
589 static void
590 indicator_sound_finalize (GObject *object)
591 {
592@@ -226,14 +169,9 @@
593 static GtkImage *
594 get_icon (IndicatorObject * io)
595 {
596- gchar* current_name = g_hash_table_lookup(volume_states,
597- GINT_TO_POINTER(current_state));
598- //g_debug("At start-up attempting to set the image to %s",
599- // current_name);
600- speaker_image = indicator_image_helper(current_name);
601- gtk_widget_show(GTK_WIDGET(speaker_image));
602-
603- return speaker_image;
604+ IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
605+ gtk_widget_show( GTK_WIDGET(sound_state_manager_get_current_icon (priv->state_manager)) );
606+ return sound_state_manager_get_current_icon (priv->state_manager);
607 }
608
609 /* Indicator based function to get the menu for the whole
610@@ -251,122 +189,15 @@
611 dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_TRANSPORT_MENUITEM_TYPE, new_transport_widget);
612 dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_METADATA_MENUITEM_TYPE, new_metadata_widget);
613 dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_TITLE_MENUITEM_TYPE, new_title_widget);
614- // register Key-press listening on the menu widget as the slider does not allow this.
615- g_signal_connect(menu, "key-press-event", G_CALLBACK(key_press_cb), io);
616- g_signal_connect(menu, "key-release-event", G_CALLBACK(key_release_cb), io);
617+ // Note: Not ideal but all key handling needs to be managed here and then
618+ // delegated to the appropriate widget.
619+ g_signal_connect (menu, "key-press-event", G_CALLBACK(key_press_cb), io);
620+ g_signal_connect (menu, "key-release-event", G_CALLBACK(key_release_cb), io);
621
622 return GTK_MENU(menu);
623 }
624
625 static void
626-free_the_animation_list()
627-{
628- if (blocked_animation_list != NULL) {
629- g_list_foreach (blocked_animation_list, (GFunc)g_object_unref, NULL);
630- g_list_free(blocked_animation_list);
631- blocked_animation_list = NULL;
632- }
633-}
634-
635-static gboolean
636-new_transport_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
637-{
638- g_debug("indicator-sound: new_transport_bar() called ");
639-
640- GtkWidget* bar = NULL;
641- IndicatorObject *io = NULL;
642-
643- g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
644- g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
645-
646- bar = transport_widget_new(newitem);
647- io = g_object_get_data (G_OBJECT (client), "indicator");
648- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
649- priv->transport_widgets_list = g_list_append ( priv->transport_widgets_list, bar );
650-
651- GtkMenuItem *menu_transport_bar = GTK_MENU_ITEM(bar);
652-
653- gtk_widget_show_all(bar);
654- dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, menu_transport_bar, parent);
655-
656- return TRUE;
657-}
658-
659-static gboolean
660-new_metadata_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
661-{
662- g_debug("indicator-sound: new_metadata_widget");
663-
664- GtkWidget* metadata = NULL;
665-
666- g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
667- g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
668-
669- metadata = metadata_widget_new (newitem);
670- GtkMenuItem *menu_metadata_widget = GTK_MENU_ITEM(metadata);
671-
672- gtk_widget_show_all(metadata);
673- dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, menu_metadata_widget, parent);
674-
675- return TRUE;
676-}
677-
678-static gboolean
679-new_title_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
680-{
681- g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
682- g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
683-
684- g_debug ("%s (\"%s\")", __func__, dbusmenu_menuitem_property_get(newitem, DBUSMENU_TITLE_MENUITEM_NAME));
685-
686- GtkWidget* title = NULL;
687-
688- title = title_widget_new (newitem);
689- GtkMenuItem *menu_title_widget = GTK_MENU_ITEM(title);
690-
691- gtk_widget_show_all(title);
692-
693- dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client),
694- newitem,
695- menu_title_widget, parent);
696- return TRUE;
697-}
698-
699-static gboolean
700-new_volume_slider_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
701-{
702- g_debug("indicator-sound: new_volume_slider_widget");
703-
704- GtkWidget* volume_widget = NULL;
705- IndicatorObject *io = NULL;
706-
707- g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
708- g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
709-
710- volume_widget = volume_widget_new (newitem);
711- io = g_object_get_data (G_OBJECT (client), "indicator");
712- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
713- priv->volume_widget = volume_widget;
714-
715- GtkWidget* ido_slider_widget = volume_widget_get_ido_slider(VOLUME_WIDGET(priv->volume_widget));
716-
717- g_signal_connect(ido_slider_widget, "style-set", G_CALLBACK(style_changed_cb), NULL);
718- gtk_widget_set_sensitive(ido_slider_widget,
719- !initial_mute);
720- gtk_widget_show_all(ido_slider_widget);
721-
722-
723- GtkMenuItem *menu_volume_item = GTK_MENU_ITEM(ido_slider_widget);
724- dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client),
725- newitem,
726- menu_volume_item,
727- parent);
728- fetch_state(INDICATOR_SOUND (io));
729- return TRUE;
730-}
731-
732-
733-static void
734 connection_changed (IndicatorServiceManager * sm,
735 gboolean connected,
736 gpointer user_data)
737@@ -377,7 +208,7 @@
738 GError *error = NULL;
739
740 if (connected == FALSE){
741- update_state (STATE_SINKS_NONE);
742+ sound_state_manager_deal_with_disconnect (priv->state_manager);
743 return;
744 //TODO: Gracefully handle disconnection
745 // do a timeout to wait for reconnection
746@@ -388,7 +219,14 @@
747 // we don't need to anything, gdbus takes care of the rest - bless.
748 // just fetch the state.
749 if (priv->dbus_proxy != NULL){
750- fetch_state (indicator);
751+ g_dbus_proxy_call ( priv->dbus_proxy,
752+ "GetSoundState",
753+ NULL,
754+ G_DBUS_CALL_FLAGS_NONE,
755+ -1,
756+ NULL,
757+ (GAsyncReadyCallback)sound_state_manager_get_state_cb,
758+ priv->state_manager);
759 return;
760 }
761
762@@ -440,336 +278,117 @@
763 g_error_free(error);
764 return;
765 }
766-
767- g_signal_connect(priv->dbus_proxy, "g-signal",
768- G_CALLBACK(g_signal_cb), self);
769-
770- fetch_state (self);
771-}
772-
773-static void fetch_state (IndicatorSound* self)
774-{
775-
776- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
777- if(priv->volume_widget != NULL){
778- determine_state_from_volume (volume_widget_get_current_volume(priv->volume_widget));
779- }
780-
781- g_dbus_proxy_call ( priv->dbus_proxy,
782- "GetSinkMute",
783- NULL,
784- G_DBUS_CALL_FLAGS_NONE,
785- -1,
786- NULL,
787- (GAsyncReadyCallback)get_sink_mute_cb,
788- self);
789-
790- g_dbus_proxy_call ( priv->dbus_proxy,
791- "GetSinkAvailability",
792- NULL,
793- G_DBUS_CALL_FLAGS_NONE,
794- -1,
795- NULL,
796- (GAsyncReadyCallback)get_sink_availability_cb,
797- self);
798-
799-}
800-
801-static void get_sink_availability_cb ( GObject *object,
802- GAsyncResult *res,
803- gpointer user_data )
804-{
805- IndicatorSound* self = INDICATOR_SOUND(user_data);
806- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
807-
808- GVariant *result, *value;
809- GError *error = NULL;
810-
811- result = g_dbus_proxy_call_finish ( priv->dbus_proxy,
812- res,
813- &error );
814-
815- if (error != NULL) {
816- g_debug("get_sink_availability call failed: %s", error->message);
817- g_error_free(error);
818- return;
819- }
820-
821- value = g_variant_get_child_value(result, 0);
822- device_available = g_variant_get_boolean(value);
823-
824- if (device_available == FALSE) {
825- update_state(STATE_SINKS_NONE);
826- }
827-
828- if(priv->volume_widget != NULL){
829- GtkWidget* slider_widget = volume_widget_get_ido_slider(VOLUME_WIDGET(priv->volume_widget));
830- gtk_widget_set_sensitive(slider_widget, device_available);
831- }
832-
833- g_variant_unref(value);
834- g_variant_unref(result);
835-}
836-
837-
838-static void get_sink_mute_cb ( GObject *object,
839- GAsyncResult *res,
840- gpointer user_data)
841-{
842- IndicatorSound* self = INDICATOR_SOUND(user_data);
843- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
844-
845- GVariant *result, *value;
846- GError *error = NULL;
847- gboolean is_muted;
848- result = g_dbus_proxy_call_finish ( priv->dbus_proxy,
849- res,
850- &error );
851-
852- if (error != NULL) {
853- g_debug("get_sink_mute call failed: %s", error->message);
854- g_error_free(error);
855- return;
856- }
857-
858- value = g_variant_get_child_value(result, 0);
859- is_muted = g_variant_get_boolean(value);
860-
861- if ( is_muted == TRUE ){
862- update_state(STATE_MUTED);
863- }
864-
865- g_variant_unref(value);
866- g_variant_unref(result);
867-}
868-
869-/*
870-Prepare states Array.
871-*/
872-void
873-prepare_state_machine()
874-{
875- volume_states = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
876- g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MUTED), g_strdup("audio-volume-muted-panel"));
877- g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_ZERO), g_strdup("audio-volume-low-zero-panel"));
878- g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_LOW), g_strdup("audio-volume-low-panel"));
879- g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MEDIUM), g_strdup("audio-volume-medium-panel"));
880- g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_HIGH), g_strdup("audio-volume-high-panel"));
881- g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT), g_strdup("audio-volume-muted-blocking-panel"));
882- g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_SINKS_NONE), g_strdup("audio-output-none-panel"));
883-}
884-
885-/*
886-prepare_blocked_animation:
887-Prepares the array of images to be used in the blocked animation.
888-Only called at startup.
889-*/
890-static void
891-prepare_blocked_animation()
892-{
893- gchar* blocked_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT));
894- gchar* muted_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_MUTED));
895-
896- GtkImage* temp_image = indicator_image_helper(muted_name);
897- GdkPixbuf* mute_buf = gtk_image_get_pixbuf(temp_image);
898-
899- temp_image = indicator_image_helper(blocked_name);
900- GdkPixbuf* blocked_buf = gtk_image_get_pixbuf(temp_image);
901-
902- if (mute_buf == NULL || blocked_buf == NULL) {
903- //g_debug("Don bother with the animation, the theme aint got the goods !");
904- return;
905- }
906-
907- int i;
908-
909- // sample 51 snapshots - range : 0-256
910- for (i = 0; i < 51; i++) {
911- gdk_pixbuf_composite(mute_buf, blocked_buf, 0, 0,
912- gdk_pixbuf_get_width(mute_buf),
913- gdk_pixbuf_get_height(mute_buf),
914- 0, 0, 1, 1, GDK_INTERP_BILINEAR, MIN(255, i * 5));
915- blocked_animation_list = g_list_append(blocked_animation_list, gdk_pixbuf_copy(blocked_buf));
916- }
917- g_object_ref_sink(mute_buf);
918- g_object_unref(mute_buf);
919- g_object_ref_sink(blocked_buf);
920- g_object_unref(blocked_buf);
921-}
922-
923-gint
924-get_state()
925-{
926- return current_state;
927-}
928-
929-gchar*
930-get_state_image_name(gint state)
931-{
932- return g_hash_table_lookup(volume_states, GINT_TO_POINTER(state));
933-}
934-
935-void
936-prepare_for_tests(IndicatorObject *io)
937-{
938- prepare_state_machine();
939- get_icon(io);
940-}
941-
942-void
943-tidy_up_hash()
944-{
945- g_hash_table_destroy(volume_states);
946-}
947-
948-static void
949-update_state(const gint state)
950-{
951- previous_state = current_state;
952- current_state = state;
953- gchar* image_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(current_state));
954- indicator_image_helper_update(speaker_image, image_name);
955-}
956-
957-
958-void
959-determine_state_from_volume(gdouble volume_percent)
960-{
961- if (device_available == FALSE)
962- return;
963- gint state = previous_state;
964- if (volume_percent < 30.0 && volume_percent > 0) {
965- state = STATE_LOW;
966- } else if (volume_percent < 70.0 && volume_percent >= 30.0) {
967- state = STATE_MEDIUM;
968- } else if (volume_percent >= 70.0) {
969- state = STATE_HIGH;
970- } else if (volume_percent == 0.0) {
971- state = STATE_ZERO;
972- }
973- update_state(state);
974-}
975-
976-
977-static gboolean
978-start_animation()
979-{
980- blocked_iter = blocked_animation_list;
981- blocked_id = 0;
982- animation_id = g_timeout_add(50, fade_back_to_mute_image, NULL);
983- return FALSE;
984-}
985-
986-static gboolean
987-fade_back_to_mute_image()
988-{
989- if (blocked_iter != NULL) {
990- gtk_image_set_from_pixbuf(speaker_image, blocked_iter->data);
991- blocked_iter = blocked_iter->next;
992- return TRUE;
993- } else {
994- animation_id = 0;
995- //g_debug("exit from animation now\n");
996- return FALSE;
997- }
998-}
999-
1000-static void
1001-reset_mute_blocking_animation()
1002-{
1003- if (animation_id != 0) {
1004- //g_debug("about to remove the animation_id callback from the mainloop!!**");
1005- g_source_remove(animation_id);
1006- animation_id = 0;
1007- }
1008- if (blocked_id != 0) {
1009- //g_debug("about to remove the blocked_id callback from the mainloop!!**");
1010- g_source_remove(blocked_id);
1011- blocked_id = 0;
1012- }
1013-}
1014-
1015-
1016-
1017-/*******************************************************************/
1018-// DBUS Signal reactions
1019-/*******************************************************************/
1020-static void g_signal_cb ( GDBusProxy* proxy,
1021- gchar* sender_name,
1022- gchar* signal_name,
1023- GVariant* parameters,
1024- gpointer user_data)
1025-{
1026- IndicatorSound *self = INDICATOR_SOUND(user_data);
1027- g_return_if_fail ( IS_INDICATOR_SOUND(self) );
1028-
1029- g_variant_ref (parameters);
1030- GVariant *value = g_variant_get_child_value (parameters, 0);
1031- gboolean input = g_variant_get_boolean (value);
1032- g_variant_unref (parameters);
1033-
1034- g_debug ( "!!! signal_cb with value %i", input);
1035-
1036- if (g_strcmp0(signal_name, INDICATOR_SOUND_SIGNAL_SINK_AVAILABLE_UPDATE) == 0){
1037- react_to_signal_sink_availability_update ( input, self );
1038- }
1039- else if (g_strcmp0(signal_name, INDICATOR_SOUND_SIGNAL_SINK_MUTE_UPDATE) == 0){
1040- react_to_signal_sink_mute_update ( input, self );
1041- }
1042- else if (g_strcmp0(signal_name, INDICATOR_SOUND_SIGNAL_SINK_INPUT_WHILE_MUTED) == 0){
1043- react_to_signal_sink_input_while_muted ( input, self );
1044- }
1045-}
1046-
1047-static void
1048-react_to_signal_sink_input_while_muted(gboolean block_value, IndicatorSound* self)
1049-{
1050- //g_debug("signal caught - sink input while muted with value %i", block_value);
1051- if (block_value == 1 && blocked_id == 0 && animation_id == 0 && blocked_animation_list != NULL) {
1052- gchar* image_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT));
1053- indicator_image_helper_update(speaker_image, image_name);
1054- blocked_id = g_timeout_add_seconds(5, start_animation, NULL);
1055- }
1056-}
1057-
1058-/*
1059- We can be sure the service won't send a mute signal unless it has changed !
1060- UNMUTE's force a volume update therefore icon is updated appropriately => no need for unmute handling here.
1061-*/
1062-static void
1063-react_to_signal_sink_mute_update(gboolean mute_value, IndicatorSound* self)
1064-{
1065- if (mute_value == TRUE && device_available == TRUE) {
1066- update_state(STATE_MUTED);
1067- } else {
1068- reset_mute_blocking_animation();
1069- }
1070- //g_debug("signal caught - sink mute update with mute value: %i", mute_value);
1071- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
1072-
1073- if(priv->volume_widget == NULL){
1074- return;
1075- }
1076- GtkWidget* slider_widget = volume_widget_get_ido_slider(VOLUME_WIDGET(priv->volume_widget));
1077- gtk_widget_set_sensitive(slider_widget, !mute_value);
1078- if(mute_value == FALSE){
1079- determine_state_from_volume (volume_widget_get_current_volume(priv->volume_widget));
1080- }
1081-}
1082-
1083-
1084-static void
1085-react_to_signal_sink_availability_update(gboolean available_value, IndicatorSound* self)
1086-{
1087- device_available = available_value;
1088- if (device_available == FALSE) {
1089- update_state(STATE_SINKS_NONE);
1090- return;
1091- }
1092- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
1093-
1094- determine_state_from_volume (volume_widget_get_current_volume(priv->volume_widget));
1095- //g_debug("signal caught - sink availability update with value: %i", available_value);
1096+ g_debug ("Connection to dbus seemed to work fine from the indicator side");
1097+ sound_state_manager_connect_to_dbus (priv->state_manager,
1098+ priv->dbus_proxy);
1099+
1100+}
1101+
1102+static gboolean
1103+new_transport_widget (DbusmenuMenuitem * newitem,
1104+ DbusmenuMenuitem * parent,
1105+ DbusmenuClient * client)
1106+{
1107+ g_debug("indicator-sound: new_transport_bar() called ");
1108+
1109+ GtkWidget* bar = NULL;
1110+ IndicatorObject *io = NULL;
1111+
1112+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
1113+ g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
1114+
1115+ bar = transport_widget_new(newitem);
1116+ io = g_object_get_data (G_OBJECT (client), "indicator");
1117+ IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
1118+ priv->transport_widgets_list = g_list_append ( priv->transport_widgets_list, bar );
1119+
1120+ GtkMenuItem *menu_transport_bar = GTK_MENU_ITEM(bar);
1121+
1122+ gtk_widget_show_all(bar);
1123+ dbusmenu_gtkclient_newitem_base (DBUSMENU_GTKCLIENT(client),
1124+ newitem,
1125+ menu_transport_bar,
1126+ parent);
1127+ return TRUE;
1128+}
1129+
1130+static gboolean
1131+new_metadata_widget (DbusmenuMenuitem * newitem,
1132+ DbusmenuMenuitem * parent,
1133+ DbusmenuClient * client)
1134+{
1135+ g_debug("indicator-sound: new_metadata_widget");
1136+
1137+ GtkWidget* metadata = NULL;
1138+
1139+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
1140+ g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
1141+
1142+ metadata = metadata_widget_new (newitem);
1143+ GtkMenuItem *menu_metadata_widget = GTK_MENU_ITEM(metadata);
1144+
1145+ gtk_widget_show_all(metadata);
1146+ dbusmenu_gtkclient_newitem_base (DBUSMENU_GTKCLIENT(client),
1147+ newitem, menu_metadata_widget, parent);
1148+ return TRUE;
1149+}
1150+
1151+static gboolean
1152+new_title_widget(DbusmenuMenuitem * newitem,
1153+ DbusmenuMenuitem * parent,
1154+ DbusmenuClient * client)
1155+{
1156+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
1157+ g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
1158+
1159+ g_debug ("%s (\"%s\")", __func__, dbusmenu_menuitem_property_get(newitem, DBUSMENU_TITLE_MENUITEM_NAME));
1160+
1161+ GtkWidget* title = NULL;
1162+
1163+ title = title_widget_new (newitem);
1164+ GtkMenuItem *menu_title_widget = GTK_MENU_ITEM(title);
1165+
1166+ gtk_widget_show_all(title);
1167+
1168+ dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client),
1169+ newitem,
1170+ menu_title_widget, parent);
1171+ return TRUE;
1172+}
1173+
1174+static gboolean
1175+new_volume_slider_widget(DbusmenuMenuitem * newitem,
1176+ DbusmenuMenuitem * parent,
1177+ DbusmenuClient * client)
1178+{
1179+ g_debug("indicator-sound: new_volume_slider_widget");
1180+
1181+ GtkWidget* volume_widget = NULL;
1182+ IndicatorObject *io = NULL;
1183+
1184+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
1185+ g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
1186+
1187+ volume_widget = volume_widget_new (newitem);
1188+ io = g_object_get_data (G_OBJECT (client), "indicator");
1189+ IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
1190+ priv->volume_widget = volume_widget;
1191+
1192+ GtkWidget* ido_slider_widget = volume_widget_get_ido_slider(VOLUME_WIDGET(priv->volume_widget));
1193+
1194+ gtk_widget_show_all(ido_slider_widget);
1195+ // register the style callback on this widget with state manager's style change
1196+ // handler (needs to remake the blocking animation for each style).
1197+ g_signal_connect (ido_slider_widget, "style-set",
1198+ G_CALLBACK(sound_state_manager_style_changed_cb),
1199+ priv->state_manager);
1200+
1201+ GtkMenuItem *menu_volume_item = GTK_MENU_ITEM(ido_slider_widget);
1202+ dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client),
1203+ newitem,
1204+ menu_volume_item,
1205+ parent);
1206+ return TRUE;
1207 }
1208
1209 /*******************************************************************/
1210@@ -833,7 +452,7 @@
1211 break;
1212 }
1213 new_value = CLAMP(new_value, 0, 100);
1214- if (new_value != current_value && current_state != STATE_MUTED) {
1215+ if (new_value != current_value && sound_state_manager_get_current_state (priv->state_manager) != MUTED) {
1216 //g_debug("Attempting to set the range from the key listener to %f", new_value);
1217 volume_widget_update(VOLUME_WIDGET(priv->volume_widget), new_value);
1218 }
1219@@ -930,25 +549,17 @@
1220 return digested;
1221 }
1222
1223-static void
1224-style_changed_cb(GtkWidget *widget, gpointer user_data)
1225-{
1226- //g_debug("Just caught a style change event");
1227- update_state(current_state);
1228- reset_mute_blocking_animation();
1229- update_state(current_state);
1230- free_the_animation_list();
1231- prepare_blocked_animation();
1232-}
1233
1234 static void
1235-indicator_sound_scroll (IndicatorObject *io, gint delta, IndicatorScrollDirection direction)
1236+indicator_sound_scroll (IndicatorObject *io, gint delta,
1237+ IndicatorScrollDirection direction)
1238 {
1239 //g_debug("indicator-sound-scroll - current slider value");
1240+ IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
1241+ SoundState current_state = sound_state_manager_get_current_state (priv->state_manager);
1242
1243- if (device_available == FALSE || current_state == STATE_MUTED)
1244+ if (current_state == UNAVAILABLE || current_state == MUTED)
1245 return;
1246- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
1247
1248 GtkWidget* slider_widget = volume_widget_get_ido_slider(VOLUME_WIDGET(priv->volume_widget));
1249 GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)slider_widget);
1250
1251=== modified file 'src/indicator-sound.h'
1252--- src/indicator-sound.h 2010-08-18 09:55:43 +0000
1253+++ src/indicator-sound.h 2011-01-26 20:58:59 +0000
1254@@ -26,7 +26,6 @@
1255 #include <libindicator/indicator.h>
1256 #include <libindicator/indicator-object.h>
1257 #include <libindicator/indicator-service-manager.h>
1258-#include <libindicator/indicator-image-helper.h>
1259
1260 #define INDICATOR_SOUND_TYPE (indicator_sound_get_type ())
1261 #define INDICATOR_SOUND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SOUND_TYPE, IndicatorSound))
1262
1263=== modified file 'src/metadata-widget.c'
1264--- src/metadata-widget.c 2011-01-11 13:22:38 +0000
1265+++ src/metadata-widget.c 2011-01-26 20:58:59 +0000
1266@@ -397,7 +397,6 @@
1267 return FALSE;
1268 }
1269
1270-// TODO: Manage empty/mangled music details <unknown artist> etc.
1271 static void
1272 metadata_widget_property_update(DbusmenuMenuitem* item, gchar* property,
1273 GVariant* value, gpointer userdata)
1274
1275=== added file 'src/mute-menu-item.c'
1276--- src/mute-menu-item.c 1970-01-01 00:00:00 +0000
1277+++ src/mute-menu-item.c 2011-01-26 20:58:59 +0000
1278@@ -0,0 +1,130 @@
1279+/*
1280+Copyright 2011 Canonical Ltd.
1281+
1282+Authors:
1283+ Conor Curran <conor.curran@canonical.com>
1284+
1285+This program is free software: you can redistribute it and/or modify it
1286+under the terms of the GNU General Public License version 3, as published
1287+by the Free Software Foundation.
1288+
1289+This program is distributed in the hope that it will be useful, but
1290+WITHOUT ANY WARRANTY; without even the implied warranties of
1291+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1292+PURPOSE. See the GNU General Public License for more details.
1293+
1294+You should have received a copy of the GNU General Public License along
1295+with this program. If not, see <http://www.gnu.org/licenses/>.
1296+*/
1297+#ifdef HAVE_CONFIG_H
1298+#include "config.h"
1299+#endif
1300+
1301+#include <glib/gi18n.h>
1302+
1303+#include "common-defs.h"
1304+#include "mute-menu-item.h"
1305+#include "pulse-manager.h"
1306+
1307+typedef struct _MuteMenuItemPrivate MuteMenuItemPrivate;
1308+
1309+struct _MuteMenuItemPrivate {
1310+ DbusmenuMenuitem* button;
1311+};
1312+
1313+#define MUTE_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MUTE_MENU_ITEM_TYPE, MuteMenuItemPrivate))
1314+
1315+/* Prototypes */
1316+static void mute_menu_item_class_init (MuteMenuItemClass *klass);
1317+static void mute_menu_item_init (MuteMenuItem *self);
1318+static void mute_menu_item_dispose (GObject *object);
1319+static void mute_menu_item_finalize (GObject *object);
1320+static void mute_menu_item_set_global_mute_from_ui (gpointer user_data);
1321+
1322+G_DEFINE_TYPE (MuteMenuItem, mute_menu_item, G_TYPE_OBJECT);
1323+
1324+static void mute_menu_item_class_init (MuteMenuItemClass *klass)
1325+{
1326+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
1327+
1328+ g_type_class_add_private (klass, sizeof (MuteMenuItemPrivate));
1329+
1330+ object_class->dispose = mute_menu_item_dispose;
1331+ object_class->finalize = mute_menu_item_finalize;
1332+
1333+ return;
1334+}
1335+
1336+static void mute_menu_item_init (MuteMenuItem *self)
1337+{
1338+ g_debug("Building new Mute Menu Item");
1339+ MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE(self);
1340+ priv->button = dbusmenu_menuitem_new();
1341+
1342+ g_signal_connect (G_OBJECT (priv->button),
1343+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
1344+ G_CALLBACK (mute_menu_item_set_global_mute_from_ui),
1345+ self);
1346+ return;
1347+}
1348+
1349+static void mute_menu_item_dispose (GObject *object)
1350+{
1351+ G_OBJECT_CLASS (mute_menu_item_parent_class)->dispose (object);
1352+ return;
1353+}
1354+
1355+static void
1356+mute_menu_item_finalize (GObject *object)
1357+{
1358+ G_OBJECT_CLASS (mute_menu_item_parent_class)->finalize (object);
1359+}
1360+
1361+static void
1362+mute_menu_item_set_global_mute_from_ui (gpointer user_data)
1363+{
1364+ g_return_if_fail (DBUSMENU_IS_MENUITEM (user_data));
1365+ DbusmenuMenuitem* button = DBUSMENU_MENUITEM (user_data);
1366+ gboolean current_value = dbusmenu_menuitem_property_get_bool (button,
1367+ DBUSMENU_MUTE_MENUITEM_VALUE);
1368+
1369+ gboolean new_value = !current_value;
1370+ // pa manager api - to be refactored
1371+ toggle_global_mute (new_value);
1372+}
1373+
1374+
1375+void mute_menu_item_update(MuteMenuItem* item, gboolean value_update)
1376+{
1377+ MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item);
1378+
1379+ dbusmenu_menuitem_property_set_bool (priv->button,
1380+ DBUSMENU_MUTE_MENUITEM_VALUE,
1381+ value_update);
1382+ dbusmenu_menuitem_property_set (priv->button,
1383+ DBUSMENU_MENUITEM_PROP_LABEL,
1384+ value_update == FALSE ? _("Mute") : _("Unmute"));
1385+}
1386+
1387+void mute_menu_item_enable(MuteMenuItem* item, gboolean active)
1388+{
1389+ MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item);
1390+
1391+ dbusmenu_menuitem_property_set_bool (priv->button,
1392+ DBUSMENU_MENUITEM_PROP_ENABLED,
1393+ active);
1394+}
1395+
1396+DbusmenuMenuitem* mute_menu_item_get_button (MuteMenuItem* item)
1397+{
1398+ MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item);
1399+ return priv->button;
1400+}
1401+
1402+MuteMenuItem* mute_menu_item_new (gboolean initial_update, gboolean enabled)
1403+{
1404+ MuteMenuItem *self = g_object_new (MUTE_MENU_ITEM_TYPE, NULL);
1405+ mute_menu_item_update (self, initial_update);
1406+ mute_menu_item_enable (self, enabled);
1407+ return self;
1408+}
1409
1410=== added file 'src/mute-menu-item.h'
1411--- src/mute-menu-item.h 1970-01-01 00:00:00 +0000
1412+++ src/mute-menu-item.h 2011-01-26 20:58:59 +0000
1413@@ -0,0 +1,59 @@
1414+/*
1415+Copyright 2010 Canonical Ltd.
1416+
1417+Authors:
1418+ Conor Curran <conor.curran@canonical.com>
1419+
1420+This program is free software: you can redistribute it and/or modify it
1421+under the terms of the GNU General Public License version 3, as published
1422+by the Free Software Foundation.
1423+
1424+This program is distributed in the hope that it will be useful, but
1425+WITHOUT ANY WARRANTY; without even the implied warranties of
1426+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1427+PURPOSE. See the GNU General Public License for more details.
1428+
1429+You should have received a copy of the GNU General Public License along
1430+with this program. If not, see <http://www.gnu.org/licenses/>.
1431+*/
1432+
1433+#ifndef __MUTE_MENU_ITEM_H__
1434+#define __MUTE_MENU_ITEM_H__
1435+
1436+#include <glib.h>
1437+#include <glib-object.h>
1438+#include <libdbusmenu-glib/menuitem.h>
1439+
1440+G_BEGIN_DECLS
1441+
1442+#define MUTE_MENU_ITEM_TYPE (mute_menu_item_get_type ())
1443+#define MUTE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTE_MENU_ITEM_TYPE, MuteMenuItem))
1444+#define MUTE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTE_MENU_ITEM_TYPE, MuteMenuItemClass))
1445+#define IS_MUTE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTE_MENU_ITEM_TYPE))
1446+#define IS_MUTE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTE_MENU_ITEM_TYPE))
1447+#define MUTE_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTE_MENU_ITEM_TYPE, MuteMenuItemClass))
1448+
1449+typedef struct _MuteMenuItem MuteMenuItem;
1450+typedef struct _MuteMenuItemClass MuteMenuItemClass;
1451+
1452+struct _MuteMenuItemClass {
1453+ GObjectClass parent_class;
1454+};
1455+
1456+struct _MuteMenuItem {
1457+ GObject parent;
1458+};
1459+
1460+GType mute_menu_item_get_type (void);
1461+
1462+MuteMenuItem* mute_menu_item_new ();
1463+
1464+void mute_menu_item_update (MuteMenuItem* item, gboolean update);
1465+void mute_menu_item_enable (MuteMenuItem* item, gboolean active);
1466+
1467+DbusmenuMenuitem* mute_menu_item_get_button (MuteMenuItem* item);
1468+
1469+G_END_DECLS
1470+
1471+#endif
1472+
1473
1474=== modified file 'src/pulse-manager.c'
1475--- src/pulse-manager.c 2010-12-16 12:36:43 +0000
1476+++ src/pulse-manager.c 2011-01-26 20:58:59 +0000
1477@@ -25,7 +25,6 @@
1478 #include <pulse/gccmacro.h>
1479
1480 #include "pulse-manager.h"
1481-#include "dbus-menu-manager.h"
1482
1483 #define RECONNECT_DELAY 5
1484
1485@@ -75,7 +74,7 @@
1486
1487 // Establish event callback registration
1488 pa_context_set_state_callback (pulse_context, context_state_callback, NULL);
1489- dbus_menu_manager_update_pa_state (FALSE, FALSE, FALSE, 0);
1490+ sound_service_dbus_update_pa_state (dbus_service, FALSE, FALSE, 0);
1491 pa_context_connect (pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL);
1492 }
1493
1494@@ -199,10 +198,12 @@
1495 /* g_debug("SINKINPUTWHILEMUTED SIGNAL EVENT TO BE SENT FROM PA MANAGER - check trace for value");*/
1496
1497 if (default_sink_is_muted(sink_index) == TRUE) {
1498- sound_service_dbus_sink_input_while_muted (dbus_service, TRUE);
1499- } else {
1500- sound_service_dbus_sink_input_while_muted(dbus_service, FALSE);
1501+ sound_service_dbus_update_sound_state(dbus_service, BLOCKED);
1502 }
1503+// Why do you need to send a false for a blocked event, it times out after 5 secs anyway
1504+//} else {
1505+ // sound_service_dbus_sink_input_while_muted(dbus_service, FALSE);
1506+ //}
1507 }
1508
1509 static gdouble get_default_sink_volume()
1510@@ -223,10 +224,8 @@
1511 if (GPOINTER_TO_INT(user_data) == 1) {
1512 sound_service_dbus_update_sink_mute(dbus_service, TRUE);
1513 } else {
1514- dbus_menu_manager_update_volume(get_default_sink_volume());
1515+ sound_service_dbus_update_volume(dbus_service, get_default_sink_volume());
1516 }
1517-
1518- /* g_debug("in the pulse manager: mute each sink %i", GPOINTER_TO_INT(user_data));*/
1519 }
1520
1521 void toggle_global_mute(gboolean mute_value)
1522@@ -309,14 +308,17 @@
1523
1524 gboolean device_available = determine_sink_availability();
1525 if (device_available == TRUE) {
1526- dbus_menu_manager_update_pa_state(TRUE,
1527- device_available,
1528- default_sink_is_muted(),
1529- get_default_sink_volume());
1530+ sound_service_dbus_update_pa_state( dbus_service,
1531+ device_available,
1532+ default_sink_is_muted(),
1533+ get_default_sink_volume() );
1534 } else {
1535 //Update the indicator to show PA either is not ready or has no available sink
1536 g_warning("Cannot find a suitable default sink ...");
1537- dbus_menu_manager_update_pa_state(FALSE, device_available, default_sink_is_muted(), get_default_sink_volume());
1538+ sound_service_dbus_update_pa_state( dbus_service,
1539+ device_available,
1540+ default_sink_is_muted(),
1541+ get_default_sink_volume() );
1542 }
1543 } else {
1544 /* g_debug("About to add an item to our hash");*/
1545@@ -346,7 +348,10 @@
1546 if (position < 0) {
1547 pa_operation_unref(pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL));
1548 } else {
1549- dbus_menu_manager_update_pa_state(TRUE, determine_sink_availability(), default_sink_is_muted(), get_default_sink_volume());
1550+ sound_service_dbus_update_pa_state(dbus_service,
1551+ determine_sink_availability(),
1552+ default_sink_is_muted(),
1553+ get_default_sink_volume());
1554 }
1555 }
1556 }
1557@@ -408,18 +413,17 @@
1558 pa_volume_t vol = pa_cvolume_max(&s->volume);
1559 gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
1560 /* g_debug("Updating volume from PA manager with volume = %f", volume_percent);*/
1561- dbus_menu_manager_update_volume(volume_percent);
1562+ sound_service_dbus_update_volume(dbus_service, volume_percent);
1563 }
1564
1565 if (mute_changed == TRUE) {
1566 /* g_debug("Updating Mute from PA manager with mute = %i", s->mute);*/
1567 sound_service_dbus_update_sink_mute(dbus_service, s->mute);
1568- dbus_menu_manager_update_mute_ui(s->mute);
1569 if (s->mute == FALSE) {
1570 pa_volume_t vol = pa_cvolume_max(&s->volume);
1571 gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
1572- /* g_debug("Updating volume from PA manager with volume = %f", volume_percent);*/
1573- dbus_menu_manager_update_volume(volume_percent);
1574+ /* g_debug("Updating volume from PA manager with volume = %f", volume_percent);*/
1575+ sound_service_dbus_update_volume(dbus_service, volume_percent);
1576 }
1577 }
1578 }
1579@@ -434,7 +438,7 @@
1580 value->base_volume = info->base_volume;
1581 g_hash_table_insert(sink_hash, GINT_TO_POINTER(value->index), value);
1582 /* g_debug("pulse-manager:update_sink_info -> After adding a new sink to our hash");*/
1583- sound_service_dbus_update_sink_availability(dbus_service, TRUE);
1584+ sound_service_dbus_update_sound_state(dbus_service, AVAILABLE);
1585 }
1586 }
1587
1588@@ -463,7 +467,7 @@
1589 pa_operation *operation;
1590 if (info == NULL) {
1591 g_warning("No server - get the hell out of here");
1592- dbus_menu_manager_update_pa_state(FALSE, FALSE, TRUE, 0);
1593+ sound_service_dbus_update_pa_state(dbus_service, FALSE, TRUE, 0);
1594 pa_server_available = FALSE;
1595 return;
1596 }
1597@@ -493,7 +497,7 @@
1598 case PA_SUBSCRIPTION_EVENT_SINK:
1599 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
1600 if (index == DEFAULT_SINK_INDEX)
1601- sound_service_dbus_update_sink_availability(dbus_service, FALSE);
1602+ sound_service_dbus_update_sound_state(dbus_service, UNAVAILABLE);
1603
1604 /* g_debug("Subscribed_events_callback - removing sink of index %i from our sink hash - keep the cache tidy !", index);*/
1605 g_hash_table_remove(sink_hash, GINT_TO_POINTER(index));
1606@@ -548,10 +552,10 @@
1607 case PA_CONTEXT_FAILED:
1608 g_warning("PA_CONTEXT_FAILED - Is PulseAudio Daemon running ?");
1609 pa_server_available = FALSE;
1610- dbus_menu_manager_update_pa_state(TRUE,
1611- pa_server_available,
1612- default_sink_is_muted(),
1613- get_default_sink_volume());
1614+ sound_service_dbus_update_pa_state( dbus_service,
1615+ pa_server_available,
1616+ default_sink_is_muted(),
1617+ get_default_sink_volume() );
1618
1619 if (reconnect_idle_id == 0){
1620 reconnect_idle_id = g_timeout_add_seconds (RECONNECT_DELAY,
1621
1622=== modified file 'src/pulse-manager.h'
1623--- src/pulse-manager.h 2010-06-18 09:02:20 +0000
1624+++ src/pulse-manager.h 2011-01-26 20:58:59 +0000
1625@@ -1,9 +1,6 @@
1626 #ifndef __INCLUDE_PULSE_MANAGER_H__
1627 #define __INCLUDE_PULSE_MANAGER_H__
1628 /*
1629-A small wrapper utility to load indicators and put them as menu items
1630-into the gnome-panel using it's applet interface.
1631-
1632 Copyright 2010 Canonical Ltd.
1633
1634 Authors:
1635
1636=== modified file 'src/slider-menu-item.c'
1637--- src/slider-menu-item.c 2011-01-11 13:04:17 +0000
1638+++ src/slider-menu-item.c 2011-01-26 20:58:59 +0000
1639@@ -29,7 +29,6 @@
1640 typedef struct _SliderMenuItemPrivate SliderMenuItemPrivate;
1641
1642 struct _SliderMenuItemPrivate {
1643- gdouble slider_value;
1644 };
1645
1646 #define SLIDER_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SLIDER_MENU_ITEM_TYPE, SliderMenuItemPrivate))
1647@@ -76,45 +75,56 @@
1648 G_OBJECT_CLASS (slider_menu_item_parent_class)->finalize (object);
1649 }
1650
1651-
1652 static void
1653 handle_event (DbusmenuMenuitem * mi,
1654 const gchar * name,
1655 GVariant * value,
1656 guint timestamp)
1657 {
1658- gdouble volume_input = 0;
1659 /*g_debug ( "handle-event in the slider at the backend, input is of type %s",
1660 g_variant_get_type_string(value));*/
1661
1662 GVariant* input = NULL;
1663 input = value;
1664- g_variant_ref (input);
1665-
1666 // Please note: Subject to change in future DBusmenu revisions
1667 if (g_variant_is_of_type(value, G_VARIANT_TYPE_VARIANT) == TRUE) {
1668 input = g_variant_get_variant(value);
1669 }
1670
1671- volume_input = g_variant_get_double(input);
1672+ gboolean volume_input = g_variant_get_double(input);
1673 if (value != NULL){
1674 set_sink_volume(volume_input);
1675 }
1676- g_variant_unref (input);
1677-}
1678-
1679-
1680-
1681-SliderMenuItem* slider_menu_item_new(gboolean sinks_available, gdouble start_volume)
1682+}
1683+
1684+void slider_menu_item_update (SliderMenuItem* item,
1685+ gdouble update)
1686+{
1687+ // TODO
1688+ // Check if that variant below will leak !!!
1689+ GVariant* new_volume = g_variant_new_double(update);
1690+ dbusmenu_menuitem_property_set_variant(DBUSMENU_MENUITEM(item),
1691+ DBUSMENU_VOLUME_MENUITEM_LEVEL,
1692+ new_volume);
1693+}
1694+
1695+void slider_menu_item_enable (SliderMenuItem* item,
1696+ gboolean active)
1697+{
1698+ dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item),
1699+ DBUSMENU_MENUITEM_PROP_ENABLED,
1700+ active );
1701+}
1702+
1703+SliderMenuItem* slider_menu_item_new (gboolean sinks_available,
1704+ gdouble start_volume)
1705 {
1706 SliderMenuItem *self = g_object_new(SLIDER_MENU_ITEM_TYPE, NULL);
1707- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_VOLUME_MENUITEM_TYPE);
1708+ dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self),
1709+ DBUSMENU_MENUITEM_PROP_TYPE,
1710+ DBUSMENU_VOLUME_MENUITEM_TYPE );
1711+ slider_menu_item_update (self, start_volume);
1712+ slider_menu_item_enable (self, sinks_available);
1713
1714- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_ENABLED, sinks_available);
1715- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_VISIBLE, sinks_available);
1716 return self;
1717-}
1718-
1719-
1720-
1721-
1722+}
1723\ No newline at end of file
1724
1725=== modified file 'src/slider-menu-item.h'
1726--- src/slider-menu-item.h 2010-06-18 09:02:20 +0000
1727+++ src/slider-menu-item.h 2011-01-26 20:58:59 +0000
1728@@ -45,8 +45,12 @@
1729 };
1730
1731 GType slider_menu_item_get_type (void);
1732-// TODO for now the volume percent param is not being used - remove once init mystery is solved
1733-SliderMenuItem* slider_menu_item_new(gboolean sinks_available, gdouble current_vol);
1734+
1735+void slider_menu_item_update(SliderMenuItem* item, gdouble update);
1736+void slider_menu_item_enable(SliderMenuItem* item, gboolean active);
1737+
1738+SliderMenuItem* slider_menu_item_new (gboolean sinks_available,
1739+ gdouble current_vol);
1740
1741 G_END_DECLS
1742
1743
1744=== modified file 'src/sound-service-dbus.c'
1745--- src/sound-service-dbus.c 2011-01-11 23:18:47 +0000
1746+++ src/sound-service-dbus.c 2011-01-26 20:58:59 +0000
1747@@ -3,7 +3,6 @@
1748 *
1749 * Authors:
1750 * Conor Curran <conor.curran@canonical.com>
1751- * Ted Gould <ted.gould@canonical.com>
1752 *
1753 * This program is free software: you can redistribute it and/or modify it
1754 * under the terms of the GNU General Public License version 3, as published
1755@@ -23,12 +22,19 @@
1756 #endif
1757
1758 #include <gio/gio.h>
1759+#include <unistd.h>
1760+#include <glib/gi18n.h>
1761 #include <libindicator/indicator-service.h>
1762+#include <libdbusmenu-glib/server.h>
1763+#include <libdbusmenu-glib/client.h>
1764+
1765+#include "sound-service-dbus.h"
1766+
1767 #include "gen-sound-service.xml.h"
1768 #include "dbus-shared-names.h"
1769-#include "sound-service-dbus.h"
1770-#include "common-defs.h"
1771 #include "pulse-manager.h"
1772+#include "slider-menu-item.h"
1773+#include "mute-menu-item.h"
1774
1775 // DBUS methods
1776 static void bus_method_call (GDBusConnection * connection,
1777@@ -50,14 +56,16 @@
1778 typedef struct _SoundServiceDbusPrivate SoundServiceDbusPrivate;
1779
1780 struct _SoundServiceDbusPrivate {
1781- GDBusConnection *connection;
1782- gboolean mute;
1783- gboolean sink_availability;
1784+ GDBusConnection* connection;
1785+ DbusmenuMenuitem* root_menuitem;
1786+ SliderMenuItem* volume_slider_menuitem;
1787+ MuteMenuItem* mute_menuitem;
1788+ SoundState current_sound_state;
1789 };
1790
1791 static GDBusNodeInfo * node_info = NULL;
1792 static GDBusInterfaceInfo * interface_info = NULL;
1793-
1794+static gboolean b_startup = TRUE;
1795 #define SOUND_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUND_SERVICE_DBUS_TYPE, SoundServiceDbusPrivate))
1796
1797 static void sound_service_dbus_class_init (SoundServiceDbusClass *klass);
1798@@ -65,7 +73,18 @@
1799 static void sound_service_dbus_dispose (GObject *object);
1800 static void sound_service_dbus_finalize (GObject *object);
1801
1802-/* GObject Boilerplate */
1803+static void sound_service_dbus_build_sound_menu ( SoundServiceDbus* root,
1804+ gboolean mute_update,
1805+ gboolean availability,
1806+ gdouble volume );
1807+static void show_sound_settings_dialog (DbusmenuMenuitem *mi,
1808+ gpointer user_data);
1809+static SoundState sound_service_dbus_get_state_from_volume (SoundServiceDbus* self);
1810+static void sound_service_dbus_determine_state (SoundServiceDbus* self,
1811+ gboolean availability,
1812+ gboolean mute,
1813+ gdouble volume);
1814+
1815 G_DEFINE_TYPE (SoundServiceDbus, sound_service_dbus, G_TYPE_OBJECT);
1816
1817 static void
1818@@ -108,8 +127,8 @@
1819 SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self);
1820
1821 priv->connection = NULL;
1822- priv->mute = FALSE;
1823- priv->sink_availability = FALSE;
1824+
1825+ priv->current_sound_state = UNAVAILABLE;
1826
1827 /* Fetch the session bus */
1828 priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1829@@ -134,6 +153,104 @@
1830 }
1831 }
1832
1833+DbusmenuMenuitem* sound_service_dbus_create_root_item (SoundServiceDbus* self)
1834+{
1835+ SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self);
1836+ priv->root_menuitem = dbusmenu_menuitem_new();
1837+ g_debug("Root ID: %d", dbusmenu_menuitem_get_id(priv->root_menuitem));
1838+ DbusmenuServer *server = dbusmenu_server_new(INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH);
1839+ dbusmenu_server_set_root (server, priv->root_menuitem);
1840+ g_object_unref (priv->root_menuitem);
1841+ establish_pulse_activities (self);
1842+ return priv->root_menuitem;
1843+}
1844+
1845+static void sound_service_dbus_build_sound_menu ( SoundServiceDbus* self,
1846+ gboolean mute_update,
1847+ gboolean availability,
1848+ gdouble volume )
1849+{
1850+ SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self);
1851+
1852+ // Mute button
1853+ priv->mute_menuitem = mute_menu_item_new ( mute_update, availability);
1854+ dbusmenu_menuitem_child_append (priv->root_menuitem,
1855+ mute_menu_item_get_button (priv->mute_menuitem));
1856+
1857+ // Slider
1858+ priv->volume_slider_menuitem = slider_menu_item_new ( availability, volume );
1859+ dbusmenu_menuitem_child_append (priv->root_menuitem, DBUSMENU_MENUITEM ( priv->volume_slider_menuitem ));
1860+
1861+ // Separator
1862+
1863+ DbusmenuMenuitem* separator = dbusmenu_menuitem_new();
1864+
1865+ dbusmenu_menuitem_property_set( separator,
1866+ DBUSMENU_MENUITEM_PROP_TYPE,
1867+ DBUSMENU_CLIENT_TYPES_SEPARATOR);
1868+ dbusmenu_menuitem_child_append(priv->root_menuitem, separator);
1869+ g_object_unref (separator);
1870+
1871+ // Sound preferences dialog
1872+ DbusmenuMenuitem* settings_mi = dbusmenu_menuitem_new();
1873+
1874+ dbusmenu_menuitem_property_set( settings_mi,
1875+ DBUSMENU_MENUITEM_PROP_LABEL,
1876+ _("Sound Preferences..."));
1877+ dbusmenu_menuitem_child_append(priv->root_menuitem, settings_mi);
1878+ g_object_unref (settings_mi);
1879+ g_signal_connect(G_OBJECT(settings_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
1880+ G_CALLBACK(show_sound_settings_dialog), NULL);
1881+
1882+ sound_service_dbus_determine_state (self, availability, mute_update, volume);
1883+}
1884+
1885+/**
1886+show_sound_settings_dialog:
1887+Bring up the gnome volume preferences dialog
1888+**/
1889+static void show_sound_settings_dialog (DbusmenuMenuitem *mi,
1890+ gpointer user_data)
1891+{
1892+ GError * error = NULL;
1893+ if (!g_spawn_command_line_async("gnome-volume-control --page=applications", &error) &&
1894+ !g_spawn_command_line_async("xfce4-mixer", &error))
1895+ {
1896+ g_warning("Unable to show dialog: %s", error->message);
1897+ g_error_free(error);
1898+ }
1899+}
1900+
1901+void sound_service_dbus_update_pa_state ( SoundServiceDbus* self,
1902+ gboolean availability,
1903+ gboolean mute_update,
1904+ gdouble volume )
1905+{
1906+ g_debug("update pa state with availability of %i, mute value of %i and a volume percent is %f", availability, mute_update, volume);
1907+ SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self);
1908+
1909+ if (b_startup == TRUE) {
1910+ sound_service_dbus_build_sound_menu ( self,
1911+ mute_update,
1912+ availability,
1913+ volume );
1914+ b_startup = FALSE;
1915+ return;
1916+ }
1917+
1918+ mute_menu_item_update ( priv->mute_menuitem,
1919+ mute_update );
1920+ slider_menu_item_update ( priv->volume_slider_menuitem,
1921+ volume );
1922+
1923+ mute_menu_item_enable ( priv->mute_menuitem, availability);
1924+ slider_menu_item_enable ( priv->volume_slider_menuitem,
1925+ availability );
1926+ sound_service_dbus_determine_state (self, availability, mute_update, volume);
1927+
1928+}
1929+
1930+
1931 static void
1932 sound_service_dbus_dispose (GObject *object)
1933 {
1934@@ -148,8 +265,110 @@
1935 return;
1936 }
1937
1938-/* A method has been called from our dbus inteface. Figure out what it
1939- is and dispatch it. */
1940+void sound_service_dbus_update_volume(SoundServiceDbus* self,
1941+ gdouble volume)
1942+{
1943+ SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self);
1944+ slider_menu_item_update (priv->volume_slider_menuitem, volume);
1945+ sound_service_dbus_update_sound_state (self,
1946+ sound_service_dbus_get_state_from_volume (self));
1947+}
1948+
1949+void sound_service_dbus_update_sink_mute(SoundServiceDbus* self,
1950+ gboolean mute_update)
1951+{
1952+ SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self);
1953+ mute_menu_item_update (priv->mute_menuitem, mute_update);
1954+ SoundState state = sound_service_dbus_get_state_from_volume (self);
1955+ if (mute_update == TRUE){
1956+ state = MUTED;
1957+ }
1958+ sound_service_dbus_update_sound_state (self, state);
1959+}
1960+
1961+static SoundState sound_service_dbus_get_state_from_volume (SoundServiceDbus* self)
1962+{
1963+ SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self);
1964+ GVariant* v = dbusmenu_menuitem_property_get_variant (DBUSMENU_MENUITEM(priv->volume_slider_menuitem),
1965+ DBUSMENU_VOLUME_MENUITEM_LEVEL);
1966+ gdouble volume_percent = g_variant_get_double (v);
1967+
1968+ SoundState state = LOW_LEVEL;
1969+
1970+ if (volume_percent < 30.0 && volume_percent > 0) {
1971+ state = LOW_LEVEL;
1972+ }
1973+ else if (volume_percent < 70.0 && volume_percent >= 30.0) {
1974+ state = MEDIUM_LEVEL;
1975+ }
1976+ else if (volume_percent >= 70.0) {
1977+ state = HIGH_LEVEL;
1978+ }
1979+ else if (volume_percent == 0.0) {
1980+ state = ZERO_LEVEL;
1981+ }
1982+ return state;
1983+}
1984+
1985+static void sound_service_dbus_determine_state (SoundServiceDbus* self,
1986+ gboolean availability,
1987+ gboolean mute,
1988+ gdouble volume)
1989+{
1990+ SoundState update;
1991+ if (availability == FALSE) {
1992+ update = UNAVAILABLE;
1993+ }
1994+ else if (mute == TRUE) {
1995+ update = MUTED;
1996+ }
1997+ else{
1998+ update = sound_service_dbus_get_state_from_volume (self);
1999+ }
2000+ sound_service_dbus_update_sound_state (self, update);
2001+}
2002+
2003+
2004+// EMIT STATE SIGNAL
2005+
2006+// TODO: this will be a bit messy until the pa_manager is sorted.
2007+// And we figure out all of the edge cases.
2008+void sound_service_dbus_update_sound_state (SoundServiceDbus* self,
2009+ SoundState new_state)
2010+{
2011+ SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self);
2012+ SoundState update = new_state;
2013+ // Ensure that after it has become available update the state with the current volume level
2014+ if (new_state == AVAILABLE &&
2015+ dbusmenu_menuitem_property_get_bool ( DBUSMENU_MENUITEM(priv->mute_menuitem),
2016+ DBUSMENU_MUTE_MENUITEM_VALUE) == FALSE ){
2017+ update = sound_service_dbus_get_state_from_volume (self);
2018+ }
2019+ if (update != BLOCKED){
2020+ priv->current_sound_state = update;
2021+ }
2022+
2023+ GVariant* v_output = g_variant_new("(i)", (int)update);
2024+
2025+ GError * error = NULL;
2026+
2027+ g_debug ("emitting signal with value %i", (int)update);
2028+ g_dbus_connection_emit_signal( priv->connection,
2029+ NULL,
2030+ INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH,
2031+ INDICATOR_SOUND_DBUS_INTERFACE,
2032+ INDICATOR_SOUND_SIGNAL_STATE_UPDATE,
2033+ v_output,
2034+ &error );
2035+ if (error != NULL) {
2036+ g_error("Unable to emit signal 'sinkinputwhilemuted' because : %s", error->message);
2037+ g_error_free(error);
2038+ return;
2039+ }
2040+}
2041+
2042+//HANDLE DBUS METHOD CALLS
2043+// TODO we will need to implement the black_list method.
2044 static void
2045 bus_method_call (GDBusConnection * connection,
2046 const gchar * sender,
2047@@ -164,96 +383,17 @@
2048 g_return_if_fail ( IS_SOUND_SERVICE_DBUS(service) );
2049 GVariant * retval = NULL;
2050 SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (service);
2051-
2052- if (g_strcmp0(method, "GetSinkMute") == 0) {
2053- g_debug("Get sink mute - sound service dbus!,about to send over mute_value of %i", priv->mute);
2054- retval = g_variant_new ( "(b)", priv->mute);
2055- }
2056- else if (g_strcmp0(method, "GetSinkAvailability") == 0) {
2057- g_debug("Get sink availability - sound service dbus!, about to send over availability_value of %i", priv->sink_availability);
2058- retval = g_variant_new ( "(b)", priv->sink_availability);
2059- }
2060+
2061+ if (g_strcmp0(method, "GetSoundState") == 0) {
2062+ g_debug("Get state - %i", priv->current_sound_state );
2063+ retval = g_variant_new ( "(i)", priv->current_sound_state);
2064+ }
2065 else {
2066 g_warning("Calling method '%s' on the sound service but it's unknown", method);
2067 }
2068- g_dbus_method_invocation_return_value(invocation, retval);
2069-}
2070-
2071-
2072-/**
2073-SIGNALS
2074-Utility methods to emit signals from the service into the ether.
2075-**/
2076-void sound_service_dbus_sink_input_while_muted(SoundServiceDbus* obj,
2077- gboolean block_value)
2078-{
2079- g_debug("Emitting signal: SINK_INPUT_WHILE_MUTED, with block_value: %i",
2080- block_value);
2081- SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj);
2082- GVariant* v_output = g_variant_new("(b)", block_value);
2083-
2084- GError * error = NULL;
2085-
2086- g_dbus_connection_emit_signal( priv->connection,
2087- NULL,
2088- INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH,
2089- INDICATOR_SOUND_DBUS_INTERFACE,
2090- INDICATOR_SOUND_SIGNAL_SINK_INPUT_WHILE_MUTED,
2091- v_output,
2092- &error );
2093- if (error != NULL) {
2094- g_error("Unable to emit signal 'sinkinputwhilemuted' because : %s", error->message);
2095- g_error_free(error);
2096- return;
2097- }
2098-}
2099-
2100-void sound_service_dbus_update_sink_mute(SoundServiceDbus* obj,
2101- gboolean sink_mute)
2102-{
2103- g_debug("Emitting signal: SINK_MUTE_UPDATE, with sink mute %i", sink_mute);
2104- SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj);
2105- priv->mute = sink_mute;
2106-
2107- GVariant* v_output = g_variant_new("(b)", sink_mute);
2108- GError * error = NULL;
2109- g_dbus_connection_emit_signal( priv->connection,
2110- NULL,
2111- INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH,
2112- INDICATOR_SOUND_DBUS_INTERFACE,
2113- INDICATOR_SOUND_SIGNAL_SINK_MUTE_UPDATE,
2114- v_output,
2115- &error );
2116- if (error != NULL) {
2117- g_error("Unable to emit signal 'sinkmuteupdate' because : %s", error->message);
2118- g_error_free(error);
2119- return;
2120- }
2121-}
2122-
2123-void sound_service_dbus_update_sink_availability(SoundServiceDbus* obj,
2124- gboolean sink_availability)
2125-{
2126- g_debug("Emitting signal: SinkAvailableUpdate, with %i", sink_availability);
2127- SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj);
2128- priv->sink_availability = sink_availability;
2129-
2130- GVariant* v_output = g_variant_new("(b)", priv->sink_availability);
2131- GError * error = NULL;
2132-
2133- g_dbus_connection_emit_signal( priv->connection,
2134- NULL,
2135- INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH,
2136- INDICATOR_SOUND_DBUS_INTERFACE,
2137- INDICATOR_SOUND_SIGNAL_SINK_AVAILABLE_UPDATE,
2138- v_output,
2139- &error );
2140- if (error != NULL) {
2141- g_error("Unable to emit signal 'SinkAvailableUpdate' because : %s", error->message);
2142- g_error_free(error);
2143- return;
2144- }
2145-}
2146+ g_dbus_method_invocation_return_value (invocation, retval);
2147+}
2148+
2149
2150
2151
2152
2153=== modified file 'src/sound-service-dbus.h'
2154--- src/sound-service-dbus.h 2011-01-10 12:57:35 +0000
2155+++ src/sound-service-dbus.h 2011-01-26 20:58:59 +0000
2156@@ -3,7 +3,6 @@
2157 *
2158 * Authors:
2159 * Conor Curran <conor.curran@canonical.com>
2160- * Cody Russell <crussell@canonical.com>
2161 *
2162 * This program is free software: you can redistribute it and/or modify it
2163 * under the terms of the GNU General Public License version 3, as published
2164@@ -23,6 +22,9 @@
2165
2166 #include <glib.h>
2167 #include <glib-object.h>
2168+#include <libdbusmenu-glib/menuitem.h>
2169+#include "common-defs.h"
2170+
2171
2172 G_BEGIN_DECLS
2173
2174@@ -51,10 +53,14 @@
2175
2176 GType sound_service_dbus_get_type (void) G_GNUC_CONST;
2177
2178-// Utility methods to get the SIGNAL messages across into the sound-service-dbus
2179-void sound_service_dbus_sink_input_while_muted (SoundServiceDbus* obj, gboolean block_value);
2180-void sound_service_dbus_update_sink_mute(SoundServiceDbus* obj, gboolean sink_mute);
2181-void sound_service_dbus_update_sink_availability(SoundServiceDbus* obj, gboolean sink_availibity);
2182+DbusmenuMenuitem* sound_service_dbus_create_root_item (SoundServiceDbus* self);
2183+void sound_service_dbus_update_sound_state (SoundServiceDbus* self, SoundState new_state);
2184+void sound_service_dbus_update_sink_mute(SoundServiceDbus* self, gboolean sink_mute);
2185+void sound_service_dbus_update_volume(SoundServiceDbus* self, gdouble volume);
2186+void sound_service_dbus_update_pa_state ( SoundServiceDbus* root,
2187+ gboolean availability,
2188+ gboolean mute_update,
2189+ gdouble volume );
2190
2191 G_END_DECLS
2192
2193
2194=== modified file 'src/sound-service.c'
2195--- src/sound-service.c 2011-01-11 17:32:58 +0000
2196+++ src/sound-service.c 2011-01-26 20:58:59 +0000
2197@@ -1,5 +1,4 @@
2198 /*
2199-This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
2200 Copyright 2010 Canonical Ltd.
2201
2202 Authors:
2203@@ -19,8 +18,9 @@
2204 */
2205
2206 #include "sound-service.h"
2207-#include "dbus-menu-manager.h"
2208+
2209 #include "pulse-manager.h"
2210+#include "sound-service-dbus.h"
2211 #include "music-player-bridge.h"
2212
2213 static GMainLoop *mainloop = NULL;
2214@@ -64,7 +64,9 @@
2215 INDICATOR_SERVICE_SIGNAL_SHUTDOWN,
2216 G_CALLBACK(service_shutdown), NULL);
2217
2218- DbusmenuMenuitem* root_menuitem = dbus_menu_manager_setup();
2219+ SoundServiceDbus* sound_service = g_object_new(SOUND_SERVICE_DBUS_TYPE, NULL);
2220+
2221+ DbusmenuMenuitem* root_menuitem = sound_service_dbus_create_root_item(sound_service);
2222 MusicPlayerBridge* server = music_player_bridge_new();
2223 music_player_bridge_set_root_menu_item(server, root_menuitem);
2224
2225
2226=== modified file 'src/sound-service.h'
2227--- src/sound-service.h 2010-06-18 09:02:20 +0000
2228+++ src/sound-service.h 2011-01-26 20:58:59 +0000
2229@@ -2,13 +2,10 @@
2230 #define __INCLUDE_SOUND_SERVICE_H__
2231
2232 /*
2233-This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
2234 Copyright 2010 Canonical Ltd.
2235
2236 Authors:
2237 Conor Curran <conor.curran@canonical.com>
2238- Ted Gould <ted@canonical.com>
2239- Cody Russell <crussell@canonical.com>
2240
2241 This program is free software: you can redistribute it and/or modify it
2242 under the terms of the GNU General Public License version 3, as published
2243
2244=== removed file 'src/sound-service.list'
2245--- src/sound-service.list 2010-01-28 18:26:00 +0000
2246+++ src/sound-service.list 1970-01-01 00:00:00 +0000
2247@@ -1,2 +0,0 @@
2248-VOID:INT,BOOLEAN
2249-
2250
2251=== modified file 'src/sound-service.xml'
2252--- src/sound-service.xml 2010-12-16 12:36:43 +0000
2253+++ src/sound-service.xml 2011-01-26 20:58:59 +0000
2254@@ -1,31 +1,17 @@
2255 <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
2256 <node name="/com/canonical/indicators/sound">
2257 <interface name="com.canonical.indicators.sound">
2258- <method name = "GetSinkMute">
2259- <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_get_sink_mute"/>
2260- <arg type='b' name='mute_input' direction="out"/>
2261- </method>
2262-
2263- <method name = "GetSinkAvailability">
2264- <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_get_sink_availability"/>
2265- <arg type='b' name='availability_input' direction="out"/>
2266- </method>
2267-
2268-<!-- Will need to hook up another signal which monitors for volume change
2269-Our respective UI element should listen to this and therefore will be updated with accurate setting-->
2270-<!-- Triggered when a sink is muted but the input has been sent to that sink -->
2271- <signal name="SinkInputWhileMuted">
2272- <arg name="block_value" type="b" direction="out"/>
2273- </signal>
2274-
2275- <signal name="SinkMuteUpdate">
2276- <arg name="mute_value" type="b" direction="out"/>
2277- </signal>
2278-
2279- <signal name="SinkAvailableUpdate">
2280- <arg name="available_value" type="b" direction="out"/>
2281- </signal>
2282-
2283+ <method name = "BlacklistMediaPlayer">
2284+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_blacklist_media_player"/>
2285+ <arg type='s' name='player_desktop_name' direction="in"/>
2286+ </method>
2287+ <method name = "GetSoundState">
2288+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_get_sink_state"/>
2289+ <arg type='i' name='current_state' direction="out"/>
2290+ </method>
2291+ <signal name="SoundStateUpdate">
2292+ <arg name="new_state" type="i" direction="out"/>
2293+ </signal>
2294 </interface>
2295 </node>
2296
2297
2298=== added file 'src/sound-state-manager.c'
2299--- src/sound-state-manager.c 1970-01-01 00:00:00 +0000
2300+++ src/sound-state-manager.c 2011-01-26 20:58:59 +0000
2301@@ -0,0 +1,388 @@
2302+/*
2303+Copyright 2011 Canonical Ltd.
2304+
2305+Authors:
2306+ Conor Curran <conor.curran@canonical.com>
2307+
2308+This program is free software: you can redistribute it and/or modify it
2309+under the terms of the GNU General Public License version 3, as published
2310+by the Free Software Foundation.
2311+
2312+This program is distributed in the hope that it will be useful, but
2313+WITHOUT ANY WARRANTY; without even the implied warranties of
2314+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2315+PURPOSE. See the GNU General Public License for more details.
2316+
2317+You should have received a copy of the GNU General Public License along
2318+with this program. If not, see <http://www.gnu.org/licenses/>.
2319+*/
2320+
2321+#include <libindicator/indicator-image-helper.h>
2322+#include "sound-state-manager.h"
2323+#include "dbus-shared-names.h"
2324+
2325+typedef struct _SoundStateManagerPrivate SoundStateManagerPrivate;
2326+
2327+struct _SoundStateManagerPrivate
2328+{
2329+ GDBusProxy* dbus_proxy;
2330+ GHashTable* volume_states;
2331+ GList* blocked_animation_list;
2332+ SoundState current_state;
2333+ GtkImage* speaker_image;
2334+};
2335+
2336+#define SOUND_STATE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUND_TYPE_STATE_MANAGER, SoundStateManagerPrivate))
2337+G_DEFINE_TYPE (SoundStateManager, sound_state_manager, G_TYPE_OBJECT);
2338+
2339+static GtkIconSize design_team_size;
2340+static gint blocked_id;
2341+static gint animation_id;
2342+static GList* blocked_iter = NULL;
2343+static gboolean can_animate = FALSE;
2344+
2345+static void sound_state_manager_prepare_blocked_animation(SoundStateManager* self);
2346+static gboolean sound_state_manager_start_animation (gpointer user_data);
2347+static gboolean sound_state_manager_fade_back_to_mute_image (gpointer user_data);
2348+static void sound_state_manager_reset_mute_blocking_animation (SoundStateManager* self);
2349+static void sound_state_manager_free_the_animation_list (SoundStateManager* self);
2350+static void sound_state_manager_prepare_state_image_names (SoundStateManager* self);
2351+static void sound_state_signal_cb ( GDBusProxy* proxy,
2352+ gchar* sender_name,
2353+ gchar* signal_name,
2354+ GVariant* parameters,
2355+ gpointer user_data );
2356+static gboolean sound_state_manager_can_proceed_with_blocking_animation (SoundStateManager* self);
2357+
2358+static void
2359+sound_state_manager_init (SoundStateManager* self)
2360+{
2361+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2362+
2363+ priv->dbus_proxy = NULL;
2364+ priv->volume_states = NULL;
2365+ priv->speaker_image = NULL;
2366+ priv->blocked_animation_list = NULL;
2367+
2368+ sound_state_manager_prepare_state_image_names (self);
2369+ sound_state_manager_prepare_blocked_animation (self);
2370+
2371+ priv->current_state = UNAVAILABLE;
2372+ priv->speaker_image = indicator_image_helper (g_hash_table_lookup (priv->volume_states,
2373+ GINT_TO_POINTER(priv->current_state)));
2374+}
2375+
2376+static void
2377+sound_state_manager_finalize (GObject *object)
2378+{
2379+ /* TODO: Add deinitalization code here */
2380+
2381+ G_OBJECT_CLASS (sound_state_manager_parent_class)->finalize (object);
2382+}
2383+
2384+static void
2385+sound_state_manager_dispose (GObject *object)
2386+{
2387+ SoundStateManager* self = SOUND_STATE_MANAGER (object);
2388+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2389+
2390+ g_hash_table_destroy (priv->volume_states);
2391+
2392+ sound_state_manager_free_the_animation_list (self);
2393+ G_OBJECT_CLASS (sound_state_manager_parent_class)->dispose (object);
2394+}
2395+
2396+
2397+static void
2398+sound_state_manager_class_init (SoundStateManagerClass *klass)
2399+{
2400+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
2401+
2402+ object_class->finalize = sound_state_manager_finalize;
2403+ object_class->dispose = sound_state_manager_dispose;
2404+
2405+ g_type_class_add_private (klass, sizeof (SoundStateManagerPrivate));
2406+
2407+ design_team_size = gtk_icon_size_register("design-team-size", 22, 22);
2408+}
2409+
2410+/*
2411+Prepare states versus images names hash.
2412+*/
2413+static void
2414+sound_state_manager_prepare_state_image_names (SoundStateManager* self)
2415+{
2416+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2417+ priv->volume_states = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
2418+ g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(MUTED), g_strdup("audio-volume-muted-panel"));
2419+ g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(ZERO_LEVEL), g_strdup("audio-volume-low-zero-panel"));
2420+ g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(LOW_LEVEL), g_strdup("audio-volume-low-panel"));
2421+ g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(MEDIUM_LEVEL), g_strdup("audio-volume-medium-panel"));
2422+ g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(HIGH_LEVEL), g_strdup("audio-volume-high-panel"));
2423+ g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(BLOCKED), g_strdup("audio-volume-muted-blocking-panel"));
2424+ g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(UNAVAILABLE), g_strdup("audio-output-none-panel"));
2425+}
2426+
2427+/*
2428+prepare_blocked_animation:
2429+Prepares the array of images to be used in the blocked animation.
2430+Only called at startup.
2431+*/
2432+static void
2433+sound_state_manager_prepare_blocked_animation (SoundStateManager* self)
2434+{
2435+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2436+
2437+ gchar* blocked_name = g_hash_table_lookup(priv->volume_states,
2438+ GINT_TO_POINTER(BLOCKED));
2439+ gchar* muted_name = g_hash_table_lookup(priv->volume_states,
2440+ GINT_TO_POINTER(MUTED));
2441+
2442+ GtkImage* temp_image = indicator_image_helper(muted_name);
2443+ GdkPixbuf* mute_buf = gtk_image_get_pixbuf(temp_image);
2444+
2445+ temp_image = indicator_image_helper(blocked_name);
2446+ GdkPixbuf* blocked_buf = gtk_image_get_pixbuf(temp_image);
2447+
2448+ if (mute_buf == NULL || blocked_buf == NULL) {
2449+ //g_debug("Don bother with the animation, the theme aint got the goods !");
2450+ return;
2451+ }
2452+
2453+ int i;
2454+
2455+ // sample 51 snapshots - range : 0-256
2456+ for (i = 0; i < 51; i++) {
2457+ gdk_pixbuf_composite(mute_buf, blocked_buf, 0, 0,
2458+ gdk_pixbuf_get_width(mute_buf),
2459+ gdk_pixbuf_get_height(mute_buf),
2460+ 0, 0, 1, 1, GDK_INTERP_BILINEAR, MIN(255, i * 5));
2461+ priv->blocked_animation_list = g_list_append(priv->blocked_animation_list,
2462+ gdk_pixbuf_copy(blocked_buf));
2463+ }
2464+ can_animate = TRUE;
2465+ g_object_ref_sink(mute_buf);
2466+ g_object_unref(mute_buf);
2467+ g_object_ref_sink(blocked_buf);
2468+ g_object_unref(blocked_buf);
2469+}
2470+
2471+
2472+GtkImage*
2473+sound_state_manager_get_current_icon (SoundStateManager* self)
2474+{
2475+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2476+ return priv->speaker_image;
2477+}
2478+
2479+SoundState
2480+sound_state_manager_get_current_state (SoundStateManager* self)
2481+{
2482+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2483+ return priv->current_state;
2484+}
2485+
2486+/**
2487+ * sound_state_manager_connect_to_dbus:
2488+ * @returns: void
2489+ * When ready the indicator-sound calls this method to enable state communication
2490+ * between the indicator and the service.
2491+ **/
2492+void
2493+sound_state_manager_connect_to_dbus (SoundStateManager* self, GDBusProxy* proxy)
2494+{
2495+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2496+ priv->dbus_proxy = proxy;
2497+ g_debug (" here about to register for signal callback on %s", g_dbus_proxy_get_name (priv->dbus_proxy));
2498+ g_signal_connect (priv->dbus_proxy, "g-signal",
2499+ G_CALLBACK (sound_state_signal_cb), self);
2500+
2501+ g_dbus_proxy_call ( priv->dbus_proxy,
2502+ "GetSoundState",
2503+ NULL,
2504+ G_DBUS_CALL_FLAGS_NONE,
2505+ -1,
2506+ NULL,
2507+ (GAsyncReadyCallback)sound_state_manager_get_state_cb,
2508+ self);
2509+}
2510+
2511+void
2512+sound_state_manager_get_state_cb (GObject *object,
2513+ GAsyncResult *res,
2514+ gpointer user_data)
2515+{
2516+ g_return_if_fail (SOUND_IS_STATE_MANAGER (user_data));
2517+ SoundStateManager* self = SOUND_STATE_MANAGER (user_data);
2518+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2519+
2520+ GVariant *result, *value;
2521+ GError *error = NULL;
2522+ result = g_dbus_proxy_call_finish ( priv->dbus_proxy,
2523+ res,
2524+ &error );
2525+
2526+ if (error != NULL) {
2527+ g_debug("get_sound_state call failed: %s", error->message);
2528+ g_error_free(error);
2529+ return;
2530+ }
2531+
2532+ value = g_variant_get_child_value(result, 0);
2533+ priv->current_state = (SoundState)g_variant_get_int32(value);
2534+
2535+ gchar* image_name = g_hash_table_lookup (priv->volume_states,
2536+ GINT_TO_POINTER(priv->current_state) );
2537+ indicator_image_helper_update (priv->speaker_image, image_name);
2538+
2539+ g_variant_unref(value);
2540+ g_variant_unref(result);
2541+}
2542+
2543+void
2544+sound_state_manager_deal_with_disconnect (SoundStateManager* self)
2545+{
2546+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2547+ priv->current_state = UNAVAILABLE;
2548+
2549+ gchar* image_name = g_hash_table_lookup (priv->volume_states,
2550+ GINT_TO_POINTER(priv->current_state) );
2551+ indicator_image_helper_update (priv->speaker_image, image_name);
2552+}
2553+
2554+static void
2555+sound_state_signal_cb ( GDBusProxy* proxy,
2556+ gchar* sender_name,
2557+ gchar* signal_name,
2558+ GVariant* parameters,
2559+ gpointer user_data)
2560+{
2561+ //g_debug ( "!!! sound state manager signal_cb" );
2562+
2563+ g_return_if_fail (SOUND_IS_STATE_MANAGER (user_data));
2564+ SoundStateManager* self = SOUND_STATE_MANAGER (user_data);
2565+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2566+
2567+ g_variant_ref (parameters);
2568+ GVariant *value = g_variant_get_child_value (parameters, 0);
2569+ gint update = g_variant_get_int32 (value);
2570+
2571+ //g_debug ( "!!! signal_cb with value %i", update);
2572+
2573+ priv->current_state = (SoundState)update;
2574+
2575+ g_variant_unref (parameters);
2576+
2577+ if (g_strcmp0(signal_name, INDICATOR_SOUND_SIGNAL_STATE_UPDATE) == 0){
2578+
2579+ gchar* image_name = g_hash_table_lookup (priv->volume_states,
2580+ GINT_TO_POINTER(priv->current_state) );
2581+ if (priv->current_state == BLOCKED &&
2582+ sound_state_manager_can_proceed_with_blocking_animation (self) == TRUE) {
2583+ blocked_id = g_timeout_add_seconds (4,
2584+ sound_state_manager_start_animation,
2585+ self);
2586+ indicator_image_helper_update (priv->speaker_image, image_name);
2587+
2588+ }
2589+ else{
2590+ indicator_image_helper_update (priv->speaker_image, image_name);
2591+ }
2592+ }
2593+ else {
2594+ g_warning ("sorry don't know what signal this is - %s", signal_name);
2595+ }
2596+
2597+}
2598+
2599+void
2600+sound_state_manager_style_changed_cb (GtkWidget *widget,
2601+ GtkStyle *previous_style,
2602+ gpointer user_data)
2603+{
2604+ g_debug("Just caught a style change event");
2605+ g_return_if_fail (SOUND_IS_STATE_MANAGER (user_data));
2606+ SoundStateManager* self = SOUND_STATE_MANAGER (user_data);
2607+ sound_state_manager_reset_mute_blocking_animation (self);
2608+ sound_state_manager_free_the_animation_list (self);
2609+ sound_state_manager_prepare_blocked_animation (self);
2610+}
2611+
2612+static void
2613+sound_state_manager_reset_mute_blocking_animation (SoundStateManager* self)
2614+{
2615+ if (animation_id != 0) {
2616+ //g_debug("about to remove the animation_id callback from the mainloop!!**");
2617+ g_source_remove(animation_id);
2618+ animation_id = 0;
2619+ }
2620+ if (blocked_id != 0) {
2621+ //g_debug("about to remove the blocked_id callback from the mainloop!!**");
2622+ g_source_remove(blocked_id);
2623+ blocked_id = 0;
2624+ }
2625+}
2626+
2627+static void
2628+sound_state_manager_free_the_animation_list (SoundStateManager* self)
2629+{
2630+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2631+
2632+ if (priv->blocked_animation_list != NULL) {
2633+ g_list_foreach (priv->blocked_animation_list, (GFunc)g_object_unref, NULL);
2634+ g_list_free (priv->blocked_animation_list);
2635+ priv->blocked_animation_list = NULL;
2636+ }
2637+}
2638+
2639+
2640+static gboolean
2641+sound_state_manager_start_animation (gpointer userdata)
2642+{
2643+ g_return_val_if_fail (SOUND_IS_STATE_MANAGER (userdata), FALSE);
2644+ SoundStateManager* self = SOUND_STATE_MANAGER (userdata);
2645+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
2646+
2647+ blocked_iter = priv->blocked_animation_list;
2648+ blocked_id = 0;
2649+ animation_id = g_timeout_add (50,
2650+ sound_state_manager_fade_back_to_mute_image,
2651+ self);
2652+ return FALSE;
2653+}
2654+
2655+static gboolean
2656+sound_state_manager_fade_back_to_mute_image (gpointer user_data)
2657+{
2658+ g_return_val_if_fail (SOUND_IS_STATE_MANAGER (user_data), FALSE);
2659+ SoundStateManager* self = SOUND_STATE_MANAGER (user_data);
2660+ SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE (self);
2661+
2662+ if (blocked_iter != NULL) {
2663+ gtk_image_set_from_pixbuf (priv->speaker_image, blocked_iter->data);
2664+ blocked_iter = blocked_iter->next;
2665+ return TRUE;
2666+ } else {
2667+ animation_id = 0;
2668+ //g_debug("exit from animation now\n");
2669+ g_dbus_proxy_call ( priv->dbus_proxy,
2670+ "GetSoundState",
2671+ NULL,
2672+ G_DBUS_CALL_FLAGS_NONE,
2673+ -1,
2674+ NULL,
2675+ (GAsyncReadyCallback)sound_state_manager_get_state_cb,
2676+ self);
2677+
2678+ return FALSE;
2679+ }
2680+}
2681+
2682+
2683+// Simple static helper to determine if the coast is clear to animate
2684+static
2685+gboolean sound_state_manager_can_proceed_with_blocking_animation (SoundStateManager* self)
2686+{
2687+ return (can_animate && blocked_id == 0 && animation_id == 0 );
2688+}
2689+
2690
2691=== added file 'src/sound-state-manager.h'
2692--- src/sound-state-manager.h 1970-01-01 00:00:00 +0000
2693+++ src/sound-state-manager.h 2011-01-26 20:58:59 +0000
2694@@ -0,0 +1,66 @@
2695+/*
2696+Copyright 2011 Canonical Ltd.
2697+
2698+Authors:
2699+ Conor Curran <conor.curran@canonical.com>
2700+
2701+This program is free software: you can redistribute it and/or modify it
2702+under the terms of the GNU General Public License version 3, as published
2703+by the Free Software Foundation.
2704+
2705+This program is distributed in the hope that it will be useful, but
2706+WITHOUT ANY WARRANTY; without even the implied warranties of
2707+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2708+PURPOSE. See the GNU General Public License for more details.
2709+
2710+You should have received a copy of the GNU General Public License along
2711+with this program. If not, see <http://www.gnu.org/licenses/>.
2712+*/
2713+
2714+#ifndef _SOUND_STATE_MANAGER_H_
2715+#define _SOUND_STATE_MANAGER_H_
2716+
2717+#include <glib.h>
2718+#include "common-defs.h"
2719+
2720+G_BEGIN_DECLS
2721+
2722+#define SOUND_TYPE_STATE_MANAGER (sound_state_manager_get_type ())
2723+#define SOUND_STATE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUND_TYPE_STATE_MANAGER, SoundStateManager))
2724+#define SOUND_STATE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUND_TYPE_STATE_MANAGER, SoundStateManagerClass))
2725+#define SOUND_IS_STATE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUND_TYPE_STATE_MANAGER))
2726+#define SOUND_IS_STATE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUND_TYPE_STATE_MANAGER))
2727+#define SOUND_STATE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUND_TYPE_STATE_MANAGER, SoundStateManagerClass))
2728+
2729+typedef struct _SoundStateManagerClass SoundStateManagerClass;
2730+typedef struct _SoundStateManager SoundStateManager;
2731+
2732+struct _SoundStateManagerClass
2733+{
2734+ GObjectClass parent_class;
2735+};
2736+
2737+struct _SoundStateManager
2738+{
2739+ GObject parent_instance;
2740+};
2741+
2742+GType sound_state_manager_get_type (void) G_GNUC_CONST;
2743+
2744+void sound_state_manager_style_changed_cb (GtkWidget *widget,
2745+ GtkStyle *previous_style,
2746+ gpointer user_data);
2747+GtkImage* sound_state_manager_get_current_icon (SoundStateManager* self);
2748+SoundState sound_state_manager_get_current_state (SoundStateManager* self);
2749+void sound_state_manager_connect_to_dbus (SoundStateManager* self,
2750+ GDBusProxy* proxy);
2751+void sound_state_manager_deal_with_disconnect (SoundStateManager* self);
2752+void sound_state_manager_get_state_cb (GObject *object,
2753+ GAsyncResult *res,
2754+ gpointer user_data);
2755+
2756+
2757+
2758+G_END_DECLS
2759+
2760+#endif /* _SOUND_STATE_MANAGER_H_ */
2761
2762=== modified file 'src/volume-widget.c'
2763--- src/volume-widget.c 2011-01-11 09:57:41 +0000
2764+++ src/volume-widget.c 2011-01-26 20:58:59 +0000
2765@@ -137,7 +137,6 @@
2766 gdouble update = g_variant_get_double (value);
2767 //g_debug("volume-widget - update level with value %f", update);
2768 gtk_range_set_value(range, update);
2769- determine_state_from_volume(update);
2770 }
2771 }
2772 }
2773@@ -157,7 +156,6 @@
2774 GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
2775 GtkRange *range = (GtkRange*)slider;
2776 gtk_range_set_value(range, initial_level);
2777- determine_state_from_volume(initial_level);
2778 }
2779
2780 static gboolean
2781@@ -169,7 +167,6 @@
2782 g_return_val_if_fail (IS_VOLUME_WIDGET (user_data), FALSE);
2783 VolumeWidget* mitem = VOLUME_WIDGET(user_data);
2784 volume_widget_update(mitem, new_value);
2785- determine_state_from_volume(new_value);
2786 return FALSE;
2787 }
2788

Subscribers

People subscribed via source and target branches