~jbicha/hud/build-depend-on-valac-not-gir

« back to all changes in this revision

Viewing changes to service/indicator-tracker.c

Merging the HUD into indicator-appmenu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Tracks the various indicators to know when they come on and off
 
3
the bus for searching their menus.
 
4
 
 
5
Copyright 2011 Canonical Ltd.
 
6
 
 
7
Authors:
 
8
    Ted Gould <ted@canonical.com>
 
9
 
 
10
This program is free software: you can redistribute it and/or modify it 
 
11
under the terms of the GNU General Public License version 3, as published 
 
12
by the Free Software Foundation.
 
13
 
 
14
This program is distributed in the hope that it will be useful, but 
 
15
WITHOUT ANY WARRANTY; without even the implied warranties of 
 
16
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
 
17
PURPOSE.  See the GNU General Public License for more details.
 
18
 
 
19
You should have received a copy of the GNU General Public License along 
 
20
with this program.  If not, see <http://www.gnu.org/licenses/>.
 
21
*/
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#include "config.h"
 
25
#endif
 
26
 
 
27
#include "indicator-tracker.h"
 
28
 
 
29
#include <glib/gi18n.h>
 
30
#include <gio/gio.h>
 
31
 
 
32
typedef struct _SystemIndicator SystemIndicator;
 
33
struct _SystemIndicator {
 
34
        gchar * dbus_name;
 
35
        gchar * dbus_menu_path;
 
36
        gchar * indicator_name;
 
37
        gchar * user_visible_name;
 
38
};
 
39
 
 
40
SystemIndicator system_indicators[] = {
 
41
        {dbus_name: "com.canonical.indicator.datetime", dbus_menu_path: "/com/canonical/indicator/datetime/menu", indicator_name: "indicator-datetime",       user_visible_name: N_("Date") },
 
42
        {dbus_name: "com.canonical.indicator.session",  dbus_menu_path: "/com/canonical/indicator/session/menu",  indicator_name: "indicator-session-device", user_visible_name: N_("Device") },
 
43
        {dbus_name: "com.canonical.indicator.session",  dbus_menu_path: "/com/canonical/indicator/user/menu",     indicator_name: "indicator-session-user",   user_visible_name: N_("User") },
 
44
        {dbus_name: "com.canonical.indicators.sound",   dbus_menu_path: "/com/canonical/indicators/sound/menu",   indicator_name: "indicator-sound",          user_visible_name: N_("Sound") },
 
45
        {dbus_name: "com.canonical.indicator.messages", dbus_menu_path: "/com/canonical/indicator/messages/menu", indicator_name: "indicator-messages",       user_visible_name: N_("Messages") }
 
46
};
 
47
 
 
48
struct _IndicatorTrackerPrivate {
 
49
        GArray * indicators;
 
50
        guint watches[G_N_ELEMENTS(system_indicators)];
 
51
};
 
52
 
 
53
#define INDICATOR_TRACKER_GET_PRIVATE(o) \
 
54
(G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_TRACKER_TYPE, IndicatorTrackerPrivate))
 
55
 
 
56
static void indicator_tracker_class_init (IndicatorTrackerClass *klass);
 
57
static void indicator_tracker_init       (IndicatorTracker *self);
 
58
static void indicator_tracker_dispose    (GObject *object);
 
59
static void indicator_tracker_finalize   (GObject *object);
 
60
static void system_watch_appeared        (GDBusConnection * connection, const gchar * name, const gchar * name_owner, gpointer user_data);
 
61
static void system_watch_vanished        (GDBusConnection * connection, const gchar * name, gpointer user_data);
 
62
 
 
63
G_DEFINE_TYPE (IndicatorTracker, indicator_tracker, G_TYPE_OBJECT);
 
64
 
 
65
static void
 
66
indicator_tracker_class_init (IndicatorTrackerClass *klass)
 
67
{
 
68
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
69
 
 
70
        g_type_class_add_private (klass, sizeof (IndicatorTrackerPrivate));
 
71
 
 
72
        object_class->dispose = indicator_tracker_dispose;
 
73
        object_class->finalize = indicator_tracker_finalize;
 
74
 
 
75
        return;
 
76
}
 
77
 
 
78
static void
 
79
indicator_tracker_init (IndicatorTracker *self)
 
80
{
 
81
        self->priv = INDICATOR_TRACKER_GET_PRIVATE(self);
 
82
        self->priv->indicators = NULL;
 
83
 
 
84
        self->priv->indicators = g_array_new(FALSE, TRUE, sizeof(IndicatorTrackerIndicator));
 
85
 
 
86
        int indicator_cnt;
 
87
        for (indicator_cnt = 0; indicator_cnt < G_N_ELEMENTS(system_indicators); indicator_cnt++) {
 
88
                self->priv->watches[indicator_cnt] = g_bus_watch_name(G_BUS_TYPE_SESSION,
 
89
                                                                      system_indicators[indicator_cnt].dbus_name,
 
90
                                                                      G_BUS_NAME_WATCHER_FLAGS_NONE,
 
91
                                                                      system_watch_appeared, /* acquired */
 
92
                                                                      system_watch_vanished, /* vanished */
 
93
                                                                      self,
 
94
                                                                      NULL); /* free func */
 
95
        }
 
96
 
 
97
        return;
 
98
}
 
99
 
 
100
static void
 
101
indicator_tracker_dispose (GObject *object)
 
102
{
 
103
        IndicatorTracker * self = INDICATOR_TRACKER(object);
 
104
 
 
105
        int indicator_cnt;
 
106
        for (indicator_cnt = 0; indicator_cnt < G_N_ELEMENTS(system_indicators); indicator_cnt++) {
 
107
                if (self->priv->watches[indicator_cnt] != 0) {
 
108
                        g_bus_unwatch_name(self->priv->watches[indicator_cnt]);
 
109
                        self->priv->watches[indicator_cnt] = 0;
 
110
                }
 
111
        }
 
112
        
 
113
 
 
114
        G_OBJECT_CLASS (indicator_tracker_parent_class)->dispose (object);
 
115
        return;
 
116
}
 
