Merge lp:~cjcurran/indicator-sound/one-big-refactor into lp:~indicator-applet-developers/indicator-sound/trunk_3
- one-big-refactor
- Merge into 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 | ||||||||
Related bugs: |
|
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.
Commit message
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 | # |
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 |
* 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. 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.
* 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_