Merge lp:~cjcurran/indicator-sound/voip-input-item into lp:~indicator-applet-developers/indicator-sound/trunk_3
- voip-input-item
- Merge into trunk_3
Proposed by
Conor Curran
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 202 | ||||||||
Proposed branch: | lp:~cjcurran/indicator-sound/voip-input-item | ||||||||
Merge into: | lp:~indicator-applet-developers/indicator-sound/trunk_3 | ||||||||
Diff against target: |
1537 lines (+1044/-44) 18 files modified
src/Makefile.am (+5/-1) src/active-sink.c (+61/-5) src/active-sink.h (+19/-6) src/common-defs.h (+5/-1) src/indicator-sound.c (+62/-4) src/music-player-bridge.vala (+5/-3) src/mute-menu-item.c (+1/-0) src/player-item.vala (+1/-2) src/pulseaudio-mgr.c (+190/-19) src/pulseaudio-mgr.h (+2/-0) src/settings-manager.vala (+2/-0) src/sound-service-dbus.c (+6/-2) src/sound-service-dbus.h (+2/-1) src/sound-service.c (+2/-0) src/voip-input-menu-item.c (+277/-0) src/voip-input-menu-item.h (+70/-0) src/voip-input-widget.c (+279/-0) src/voip-input-widget.h (+55/-0) |
||||||||
To merge this branch: | bzr merge lp:~cjcurran/indicator-sound/voip-input-item | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ted Gould (community) | Approve | ||
Review via email: mp+50364@code.launchpad.net |
Commit message
Description of the change
- big Voip input menu item feature added
- little keyboard shortcut feature removal
To post a comment you must log in.
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-02-11 15:22:10 +0000 |
3 | +++ src/Makefile.am 2011-02-18 17:27:12 +0000 |
4 | @@ -20,6 +20,8 @@ |
5 | title-widget.h \ |
6 | volume-widget.c \ |
7 | volume-widget.h \ |
8 | + voip-input-widget.c \ |
9 | + voip-input-widget.h \ |
10 | gen-sound-service.xml.h \ |
11 | gen-sound-service.xml.c \ |
12 | dbus-shared-names.h |
13 | @@ -85,7 +87,7 @@ |
14 | # Sound Service C |
15 | ############################### |
16 | indicator_sound_service_SOURCES = \ |
17 | - common-defs.h \ |
18 | + common-defs.h \ |
19 | sound-service.h \ |
20 | sound-service.c \ |
21 | pulseaudio-mgr.h \ |
22 | @@ -96,6 +98,8 @@ |
23 | sound-service-dbus.c \ |
24 | slider-menu-item.h \ |
25 | slider-menu-item.c \ |
26 | + voip-input-menu-item.h \ |
27 | + voip-input-menu-item.c \ |
28 | mute-menu-item.h \ |
29 | mute-menu-item.c \ |
30 | gen-sound-service.xml.h \ |
31 | |
32 | === modified file 'src/active-sink.c' |
33 | --- src/active-sink.c 2011-02-07 12:53:45 +0000 |
34 | +++ src/active-sink.c 2011-02-18 17:27:12 +0000 |
35 | @@ -21,7 +21,7 @@ |
36 | #include "active-sink.h" |
37 | #include "slider-menu-item.h" |
38 | #include "mute-menu-item.h" |
39 | - |
40 | +#include "voip-input-menu-item.h" |
41 | #include "pulseaudio-mgr.h" |
42 | |
43 | typedef struct _ActiveSinkPrivate ActiveSinkPrivate; |
44 | @@ -30,7 +30,8 @@ |
45 | { |
46 | SliderMenuItem* volume_slider_menuitem; |
47 | MuteMenuItem* mute_menuitem; |
48 | - SoundState current_sound_state; |
49 | + VoipInputMenuItem* voip_input_menu_item; |
50 | + SoundState current_sound_state; |
51 | SoundServiceDbus* service; |
52 | gint index; |
53 | gchar* name; |
54 | @@ -52,7 +53,6 @@ |
55 | static void active_sink_volume_update (ActiveSink* self, gdouble percent); |
56 | static void active_sink_mute_update (ActiveSink* self, gboolean muted); |
57 | |
58 | - |
59 | G_DEFINE_TYPE (ActiveSink, active_sink, G_TYPE_OBJECT); |
60 | |
61 | static void |
62 | @@ -72,6 +72,7 @@ |
63 | ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); |
64 | priv->mute_menuitem = NULL; |
65 | priv->volume_slider_menuitem = NULL; |
66 | + priv->voip_input_menu_item = NULL; |
67 | priv->current_sound_state = UNAVAILABLE; |
68 | priv->index = -1; |
69 | priv->name = NULL; |
70 | @@ -79,6 +80,7 @@ |
71 | |
72 | // Init our menu items. |
73 | priv->mute_menuitem = g_object_new (MUTE_MENU_ITEM_TYPE, NULL); |
74 | + priv->voip_input_menu_item = g_object_new (VOIP_INPUT_MENU_ITEM_TYPE, NULL);; |
75 | priv->volume_slider_menuitem = slider_menu_item_new (self); |
76 | mute_menu_item_enable (priv->mute_menuitem, FALSE); |
77 | slider_menu_item_enable (priv->volume_slider_menuitem, FALSE); |
78 | @@ -121,6 +123,32 @@ |
79 | } |
80 | |
81 | void |
82 | +active_sink_activate_voip_item (ActiveSink* self, gint sink_input_index, gint client_index) |
83 | +{ |
84 | + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); |
85 | + if (voip_input_menu_item_is_interested (priv->voip_input_menu_item, |
86 | + sink_input_index, |
87 | + client_index)){ |
88 | + voip_input_menu_item_enable (priv->voip_input_menu_item, TRUE); |
89 | + } |
90 | +} |
91 | + |
92 | +void |
93 | +active_sink_deactivate_voip_source (ActiveSink* self, gboolean visible) |
94 | +{ |
95 | + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); |
96 | + visible &= voip_input_menu_item_is_active (priv->voip_input_menu_item); |
97 | + voip_input_menu_item_deactivate_source (priv->voip_input_menu_item, visible); |
98 | +} |
99 | + |
100 | +void |
101 | +active_sink_deactivate_voip_client (ActiveSink* self) |
102 | +{ |
103 | + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); |
104 | + voip_input_menu_item_deactivate_voip_client (priv->voip_input_menu_item); |
105 | +} |
106 | + |
107 | +void |
108 | active_sink_update (ActiveSink* sink, |
109 | const pa_sink_info* update) |
110 | { |
111 | @@ -168,6 +196,13 @@ |
112 | } |
113 | |
114 | |
115 | +gint |
116 | +active_sink_get_current_sink_input_index (ActiveSink* sink) |
117 | +{ |
118 | + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (sink); |
119 | + return voip_input_menu_item_get_sink_input_index (priv->voip_input_menu_item); |
120 | +} |
121 | + |
122 | static void |
123 | active_sink_mute_update (ActiveSink* self, gboolean muted) |
124 | { |
125 | @@ -219,7 +254,7 @@ |
126 | return state; |
127 | } |
128 | |
129 | -static pa_cvolume |
130 | +pa_cvolume |
131 | active_sink_construct_mono_volume (const pa_cvolume* vol) |
132 | { |
133 | pa_cvolume new_volume; |
134 | @@ -279,6 +314,26 @@ |
135 | return priv->current_sound_state; |
136 | } |
137 | |
138 | +void |
139 | +active_sink_update_voip_input_source (ActiveSink* self, const pa_source_info* update) |
140 | +{ |
141 | + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); |
142 | + voip_input_menu_item_update (priv->voip_input_menu_item, update); |
143 | +} |
144 | + |
145 | +gboolean |
146 | +active_sink_is_voip_source_populated (ActiveSink* self) |
147 | +{ |
148 | + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); |
149 | + return voip_input_menu_item_is_populated (priv->voip_input_menu_item); |
150 | +} |
151 | + |
152 | +gint active_sink_get_source_index (ActiveSink* self) |
153 | +{ |
154 | + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); |
155 | + return voip_input_menu_item_get_index (priv->voip_input_menu_item); |
156 | +} |
157 | + |
158 | ActiveSink* |
159 | active_sink_new (SoundServiceDbus* service) |
160 | { |
161 | @@ -287,7 +342,8 @@ |
162 | priv->service = service; |
163 | sound_service_dbus_build_sound_menu (service, |
164 | mute_menu_item_get_button (priv->mute_menuitem), |
165 | - DBUSMENU_MENUITEM (priv->volume_slider_menuitem)); |
166 | + DBUSMENU_MENUITEM (priv->volume_slider_menuitem), |
167 | + DBUSMENU_MENUITEM (priv->voip_input_menu_item)); |
168 | pm_establish_pulse_connection (sink); |
169 | return sink; |
170 | } |
171 | |
172 | === modified file 'src/active-sink.h' |
173 | --- src/active-sink.h 2011-02-07 11:45:06 +0000 |
174 | +++ src/active-sink.h 2011-02-18 17:27:12 +0000 |
175 | @@ -50,21 +50,34 @@ |
176 | |
177 | GType active_sink_get_type (void) G_GNUC_CONST; |
178 | |
179 | +/** |
180 | + * TODO |
181 | + * Refactor this to become a device manager obj basically acting as wrapper for |
182 | + * the communication between pulseaudio-mgr and the individual items. |
183 | + * First steps collapse slider/volume related stuff into slider-menu-item. |
184 | + */ |
185 | + |
186 | +// Sink related |
187 | void active_sink_populate (ActiveSink* sink, const pa_sink_info* update); |
188 | void active_sink_update (ActiveSink* sink, const pa_sink_info* update); |
189 | - |
190 | gboolean active_sink_is_populated (ActiveSink* sink); |
191 | -void active_sink_determine_blocking_state (ActiveSink* self); |
192 | - |
193 | gint active_sink_get_index (ActiveSink* self); |
194 | -SoundState active_sink_get_state (ActiveSink* self); |
195 | - |
196 | void active_sink_deactivate (ActiveSink* self); |
197 | - |
198 | void active_sink_update_mute (ActiveSink* self, gboolean mute_update); |
199 | void active_sink_update_volume (ActiveSink* self, gdouble percent); |
200 | void active_sink_ensure_sink_is_unmuted (ActiveSink* self); |
201 | |
202 | +// source and sinkinput/client related for VOIP functionality |
203 | +void active_sink_update_voip_input_source (ActiveSink* sink, const pa_source_info* update); |
204 | +void active_sink_activate_voip_item (ActiveSink* sink, gint sink_input_index, gint client_index); |
205 | +gint active_sink_get_current_sink_input_index (ActiveSink* sink); |
206 | +gboolean active_sink_is_voip_source_populated (ActiveSink* sink); |
207 | +gint active_sink_get_source_index (ActiveSink* self); |
208 | +void active_sink_determine_blocking_state (ActiveSink* self); |
209 | +void active_sink_deactivate_voip_source (ActiveSink* self, gboolean visible); |
210 | +void active_sink_deactivate_voip_client (ActiveSink* self); |
211 | +SoundState active_sink_get_state (ActiveSink* self); |
212 | + |
213 | ActiveSink* active_sink_new (SoundServiceDbus* service); |
214 | |
215 | G_END_DECLS |
216 | |
217 | === modified file 'src/common-defs.h' |
218 | --- src/common-defs.h 2011-02-08 18:58:10 +0000 |
219 | +++ src/common-defs.h 2011-02-18 17:27:12 +0000 |
220 | @@ -31,13 +31,17 @@ |
221 | AVAILABLE |
222 | }SoundState; |
223 | |
224 | - |
225 | +#define NOT_ACTIVE -1 |
226 | #define DBUSMENU_PROPERTY_EMPTY -1 |
227 | |
228 | /* DBUS Custom Items */ |
229 | #define DBUSMENU_VOLUME_MENUITEM_TYPE "x-canonical-ido-volume-type" |
230 | #define DBUSMENU_VOLUME_MENUITEM_LEVEL "x-canonical-ido-volume-level" |
231 | |
232 | +#define DBUSMENU_VOIP_INPUT_MENUITEM_TYPE "x-canonical-ido-voip-input-type" |
233 | +#define DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL "x-canonical-ido-voip-input-level" |
234 | +#define DBUSMENU_VOIP_INPUT_MENUITEM_MUTE "x-canonical-ido-voip-input-mute" |
235 | + |
236 | #define DBUSMENU_MUTE_MENUITEM_TYPE "x-canonical-sound-menu-mute-type" |
237 | #define DBUSMENU_MUTE_MENUITEM_VALUE "x-canonical-sound-menu-mute-value" |
238 | |
239 | |
240 | === modified file 'src/indicator-sound.c' |
241 | --- src/indicator-sound.c 2011-02-16 11:20:21 +0000 |
242 | +++ src/indicator-sound.c 2011-02-18 17:27:12 +0000 |
243 | @@ -32,12 +32,12 @@ |
244 | #include "metadata-widget.h" |
245 | #include "title-widget.h" |
246 | #include "volume-widget.h" |
247 | - |
248 | +#include "voip-input-widget.h" |
249 | #include "dbus-shared-names.h" |
250 | +#include "sound-state-manager.h" |
251 | |
252 | #include "gen-sound-service.xml.h" |
253 | #include "common-defs.h" |
254 | -#include "sound-state-manager.h" |
255 | |
256 | typedef struct _IndicatorSoundPrivate IndicatorSoundPrivate; |
257 | |
258 | @@ -79,6 +79,10 @@ |
259 | DbusmenuMenuitem * parent, |
260 | DbusmenuClient * client, |
261 | gpointer user_data); |
262 | +static gboolean new_voip_slider_widget (DbusmenuMenuitem * newitem, |
263 | + DbusmenuMenuitem * parent, |
264 | + DbusmenuClient * client, |
265 | + gpointer user_data); |
266 | static gboolean new_transport_widget (DbusmenuMenuitem * newitem, |
267 | DbusmenuMenuitem * parent, |
268 | DbusmenuClient * client, |
269 | @@ -191,6 +195,9 @@ |
270 | DBUSMENU_VOLUME_MENUITEM_TYPE, |
271 | new_volume_slider_widget); |
272 | dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client), |
273 | + DBUSMENU_VOIP_INPUT_MENUITEM_TYPE, |
274 | + new_voip_slider_widget); |
275 | + dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client), |
276 | DBUSMENU_TRANSPORT_MENUITEM_TYPE, |
277 | new_transport_widget); |
278 | dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client), |
279 | @@ -403,6 +410,53 @@ |
280 | parent); |
281 | return TRUE; |
282 | } |
283 | +/** |
284 | + * new_voip_slider_widget |
285 | + * Create the voip menu item widget, must of the time this widget will be hidden. |
286 | + * @param newitem |
287 | + * @param parent |
288 | + * @param client |
289 | + * @param user_data |
290 | + * @return |
291 | + */ |
292 | +static gboolean |
293 | +new_voip_slider_widget (DbusmenuMenuitem * newitem, |
294 | + DbusmenuMenuitem * parent, |
295 | + DbusmenuClient * client, |
296 | + gpointer user_data) |
297 | +{ |
298 | + g_debug("indicator-sound: new_voip_slider_widget"); |
299 | + GtkWidget* voip_widget = NULL; |
300 | + //IndicatorObject *io = NULL; |
301 | + |
302 | + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); |
303 | + g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); |
304 | + |
305 | + voip_widget = voip_input_widget_new (newitem); |
306 | +/* |
307 | + / io = g_object_get_data (G_OBJECT (client), "indicator"); |
308 | +*/ |
309 | + //IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io)); |
310 | + //priv->volume_widget = volume_widget; |
311 | + |
312 | + GtkWidget* ido_slider_widget = voip_input_widget_get_ido_slider(VOIP_INPUT_WIDGET(voip_widget)); |
313 | + |
314 | + gtk_widget_show_all(ido_slider_widget); |
315 | + // register the style callback on this widget with state manager's style change |
316 | + // handler (needs to remake the blocking animation for each style). |
317 | +/* |
318 | + g_signal_connect (ido_slider_widget, "style-set", |
319 | + G_CALLBACK(sound_state_manager_style_changed_cb), |
320 | + priv->state_manager); |
321 | +*/ |
322 | + |
323 | + GtkMenuItem *menu_volume_item = GTK_MENU_ITEM(ido_slider_widget); |
324 | + dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), |
325 | + newitem, |
326 | + menu_volume_item, |
327 | + parent); |
328 | + return TRUE; |
329 | +} |
330 | |
331 | /*******************************************************************/ |
332 | //UI callbacks |
333 | @@ -439,19 +493,23 @@ |
334 | switch (event->keyval) { |
335 | case GDK_Right: |
336 | digested = TRUE; |
337 | +/* |
338 | if (event->state & GDK_CONTROL_MASK) { |
339 | new_value = 100; |
340 | } else { |
341 | +*/ |
342 | new_value = current_value + five_percent; |
343 | - } |
344 | + //} |
345 | break; |
346 | case GDK_Left: |
347 | digested = TRUE; |
348 | +/* |
349 | if (event->state & GDK_CONTROL_MASK) { |
350 | new_value = 0; |
351 | } else { |
352 | +*/ |
353 | new_value = current_value - five_percent; |
354 | - } |
355 | + //} |
356 | break; |
357 | case GDK_plus: |
358 | digested = TRUE; |
359 | |
360 | === modified file 'src/music-player-bridge.vala' |
361 | --- src/music-player-bridge.vala 2011-01-31 19:14:47 +0000 |
362 | +++ src/music-player-bridge.vala 2011-02-18 17:27:12 +0000 |
363 | @@ -23,11 +23,13 @@ |
364 | |
365 | public class MusicPlayerBridge : GLib.Object |
366 | { |
367 | + const int DEVICE_ITEMS_COUNT = 3; |
368 | + |
369 | private SettingsManager settings_manager; |
370 | private Dbusmenu.Menuitem root_menu; |
371 | private HashMap<string, PlayerController> registered_clients; |
372 | private Mpris2Watcher watcher; |
373 | - |
374 | + |
375 | public MusicPlayerBridge() |
376 | { |
377 | } |
378 | @@ -79,10 +81,10 @@ |
379 | private int calculate_menu_position() |
380 | { |
381 | if(this.registered_clients.size == 0){ |
382 | - return 2; |
383 | + return DEVICE_ITEMS_COUNT; |
384 | } |
385 | else{ |
386 | - return (2 + (this.registered_clients.size * PlayerController.WIDGET_QUANTITY)); |
387 | + return (DEVICE_ITEMS_COUNT + (this.registered_clients.size * PlayerController.WIDGET_QUANTITY)); |
388 | } |
389 | } |
390 | |
391 | |
392 | === modified file 'src/mute-menu-item.c' |
393 | --- src/mute-menu-item.c 2011-02-07 18:08:19 +0000 |
394 | +++ src/mute-menu-item.c 2011-02-18 17:27:12 +0000 |
395 | @@ -61,6 +61,7 @@ |
396 | { |
397 | g_debug("Building new Mute Menu Item"); |
398 | MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE(self); |
399 | + priv->button = NULL; |
400 | priv->button = dbusmenu_menuitem_new(); |
401 | dbusmenu_menuitem_property_set_bool (priv->button, |
402 | DBUSMENU_MENUITEM_PROP_VISIBLE, |
403 | |
404 | === modified file 'src/player-item.vala' |
405 | --- src/player-item.vala 2011-02-09 10:56:49 +0000 |
406 | +++ src/player-item.vala 2011-02-18 17:27:12 +0000 |
407 | @@ -94,9 +94,8 @@ |
408 | { |
409 | foreach(string prop in attrs){ |
410 | //debug("populated ? - prop: %s", prop); |
411 | - int value_int = property_get_int(prop); |
412 | if(property_get_int(prop) != EMPTY){ |
413 | - //debug("populated - prop %s and value %i", prop, value_int); |
414 | + //debug("populated - prop %s and value %i", prop, property_get_int(prop)); |
415 | return true; |
416 | } |
417 | } |
418 | |
419 | === modified file 'src/pulseaudio-mgr.c' |
420 | --- src/pulseaudio-mgr.c 2011-02-10 14:34:51 +0000 |
421 | +++ src/pulseaudio-mgr.c 2011-02-18 17:27:12 +0000 |
422 | @@ -19,9 +19,9 @@ |
423 | |
424 | /**Notes |
425 | * |
426 | - * Approach now is to set up the communication channels then query the server |
427 | - * fetch its default sink. If this fails then fetch the list of sinks and take |
428 | - * the first one which is not the auto-null sink. |
429 | + * Approach now is to set up the communication channels, query the server |
430 | + * fetch its default sink/source. If this fails then fetch the list of sinks/sources |
431 | + * and take the first one which is not the auto-null sink. |
432 | * TODO: need to handle the situation where one chink in this linear chain breaks |
433 | * i.e. start off the process again and count the attempts (note different to |
434 | reconnect attempts) |
435 | @@ -47,10 +47,22 @@ |
436 | const pa_sink_info *info, |
437 | int eol, |
438 | void *userdata); |
439 | +static void pm_default_source_info_callback (pa_context *c, |
440 | + const pa_source_info *info, |
441 | + int eol, |
442 | + void *userdata); |
443 | static void pm_sink_info_callback (pa_context *c, |
444 | const pa_sink_info *sink, |
445 | int eol, |
446 | void *userdata); |
447 | +static void pm_source_info_callback (pa_context *c, |
448 | + const pa_source_info *info, |
449 | + int eol, |
450 | + void *userdata); |
451 | +static void pm_update_source_info_callback (pa_context *c, |
452 | + const pa_source_info *info, |
453 | + int eol, |
454 | + void *userdata); |
455 | static void pm_sink_input_info_callback (pa_context *c, |
456 | const pa_sink_input_info *info, |
457 | int eol, |
458 | @@ -64,6 +76,7 @@ |
459 | int eol, |
460 | void* userdata); |
461 | |
462 | + |
463 | static gboolean reconnect_to_pulse (gpointer user_data); |
464 | |
465 | static gint connection_attempts = 0; |
466 | @@ -152,6 +165,25 @@ |
467 | GINT_TO_POINTER (update))); |
468 | } |
469 | |
470 | +void |
471 | +pm_update_mic_gain (gint source_index, pa_cvolume new_gain) |
472 | +{ |
473 | + pa_operation_unref (pa_context_set_source_volume_by_index (pulse_context, |
474 | + source_index, |
475 | + &new_gain, |
476 | + NULL, |
477 | + NULL) ); |
478 | +} |
479 | + |
480 | +void |
481 | +pm_update_mic_mute (gint source_index, gint mute_update) |
482 | +{ |
483 | + pa_operation_unref (pa_context_set_source_mute_by_index (pulse_context, |
484 | + source_index, |
485 | + mute_update, |
486 | + NULL, |
487 | + NULL)); |
488 | +} |
489 | /**********************************************************************************************************************/ |
490 | // Pulse-Audio asychronous call-backs |
491 | /**********************************************************************************************************************/ |
492 | @@ -163,19 +195,21 @@ |
493 | uint32_t index, |
494 | void* userdata) |
495 | { |
496 | + if (IS_ACTIVE_SINK (userdata) == FALSE){ |
497 | + g_critical ("subscribed events callback - our userdata is not what we think it should be"); |
498 | + return; |
499 | + } |
500 | + ActiveSink* sink = ACTIVE_SINK (userdata); |
501 | + |
502 | switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { |
503 | case PA_SUBSCRIPTION_EVENT_SINK: |
504 | - if (IS_ACTIVE_SINK (userdata) == FALSE){ |
505 | - g_warning ("subscribed events callback - our userdata is not what we think it should be"); |
506 | - return; |
507 | - } |
508 | - ActiveSink* sink = ACTIVE_SINK (userdata); |
509 | + |
510 | // We don't care about any other sink other than the active one. |
511 | if (index != active_sink_get_index (sink)) |
512 | - return; |
513 | + return; |
514 | |
515 | if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { |
516 | - active_sink_deactivate (ACTIVE_SINK (userdata)); |
517 | + active_sink_deactivate (sink); |
518 | |
519 | } |
520 | else{ |
521 | @@ -185,9 +219,36 @@ |
522 | userdata) ); |
523 | } |
524 | break; |
525 | + case PA_SUBSCRIPTION_EVENT_SOURCE: |
526 | + g_debug ("Looks like source event of some description"); |
527 | + // We don't care about any other sink other than the active one. |
528 | + if (index != active_sink_get_source_index (sink)) |
529 | + return; |
530 | + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { |
531 | + active_sink_deactivate_voip_source (sink, FALSE); |
532 | + } |
533 | + else{ |
534 | + pa_operation_unref (pa_context_get_source_info_by_index (c, |
535 | + index, |
536 | + pm_update_source_info_callback, |
537 | + userdata) ); |
538 | + } |
539 | + break; |
540 | case PA_SUBSCRIPTION_EVENT_SINK_INPUT: |
541 | // We don't care about sink input removals. |
542 | - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_REMOVE) { |
543 | + g_debug ("sink input event"); |
544 | + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { |
545 | + gint cached_index = active_sink_get_current_sink_input_index (sink); |
546 | + |
547 | + g_debug ("Just saw a sink input removal event - index = %i and cached index = %i", index, cached_index); |
548 | + |
549 | + if (index == cached_index){ |
550 | + active_sink_deactivate_voip_client (sink); |
551 | + } |
552 | + } |
553 | + else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { |
554 | + g_debug ("some new sink input event ? - index = %i", index); |
555 | + // Determine if its a VOIP app or a maybe blocking state. |
556 | pa_operation_unref (pa_context_get_sink_input_info (c, |
557 | index, |
558 | pm_sink_input_info_callback, userdata)); |
559 | @@ -206,6 +267,7 @@ |
560 | } |
561 | |
562 | |
563 | + |
564 | static void |
565 | pm_context_state_callback (pa_context *c, void *userdata) |
566 | { |
567 | @@ -244,6 +306,7 @@ |
568 | |
569 | if (!(o = pa_context_subscribe (c, (pa_subscription_mask_t) |
570 | (PA_SUBSCRIPTION_MASK_SINK| |
571 | + PA_SUBSCRIPTION_MASK_SOURCE| |
572 | PA_SUBSCRIPTION_MASK_SINK_INPUT| |
573 | PA_SUBSCRIPTION_MASK_SERVER), NULL, NULL))) { |
574 | g_warning("pa_context_subscribe() failed"); |
575 | @@ -261,7 +324,8 @@ |
576 | |
577 | /** |
578 | After startup we go straight for the server info to see if it has details of |
579 | - the default sink. If so it makes things much easier. |
580 | + the default sink and source. Normally these are valid, if there is none set |
581 | + fetch the list of each and try to determine the sink. |
582 | **/ |
583 | static void |
584 | pm_server_info_callback (pa_context *c, |
585 | @@ -276,24 +340,46 @@ |
586 | active_sink_deactivate (ACTIVE_SINK (userdata)); |
587 | return; |
588 | } |
589 | + // Go for the default sink |
590 | if (info->default_sink_name != NULL) { |
591 | g_debug ("default sink name from the server ain't null'"); |
592 | if (!(operation = pa_context_get_sink_info_by_name (c, |
593 | info->default_sink_name, |
594 | pm_default_sink_info_callback, |
595 | userdata) )) { |
596 | - } |
597 | - else{ |
598 | + g_warning("pa_context_get_sink_info_by_namet() failed"); |
599 | + active_sink_deactivate (ACTIVE_SINK (userdata)); |
600 | pa_operation_unref(operation); |
601 | return; |
602 | } |
603 | - } |
604 | + } // If there is no default sink, try to determine a sink from the list of sinks |
605 | else if (!(operation = pa_context_get_sink_info_list(c, |
606 | pm_sink_info_callback, |
607 | - NULL))) { |
608 | + userdata))) { |
609 | g_warning("pa_context_get_sink_info_list() failed"); |
610 | + active_sink_deactivate (ACTIVE_SINK (userdata)); |
611 | + pa_operation_unref(operation); |
612 | return; |
613 | } |
614 | + // And the source |
615 | + if (info->default_source_name != NULL) { |
616 | + g_debug ("default source name from the server is not null'"); |
617 | + if (!(operation = pa_context_get_source_info_by_name (c, |
618 | + info->default_source_name, |
619 | + pm_default_source_info_callback, |
620 | + userdata) )) { |
621 | + g_warning("pa_context_get_default_source_info() failed"); |
622 | + // TODO: call some input deactivate method on active sink |
623 | + pa_operation_unref(operation); |
624 | + return; |
625 | + } |
626 | + } |
627 | + else if (!(operation = pa_context_get_source_info_list(c, |
628 | + pm_source_info_callback, |
629 | + userdata))) { |
630 | + g_warning("pa_context_get_sink_info_list() failed"); |
631 | + // TODO: call some input deactivate method for the source |
632 | + } |
633 | pa_operation_unref(operation); |
634 | } |
635 | |
636 | @@ -335,8 +421,12 @@ |
637 | if (IS_ACTIVE_SINK (userdata) == FALSE){ |
638 | g_warning ("Default sink info callback - our user data is not what we think it should be"); |
639 | return; |
640 | - } |
641 | - g_debug ("server has handed us a default sink"); |
642 | + } |
643 | + // Only repopulate if there is a change with regards the index |
644 | + if (active_sink_get_index (ACTIVE_SINK (userdata)) == info->index) |
645 | + return; |
646 | + |
647 | + g_debug ("Pulse Server has handed us a new default sink"); |
648 | active_sink_populate (ACTIVE_SINK (userdata), info); |
649 | } |
650 | } |
651 | @@ -356,12 +446,30 @@ |
652 | g_warning("\n Sink input info callback : SINK INPUT INFO IS NULL BUT EOL was not POSITIVE!!!"); |
653 | return; |
654 | } |
655 | + |
656 | if (IS_ACTIVE_SINK (userdata) == FALSE){ |
657 | g_warning ("sink input info callback - our user data is not what we think it should be"); |
658 | return; |
659 | } |
660 | - |
661 | + // Check if this is Voip sink input |
662 | + gint result = pa_proplist_contains (info->proplist, PA_PROP_MEDIA_ROLE); |
663 | ActiveSink* a_sink = ACTIVE_SINK (userdata); |
664 | + |
665 | + if (result == 1){ |
666 | + g_debug ("Sink input info has media role property"); |
667 | + const char* value = pa_proplist_gets (info->proplist, PA_PROP_MEDIA_ROLE); |
668 | + g_debug ("prop role = %s", value); |
669 | + if (g_strcmp0 (value, "phone") == 0) { |
670 | + g_debug ("And yes its a VOIP app ... sink input index = %i", info->index); |
671 | + active_sink_activate_voip_item (a_sink, (gint)info->index, (gint)info->client); |
672 | + // TODO to start with we will assume our source is the same as what this 'client' |
673 | + // is pointing at. This should probably be more intelligent : |
674 | + // query for the list of source output info's and going on the name of the client |
675 | + // from the sink input ensure our voip item is using the right source. |
676 | + } |
677 | + } |
678 | + |
679 | + // And finally check for the mute blocking state |
680 | if (active_sink_get_index (a_sink) == info->sink){ |
681 | active_sink_determine_blocking_state (a_sink); |
682 | } |
683 | @@ -404,3 +512,66 @@ |
684 | } |
685 | } |
686 | |
687 | +// Source info related callbacks |
688 | +static void |
689 | +pm_default_source_info_callback (pa_context *c, |
690 | + const pa_source_info *info, |
691 | + int eol, |
692 | + void *userdata) |
693 | +{ |
694 | + if (eol > 0) { |
695 | + return; |
696 | + } |
697 | + else { |
698 | + if (IS_ACTIVE_SINK (userdata) == FALSE){ |
699 | + g_warning ("Default sink info callback - our user data is not what we think it should be"); |
700 | + return; |
701 | + } |
702 | + // If there is an index change we need to change our cached source |
703 | + if (active_sink_get_source_index (ACTIVE_SINK (userdata)) == info->index) |
704 | + return; |
705 | + g_debug ("Pulse Server has handed us a new default source"); |
706 | + active_sink_deactivate_voip_source (ACTIVE_SINK (userdata), TRUE); |
707 | + active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info); |
708 | + } |
709 | +} |
710 | + |
711 | +static void |
712 | +pm_source_info_callback (pa_context *c, |
713 | + const pa_source_info *info, |
714 | + int eol, |
715 | + void *userdata) |
716 | +{ |
717 | + if (eol > 0) { |
718 | + return; |
719 | + } |
720 | + else { |
721 | + if (IS_ACTIVE_SINK (userdata) == FALSE){ |
722 | + g_warning ("Default sink info callback - our user data is not what we think it should be"); |
723 | + return; |
724 | + } |
725 | + // For now we will take the first available |
726 | + if (active_sink_is_voip_source_populated (ACTIVE_SINK (userdata)) == FALSE){ |
727 | + active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info); |
728 | + } |
729 | + } |
730 | +} |
731 | + |
732 | +static void |
733 | +pm_update_source_info_callback (pa_context *c, |
734 | + const pa_source_info *info, |
735 | + int eol, |
736 | + void *userdata) |
737 | +{ |
738 | + if (eol > 0) { |
739 | + return; |
740 | + } |
741 | + else { |
742 | + if (IS_ACTIVE_SINK (userdata) == FALSE){ |
743 | + g_warning ("Default sink info callback - our user data is not what we think it should be"); |
744 | + return; |
745 | + } |
746 | + g_debug ("Got a source update for %s , index %i", info->name, info->index); |
747 | + active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info); |
748 | + } |
749 | +} |
750 | \ No newline at end of file |
751 | |
752 | === modified file 'src/pulseaudio-mgr.h' |
753 | --- src/pulseaudio-mgr.h 2011-02-07 11:19:17 +0000 |
754 | +++ src/pulseaudio-mgr.h 2011-02-18 17:27:12 +0000 |
755 | @@ -22,6 +22,8 @@ |
756 | void pm_establish_pulse_connection (ActiveSink* active_sink); |
757 | void close_pulse_activites(); |
758 | void pm_update_volume (gint sink_index, pa_cvolume new_volume); |
759 | +void pm_update_mic_gain (gint source_index, pa_cvolume new_gain); |
760 | +void pm_update_mic_mute (gint source_index, int mute_update); |
761 | void pm_update_mute (gboolean update); |
762 | |
763 | |
764 | |
765 | === modified file 'src/settings-manager.vala' |
766 | --- src/settings-manager.vala 2011-02-01 01:33:46 +0000 |
767 | +++ src/settings-manager.vala 2011-02-18 17:27:12 +0000 |
768 | @@ -71,6 +71,7 @@ |
769 | |
770 | // Convenient debug method inorder to provide visability over |
771 | // the contents of both interested and blacklisted containers in its gsettings |
772 | +/** |
773 | private void reveal_contents() |
774 | { |
775 | var already_interested = this.settings.get_strv ("interested-media-players"); |
776 | @@ -87,4 +88,5 @@ |
777 | debug ("interested array size = %i", already_interested.length); |
778 | debug ("blacklisted array size = %i", blacklisted.length); |
779 | } |
780 | +**/ |
781 | } |
782 | |
783 | === modified file 'src/sound-service-dbus.c' |
784 | --- src/sound-service-dbus.c 2011-02-04 18:25:54 +0000 |
785 | +++ src/sound-service-dbus.c 2011-02-18 17:27:12 +0000 |
786 | @@ -157,14 +157,18 @@ |
787 | void |
788 | sound_service_dbus_build_sound_menu ( SoundServiceDbus* self, |
789 | DbusmenuMenuitem* mute_item, |
790 | - DbusmenuMenuitem* slider_item) |
791 | + DbusmenuMenuitem* slider_item, |
792 | + DbusmenuMenuitem* voip_input_menu_item) |
793 | { |
794 | SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self); |
795 | |
796 | // Mute button |
797 | + // TODO this additions should be fixed position, i.e. add via position and not just append |
798 | + // be explicit as it is fixed. |
799 | dbusmenu_menuitem_child_append (priv->root_menuitem, mute_item); |
800 | + dbusmenu_menuitem_child_append (priv->root_menuitem, slider_item); |
801 | g_debug ("just about to add the slider %i", DBUSMENU_IS_MENUITEM(slider_item)); |
802 | - dbusmenu_menuitem_child_append (priv->root_menuitem, slider_item); |
803 | + dbusmenu_menuitem_child_append (priv->root_menuitem, voip_input_menu_item); |
804 | |
805 | // Separator |
806 | DbusmenuMenuitem* separator = dbusmenu_menuitem_new(); |
807 | |
808 | === modified file 'src/sound-service-dbus.h' |
809 | --- src/sound-service-dbus.h 2011-02-04 16:17:31 +0000 |
810 | +++ src/sound-service-dbus.h 2011-02-18 17:27:12 +0000 |
811 | @@ -57,7 +57,8 @@ |
812 | void sound_service_dbus_update_sound_state (SoundServiceDbus* self, SoundState new_state); |
813 | void sound_service_dbus_build_sound_menu ( SoundServiceDbus* self, |
814 | DbusmenuMenuitem* mute_item, |
815 | - DbusmenuMenuitem* slider_item); |
816 | + DbusmenuMenuitem* slider_item, |
817 | + DbusmenuMenuitem* voip_input_menu_item); |
818 | |
819 | |
820 | G_END_DECLS |
821 | |
822 | === modified file 'src/sound-service.c' |
823 | --- src/sound-service.c 2011-02-09 10:57:13 +0000 |
824 | +++ src/sound-service.c 2011-02-18 17:27:12 +0000 |
825 | @@ -39,8 +39,10 @@ |
826 | { |
827 | if (mainloop != NULL) { |
828 | g_debug("Service shutdown !"); |
829 | + |
830 | close_pulse_activites(); |
831 | g_main_loop_quit(mainloop); |
832 | + |
833 | } |
834 | return; |
835 | } |
836 | |
837 | === added file 'src/voip-input-menu-item.c' |
838 | --- src/voip-input-menu-item.c 1970-01-01 00:00:00 +0000 |
839 | +++ src/voip-input-menu-item.c 2011-02-18 17:27:12 +0000 |
840 | @@ -0,0 +1,277 @@ |
841 | +/* |
842 | +Copyright 2011 Canonical Ltd. |
843 | + |
844 | +Authors: |
845 | + Conor Curran <conor.curran@canonical.com> |
846 | + |
847 | +This program is free software: you can redistribute it and/or modify it |
848 | +under the terms of the GNU General Public License version 3, as published |
849 | +by the Free Software Foundation. |
850 | + |
851 | +This program is distributed in the hope that it will be useful, but |
852 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
853 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
854 | +PURPOSE. See the GNU General Public License for more details. |
855 | + |
856 | +You should have received a copy of the GNU General Public License along |
857 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
858 | +*/ |
859 | +#ifdef HAVE_CONFIG_H |
860 | +#include "config.h" |
861 | +#endif |
862 | + |
863 | +#include <glib/gi18n.h> |
864 | +#include "voip-input-menu-item.h" |
865 | +#include "common-defs.h" |
866 | +#include "pulseaudio-mgr.h" |
867 | + |
868 | +typedef struct _VoipInputMenuItemPrivate VoipInputMenuItemPrivate; |
869 | + |
870 | +struct _VoipInputMenuItemPrivate { |
871 | + ActiveSink* a_sink; |
872 | + pa_cvolume volume; |
873 | + gint mute; |
874 | + guint32 volume_steps; |
875 | + pa_channel_map channel_map; |
876 | + pa_volume_t base_volume; |
877 | + gint source_index; |
878 | + gint sink_input_index; |
879 | + gint client_index; |
880 | +}; |
881 | + |
882 | +#define VOIP_INPUT_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItemPrivate)) |
883 | + |
884 | +/* Prototypes */ |
885 | +static void voip_input_menu_item_class_init (VoipInputMenuItemClass *klass); |
886 | +static void voip_input_menu_item_init (VoipInputMenuItem *self); |
887 | +static void voip_input_menu_item_dispose (GObject *object); |
888 | +static void voip_input_menu_item_finalize (GObject *object); |
889 | +static void handle_event (DbusmenuMenuitem * mi, const gchar * name, |
890 | + GVariant * value, guint timestamp); |
891 | +// TODO: |
892 | +// This method should really be shared between this and the volume slider obj |
893 | +// perfectly static - wait until the device mgr wrapper is properly sorted and |
894 | +// then consolidate |
895 | +static pa_cvolume voip_input_menu_item_construct_mono_volume (const pa_cvolume* vol); |
896 | + |
897 | +G_DEFINE_TYPE (VoipInputMenuItem, voip_input_menu_item, DBUSMENU_TYPE_MENUITEM); |
898 | + |
899 | +static void |
900 | +voip_input_menu_item_class_init (VoipInputMenuItemClass *klass) |
901 | +{ |
902 | + GObjectClass *object_class = G_OBJECT_CLASS (klass); |
903 | + |
904 | + g_type_class_add_private (klass, sizeof (VoipInputMenuItemPrivate)); |
905 | + |
906 | + object_class->dispose = voip_input_menu_item_dispose; |
907 | + object_class->finalize = voip_input_menu_item_finalize; |
908 | + |
909 | + DbusmenuMenuitemClass * mclass = DBUSMENU_MENUITEM_CLASS(klass); |
910 | + mclass->handle_event = handle_event; |
911 | +} |
912 | + |
913 | +static void |
914 | +voip_input_menu_item_init (VoipInputMenuItem *self) |
915 | +{ |
916 | + g_debug("Building new Slider Menu Item"); |
917 | + dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self), |
918 | + DBUSMENU_MENUITEM_PROP_TYPE, |
919 | + DBUSMENU_VOIP_INPUT_MENUITEM_TYPE ); |
920 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (self); |
921 | + dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(self), |
922 | + DBUSMENU_MENUITEM_PROP_VISIBLE, |
923 | + FALSE ); |
924 | + |
925 | + priv->source_index = NOT_ACTIVE; |
926 | + priv->sink_input_index = NOT_ACTIVE; |
927 | + priv->client_index = NOT_ACTIVE; |
928 | + priv->mute = NOT_ACTIVE; |
929 | +} |
930 | + |
931 | +static void |
932 | +voip_input_menu_item_dispose (GObject *object) |
933 | +{ |
934 | + G_OBJECT_CLASS (voip_input_menu_item_parent_class)->dispose (object); |
935 | + return; |
936 | +} |
937 | + |
938 | +static void |
939 | +voip_input_menu_item_finalize (GObject *object) |
940 | +{ |
941 | + G_OBJECT_CLASS (voip_input_menu_item_parent_class)->finalize (object); |
942 | +} |
943 | + |
944 | +static void |
945 | +handle_event (DbusmenuMenuitem * mi, |
946 | + const gchar * name, |
947 | + GVariant * value, |
948 | + guint timestamp) |
949 | +{ |
950 | + GVariant* input = NULL; |
951 | + input = value; |
952 | + if (g_variant_is_of_type(value, G_VARIANT_TYPE_VARIANT) == TRUE) { |
953 | + input = g_variant_get_variant(value); |
954 | + } |
955 | + |
956 | + gdouble percent = g_variant_get_double(input); |
957 | + if (value != NULL){ |
958 | + if (IS_VOIP_INPUT_MENU_ITEM (mi)) { |
959 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (VOIP_INPUT_MENU_ITEM (mi)); |
960 | + g_debug ("Handle event in the voip input level backend instance - %f", percent); |
961 | + pa_cvolume new_volume; |
962 | + pa_cvolume_init(&new_volume); |
963 | + new_volume.channels = 1; |
964 | + pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100); |
965 | + pa_cvolume_set(&new_volume, 1, new_volume_value); |
966 | + |
967 | + pm_update_mic_gain (priv->source_index, new_volume); |
968 | + // finally unmute if needed |
969 | + if (priv->mute == 1) { |
970 | + pm_update_mic_mute (priv->source_index, 0); |
971 | + } |
972 | + //active_sink_update_volume (priv->a_sink, volume_input); |
973 | + //active_sink_ensure_sink_is_unmuted (priv->a_sink); |
974 | + } |
975 | + } |
976 | +} |
977 | + |
978 | +static pa_cvolume |
979 | +voip_input_menu_item_construct_mono_volume (const pa_cvolume* vol) |
980 | +{ |
981 | + pa_cvolume new_volume; |
982 | + pa_cvolume_init(&new_volume); |
983 | + new_volume.channels = 1; |
984 | + pa_volume_t max_vol = pa_cvolume_max(vol); |
985 | + pa_cvolume_set(&new_volume, 1, max_vol); |
986 | + return new_volume; |
987 | +} |
988 | + |
989 | +void |
990 | +voip_input_menu_item_update (VoipInputMenuItem* item, |
991 | + const pa_source_info* source) |
992 | +{ |
993 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); |
994 | + // only overwrite the constants of each source if the device has changed |
995 | + if (priv->source_index == NOT_ACTIVE){ |
996 | + priv->base_volume = source->base_volume; |
997 | + priv->volume_steps = source->n_volume_steps; |
998 | + priv->channel_map = source->channel_map; |
999 | + priv->source_index = source->index; |
1000 | + } |
1001 | + priv->volume = voip_input_menu_item_construct_mono_volume (&source->volume); |
1002 | + pa_volume_t vol = pa_cvolume_max (&source->volume); |
1003 | + gdouble update = ((gdouble) vol * 100) / PA_VOLUME_NORM; |
1004 | + |
1005 | + GVariant* new_volume = g_variant_new_double(update); |
1006 | + dbusmenu_menuitem_property_set_variant(DBUSMENU_MENUITEM(item), |
1007 | + DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL, |
1008 | + new_volume); |
1009 | + // Only send over the mute updates if the state has changed. |
1010 | + // in this order - volume first mute last!! |
1011 | + if (priv->mute != source->mute){ |
1012 | + g_debug ("voip menu item - update - mute = %i", priv->mute); |
1013 | + GVariant* new_mute_update = g_variant_new_int32 (source->mute); |
1014 | + dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(item), |
1015 | + DBUSMENU_VOIP_INPUT_MENUITEM_MUTE, |
1016 | + new_mute_update); |
1017 | + } |
1018 | + |
1019 | + priv->mute = source->mute; |
1020 | + |
1021 | +} |
1022 | + |
1023 | +gboolean |
1024 | +voip_input_menu_item_is_interested (VoipInputMenuItem* item, |
1025 | + gint sink_input_index, |
1026 | + gint client_index) |
1027 | +{ |
1028 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); |
1029 | + // Check to make sure we are not handling another voip beforehand and that we |
1030 | + // have an active sink (might need to match up at start up) |
1031 | + if (priv->sink_input_index != NOT_ACTIVE && |
1032 | + priv->source_index != NOT_ACTIVE){ |
1033 | + return FALSE; |
1034 | + } |
1035 | + |
1036 | + priv->sink_input_index = sink_input_index; |
1037 | + priv->client_index = client_index; |
1038 | + |
1039 | + return TRUE; |
1040 | +} |
1041 | + |
1042 | +gboolean |
1043 | +voip_input_menu_item_is_active (VoipInputMenuItem* item) |
1044 | +{ |
1045 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); |
1046 | + return (priv->sink_input_index != NOT_ACTIVE && priv->client_index != NOT_ACTIVE); |
1047 | +} |
1048 | + |
1049 | + |
1050 | +gboolean |
1051 | +voip_input_menu_item_is_populated (VoipInputMenuItem* item) |
1052 | +{ |
1053 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); |
1054 | + return priv->source_index != NOT_ACTIVE; |
1055 | +} |
1056 | + |
1057 | +gint |
1058 | +voip_input_menu_item_get_index (VoipInputMenuItem* item) |
1059 | +{ |
1060 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); |
1061 | + return priv->source_index; |
1062 | +} |
1063 | + |
1064 | +gint |
1065 | +voip_input_menu_item_get_sink_input_index (VoipInputMenuItem* item) |
1066 | +{ |
1067 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); |
1068 | + |
1069 | + return priv->sink_input_index; |
1070 | +} |
1071 | + |
1072 | +/** |
1073 | + * If the pulse server informs of a default source change |
1074 | + * or the source in question is removed. |
1075 | + * @param item |
1076 | + */ |
1077 | +void |
1078 | +voip_input_menu_item_deactivate_source (VoipInputMenuItem* item, gboolean visible) |
1079 | +{ |
1080 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); |
1081 | + priv->source_index = NOT_ACTIVE; |
1082 | + dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item), |
1083 | + DBUSMENU_MENUITEM_PROP_VISIBLE, |
1084 | + visible ); |
1085 | +} |
1086 | + |
1087 | +void |
1088 | +voip_input_menu_item_deactivate_voip_client (VoipInputMenuItem* item) |
1089 | +{ |
1090 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); |
1091 | + priv->client_index = NOT_ACTIVE; |
1092 | + priv->sink_input_index = NOT_ACTIVE; |
1093 | + voip_input_menu_item_enable (item, FALSE); |
1094 | +} |
1095 | + |
1096 | +void |
1097 | +voip_input_menu_item_enable (VoipInputMenuItem* item, |
1098 | + gboolean active) |
1099 | +{ |
1100 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); |
1101 | + if (priv->source_index == NOT_ACTIVE && active == TRUE) { |
1102 | + g_warning ("Tried to enable the VOIP menuitem but we don't have an active source ??"); |
1103 | + active = FALSE; |
1104 | + } |
1105 | + dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item), |
1106 | + DBUSMENU_MENUITEM_PROP_VISIBLE, |
1107 | + active ); |
1108 | +} |
1109 | + |
1110 | +VoipInputMenuItem* |
1111 | +voip_input_menu_item_new (ActiveSink* sink) |
1112 | +{ |
1113 | + VoipInputMenuItem *self = g_object_new(VOIP_INPUT_MENU_ITEM_TYPE, NULL); |
1114 | + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (self); |
1115 | + priv->a_sink = sink; |
1116 | + return self; |
1117 | +} |
1118 | \ No newline at end of file |
1119 | |
1120 | === added file 'src/voip-input-menu-item.h' |
1121 | --- src/voip-input-menu-item.h 1970-01-01 00:00:00 +0000 |
1122 | +++ src/voip-input-menu-item.h 2011-02-18 17:27:12 +0000 |
1123 | @@ -0,0 +1,70 @@ |
1124 | +/* |
1125 | +Copyright 2011 Canonical Ltd. |
1126 | + |
1127 | +Authors: |
1128 | + Conor Curran <conor.curran@canonical.com> |
1129 | + |
1130 | +This program is free software: you can redistribute it and/or modify it |
1131 | +under the terms of the GNU General Public License version 3, as published |
1132 | +by the Free Software Foundation. |
1133 | + |
1134 | +This program is distributed in the hope that it will be useful, but |
1135 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
1136 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1137 | +PURPOSE. See the GNU General Public License for more details. |
1138 | + |
1139 | +You should have received a copy of the GNU General Public License along |
1140 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
1141 | +*/ |
1142 | +#ifndef __VOIP_INPUT_MENU_ITEM_H__ |
1143 | +#define __VOIP_INPUT_MENU_ITEM_H__ |
1144 | + |
1145 | +#include <glib.h> |
1146 | +#include <pulse/pulseaudio.h> |
1147 | +#include <libdbusmenu-glib/menuitem.h> |
1148 | +#include "active-sink.h" |
1149 | + |
1150 | +G_BEGIN_DECLS |
1151 | + |
1152 | +#define VOIP_INPUT_MENU_ITEM_TYPE (voip_input_menu_item_get_type ()) |
1153 | +#define VOIP_INPUT_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItem)) |
1154 | +#define VOIP_INPUT_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItemClass)) |
1155 | +#define IS_VOIP_INPUT_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VOIP_INPUT_MENU_ITEM_TYPE)) |
1156 | +#define IS_VOIP_INPUT_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VOIP_INPUT_MENU_ITEM_TYPE)) |
1157 | +#define VOIP_INPUT_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItemClass)) |
1158 | + |
1159 | +typedef struct _VoipInputMenuItem VoipInputMenuItem; |
1160 | +typedef struct _VoipInputMenuItemClass VoipInputMenuItemClass; |
1161 | + |
1162 | +struct _VoipInputMenuItemClass { |
1163 | + DbusmenuMenuitemClass parent_class; |
1164 | +}; |
1165 | + |
1166 | +struct _VoipInputMenuItem { |
1167 | + DbusmenuMenuitem parent; |
1168 | +}; |
1169 | + |
1170 | +GType voip_input_menu_item_get_type (void); |
1171 | + |
1172 | +void voip_input_menu_item_update (VoipInputMenuItem* item, |
1173 | + const pa_source_info* source); |
1174 | +void voip_input_menu_item_enable (VoipInputMenuItem* item, gboolean active); |
1175 | +gboolean voip_input_menu_item_is_interested (VoipInputMenuItem* item, |
1176 | + gint sink_input_index, |
1177 | + gint client_index); |
1178 | +gboolean voip_input_menu_item_is_active (VoipInputMenuItem* item); |
1179 | +gboolean voip_input_menu_item_is_populated (VoipInputMenuItem* item); |
1180 | +// TODO rename get source index |
1181 | +gint voip_input_menu_item_get_index (VoipInputMenuItem* item); |
1182 | + |
1183 | +gint voip_input_menu_item_get_sink_input_index (VoipInputMenuItem* item); |
1184 | + |
1185 | +void voip_input_menu_item_deactivate_source (VoipInputMenuItem* item, gboolean visible); |
1186 | +void voip_input_menu_item_deactivate_voip_client (VoipInputMenuItem* item); |
1187 | + |
1188 | +VoipInputMenuItem* voip_input_menu_item_new (ActiveSink* sink); |
1189 | + |
1190 | +G_END_DECLS |
1191 | + |
1192 | +#endif |
1193 | + |
1194 | |
1195 | === added file 'src/voip-input-widget.c' |
1196 | --- src/voip-input-widget.c 1970-01-01 00:00:00 +0000 |
1197 | +++ src/voip-input-widget.c 2011-02-18 17:27:12 +0000 |
1198 | @@ -0,0 +1,279 @@ |
1199 | + |
1200 | +/* |
1201 | +Copyright 2011 Canonical Ltd. |
1202 | + |
1203 | +Authors: |
1204 | + Conor Curran <conor.curran@canonical.com> |
1205 | + |
1206 | +This program is free software: you can redistribute it and/or modify it |
1207 | +under the terms of the GNU General Public License version 3, as published |
1208 | +by the Free Software Foundation. |
1209 | + |
1210 | +This program is distributed in the hope that it will be useful, but |
1211 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
1212 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1213 | +PURPOSE. See the GNU General Public License for more details. |
1214 | + |
1215 | +You should have received a copy of the GNU General Public License along |
1216 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
1217 | +*/ |
1218 | + |
1219 | +#ifdef HAVE_CONFIG_H |
1220 | +#include "config.h" |
1221 | +#endif |
1222 | + |
1223 | +#include <glib/gi18n.h> |
1224 | +#include <math.h> |
1225 | +#include <glib.h> |
1226 | +#include "voip-input-widget.h" |
1227 | +#include "common-defs.h" |
1228 | +#include <libido/idoscalemenuitem.h> |
1229 | + |
1230 | +typedef struct _VoipInputWidgetPrivate VoipInputWidgetPrivate; |
1231 | + |
1232 | +struct _VoipInputWidgetPrivate |
1233 | +{ |
1234 | + DbusmenuMenuitem* twin_item; |
1235 | + GtkWidget* ido_voip_input_slider; |
1236 | + gboolean grabbed; |
1237 | +}; |
1238 | + |
1239 | +#define VOIP_INPUT_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOIP_INPUT_WIDGET_TYPE, VoipInputWidgetPrivate)) |
1240 | + |
1241 | +/* Prototypes */ |
1242 | +static void voip_input_widget_class_init (VoipInputWidgetClass *klass); |
1243 | +static void voip_input_widget_init (VoipInputWidget *self); |
1244 | +static void voip_input_widget_dispose (GObject *object); |
1245 | +static void voip_input_widget_finalize (GObject *object); |
1246 | +static void voip_input_widget_set_twin_item( VoipInputWidget* self, |
1247 | + DbusmenuMenuitem* twin_item); |
1248 | +static void voip_input_widget_property_update( DbusmenuMenuitem* item, gchar* property, |
1249 | + GVariant* value, gpointer userdata ); |
1250 | + |
1251 | +static gboolean voip_input_widget_change_value_cb (GtkRange *range, |
1252 | + GtkScrollType scroll, |
1253 | + gdouble value, |
1254 | + gpointer user_data); |
1255 | +static gboolean voip_input_widget_value_changed_cb(GtkRange *range, gpointer user_data); |
1256 | +static void voip_input_widget_slider_grabbed(GtkWidget *widget, gpointer user_data); |
1257 | +static void voip_input_widget_slider_released(GtkWidget *widget, gpointer user_data); |
1258 | +static void voip_input_widget_parent_changed (GtkWidget *widget, gpointer user_data); |
1259 | + |
1260 | +G_DEFINE_TYPE (VoipInputWidget, voip_input_widget, G_TYPE_OBJECT); |
1261 | + |
1262 | + |
1263 | +static void |
1264 | +voip_input_widget_class_init (VoipInputWidgetClass *klass) |
1265 | +{ |
1266 | + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
1267 | + |
1268 | + g_type_class_add_private (klass, sizeof (VoipInputWidgetPrivate)); |
1269 | + |
1270 | + gobject_class->dispose = voip_input_widget_dispose; |
1271 | + gobject_class->finalize = voip_input_widget_finalize; |
1272 | +} |
1273 | + |
1274 | +static void |
1275 | +voip_input_widget_init (VoipInputWidget *self) |
1276 | +{ |
1277 | + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self); |
1278 | + |
1279 | + priv->ido_voip_input_slider = ido_scale_menu_item_new_with_range ("VOLUME", IDO_RANGE_STYLE_DEFAULT, 0, 0, 100, 1); |
1280 | + g_object_ref (priv->ido_voip_input_slider); |
1281 | + ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM (priv->ido_voip_input_slider), IDO_SCALE_MENU_ITEM_STYLE_IMAGE); |
1282 | + g_object_set(priv->ido_voip_input_slider, "reverse-scroll-events", TRUE, NULL); |
1283 | + |
1284 | + g_signal_connect (priv->ido_voip_input_slider, |
1285 | + "notify::parent", G_CALLBACK (voip_input_widget_parent_changed), |
1286 | + NULL); |
1287 | + |
1288 | + GtkWidget* voip_input_widget = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); |
1289 | + |
1290 | + g_signal_connect(voip_input_widget, "change-value", G_CALLBACK(voip_input_widget_change_value_cb), self); |
1291 | + g_signal_connect(voip_input_widget, "value-changed", G_CALLBACK(voip_input_widget_value_changed_cb), self); |
1292 | + g_signal_connect(priv->ido_voip_input_slider, "slider-grabbed", G_CALLBACK(voip_input_widget_slider_grabbed), self); |
1293 | + g_signal_connect(priv->ido_voip_input_slider, "slider-released", G_CALLBACK(voip_input_widget_slider_released), self); |
1294 | + |
1295 | + GtkWidget* primary_image = ido_scale_menu_item_get_primary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider); |
1296 | + GIcon * primary_gicon = g_themed_icon_new_with_default_fallbacks("audio-input-microphone"); |
1297 | + gtk_image_set_from_gicon(GTK_IMAGE(primary_image), primary_gicon, GTK_ICON_SIZE_MENU); |
1298 | + g_object_unref(primary_gicon); |
1299 | + |
1300 | + GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider); |
1301 | + GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks("audio-input-microphone-high"); |
1302 | + gtk_image_set_from_gicon(GTK_IMAGE(secondary_image), secondary_gicon, GTK_ICON_SIZE_MENU); |
1303 | + g_object_unref(secondary_gicon); |
1304 | + |
1305 | + GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (voip_input_widget)); |
1306 | + gtk_adjustment_set_step_increment(adj, 4); |
1307 | +} |
1308 | + |
1309 | +static void |
1310 | +voip_input_widget_dispose (GObject *object) |
1311 | +{ |
1312 | + G_OBJECT_CLASS (voip_input_widget_parent_class)->dispose (object); |
1313 | +} |
1314 | + |
1315 | +static void |
1316 | +voip_input_widget_finalize (GObject *object) |
1317 | +{ |
1318 | + G_OBJECT_CLASS (voip_input_widget_parent_class)->finalize (object); |
1319 | +} |
1320 | + |
1321 | +static void |
1322 | +voip_input_widget_property_update (DbusmenuMenuitem* item, gchar* property, |
1323 | + GVariant* value, gpointer userdata) |
1324 | +{ |
1325 | + g_return_if_fail (IS_VOIP_INPUT_WIDGET (userdata)); |
1326 | + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(userdata); |
1327 | + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); |
1328 | + //g_debug("scrub-widget::property_update for prop %s", property); |
1329 | + if(g_ascii_strcasecmp(DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL, property) == 0){ |
1330 | + if(priv->grabbed == FALSE){ |
1331 | + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); |
1332 | + GtkRange *range = (GtkRange*)slider; |
1333 | + gdouble update = g_variant_get_double (value); |
1334 | + //g_debug("volume-widget - update level with value %f", update); |
1335 | + gtk_range_set_value(range, update); |
1336 | + } |
1337 | + } |
1338 | + if(g_ascii_strcasecmp(DBUSMENU_VOIP_INPUT_MENUITEM_MUTE, property) == 0){ |
1339 | + if(priv->grabbed == FALSE){ |
1340 | + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); |
1341 | + GtkRange *range = (GtkRange*)slider; |
1342 | + gint update = g_variant_get_int32 (value); |
1343 | + gdouble level; |
1344 | + if (update == 1){ |
1345 | + level = 0; |
1346 | + } |
1347 | + else{ |
1348 | + level = g_variant_get_double (dbusmenu_menuitem_property_get_variant (priv->twin_item, |
1349 | + DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL)); |
1350 | + } |
1351 | + gtk_range_set_value(range, level); |
1352 | + |
1353 | + g_debug ("voip-item-widget - update mute with value %i", update); |
1354 | + } |
1355 | + } |
1356 | +} |
1357 | + |
1358 | +static void |
1359 | +voip_input_widget_set_twin_item (VoipInputWidget* self, |
1360 | + DbusmenuMenuitem* twin_item) |
1361 | +{ |
1362 | + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self); |
1363 | + priv->twin_item = twin_item; |
1364 | + g_object_ref(priv->twin_item); |
1365 | + g_signal_connect(G_OBJECT(twin_item), "property-changed", |
1366 | + G_CALLBACK(voip_input_widget_property_update), self); |
1367 | + gdouble initial_level = g_variant_get_double (dbusmenu_menuitem_property_get_variant(twin_item, |
1368 | + DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL)); |
1369 | + //g_debug("voip_input_widget_set_twin_item initial level = %f", initial_level); |
1370 | + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); |
1371 | + GtkRange *range = (GtkRange*)slider; |
1372 | + gtk_range_set_value(range, initial_level); |
1373 | + |
1374 | + gint mute = g_variant_get_int32 (dbusmenu_menuitem_property_get_variant (priv->twin_item, |
1375 | + DBUSMENU_VOIP_INPUT_MENUITEM_MUTE)); |
1376 | + if (mute == 1){ |
1377 | + gtk_range_set_value (range, 0.0); |
1378 | + } |
1379 | +} |
1380 | + |
1381 | +static gboolean |
1382 | +voip_input_widget_change_value_cb (GtkRange *range, |
1383 | + GtkScrollType scroll, |
1384 | + gdouble new_value, |
1385 | + gpointer user_data) |
1386 | +{ |
1387 | + g_return_val_if_fail (IS_VOIP_INPUT_WIDGET (user_data), FALSE); |
1388 | + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data); |
1389 | + voip_input_widget_update(mitem, new_value); |
1390 | + return FALSE; |
1391 | +} |
1392 | + |
1393 | + |
1394 | +/** |
1395 | + * We only want this callback to catch mouse icon press events which set the |
1396 | + * slider to 0 or 100. Ignore all other events including the new Mute behaviour |
1397 | + * (slider to go to 0 on mute without setting the level to 0 and return to |
1398 | + * previous level on unmute) |
1399 | + **/ |
1400 | +static gboolean |
1401 | +voip_input_widget_value_changed_cb(GtkRange *range, gpointer user_data) |
1402 | +{ |
1403 | + g_return_val_if_fail (IS_VOIP_INPUT_WIDGET (user_data), FALSE); |
1404 | + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data); |
1405 | + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); |
1406 | + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); |
1407 | + gdouble current_value = CLAMP(gtk_range_get_value(GTK_RANGE(slider)), 0, 100); |
1408 | + |
1409 | + gint mute = g_variant_get_int32 (dbusmenu_menuitem_property_get_variant (priv->twin_item, |
1410 | + DBUSMENU_VOIP_INPUT_MENUITEM_MUTE)); |
1411 | + if ((current_value == 0 && mute != 1) || current_value == 100 ){ |
1412 | + voip_input_widget_update(mitem, current_value); |
1413 | + } |
1414 | + return FALSE; |
1415 | +} |
1416 | + |
1417 | +void |
1418 | +voip_input_widget_update(VoipInputWidget* self, gdouble update) |
1419 | +{ |
1420 | + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self); |
1421 | + gdouble clamped = CLAMP(update, 0, 100); |
1422 | + GVariant* new_volume = g_variant_new_double(clamped); |
1423 | + dbusmenu_menuitem_handle_event (priv->twin_item, "update", new_volume, 0); |
1424 | +} |
1425 | + |
1426 | +GtkWidget* |
1427 | +voip_input_widget_get_ido_slider(VoipInputWidget* self) |
1428 | +{ |
1429 | + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self); |
1430 | + return priv->ido_voip_input_slider; |
1431 | +} |
1432 | + |
1433 | +static void |
1434 | +voip_input_widget_parent_changed (GtkWidget *widget, |
1435 | + gpointer user_data) |
1436 | +{ |
1437 | + gtk_widget_set_size_request (widget, 200, -1); |
1438 | + //g_debug("voip_input_widget_parent_changed"); |
1439 | +} |
1440 | + |
1441 | +static void |
1442 | +voip_input_widget_slider_grabbed(GtkWidget *widget, gpointer user_data) |
1443 | +{ |
1444 | + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data); |
1445 | + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); |
1446 | + priv->grabbed = TRUE; |
1447 | +} |
1448 | + |
1449 | +static void |
1450 | +voip_input_widget_slider_released(GtkWidget *widget, gpointer user_data) |
1451 | +{ |
1452 | + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data); |
1453 | + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); |
1454 | + priv->grabbed = FALSE; |
1455 | +} |
1456 | + |
1457 | +void |
1458 | +voip_input_widget_tidy_up (GtkWidget *widget) |
1459 | +{ |
1460 | + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(widget); |
1461 | + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); |
1462 | + gtk_widget_destroy (priv->ido_voip_input_slider); |
1463 | +} |
1464 | + |
1465 | +/** |
1466 | + * voip_input_widget_new: |
1467 | + * @returns: a new #VoipInputWidget. |
1468 | + **/ |
1469 | +GtkWidget* |
1470 | +voip_input_widget_new(DbusmenuMenuitem *item) |
1471 | +{ |
1472 | + GtkWidget* widget = g_object_new(VOIP_INPUT_WIDGET_TYPE, NULL); |
1473 | + voip_input_widget_set_twin_item((VoipInputWidget*)widget, item); |
1474 | + return widget; |
1475 | +} |
1476 | + |
1477 | + |
1478 | |
1479 | === added file 'src/voip-input-widget.h' |
1480 | --- src/voip-input-widget.h 1970-01-01 00:00:00 +0000 |
1481 | +++ src/voip-input-widget.h 2011-02-18 17:27:12 +0000 |
1482 | @@ -0,0 +1,55 @@ |
1483 | +/* |
1484 | +Copyright 2011 Canonical Ltd. |
1485 | + |
1486 | +Authors: |
1487 | + Conor Curran <conor.curran@canonical.com> |
1488 | + |
1489 | +This program is free software: you can redistribute it and/or modify it |
1490 | +under the terms of the GNU General Public License version 3, as published |
1491 | +by the Free Software Foundation. |
1492 | + |
1493 | +This program is distributed in the hope that it will be useful, but |
1494 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
1495 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1496 | +PURPOSE. See the GNU General Public License for more details. |
1497 | + |
1498 | +You should have received a copy of the GNU General Public License along |
1499 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
1500 | +*/ |
1501 | +#ifndef __VOIP_INPUT_WIDGET_H__ |
1502 | +#define __VOIP_INPUT_WIDGET_H__ |
1503 | + |
1504 | +#include <glib.h> |
1505 | +#include <glib-object.h> |
1506 | +#include <libdbusmenu-gtk/menuitem.h> |
1507 | + |
1508 | +G_BEGIN_DECLS |
1509 | + |
1510 | +#define VOIP_INPUT_WIDGET_TYPE (voip_input_widget_get_type ()) |
1511 | +#define VOIP_INPUT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VOIP_INPUT_WIDGET_TYPE, VoipInputWidget)) |
1512 | +#define VOIP_INPUT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VOIP_INPUT_WIDGET_TYPE, VoipInputWidgetClass)) |
1513 | +#define IS_VOIP_INPUT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VOIP_INPUT_WIDGET_TYPE)) |
1514 | +#define IS_VOIP_INPUT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VOIP_INPUT_WIDGET_TYPE)) |
1515 | +#define VOIP_INPUT_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VOIP_INPUT_WIDGET_TYPE, VoipInputWidgetClass)) |
1516 | + |
1517 | +typedef struct _VoipInputWidget VoipInputWidget; |
1518 | +typedef struct _VoipInputWidgetClass VoipInputWidgetClass; |
1519 | + |
1520 | +struct _VoipInputWidgetClass { |
1521 | + GObjectClass parent_class; |
1522 | +}; |
1523 | + |
1524 | +struct _VoipInputWidget { |
1525 | + GObject parent; |
1526 | +}; |
1527 | + |
1528 | +GType voip_input_widget_get_type (void) G_GNUC_CONST; |
1529 | +GtkWidget* voip_input_widget_new(DbusmenuMenuitem* twin_item); |
1530 | +GtkWidget* voip_input_widget_get_ido_slider(VoipInputWidget* self); |
1531 | +void voip_input_widget_update(VoipInputWidget* self, gdouble update); |
1532 | +void voip_input_widget_tidy_up (GtkWidget *widget); |
1533 | + |
1534 | +G_END_DECLS |
1535 | + |
1536 | +#endif |
1537 | + |
Don't see anything odd. Looks good.