117
 
 
118
static void
 
119
indicator_tracker_finalize (GObject *object)
 
120
{
 
121
 
 
122
        G_OBJECT_CLASS (indicator_tracker_parent_class)->finalize (object);
 
123
        return;
 
124
}
 
125
 
 
126
IndicatorTracker *
 
127
indicator_tracker_new (void)
 
128
{
 
129
        return INDICATOR_TRACKER(g_object_new(INDICATOR_TRACKER_TYPE, NULL));
 
130
}
 
131
 
 
132
GArray *
 
133
indicator_tracker_get_indicators (IndicatorTracker * tracker)
 
134
{
 
135
        g_return_val_if_fail(IS_INDICATOR_TRACKER(tracker), NULL);
 
136
        return tracker->priv->indicators;
 
137
}
 
138
 
 
139
/* Function watches names on Dbus to find out when the system indicators
 
140
   go on and off the bus.  This makes it so that we can handle them properly
 
141
   at the higher levels in the system.  If a system indicator gets added to
 
142
   the list it gets put the indicator structure. */
 
143
static void
 
144
system_watch_appeared (GDBusConnection * connection, const gchar * name, const gchar * name_owner, gpointer user_data)
 
145
{
 
146
        g_return_if_fail(IS_INDICATOR_TRACKER(user_data));
 
147
        g_return_if_fail(name_owner != NULL);
 
148
        g_return_if_fail(name_owner[0] != '\0');
 
149
        IndicatorTracker * self = INDICATOR_TRACKER(user_data);
 
150
 
 
151
        /* Check all the system indicators because there might be more than
 
152
           one menu/indicator on a well known name */
 
153
        int indicator_cnt;
 
154
        for (indicator_cnt = 0; indicator_cnt < G_N_ELEMENTS(system_indicators); indicator_cnt++) {
 
155
                SystemIndicator * sys_indicator = &system_indicators[indicator_cnt];
 
156
 
 
157
                if (g_strcmp0(sys_indicator->dbus_name, name) != 0) {
 
158
                        continue;
 
159
                }
 
160
 
 
161
                /* Check to see if we already have this system indicator in the
 
162
                   list of indicators */
 
163
                int i;
 
164
                for (i = 0; i < self->priv->indicators->len; i++) {
 
165
                        IndicatorTrackerIndicator * indicator = &g_array_index(self->priv->indicators, IndicatorTrackerIndicator, i);
 
166
 
 
167
                        if (g_strcmp0(sys_indicator->dbus_name, indicator->dbus_name_wellknown) != 0) {
 
168
                                continue;
 
169
                        }
 
170
 
 
171
                        if (g_strcmp0(sys_indicator->dbus_menu_path, indicator->dbus_object) != 0) {
 
172
                                continue;
 
173
                        }
 
174
 
 
175
                        /* If both of them match, we need to break */
 
176
                        break;
 
177
                }
 
178
 
 
179
                /* We found it in the list so we broke out eary */
 
180
                if (i != self->priv->indicators->len) {
 
181
                        continue;
 
182
                }
 
183
 
 
184
                g_debug("Adding an indicator for '%s' at owner '%s'", name, name_owner);
 
185
                /* Okay, we need to build one for this system indicator */
 
186
                IndicatorTrackerIndicator final_indicator = {
 
187
                        name: g_strdup(sys_indicator->indicator_name),
 
188
                        dbus_name: g_strdup(name_owner),
 
189
                        dbus_name_wellknown: g_strdup(sys_indicator->dbus_name),
 
190
                        dbus_object: g_strdup(sys_indicator->dbus_menu_path),
 
191
                        prefix: g_strdup(_(sys_indicator->user_visible_name))
 
192
                };
 
193
 
 
194
                g_array_append_val(self->priv->indicators, final_indicator);
 
195
        }
 
196
 
 
197
        return;
 
198
}
 
199
 
 
200
/* When the names drop off of DBus we need to check to see if that
 
201
   means any indicators getting lost as well.  If so, remove them from
 
202
   the indicator list. */
 
203
static void
 
204
system_watch_vanished (GDBusConnection * connection, const gchar * name, gpointer user_data)
 
205
{
 
206
        g_return_if_fail(IS_INDICATOR_TRACKER(user_data));
 
207
        IndicatorTracker * self = INDICATOR_TRACKER(user_data);
 
208
 
 
209
        /* See if any of our indicators know this name */
 
210
        int i;
 
211
        for (i = 0; i < self->priv->indicators->len; i++) {
 
212
                IndicatorTrackerIndicator * indicator = &g_array_index(self->priv->indicators, IndicatorTrackerIndicator, i);
 
213
 
 
214
                /* Doesn't match */
 
215
                if (g_strcmp0(indicator->dbus_name_wellknown, name) != 0) {
 
216
                        continue;
 
217
                }
 
218
 
 
219
                g_free(indicator->name);
 
220
                g_free(indicator->dbus_name);
 
221
                g_free(indicator->dbus_name_wellknown);
 
222
                g_free(indicator->dbus_object);
 
223
                g_free(indicator->prefix);
 
224
 
 
225
                g_array_remove_index_fast(self->priv->indicators, i);
 
226
                /* Oh, this is confusing.  Basically becasue we shorten the array
 
227
                   we need to check the one that replaced the entry we deleted
 
228
                   so we have to look in this same slot again. */
 
229
                i--;
 
230
        }
 
231
 
 
232
        return;
 
233
}