Merge lp:~cjcurran/indicator-sound/voip-input-item into lp:~indicator-applet-developers/indicator-sound/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
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+50364@code.launchpad.net

Description of the change

- big Voip input menu item feature added
- little keyboard shortcut feature removal

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

Don't see anything odd. Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2011-02-11 15:22:10 +0000
+++ src/Makefile.am 2011-02-18 17:27:12 +0000
@@ -20,6 +20,8 @@
20 title-widget.h \20 title-widget.h \
21 volume-widget.c \21 volume-widget.c \
22 volume-widget.h \22 volume-widget.h \
23 voip-input-widget.c \
24 voip-input-widget.h \
23 gen-sound-service.xml.h \25 gen-sound-service.xml.h \
24 gen-sound-service.xml.c \26 gen-sound-service.xml.c \
25 dbus-shared-names.h27 dbus-shared-names.h
@@ -85,7 +87,7 @@
85# Sound Service C87# Sound Service C
86###############################88###############################
87indicator_sound_service_SOURCES = \89indicator_sound_service_SOURCES = \
88 common-defs.h \90 common-defs.h \
89 sound-service.h \91 sound-service.h \
90 sound-service.c \92 sound-service.c \
91 pulseaudio-mgr.h \93 pulseaudio-mgr.h \
@@ -96,6 +98,8 @@
96 sound-service-dbus.c \98 sound-service-dbus.c \
97 slider-menu-item.h \99 slider-menu-item.h \
98 slider-menu-item.c \100 slider-menu-item.c \
101 voip-input-menu-item.h \
102 voip-input-menu-item.c \
99 mute-menu-item.h \103 mute-menu-item.h \
100 mute-menu-item.c \104 mute-menu-item.c \
101 gen-sound-service.xml.h \105 gen-sound-service.xml.h \
102106
=== modified file 'src/active-sink.c'
--- src/active-sink.c 2011-02-07 12:53:45 +0000
+++ src/active-sink.c 2011-02-18 17:27:12 +0000
@@ -21,7 +21,7 @@
21#include "active-sink.h"21#include "active-sink.h"
22#include "slider-menu-item.h"22#include "slider-menu-item.h"
23#include "mute-menu-item.h"23#include "mute-menu-item.h"
2424#include "voip-input-menu-item.h"
25#include "pulseaudio-mgr.h"25#include "pulseaudio-mgr.h"
2626
27typedef struct _ActiveSinkPrivate ActiveSinkPrivate;27typedef struct _ActiveSinkPrivate ActiveSinkPrivate;
@@ -30,7 +30,8 @@
30{30{
31 SliderMenuItem* volume_slider_menuitem;31 SliderMenuItem* volume_slider_menuitem;
32 MuteMenuItem* mute_menuitem;32 MuteMenuItem* mute_menuitem;
33 SoundState current_sound_state; 33 VoipInputMenuItem* voip_input_menu_item;
34 SoundState current_sound_state;
34 SoundServiceDbus* service;35 SoundServiceDbus* service;
35 gint index;36 gint index;
36 gchar* name;37 gchar* name;
@@ -52,7 +53,6 @@
52static void active_sink_volume_update (ActiveSink* self, gdouble percent);53static void active_sink_volume_update (ActiveSink* self, gdouble percent);
53static void active_sink_mute_update (ActiveSink* self, gboolean muted);54static void active_sink_mute_update (ActiveSink* self, gboolean muted);
5455
55
56G_DEFINE_TYPE (ActiveSink, active_sink, G_TYPE_OBJECT);56G_DEFINE_TYPE (ActiveSink, active_sink, G_TYPE_OBJECT);
5757
58static void58static void
@@ -72,6 +72,7 @@
72 ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);72 ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
73 priv->mute_menuitem = NULL;73 priv->mute_menuitem = NULL;
74 priv->volume_slider_menuitem = NULL;74 priv->volume_slider_menuitem = NULL;
75 priv->voip_input_menu_item = NULL;
75 priv->current_sound_state = UNAVAILABLE;76 priv->current_sound_state = UNAVAILABLE;
76 priv->index = -1;77 priv->index = -1;
77 priv->name = NULL;78 priv->name = NULL;
@@ -79,6 +80,7 @@
7980
80 // Init our menu items.81 // Init our menu items.
81 priv->mute_menuitem = g_object_new (MUTE_MENU_ITEM_TYPE, NULL);82 priv->mute_menuitem = g_object_new (MUTE_MENU_ITEM_TYPE, NULL);
83 priv->voip_input_menu_item = g_object_new (VOIP_INPUT_MENU_ITEM_TYPE, NULL);;
82 priv->volume_slider_menuitem = slider_menu_item_new (self);84 priv->volume_slider_menuitem = slider_menu_item_new (self);
83 mute_menu_item_enable (priv->mute_menuitem, FALSE);85 mute_menu_item_enable (priv->mute_menuitem, FALSE);
84 slider_menu_item_enable (priv->volume_slider_menuitem, FALSE); 86 slider_menu_item_enable (priv->volume_slider_menuitem, FALSE);
@@ -121,6 +123,32 @@
121}123}
122124
123void125void
126active_sink_activate_voip_item (ActiveSink* self, gint sink_input_index, gint client_index)
127{
128 ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
129 if (voip_input_menu_item_is_interested (priv->voip_input_menu_item,
130 sink_input_index,
131 client_index)){
132 voip_input_menu_item_enable (priv->voip_input_menu_item, TRUE);
133 }
134}
135
136void
137active_sink_deactivate_voip_source (ActiveSink* self, gboolean visible)
138{
139 ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
140 visible &= voip_input_menu_item_is_active (priv->voip_input_menu_item);
141 voip_input_menu_item_deactivate_source (priv->voip_input_menu_item, visible);
142}
143
144void
145active_sink_deactivate_voip_client (ActiveSink* self)
146{
147 ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
148 voip_input_menu_item_deactivate_voip_client (priv->voip_input_menu_item);
149}
150
151void
124active_sink_update (ActiveSink* sink,152active_sink_update (ActiveSink* sink,
125 const pa_sink_info* update)153 const pa_sink_info* update)
126{154{
@@ -168,6 +196,13 @@
168}196}
169197
170198
199gint
200active_sink_get_current_sink_input_index (ActiveSink* sink)
201{
202 ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (sink);
203 return voip_input_menu_item_get_sink_input_index (priv->voip_input_menu_item);
204}
205
171static void 206static void
172active_sink_mute_update (ActiveSink* self, gboolean muted)207active_sink_mute_update (ActiveSink* self, gboolean muted)
173{208{
@@ -219,7 +254,7 @@
219 return state;254 return state;
220}255}
221256
222static pa_cvolume257pa_cvolume
223active_sink_construct_mono_volume (const pa_cvolume* vol)258active_sink_construct_mono_volume (const pa_cvolume* vol)
224{259{
225 pa_cvolume new_volume;260 pa_cvolume new_volume;
@@ -279,6 +314,26 @@
279 return priv->current_sound_state;314 return priv->current_sound_state;
280}315}
281316
317void
318active_sink_update_voip_input_source (ActiveSink* self, const pa_source_info* update)
319{
320 ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
321 voip_input_menu_item_update (priv->voip_input_menu_item, update);
322}
323
324gboolean
325active_sink_is_voip_source_populated (ActiveSink* self)
326{
327 ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
328 return voip_input_menu_item_is_populated (priv->voip_input_menu_item);
329}
330
331gint active_sink_get_source_index (ActiveSink* self)
332{
333 ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
334 return voip_input_menu_item_get_index (priv->voip_input_menu_item);
335}
336
282ActiveSink*337ActiveSink*
283active_sink_new (SoundServiceDbus* service)338active_sink_new (SoundServiceDbus* service)
284{339{
@@ -287,7 +342,8 @@
287 priv->service = service;342 priv->service = service;
288 sound_service_dbus_build_sound_menu (service,343 sound_service_dbus_build_sound_menu (service,
289 mute_menu_item_get_button (priv->mute_menuitem),344 mute_menu_item_get_button (priv->mute_menuitem),
290 DBUSMENU_MENUITEM (priv->volume_slider_menuitem));345 DBUSMENU_MENUITEM (priv->volume_slider_menuitem),
346 DBUSMENU_MENUITEM (priv->voip_input_menu_item));
291 pm_establish_pulse_connection (sink);347 pm_establish_pulse_connection (sink);
292 return sink; 348 return sink;
293}349}
294350
=== modified file 'src/active-sink.h'
--- src/active-sink.h 2011-02-07 11:45:06 +0000
+++ src/active-sink.h 2011-02-18 17:27:12 +0000
@@ -50,21 +50,34 @@
5050
51GType active_sink_get_type (void) G_GNUC_CONST;51GType active_sink_get_type (void) G_GNUC_CONST;
5252
53/**
54 * TODO
55 * Refactor this to become a device manager obj basically acting as wrapper for
56 * the communication between pulseaudio-mgr and the individual items.
57 * First steps collapse slider/volume related stuff into slider-menu-item.
58 */
59
60// Sink related
53void active_sink_populate (ActiveSink* sink, const pa_sink_info* update); 61void active_sink_populate (ActiveSink* sink, const pa_sink_info* update);
54void active_sink_update (ActiveSink* sink, const pa_sink_info* update); 62void active_sink_update (ActiveSink* sink, const pa_sink_info* update);
55
56gboolean active_sink_is_populated (ActiveSink* sink);63gboolean active_sink_is_populated (ActiveSink* sink);
57void active_sink_determine_blocking_state (ActiveSink* self);
58
59gint active_sink_get_index (ActiveSink* self);64gint active_sink_get_index (ActiveSink* self);
60SoundState active_sink_get_state (ActiveSink* self);
61
62void active_sink_deactivate (ActiveSink* self);65void active_sink_deactivate (ActiveSink* self);
63
64void active_sink_update_mute (ActiveSink* self, gboolean mute_update);66void active_sink_update_mute (ActiveSink* self, gboolean mute_update);
65void active_sink_update_volume (ActiveSink* self, gdouble percent);67void active_sink_update_volume (ActiveSink* self, gdouble percent);
66void active_sink_ensure_sink_is_unmuted (ActiveSink* self);68void active_sink_ensure_sink_is_unmuted (ActiveSink* self);
6769
70// source and sinkinput/client related for VOIP functionality
71void active_sink_update_voip_input_source (ActiveSink* sink, const pa_source_info* update);
72void active_sink_activate_voip_item (ActiveSink* sink, gint sink_input_index, gint client_index);
73gint active_sink_get_current_sink_input_index (ActiveSink* sink);
74gboolean active_sink_is_voip_source_populated (ActiveSink* sink);
75gint active_sink_get_source_index (ActiveSink* self);
76void active_sink_determine_blocking_state (ActiveSink* self);
77void active_sink_deactivate_voip_source (ActiveSink* self, gboolean visible);
78void active_sink_deactivate_voip_client (ActiveSink* self);
79SoundState active_sink_get_state (ActiveSink* self);
80
68ActiveSink* active_sink_new (SoundServiceDbus* service);81ActiveSink* active_sink_new (SoundServiceDbus* service);
6982
70G_END_DECLS83G_END_DECLS
7184
=== modified file 'src/common-defs.h'
--- src/common-defs.h 2011-02-08 18:58:10 +0000
+++ src/common-defs.h 2011-02-18 17:27:12 +0000
@@ -31,13 +31,17 @@
31 AVAILABLE31 AVAILABLE
32}SoundState;32}SoundState;
3333
3434#define NOT_ACTIVE -1
35#define DBUSMENU_PROPERTY_EMPTY -135#define DBUSMENU_PROPERTY_EMPTY -1
3636
37/* DBUS Custom Items */37/* DBUS Custom Items */
38#define DBUSMENU_VOLUME_MENUITEM_TYPE "x-canonical-ido-volume-type"38#define DBUSMENU_VOLUME_MENUITEM_TYPE "x-canonical-ido-volume-type"
39#define DBUSMENU_VOLUME_MENUITEM_LEVEL "x-canonical-ido-volume-level"39#define DBUSMENU_VOLUME_MENUITEM_LEVEL "x-canonical-ido-volume-level"
4040
41#define DBUSMENU_VOIP_INPUT_MENUITEM_TYPE "x-canonical-ido-voip-input-type"
42#define DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL "x-canonical-ido-voip-input-level"
43#define DBUSMENU_VOIP_INPUT_MENUITEM_MUTE "x-canonical-ido-voip-input-mute"
44
41#define DBUSMENU_MUTE_MENUITEM_TYPE "x-canonical-sound-menu-mute-type"45#define DBUSMENU_MUTE_MENUITEM_TYPE "x-canonical-sound-menu-mute-type"
42#define DBUSMENU_MUTE_MENUITEM_VALUE "x-canonical-sound-menu-mute-value"46#define DBUSMENU_MUTE_MENUITEM_VALUE "x-canonical-sound-menu-mute-value"
4347
4448
=== modified file 'src/indicator-sound.c'
--- src/indicator-sound.c 2011-02-16 11:20:21 +0000
+++ src/indicator-sound.c 2011-02-18 17:27:12 +0000
@@ -32,12 +32,12 @@
32#include "metadata-widget.h"32#include "metadata-widget.h"
33#include "title-widget.h"33#include "title-widget.h"
34#include "volume-widget.h"34#include "volume-widget.h"
3535#include "voip-input-widget.h"
36#include "dbus-shared-names.h"36#include "dbus-shared-names.h"
37#include "sound-state-manager.h"
3738
38#include "gen-sound-service.xml.h"39#include "gen-sound-service.xml.h"
39#include "common-defs.h"40#include "common-defs.h"
40#include "sound-state-manager.h"
4141
42typedef struct _IndicatorSoundPrivate IndicatorSoundPrivate;42typedef struct _IndicatorSoundPrivate IndicatorSoundPrivate;
4343
@@ -79,6 +79,10 @@
79 DbusmenuMenuitem * parent,79 DbusmenuMenuitem * parent,
80 DbusmenuClient * client,80 DbusmenuClient * client,
81 gpointer user_data);81 gpointer user_data);
82static gboolean new_voip_slider_widget (DbusmenuMenuitem * newitem,
83 DbusmenuMenuitem * parent,
84 DbusmenuClient * client,
85 gpointer user_data);
82static gboolean new_transport_widget (DbusmenuMenuitem * newitem,86static gboolean new_transport_widget (DbusmenuMenuitem * newitem,
83 DbusmenuMenuitem * parent,87 DbusmenuMenuitem * parent,
84 DbusmenuClient * client,88 DbusmenuClient * client,
@@ -191,6 +195,9 @@
191 DBUSMENU_VOLUME_MENUITEM_TYPE,195 DBUSMENU_VOLUME_MENUITEM_TYPE,
192 new_volume_slider_widget);196 new_volume_slider_widget);
193 dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client),197 dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client),
198 DBUSMENU_VOIP_INPUT_MENUITEM_TYPE,
199 new_voip_slider_widget);
200 dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client),
194 DBUSMENU_TRANSPORT_MENUITEM_TYPE,201 DBUSMENU_TRANSPORT_MENUITEM_TYPE,
195 new_transport_widget);202 new_transport_widget);
196 dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client),203 dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client),
@@ -403,6 +410,53 @@
403 parent);410 parent);
404 return TRUE;411 return TRUE;
405}412}
413/**
414 * new_voip_slider_widget
415 * Create the voip menu item widget, must of the time this widget will be hidden.
416 * @param newitem
417 * @param parent
418 * @param client
419 * @param user_data
420 * @return
421 */
422static gboolean
423new_voip_slider_widget (DbusmenuMenuitem * newitem,
424 DbusmenuMenuitem * parent,
425 DbusmenuClient * client,
426 gpointer user_data)
427{
428 g_debug("indicator-sound: new_voip_slider_widget");
429 GtkWidget* voip_widget = NULL;
430 //IndicatorObject *io = NULL;
431
432 g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
433 g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
434
435 voip_widget = voip_input_widget_new (newitem);
436/*
437 / io = g_object_get_data (G_OBJECT (client), "indicator");
438*/
439 //IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
440 //priv->volume_widget = volume_widget;
441
442 GtkWidget* ido_slider_widget = voip_input_widget_get_ido_slider(VOIP_INPUT_WIDGET(voip_widget));
443
444 gtk_widget_show_all(ido_slider_widget);
445 // register the style callback on this widget with state manager's style change
446 // handler (needs to remake the blocking animation for each style).
447/*
448 g_signal_connect (ido_slider_widget, "style-set",
449 G_CALLBACK(sound_state_manager_style_changed_cb),
450 priv->state_manager);
451*/
452
453 GtkMenuItem *menu_volume_item = GTK_MENU_ITEM(ido_slider_widget);
454 dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client),
455 newitem,
456 menu_volume_item,
457 parent);
458 return TRUE;
459}
406460
407/*******************************************************************/461/*******************************************************************/
408//UI callbacks462//UI callbacks
@@ -439,19 +493,23 @@
439 switch (event->keyval) {493 switch (event->keyval) {
440 case GDK_Right:494 case GDK_Right:
441 digested = TRUE;495 digested = TRUE;
496/*
442 if (event->state & GDK_CONTROL_MASK) {497 if (event->state & GDK_CONTROL_MASK) {
443 new_value = 100;498 new_value = 100;
444 } else {499 } else {
500*/
445 new_value = current_value + five_percent;501 new_value = current_value + five_percent;
446 }502 //}
447 break;503 break;
448 case GDK_Left:504 case GDK_Left:
449 digested = TRUE;505 digested = TRUE;
506/*
450 if (event->state & GDK_CONTROL_MASK) {507 if (event->state & GDK_CONTROL_MASK) {
451 new_value = 0;508 new_value = 0;
452 } else {509 } else {
510*/
453 new_value = current_value - five_percent;511 new_value = current_value - five_percent;
454 }512 //}
455 break;513 break;
456 case GDK_plus:514 case GDK_plus:
457 digested = TRUE;515 digested = TRUE;
458516
=== modified file 'src/music-player-bridge.vala'
--- src/music-player-bridge.vala 2011-01-31 19:14:47 +0000
+++ src/music-player-bridge.vala 2011-02-18 17:27:12 +0000
@@ -23,11 +23,13 @@
2323
24public class MusicPlayerBridge : GLib.Object24public class MusicPlayerBridge : GLib.Object
25{25{
26 const int DEVICE_ITEMS_COUNT = 3;
27
26 private SettingsManager settings_manager;28 private SettingsManager settings_manager;
27 private Dbusmenu.Menuitem root_menu;29 private Dbusmenu.Menuitem root_menu;
28 private HashMap<string, PlayerController> registered_clients; 30 private HashMap<string, PlayerController> registered_clients;
29 private Mpris2Watcher watcher;31 private Mpris2Watcher watcher;
30 32
31 public MusicPlayerBridge()33 public MusicPlayerBridge()
32 {34 {
33 }35 }
@@ -79,10 +81,10 @@
79 private int calculate_menu_position()81 private int calculate_menu_position()
80 {82 {
81 if(this.registered_clients.size == 0){83 if(this.registered_clients.size == 0){
82 return 2;84 return DEVICE_ITEMS_COUNT;
83 }85 }
84 else{86 else{
85 return (2 + (this.registered_clients.size * PlayerController.WIDGET_QUANTITY));87 return (DEVICE_ITEMS_COUNT + (this.registered_clients.size * PlayerController.WIDGET_QUANTITY));
86 }88 }
87 }89 }
8890
8991
=== modified file 'src/mute-menu-item.c'
--- src/mute-menu-item.c 2011-02-07 18:08:19 +0000
+++ src/mute-menu-item.c 2011-02-18 17:27:12 +0000
@@ -61,6 +61,7 @@
61{61{
62 g_debug("Building new Mute Menu Item");62 g_debug("Building new Mute Menu Item");
63 MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE(self);63 MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE(self);
64 priv->button = NULL;
64 priv->button = dbusmenu_menuitem_new();65 priv->button = dbusmenu_menuitem_new();
65 dbusmenu_menuitem_property_set_bool (priv->button,66 dbusmenu_menuitem_property_set_bool (priv->button,
66 DBUSMENU_MENUITEM_PROP_VISIBLE,67 DBUSMENU_MENUITEM_PROP_VISIBLE,
6768
=== modified file 'src/player-item.vala'
--- src/player-item.vala 2011-02-09 10:56:49 +0000
+++ src/player-item.vala 2011-02-18 17:27:12 +0000
@@ -94,9 +94,8 @@
94 {94 {
95 foreach(string prop in attrs){95 foreach(string prop in attrs){
96 //debug("populated ? - prop: %s", prop);96 //debug("populated ? - prop: %s", prop);
97 int value_int = property_get_int(prop);
98 if(property_get_int(prop) != EMPTY){97 if(property_get_int(prop) != EMPTY){
99 //debug("populated - prop %s and value %i", prop, value_int); 98 //debug("populated - prop %s and value %i", prop, property_get_int(prop));
100 return true;99 return true;
101 }100 }
102 }101 }
103102
=== modified file 'src/pulseaudio-mgr.c'
--- src/pulseaudio-mgr.c 2011-02-10 14:34:51 +0000
+++ src/pulseaudio-mgr.c 2011-02-18 17:27:12 +0000
@@ -19,9 +19,9 @@
1919
20/**Notes20/**Notes
21 *21 *
22 * Approach now is to set up the communication channels then query the server22 * Approach now is to set up the communication channels, query the server
23 * fetch its default sink. If this fails then fetch the list of sinks and take23 * fetch its default sink/source. If this fails then fetch the list of sinks/sources
24 * the first one which is not the auto-null sink.24 * and take the first one which is not the auto-null sink.
25 * TODO: need to handle the situation where one chink in this linear chain breaks25 * TODO: need to handle the situation where one chink in this linear chain breaks
26 * i.e. start off the process again and count the attempts (note different to26 * i.e. start off the process again and count the attempts (note different to
27 reconnect attempts)27 reconnect attempts)
@@ -47,10 +47,22 @@
47 const pa_sink_info *info,47 const pa_sink_info *info,
48 int eol,48 int eol,
49 void *userdata);49 void *userdata);
50static void pm_default_source_info_callback (pa_context *c,
51 const pa_source_info *info,
52 int eol,
53 void *userdata);
50static void pm_sink_info_callback (pa_context *c,54static void pm_sink_info_callback (pa_context *c,
51 const pa_sink_info *sink,55 const pa_sink_info *sink,
52 int eol,56 int eol,
53 void *userdata);57 void *userdata);
58static void pm_source_info_callback (pa_context *c,
59 const pa_source_info *info,
60 int eol,
61 void *userdata);
62static void pm_update_source_info_callback (pa_context *c,
63 const pa_source_info *info,
64 int eol,
65 void *userdata);
54static void pm_sink_input_info_callback (pa_context *c,66static void pm_sink_input_info_callback (pa_context *c,
55 const pa_sink_input_info *info,67 const pa_sink_input_info *info,
56 int eol,68 int eol,
@@ -64,6 +76,7 @@
64 int eol,76 int eol,
65 void* userdata);77 void* userdata);
6678
79
67static gboolean reconnect_to_pulse (gpointer user_data);80static gboolean reconnect_to_pulse (gpointer user_data);
6881
69static gint connection_attempts = 0;82static gint connection_attempts = 0;
@@ -152,6 +165,25 @@
152 GINT_TO_POINTER (update)));165 GINT_TO_POINTER (update)));
153}166}
154167
168void
169pm_update_mic_gain (gint source_index, pa_cvolume new_gain)
170{
171 pa_operation_unref (pa_context_set_source_volume_by_index (pulse_context,
172 source_index,
173 &new_gain,
174 NULL,
175 NULL) );
176}
177
178void
179pm_update_mic_mute (gint source_index, gint mute_update)
180{
181 pa_operation_unref (pa_context_set_source_mute_by_index (pulse_context,
182 source_index,
183 mute_update,
184 NULL,
185 NULL));
186}
155/**********************************************************************************************************************/187/**********************************************************************************************************************/
156// Pulse-Audio asychronous call-backs188// Pulse-Audio asychronous call-backs
157/**********************************************************************************************************************/189/**********************************************************************************************************************/
@@ -163,19 +195,21 @@
163 uint32_t index,195 uint32_t index,
164 void* userdata)196 void* userdata)
165{197{
198 if (IS_ACTIVE_SINK (userdata) == FALSE){
199 g_critical ("subscribed events callback - our userdata is not what we think it should be");
200 return;
201 }
202 ActiveSink* sink = ACTIVE_SINK (userdata);
203
166 switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {204 switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
167 case PA_SUBSCRIPTION_EVENT_SINK:205 case PA_SUBSCRIPTION_EVENT_SINK:
168 if (IS_ACTIVE_SINK (userdata) == FALSE){206
169 g_warning ("subscribed events callback - our userdata is not what we think it should be");
170 return;
171 }
172 ActiveSink* sink = ACTIVE_SINK (userdata);
173 // We don't care about any other sink other than the active one.207 // We don't care about any other sink other than the active one.
174 if (index != active_sink_get_index (sink))208 if (index != active_sink_get_index (sink))
175 return;209 return;
176 210
177 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {211 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
178 active_sink_deactivate (ACTIVE_SINK (userdata));212 active_sink_deactivate (sink);
179 213
180 }214 }
181 else{215 else{
@@ -185,9 +219,36 @@
185 userdata) );219 userdata) );
186 }220 }
187 break;221 break;
222 case PA_SUBSCRIPTION_EVENT_SOURCE:
223 g_debug ("Looks like source event of some description");
224 // We don't care about any other sink other than the active one.
225 if (index != active_sink_get_source_index (sink))
226 return;
227 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
228 active_sink_deactivate_voip_source (sink, FALSE);
229 }
230 else{
231 pa_operation_unref (pa_context_get_source_info_by_index (c,
232 index,
233 pm_update_source_info_callback,
234 userdata) );
235 }
236 break;
188 case PA_SUBSCRIPTION_EVENT_SINK_INPUT:237 case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
189 // We don't care about sink input removals.238 // We don't care about sink input removals.
190 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_REMOVE) {239 g_debug ("sink input event");
240 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
241 gint cached_index = active_sink_get_current_sink_input_index (sink);
242
243 g_debug ("Just saw a sink input removal event - index = %i and cached index = %i", index, cached_index);
244
245 if (index == cached_index){
246 active_sink_deactivate_voip_client (sink);
247 }
248 }
249 else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
250 g_debug ("some new sink input event ? - index = %i", index);
251 // Determine if its a VOIP app or a maybe blocking state.
191 pa_operation_unref (pa_context_get_sink_input_info (c,252 pa_operation_unref (pa_context_get_sink_input_info (c,
192 index,253 index,
193 pm_sink_input_info_callback, userdata));254 pm_sink_input_info_callback, userdata));
@@ -206,6 +267,7 @@
206}267}
207268
208269
270
209static void271static void
210pm_context_state_callback (pa_context *c, void *userdata)272pm_context_state_callback (pa_context *c, void *userdata)
211{273{
@@ -244,6 +306,7 @@
244306
245 if (!(o = pa_context_subscribe (c, (pa_subscription_mask_t)307 if (!(o = pa_context_subscribe (c, (pa_subscription_mask_t)
246 (PA_SUBSCRIPTION_MASK_SINK|308 (PA_SUBSCRIPTION_MASK_SINK|
309 PA_SUBSCRIPTION_MASK_SOURCE|
247 PA_SUBSCRIPTION_MASK_SINK_INPUT|310 PA_SUBSCRIPTION_MASK_SINK_INPUT|
248 PA_SUBSCRIPTION_MASK_SERVER), NULL, NULL))) {311 PA_SUBSCRIPTION_MASK_SERVER), NULL, NULL))) {
249 g_warning("pa_context_subscribe() failed");312 g_warning("pa_context_subscribe() failed");
@@ -261,7 +324,8 @@
261324
262/**325/**
263 After startup we go straight for the server info to see if it has details of326 After startup we go straight for the server info to see if it has details of
264 the default sink. If so it makes things much easier.327 the default sink and source. Normally these are valid, if there is none set
328 fetch the list of each and try to determine the sink.
265 **/329 **/
266static void 330static void
267pm_server_info_callback (pa_context *c,331pm_server_info_callback (pa_context *c,
@@ -276,24 +340,46 @@
276 active_sink_deactivate (ACTIVE_SINK (userdata));340 active_sink_deactivate (ACTIVE_SINK (userdata));
277 return;341 return;
278 }342 }
343 // Go for the default sink
279 if (info->default_sink_name != NULL) {344 if (info->default_sink_name != NULL) {
280 g_debug ("default sink name from the server ain't null'");345 g_debug ("default sink name from the server ain't null'");
281 if (!(operation = pa_context_get_sink_info_by_name (c,346 if (!(operation = pa_context_get_sink_info_by_name (c,
282 info->default_sink_name,347 info->default_sink_name,
283 pm_default_sink_info_callback,348 pm_default_sink_info_callback,
284 userdata) )) {349 userdata) )) {
285 } 350 g_warning("pa_context_get_sink_info_by_namet() failed");
286 else{351 active_sink_deactivate (ACTIVE_SINK (userdata));
287 pa_operation_unref(operation);352 pa_operation_unref(operation);
288 return;353 return;
289 }354 }
290 }355 } // If there is no default sink, try to determine a sink from the list of sinks
291 else if (!(operation = pa_context_get_sink_info_list(c,356 else if (!(operation = pa_context_get_sink_info_list(c,
292 pm_sink_info_callback,357 pm_sink_info_callback,
293 NULL))) {358 userdata))) {
294 g_warning("pa_context_get_sink_info_list() failed");359 g_warning("pa_context_get_sink_info_list() failed");
360 active_sink_deactivate (ACTIVE_SINK (userdata));
361 pa_operation_unref(operation);
295 return;362 return;
296 }363 }
364 // And the source
365 if (info->default_source_name != NULL) {
366 g_debug ("default source name from the server is not null'");
367 if (!(operation = pa_context_get_source_info_by_name (c,
368 info->default_source_name,
369 pm_default_source_info_callback,
370 userdata) )) {
371 g_warning("pa_context_get_default_source_info() failed");
372 // TODO: call some input deactivate method on active sink
373 pa_operation_unref(operation);
374 return;
375 }
376 }
377 else if (!(operation = pa_context_get_source_info_list(c,
378 pm_source_info_callback,
379 userdata))) {
380 g_warning("pa_context_get_sink_info_list() failed");
381 // TODO: call some input deactivate method for the source
382 }
297 pa_operation_unref(operation);383 pa_operation_unref(operation);
298}384}
299385
@@ -335,8 +421,12 @@
335 if (IS_ACTIVE_SINK (userdata) == FALSE){421 if (IS_ACTIVE_SINK (userdata) == FALSE){
336 g_warning ("Default sink info callback - our user data is not what we think it should be");422 g_warning ("Default sink info callback - our user data is not what we think it should be");
337 return;423 return;
338 } 424 }
339 g_debug ("server has handed us a default sink");425 // Only repopulate if there is a change with regards the index
426 if (active_sink_get_index (ACTIVE_SINK (userdata)) == info->index)
427 return;
428
429 g_debug ("Pulse Server has handed us a new default sink");
340 active_sink_populate (ACTIVE_SINK (userdata), info);430 active_sink_populate (ACTIVE_SINK (userdata), info);
341 }431 }
342}432}
@@ -356,12 +446,30 @@
356 g_warning("\n Sink input info callback : SINK INPUT INFO IS NULL BUT EOL was not POSITIVE!!!");446 g_warning("\n Sink input info callback : SINK INPUT INFO IS NULL BUT EOL was not POSITIVE!!!");
357 return;447 return;
358 }448 }
449
359 if (IS_ACTIVE_SINK (userdata) == FALSE){450 if (IS_ACTIVE_SINK (userdata) == FALSE){
360 g_warning ("sink input info callback - our user data is not what we think it should be");451 g_warning ("sink input info callback - our user data is not what we think it should be");
361 return;452 return;
362 }453 }
363 454 // Check if this is Voip sink input
455 gint result = pa_proplist_contains (info->proplist, PA_PROP_MEDIA_ROLE);
364 ActiveSink* a_sink = ACTIVE_SINK (userdata);456 ActiveSink* a_sink = ACTIVE_SINK (userdata);
457
458 if (result == 1){
459 g_debug ("Sink input info has media role property");
460 const char* value = pa_proplist_gets (info->proplist, PA_PROP_MEDIA_ROLE);
461 g_debug ("prop role = %s", value);
462 if (g_strcmp0 (value, "phone") == 0) {
463 g_debug ("And yes its a VOIP app ... sink input index = %i", info->index);
464 active_sink_activate_voip_item (a_sink, (gint)info->index, (gint)info->client);
465 // TODO to start with we will assume our source is the same as what this 'client'
466 // is pointing at. This should probably be more intelligent :
467 // query for the list of source output info's and going on the name of the client
468 // from the sink input ensure our voip item is using the right source.
469 }
470 }
471
472 // And finally check for the mute blocking state
365 if (active_sink_get_index (a_sink) == info->sink){473 if (active_sink_get_index (a_sink) == info->sink){
366 active_sink_determine_blocking_state (a_sink);474 active_sink_determine_blocking_state (a_sink);
367 }475 }
@@ -404,3 +512,66 @@
404 }512 }
405}513}
406514
515// Source info related callbacks
516static void
517pm_default_source_info_callback (pa_context *c,
518 const pa_source_info *info,
519 int eol,
520 void *userdata)
521{
522 if (eol > 0) {
523 return;
524 }
525 else {
526 if (IS_ACTIVE_SINK (userdata) == FALSE){
527 g_warning ("Default sink info callback - our user data is not what we think it should be");
528 return;
529 }
530 // If there is an index change we need to change our cached source
531 if (active_sink_get_source_index (ACTIVE_SINK (userdata)) == info->index)
532 return;
533 g_debug ("Pulse Server has handed us a new default source");
534 active_sink_deactivate_voip_source (ACTIVE_SINK (userdata), TRUE);
535 active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info);
536 }
537}
538
539static void
540pm_source_info_callback (pa_context *c,
541 const pa_source_info *info,
542 int eol,
543 void *userdata)
544{
545 if (eol > 0) {
546 return;
547 }
548 else {
549 if (IS_ACTIVE_SINK (userdata) == FALSE){
550 g_warning ("Default sink info callback - our user data is not what we think it should be");
551 return;
552 }
553 // For now we will take the first available
554 if (active_sink_is_voip_source_populated (ACTIVE_SINK (userdata)) == FALSE){
555 active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info);
556 }
557 }
558}
559
560static void
561pm_update_source_info_callback (pa_context *c,
562 const pa_source_info *info,
563 int eol,
564 void *userdata)
565{
566 if (eol > 0) {
567 return;
568 }
569 else {
570 if (IS_ACTIVE_SINK (userdata) == FALSE){
571 g_warning ("Default sink info callback - our user data is not what we think it should be");
572 return;
573 }
574 g_debug ("Got a source update for %s , index %i", info->name, info->index);
575 active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info);
576 }
577}
407\ No newline at end of file578\ No newline at end of file
408579
=== modified file 'src/pulseaudio-mgr.h'
--- src/pulseaudio-mgr.h 2011-02-07 11:19:17 +0000
+++ src/pulseaudio-mgr.h 2011-02-18 17:27:12 +0000
@@ -22,6 +22,8 @@
22void pm_establish_pulse_connection (ActiveSink* active_sink);22void pm_establish_pulse_connection (ActiveSink* active_sink);
23void close_pulse_activites();23void close_pulse_activites();
24void pm_update_volume (gint sink_index, pa_cvolume new_volume);24void pm_update_volume (gint sink_index, pa_cvolume new_volume);
25void pm_update_mic_gain (gint source_index, pa_cvolume new_gain);
26void pm_update_mic_mute (gint source_index, int mute_update);
25void pm_update_mute (gboolean update);27void pm_update_mute (gboolean update);
2628
2729
2830
=== modified file 'src/settings-manager.vala'
--- src/settings-manager.vala 2011-02-01 01:33:46 +0000
+++ src/settings-manager.vala 2011-02-18 17:27:12 +0000
@@ -71,6 +71,7 @@
7171
72 // Convenient debug method inorder to provide visability over 72 // Convenient debug method inorder to provide visability over
73 // the contents of both interested and blacklisted containers in its gsettings73 // the contents of both interested and blacklisted containers in its gsettings
74/**
74 private void reveal_contents()75 private void reveal_contents()
75 {76 {
76 var already_interested = this.settings.get_strv ("interested-media-players");77 var already_interested = this.settings.get_strv ("interested-media-players");
@@ -87,4 +88,5 @@
87 debug ("interested array size = %i", already_interested.length);88 debug ("interested array size = %i", already_interested.length);
88 debug ("blacklisted array size = %i", blacklisted.length);89 debug ("blacklisted array size = %i", blacklisted.length);
89 }90 }
91**/
90}92}
9193
=== modified file 'src/sound-service-dbus.c'
--- src/sound-service-dbus.c 2011-02-04 18:25:54 +0000
+++ src/sound-service-dbus.c 2011-02-18 17:27:12 +0000
@@ -157,14 +157,18 @@
157void157void
158sound_service_dbus_build_sound_menu ( SoundServiceDbus* self,158sound_service_dbus_build_sound_menu ( SoundServiceDbus* self,
159 DbusmenuMenuitem* mute_item,159 DbusmenuMenuitem* mute_item,
160 DbusmenuMenuitem* slider_item) 160 DbusmenuMenuitem* slider_item,
161 DbusmenuMenuitem* voip_input_menu_item)
161{162{
162 SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self);163 SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self);
163164
164 // Mute button165 // Mute button
166 // TODO this additions should be fixed position, i.e. add via position and not just append
167 // be explicit as it is fixed.
165 dbusmenu_menuitem_child_append (priv->root_menuitem, mute_item);168 dbusmenu_menuitem_child_append (priv->root_menuitem, mute_item);
169 dbusmenu_menuitem_child_append (priv->root_menuitem, slider_item);
166 g_debug ("just about to add the slider %i", DBUSMENU_IS_MENUITEM(slider_item));170 g_debug ("just about to add the slider %i", DBUSMENU_IS_MENUITEM(slider_item));
167 dbusmenu_menuitem_child_append (priv->root_menuitem, slider_item);171 dbusmenu_menuitem_child_append (priv->root_menuitem, voip_input_menu_item);
168172
169 // Separator173 // Separator
170 DbusmenuMenuitem* separator = dbusmenu_menuitem_new();174 DbusmenuMenuitem* separator = dbusmenu_menuitem_new();
171175
=== modified file 'src/sound-service-dbus.h'
--- src/sound-service-dbus.h 2011-02-04 16:17:31 +0000
+++ src/sound-service-dbus.h 2011-02-18 17:27:12 +0000
@@ -57,7 +57,8 @@
57void sound_service_dbus_update_sound_state (SoundServiceDbus* self, SoundState new_state);57void sound_service_dbus_update_sound_state (SoundServiceDbus* self, SoundState new_state);
58void sound_service_dbus_build_sound_menu ( SoundServiceDbus* self,58void sound_service_dbus_build_sound_menu ( SoundServiceDbus* self,
59 DbusmenuMenuitem* mute_item,59 DbusmenuMenuitem* mute_item,
60 DbusmenuMenuitem* slider_item);60 DbusmenuMenuitem* slider_item,
61 DbusmenuMenuitem* voip_input_menu_item);
6162
6263
63G_END_DECLS64G_END_DECLS
6465
=== modified file 'src/sound-service.c'
--- src/sound-service.c 2011-02-09 10:57:13 +0000
+++ src/sound-service.c 2011-02-18 17:27:12 +0000
@@ -39,8 +39,10 @@
39{39{
40 if (mainloop != NULL) {40 if (mainloop != NULL) {
41 g_debug("Service shutdown !");41 g_debug("Service shutdown !");
42
42 close_pulse_activites();43 close_pulse_activites();
43 g_main_loop_quit(mainloop);44 g_main_loop_quit(mainloop);
45
44 }46 }
45 return;47 return;
46}48}
4749
=== added file 'src/voip-input-menu-item.c'
--- src/voip-input-menu-item.c 1970-01-01 00:00:00 +0000
+++ src/voip-input-menu-item.c 2011-02-18 17:27:12 +0000
@@ -0,0 +1,277 @@
1/*
2Copyright 2011 Canonical Ltd.
3
4Authors:
5 Conor Curran <conor.curran@canonical.com>
6
7This program is free software: you can redistribute it and/or modify it
8under the terms of the GNU General Public License version 3, as published
9by the Free Software Foundation.
10
11This program is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranties of
13MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14PURPOSE. See the GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License along
17with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <glib/gi18n.h>
24#include "voip-input-menu-item.h"
25#include "common-defs.h"
26#include "pulseaudio-mgr.h"
27
28typedef struct _VoipInputMenuItemPrivate VoipInputMenuItemPrivate;
29
30struct _VoipInputMenuItemPrivate {
31 ActiveSink* a_sink;
32 pa_cvolume volume;
33 gint mute;
34 guint32 volume_steps;
35 pa_channel_map channel_map;
36 pa_volume_t base_volume;
37 gint source_index;
38 gint sink_input_index;
39 gint client_index;
40};
41
42#define VOIP_INPUT_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItemPrivate))
43
44/* Prototypes */
45static void voip_input_menu_item_class_init (VoipInputMenuItemClass *klass);
46static void voip_input_menu_item_init (VoipInputMenuItem *self);
47static void voip_input_menu_item_dispose (GObject *object);
48static void voip_input_menu_item_finalize (GObject *object);
49static void handle_event (DbusmenuMenuitem * mi, const gchar * name,
50 GVariant * value, guint timestamp);
51// TODO:
52// This method should really be shared between this and the volume slider obj
53// perfectly static - wait until the device mgr wrapper is properly sorted and
54// then consolidate
55static pa_cvolume voip_input_menu_item_construct_mono_volume (const pa_cvolume* vol);
56
57G_DEFINE_TYPE (VoipInputMenuItem, voip_input_menu_item, DBUSMENU_TYPE_MENUITEM);
58
59static void
60voip_input_menu_item_class_init (VoipInputMenuItemClass *klass)
61{
62 GObjectClass *object_class = G_OBJECT_CLASS (klass);
63
64 g_type_class_add_private (klass, sizeof (VoipInputMenuItemPrivate));
65
66 object_class->dispose = voip_input_menu_item_dispose;
67 object_class->finalize = voip_input_menu_item_finalize;
68
69 DbusmenuMenuitemClass * mclass = DBUSMENU_MENUITEM_CLASS(klass);
70 mclass->handle_event = handle_event;
71}
72
73static void
74voip_input_menu_item_init (VoipInputMenuItem *self)
75{
76 g_debug("Building new Slider Menu Item");
77 dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self),
78 DBUSMENU_MENUITEM_PROP_TYPE,
79 DBUSMENU_VOIP_INPUT_MENUITEM_TYPE );
80 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (self);
81 dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(self),
82 DBUSMENU_MENUITEM_PROP_VISIBLE,
83 FALSE );
84
85 priv->source_index = NOT_ACTIVE;
86 priv->sink_input_index = NOT_ACTIVE;
87 priv->client_index = NOT_ACTIVE;
88 priv->mute = NOT_ACTIVE;
89}
90
91static void
92voip_input_menu_item_dispose (GObject *object)
93{
94 G_OBJECT_CLASS (voip_input_menu_item_parent_class)->dispose (object);
95 return;
96}
97
98static void
99voip_input_menu_item_finalize (GObject *object)
100{
101 G_OBJECT_CLASS (voip_input_menu_item_parent_class)->finalize (object);
102}
103
104static void
105handle_event (DbusmenuMenuitem * mi,
106 const gchar * name,
107 GVariant * value,
108 guint timestamp)
109{
110 GVariant* input = NULL;
111 input = value;
112 if (g_variant_is_of_type(value, G_VARIANT_TYPE_VARIANT) == TRUE) {
113 input = g_variant_get_variant(value);
114 }
115
116 gdouble percent = g_variant_get_double(input);
117 if (value != NULL){
118 if (IS_VOIP_INPUT_MENU_ITEM (mi)) {
119 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (VOIP_INPUT_MENU_ITEM (mi));
120 g_debug ("Handle event in the voip input level backend instance - %f", percent);
121 pa_cvolume new_volume;
122 pa_cvolume_init(&new_volume);
123 new_volume.channels = 1;
124 pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100);
125 pa_cvolume_set(&new_volume, 1, new_volume_value);
126
127 pm_update_mic_gain (priv->source_index, new_volume);
128 // finally unmute if needed
129 if (priv->mute == 1) {
130 pm_update_mic_mute (priv->source_index, 0);
131 }
132 //active_sink_update_volume (priv->a_sink, volume_input);
133 //active_sink_ensure_sink_is_unmuted (priv->a_sink);
134 }
135 }
136}
137
138static pa_cvolume
139voip_input_menu_item_construct_mono_volume (const pa_cvolume* vol)
140{
141 pa_cvolume new_volume;
142 pa_cvolume_init(&new_volume);
143 new_volume.channels = 1;
144 pa_volume_t max_vol = pa_cvolume_max(vol);
145 pa_cvolume_set(&new_volume, 1, max_vol);
146 return new_volume;
147}
148
149void
150voip_input_menu_item_update (VoipInputMenuItem* item,
151 const pa_source_info* source)
152{
153 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
154 // only overwrite the constants of each source if the device has changed
155 if (priv->source_index == NOT_ACTIVE){
156 priv->base_volume = source->base_volume;
157 priv->volume_steps = source->n_volume_steps;
158 priv->channel_map = source->channel_map;
159 priv->source_index = source->index;
160 }
161 priv->volume = voip_input_menu_item_construct_mono_volume (&source->volume);
162 pa_volume_t vol = pa_cvolume_max (&source->volume);
163 gdouble update = ((gdouble) vol * 100) / PA_VOLUME_NORM;
164
165 GVariant* new_volume = g_variant_new_double(update);
166 dbusmenu_menuitem_property_set_variant(DBUSMENU_MENUITEM(item),
167 DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL,
168 new_volume);
169 // Only send over the mute updates if the state has changed.
170 // in this order - volume first mute last!!
171 if (priv->mute != source->mute){
172 g_debug ("voip menu item - update - mute = %i", priv->mute);
173 GVariant* new_mute_update = g_variant_new_int32 (source->mute);
174 dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(item),
175 DBUSMENU_VOIP_INPUT_MENUITEM_MUTE,
176 new_mute_update);
177 }
178
179 priv->mute = source->mute;
180
181}
182
183gboolean
184voip_input_menu_item_is_interested (VoipInputMenuItem* item,
185 gint sink_input_index,
186 gint client_index)
187{
188 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
189 // Check to make sure we are not handling another voip beforehand and that we
190 // have an active sink (might need to match up at start up)
191 if (priv->sink_input_index != NOT_ACTIVE &&
192 priv->source_index != NOT_ACTIVE){
193 return FALSE;
194 }
195
196 priv->sink_input_index = sink_input_index;
197 priv->client_index = client_index;
198
199 return TRUE;
200}
201
202gboolean
203voip_input_menu_item_is_active (VoipInputMenuItem* item)
204{
205 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
206 return (priv->sink_input_index != NOT_ACTIVE && priv->client_index != NOT_ACTIVE);
207}
208
209
210gboolean
211voip_input_menu_item_is_populated (VoipInputMenuItem* item)
212{
213 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
214 return priv->source_index != NOT_ACTIVE;
215}
216
217gint
218voip_input_menu_item_get_index (VoipInputMenuItem* item)
219{
220 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
221 return priv->source_index;
222}
223
224gint
225voip_input_menu_item_get_sink_input_index (VoipInputMenuItem* item)
226{
227 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
228
229 return priv->sink_input_index;
230}
231
232/**
233 * If the pulse server informs of a default source change
234 * or the source in question is removed.
235 * @param item
236 */
237void
238voip_input_menu_item_deactivate_source (VoipInputMenuItem* item, gboolean visible)
239{
240 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
241 priv->source_index = NOT_ACTIVE;
242 dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item),
243 DBUSMENU_MENUITEM_PROP_VISIBLE,
244 visible );
245}
246
247void
248voip_input_menu_item_deactivate_voip_client (VoipInputMenuItem* item)
249{
250 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
251 priv->client_index = NOT_ACTIVE;
252 priv->sink_input_index = NOT_ACTIVE;
253 voip_input_menu_item_enable (item, FALSE);
254}
255
256void
257voip_input_menu_item_enable (VoipInputMenuItem* item,
258 gboolean active)
259{
260 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
261 if (priv->source_index == NOT_ACTIVE && active == TRUE) {
262 g_warning ("Tried to enable the VOIP menuitem but we don't have an active source ??");
263 active = FALSE;
264 }
265 dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item),
266 DBUSMENU_MENUITEM_PROP_VISIBLE,
267 active );
268}
269
270VoipInputMenuItem*
271voip_input_menu_item_new (ActiveSink* sink)
272{
273 VoipInputMenuItem *self = g_object_new(VOIP_INPUT_MENU_ITEM_TYPE, NULL);
274 VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (self);
275 priv->a_sink = sink;
276 return self;
277}
0\ No newline at end of file278\ No newline at end of file
1279
=== added file 'src/voip-input-menu-item.h'
--- src/voip-input-menu-item.h 1970-01-01 00:00:00 +0000
+++ src/voip-input-menu-item.h 2011-02-18 17:27:12 +0000
@@ -0,0 +1,70 @@
1/*
2Copyright 2011 Canonical Ltd.
3
4Authors:
5 Conor Curran <conor.curran@canonical.com>
6
7This program is free software: you can redistribute it and/or modify it
8under the terms of the GNU General Public License version 3, as published
9by the Free Software Foundation.
10
11This program is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranties of
13MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14PURPOSE. See the GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License along
17with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifndef __VOIP_INPUT_MENU_ITEM_H__
20#define __VOIP_INPUT_MENU_ITEM_H__
21
22#include <glib.h>
23#include <pulse/pulseaudio.h>
24#include <libdbusmenu-glib/menuitem.h>
25#include "active-sink.h"
26
27G_BEGIN_DECLS
28
29#define VOIP_INPUT_MENU_ITEM_TYPE (voip_input_menu_item_get_type ())
30#define VOIP_INPUT_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItem))
31#define VOIP_INPUT_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItemClass))
32#define IS_VOIP_INPUT_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VOIP_INPUT_MENU_ITEM_TYPE))
33#define IS_VOIP_INPUT_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VOIP_INPUT_MENU_ITEM_TYPE))
34#define VOIP_INPUT_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItemClass))
35
36typedef struct _VoipInputMenuItem VoipInputMenuItem;
37typedef struct _VoipInputMenuItemClass VoipInputMenuItemClass;
38
39struct _VoipInputMenuItemClass {
40 DbusmenuMenuitemClass parent_class;
41};
42
43struct _VoipInputMenuItem {
44 DbusmenuMenuitem parent;
45};
46
47GType voip_input_menu_item_get_type (void);
48
49void voip_input_menu_item_update (VoipInputMenuItem* item,
50 const pa_source_info* source);
51void voip_input_menu_item_enable (VoipInputMenuItem* item, gboolean active);
52gboolean voip_input_menu_item_is_interested (VoipInputMenuItem* item,
53 gint sink_input_index,
54 gint client_index);
55gboolean voip_input_menu_item_is_active (VoipInputMenuItem* item);
56gboolean voip_input_menu_item_is_populated (VoipInputMenuItem* item);
57// TODO rename get source index
58gint voip_input_menu_item_get_index (VoipInputMenuItem* item);
59
60gint voip_input_menu_item_get_sink_input_index (VoipInputMenuItem* item);
61
62void voip_input_menu_item_deactivate_source (VoipInputMenuItem* item, gboolean visible);
63void voip_input_menu_item_deactivate_voip_client (VoipInputMenuItem* item);
64
65VoipInputMenuItem* voip_input_menu_item_new (ActiveSink* sink);
66
67G_END_DECLS
68
69#endif
70
071
=== added file 'src/voip-input-widget.c'
--- src/voip-input-widget.c 1970-01-01 00:00:00 +0000
+++ src/voip-input-widget.c 2011-02-18 17:27:12 +0000
@@ -0,0 +1,279 @@
1
2/*
3Copyright 2011 Canonical Ltd.
4
5Authors:
6 Conor Curran <conor.curran@canonical.com>
7
8This program is free software: you can redistribute it and/or modify it
9under the terms of the GNU General Public License version 3, as published
10by the Free Software Foundation.
11
12This program is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranties of
14MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15PURPOSE. See the GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along
18with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include <glib/gi18n.h>
26#include <math.h>
27#include <glib.h>
28#include "voip-input-widget.h"
29#include "common-defs.h"
30#include <libido/idoscalemenuitem.h>
31
32typedef struct _VoipInputWidgetPrivate VoipInputWidgetPrivate;
33
34struct _VoipInputWidgetPrivate
35{
36 DbusmenuMenuitem* twin_item;
37 GtkWidget* ido_voip_input_slider;
38 gboolean grabbed;
39};
40
41#define VOIP_INPUT_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOIP_INPUT_WIDGET_TYPE, VoipInputWidgetPrivate))
42
43/* Prototypes */
44static void voip_input_widget_class_init (VoipInputWidgetClass *klass);
45static void voip_input_widget_init (VoipInputWidget *self);
46static void voip_input_widget_dispose (GObject *object);
47static void voip_input_widget_finalize (GObject *object);
48static void voip_input_widget_set_twin_item( VoipInputWidget* self,
49 DbusmenuMenuitem* twin_item);
50static void voip_input_widget_property_update( DbusmenuMenuitem* item, gchar* property,
51 GVariant* value, gpointer userdata );
52
53static gboolean voip_input_widget_change_value_cb (GtkRange *range,
54 GtkScrollType scroll,
55 gdouble value,
56 gpointer user_data);
57static gboolean voip_input_widget_value_changed_cb(GtkRange *range, gpointer user_data);
58static void voip_input_widget_slider_grabbed(GtkWidget *widget, gpointer user_data);
59static void voip_input_widget_slider_released(GtkWidget *widget, gpointer user_data);
60static void voip_input_widget_parent_changed (GtkWidget *widget, gpointer user_data);
61
62G_DEFINE_TYPE (VoipInputWidget, voip_input_widget, G_TYPE_OBJECT);
63
64
65static void
66voip_input_widget_class_init (VoipInputWidgetClass *klass)
67{
68 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
69
70 g_type_class_add_private (klass, sizeof (VoipInputWidgetPrivate));
71
72 gobject_class->dispose = voip_input_widget_dispose;
73 gobject_class->finalize = voip_input_widget_finalize;
74}
75
76static void
77voip_input_widget_init (VoipInputWidget *self)
78{
79 VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self);
80
81 priv->ido_voip_input_slider = ido_scale_menu_item_new_with_range ("VOLUME", IDO_RANGE_STYLE_DEFAULT, 0, 0, 100, 1);
82 g_object_ref (priv->ido_voip_input_slider);
83 ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM (priv->ido_voip_input_slider), IDO_SCALE_MENU_ITEM_STYLE_IMAGE);
84 g_object_set(priv->ido_voip_input_slider, "reverse-scroll-events", TRUE, NULL);
85
86 g_signal_connect (priv->ido_voip_input_slider,
87 "notify::parent", G_CALLBACK (voip_input_widget_parent_changed),
88 NULL);
89
90 GtkWidget* voip_input_widget = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider);
91
92 g_signal_connect(voip_input_widget, "change-value", G_CALLBACK(voip_input_widget_change_value_cb), self);
93 g_signal_connect(voip_input_widget, "value-changed", G_CALLBACK(voip_input_widget_value_changed_cb), self);
94 g_signal_connect(priv->ido_voip_input_slider, "slider-grabbed", G_CALLBACK(voip_input_widget_slider_grabbed), self);
95 g_signal_connect(priv->ido_voip_input_slider, "slider-released", G_CALLBACK(voip_input_widget_slider_released), self);
96
97 GtkWidget* primary_image = ido_scale_menu_item_get_primary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider);
98 GIcon * primary_gicon = g_themed_icon_new_with_default_fallbacks("audio-input-microphone");
99 gtk_image_set_from_gicon(GTK_IMAGE(primary_image), primary_gicon, GTK_ICON_SIZE_MENU);
100 g_object_unref(primary_gicon);
101
102 GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider);
103 GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks("audio-input-microphone-high");
104 gtk_image_set_from_gicon(GTK_IMAGE(secondary_image), secondary_gicon, GTK_ICON_SIZE_MENU);
105 g_object_unref(secondary_gicon);
106
107 GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (voip_input_widget));
108 gtk_adjustment_set_step_increment(adj, 4);
109}
110
111static void
112voip_input_widget_dispose (GObject *object)
113{
114 G_OBJECT_CLASS (voip_input_widget_parent_class)->dispose (object);
115}
116
117static void
118voip_input_widget_finalize (GObject *object)
119{
120 G_OBJECT_CLASS (voip_input_widget_parent_class)->finalize (object);
121}
122
123static void
124voip_input_widget_property_update (DbusmenuMenuitem* item, gchar* property,
125 GVariant* value, gpointer userdata)
126{
127 g_return_if_fail (IS_VOIP_INPUT_WIDGET (userdata));
128 VoipInputWidget* mitem = VOIP_INPUT_WIDGET(userdata);
129 VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem);
130 //g_debug("scrub-widget::property_update for prop %s", property);
131 if(g_ascii_strcasecmp(DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL, property) == 0){
132 if(priv->grabbed == FALSE){
133 GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider);
134 GtkRange *range = (GtkRange*)slider;
135 gdouble update = g_variant_get_double (value);
136 //g_debug("volume-widget - update level with value %f", update);
137 gtk_range_set_value(range, update);
138 }
139 }
140 if(g_ascii_strcasecmp(DBUSMENU_VOIP_INPUT_MENUITEM_MUTE, property) == 0){
141 if(priv->grabbed == FALSE){
142 GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider);
143 GtkRange *range = (GtkRange*)slider;
144 gint update = g_variant_get_int32 (value);
145 gdouble level;
146 if (update == 1){
147 level = 0;
148 }
149 else{
150 level = g_variant_get_double (dbusmenu_menuitem_property_get_variant (priv->twin_item,
151 DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL));
152 }
153 gtk_range_set_value(range, level);
154
155 g_debug ("voip-item-widget - update mute with value %i", update);
156 }
157 }
158}
159
160static void
161voip_input_widget_set_twin_item (VoipInputWidget* self,
162 DbusmenuMenuitem* twin_item)
163{
164 VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self);
165 priv->twin_item = twin_item;
166 g_object_ref(priv->twin_item);
167 g_signal_connect(G_OBJECT(twin_item), "property-changed",
168 G_CALLBACK(voip_input_widget_property_update), self);
169 gdouble initial_level = g_variant_get_double (dbusmenu_menuitem_property_get_variant(twin_item,
170 DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL));
171 //g_debug("voip_input_widget_set_twin_item initial level = %f", initial_level);
172 GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider);
173 GtkRange *range = (GtkRange*)slider;
174 gtk_range_set_value(range, initial_level);
175
176 gint mute = g_variant_get_int32 (dbusmenu_menuitem_property_get_variant (priv->twin_item,
177 DBUSMENU_VOIP_INPUT_MENUITEM_MUTE));
178 if (mute == 1){
179 gtk_range_set_value (range, 0.0);
180 }
181}
182
183static gboolean
184voip_input_widget_change_value_cb (GtkRange *range,
185 GtkScrollType scroll,
186 gdouble new_value,
187 gpointer user_data)
188{
189 g_return_val_if_fail (IS_VOIP_INPUT_WIDGET (user_data), FALSE);
190 VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data);
191 voip_input_widget_update(mitem, new_value);
192 return FALSE;
193}
194
195
196/**
197 * We only want this callback to catch mouse icon press events which set the
198 * slider to 0 or 100. Ignore all other events including the new Mute behaviour
199 * (slider to go to 0 on mute without setting the level to 0 and return to
200 * previous level on unmute)
201 **/
202static gboolean
203voip_input_widget_value_changed_cb(GtkRange *range, gpointer user_data)
204{
205 g_return_val_if_fail (IS_VOIP_INPUT_WIDGET (user_data), FALSE);
206 VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data);
207 VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem);
208 GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider);
209 gdouble current_value = CLAMP(gtk_range_get_value(GTK_RANGE(slider)), 0, 100);
210
211 gint mute = g_variant_get_int32 (dbusmenu_menuitem_property_get_variant (priv->twin_item,
212 DBUSMENU_VOIP_INPUT_MENUITEM_MUTE));
213 if ((current_value == 0 && mute != 1) || current_value == 100 ){
214 voip_input_widget_update(mitem, current_value);
215 }
216 return FALSE;
217}
218
219void
220voip_input_widget_update(VoipInputWidget* self, gdouble update)
221{
222 VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self);
223 gdouble clamped = CLAMP(update, 0, 100);
224 GVariant* new_volume = g_variant_new_double(clamped);
225 dbusmenu_menuitem_handle_event (priv->twin_item, "update", new_volume, 0);
226}
227
228GtkWidget*
229voip_input_widget_get_ido_slider(VoipInputWidget* self)
230{
231 VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self);
232 return priv->ido_voip_input_slider;
233}
234
235static void
236voip_input_widget_parent_changed (GtkWidget *widget,
237 gpointer user_data)
238{
239 gtk_widget_set_size_request (widget, 200, -1);
240 //g_debug("voip_input_widget_parent_changed");
241}
242
243static void
244voip_input_widget_slider_grabbed(GtkWidget *widget, gpointer user_data)
245{
246 VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data);
247 VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem);
248 priv->grabbed = TRUE;
249}
250
251static void
252voip_input_widget_slider_released(GtkWidget *widget, gpointer user_data)
253{
254 VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data);
255 VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem);
256 priv->grabbed = FALSE;
257}
258
259void
260voip_input_widget_tidy_up (GtkWidget *widget)
261{
262 VoipInputWidget* mitem = VOIP_INPUT_WIDGET(widget);
263 VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem);
264 gtk_widget_destroy (priv->ido_voip_input_slider);
265}
266
267/**
268 * voip_input_widget_new:
269 * @returns: a new #VoipInputWidget.
270 **/
271GtkWidget*
272voip_input_widget_new(DbusmenuMenuitem *item)
273{
274 GtkWidget* widget = g_object_new(VOIP_INPUT_WIDGET_TYPE, NULL);
275 voip_input_widget_set_twin_item((VoipInputWidget*)widget, item);
276 return widget;
277}
278
279
0280
=== added file 'src/voip-input-widget.h'
--- src/voip-input-widget.h 1970-01-01 00:00:00 +0000
+++ src/voip-input-widget.h 2011-02-18 17:27:12 +0000
@@ -0,0 +1,55 @@
1/*
2Copyright 2011 Canonical Ltd.
3
4Authors:
5 Conor Curran <conor.curran@canonical.com>
6
7This program is free software: you can redistribute it and/or modify it
8under the terms of the GNU General Public License version 3, as published
9by the Free Software Foundation.
10
11This program is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranties of
13MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14PURPOSE. See the GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License along
17with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifndef __VOIP_INPUT_WIDGET_H__
20#define __VOIP_INPUT_WIDGET_H__
21
22#include <glib.h>
23#include <glib-object.h>
24#include <libdbusmenu-gtk/menuitem.h>
25
26G_BEGIN_DECLS
27
28#define VOIP_INPUT_WIDGET_TYPE (voip_input_widget_get_type ())
29#define VOIP_INPUT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VOIP_INPUT_WIDGET_TYPE, VoipInputWidget))
30#define VOIP_INPUT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VOIP_INPUT_WIDGET_TYPE, VoipInputWidgetClass))
31#define IS_VOIP_INPUT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VOIP_INPUT_WIDGET_TYPE))
32#define IS_VOIP_INPUT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VOIP_INPUT_WIDGET_TYPE))
33#define VOIP_INPUT_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VOIP_INPUT_WIDGET_TYPE, VoipInputWidgetClass))
34
35typedef struct _VoipInputWidget VoipInputWidget;
36typedef struct _VoipInputWidgetClass VoipInputWidgetClass;
37
38struct _VoipInputWidgetClass {
39 GObjectClass parent_class;
40};
41
42struct _VoipInputWidget {
43 GObject parent;
44};
45
46GType voip_input_widget_get_type (void) G_GNUC_CONST;
47GtkWidget* voip_input_widget_new(DbusmenuMenuitem* twin_item);
48GtkWidget* voip_input_widget_get_ido_slider(VoipInputWidget* self);
49void voip_input_widget_update(VoipInputWidget* self, gdouble update);
50void voip_input_widget_tidy_up (GtkWidget *widget);
51
52G_END_DECLS
53
54#endif
55

Subscribers

People subscribed via source and target branches