~skypce/indicator-session/indicator-session

« back to all changes in this revision

Viewing changes to src/status-provider-telepathy.c

  • Committer: Bazaar Package Importer
  • Author(s): Ted Gould
  • Date: 2009-08-27 21:30:27 UTC
  • mto: (13.1.3 lucid)
  • mto: This revision was merged to the branch mainline in revision 2.
  • Revision ID: james.westby@ubuntu.com-20090827213027-njdte02ngc9e4bbn
Tags: upstream-0.1
ImportĀ upstreamĀ versionĀ 0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
A small wrapper utility to load indicators and put them as menu items
 
3
into the gnome-panel using it's applet interface.
 
4
 
 
5
Copyright 2009 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 "status-provider.h"
 
28
#include "status-provider-telepathy.h"
 
29
#include "status-provider-telepathy-marshal.h"
 
30
 
 
31
#include <dbus/dbus-glib.h>
 
32
 
 
33
typedef enum {
 
34
        MC_STATUS_UNSET,
 
35
        MC_STATUS_OFFLINE,
 
36
        MC_STATUS_AVAILABLE,
 
37
        MC_STATUS_AWAY,
 
38
        MC_STATUS_EXTENDED_AWAY,
 
39
        MC_STATUS_HIDDEN,
 
40
        MC_STATUS_DND
 
41
} mc_status_t;
 
42
 
 
43
static StatusProviderStatus mc_to_sp_map[] = {
 
44
        /* MC_STATUS_UNSET,         */  STATUS_PROVIDER_STATUS_OFFLINE,
 
45
        /* MC_STATUS_OFFLINE,       */  STATUS_PROVIDER_STATUS_OFFLINE,
 
46
        /* MC_STATUS_AVAILABLE,     */  STATUS_PROVIDER_STATUS_ONLINE,
 
47
        /* MC_STATUS_AWAY,          */  STATUS_PROVIDER_STATUS_AWAY,
 
48
        /* MC_STATUS_EXTENDED_AWAY, */  STATUS_PROVIDER_STATUS_AWAY,
 
49
        /* MC_STATUS_HIDDEN,        */  STATUS_PROVIDER_STATUS_INVISIBLE,
 
50
        /* MC_STATUS_DND            */  STATUS_PROVIDER_STATUS_DND
 
51
};
 
52
 
 
53
static mc_status_t sp_to_mc_map[] = {
 
54
        /* STATUS_PROVIDER_STATUS_ONLINE,  */  MC_STATUS_AVAILABLE,
 
55
        /* STATUS_PROVIDER_STATUS_AWAY,    */  MC_STATUS_AWAY,
 
56
        /* STATUS_PROVIDER_STATUS_DND      */  MC_STATUS_DND,
 
57
        /* STATUS_PROVIDER_STATUS_INVISIBLE*/  MC_STATUS_HIDDEN,
 
58
        /* STATUS_PROVIDER_STATUS_OFFLINE  */  MC_STATUS_OFFLINE
 
59
};
 
60
 
 
61
typedef struct _StatusProviderTelepathyPrivate StatusProviderTelepathyPrivate;
 
62
struct _StatusProviderTelepathyPrivate {
 
63
        DBusGProxy * proxy;
 
64
        mc_status_t  mc_status;
 
65
};
 
66
 
 
67
#define STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(o) \
 
68
(G_TYPE_INSTANCE_GET_PRIVATE ((o), STATUS_PROVIDER_TELEPATHY_TYPE, StatusProviderTelepathyPrivate))
 
69
 
 
70
/* Prototypes */
 
71
/* GObject stuff */
 
72
static void status_provider_telepathy_class_init (StatusProviderTelepathyClass *klass);
 
73
static void status_provider_telepathy_init       (StatusProviderTelepathy *self);
 
74
static void status_provider_telepathy_dispose    (GObject *object);
 
75
static void status_provider_telepathy_finalize   (GObject *object);
 
76
/* Internal Funcs */
 
77
static void set_status (StatusProvider * sp, StatusProviderStatus status);
 
78
static StatusProviderStatus get_status (StatusProvider * sp);
 
79
static void changed_status (DBusGProxy * proxy, guint status, gchar * message, StatusProvider * sp);
 
80
static void proxy_destroy (DBusGProxy * proxy, StatusProvider * sp);
 
81
static void get_status_async (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata);
 
82
 
 
83
G_DEFINE_TYPE (StatusProviderTelepathy, status_provider_telepathy, STATUS_PROVIDER_TYPE);
 
84
 
 
85
static void
 
86
status_provider_telepathy_class_init (StatusProviderTelepathyClass *klass)
 
87
{
 
88
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
89
 
 
90
        g_type_class_add_private (klass, sizeof (StatusProviderTelepathyPrivate));
 
91
 
 
92
        object_class->dispose = status_provider_telepathy_dispose;
 
93
        object_class->finalize = status_provider_telepathy_finalize;
 
94
 
 
95
        StatusProviderClass * spclass = STATUS_PROVIDER_CLASS(klass);
 
96
 
 
97
        spclass->set_status = set_status;
 
98
        spclass->get_status = get_status;
 
99
 
 
100
        return;
 
101
}
 
102
 
 
103
 
 
104
static void
 
105
status_provider_telepathy_init (StatusProviderTelepathy *self)
 
106
{
 
107
        StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(self);
 
108
 
 
109
        priv->proxy = NULL;
 
110
        priv->mc_status = MC_STATUS_OFFLINE;
 
111
 
 
112
        GError * error = NULL;
 
113
 
 
114
        DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
 
115
        if (session_bus == NULL) {
 
116
                g_warning("Unable to connect to Session Bus: %s", error == NULL ? "No message" : error->message);
 
117
                g_error_free(error);
 
118
                return;
 
119
        }
 
120
 
 
121
        priv->proxy = NULL;
 
122
        priv->proxy = dbus_g_proxy_new_for_name_owner(session_bus,
 
123
                                 "org.freedesktop.Telepathy.MissionControl",
 
124
                                "/org/freedesktop/Telepathy/MissionControl",
 
125
                                 "org.freedesktop.Telepathy.MissionControl",
 
126
                                 &error);
 
127
 
 
128
        if (priv->proxy != NULL) {
 
129
                g_object_add_weak_pointer (G_OBJECT(priv->proxy), (gpointer *)&priv->proxy);
 
130
                g_signal_connect(G_OBJECT(priv->proxy), "destroy",
 
131
                                 G_CALLBACK(proxy_destroy), self);
 
132
 
 
133
                dbus_g_object_register_marshaller(_status_provider_telepathy_marshal_VOID__UINT_STRING,
 
134
                                            G_TYPE_NONE,
 
135
                                            G_TYPE_UINT,
 
136
                                            G_TYPE_STRING,
 
137
                                            G_TYPE_INVALID);
 
138
                dbus_g_proxy_add_signal    (priv->proxy,
 
139
                                            "PresenceChanged",
 
140
                                            G_TYPE_UINT,
 
141
                                            G_TYPE_STRING,
 
142
                                            G_TYPE_INVALID);
 
143
                dbus_g_proxy_connect_signal(priv->proxy,
 
144
                                            "PresenceChanged",
 
145
                                            G_CALLBACK(changed_status),
 
146
                                            (void *)self,
 
147
                                            NULL);
 
148
 
 
149
                /* Do a get here, to init the status */
 
150
                dbus_g_proxy_begin_call(priv->proxy,
 
151
                                        "GetStatus",
 
152
                                        get_status_async,
 
153
                                        self,
 
154
                                        NULL,
 
155
                                        G_TYPE_INVALID);
 
156
        } else {
 
157
                g_warning("Unable to connect to Mission Control");
 
158
                if (error != NULL) {
 
159
                        g_error_free(error);
 
160
                }
 
161
        }
 
162
 
 
163
        return;
 
164
}
 
165
 
 
166
static void
 
167
status_provider_telepathy_dispose (GObject *object)
 
168
{
 
169
        StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(object);
 
170
 
 
171
        if (priv->proxy != NULL) {
 
172
                g_object_unref(priv->proxy);
 
173
                priv->proxy = NULL;
 
174
        }
 
175
 
 
176
        G_OBJECT_CLASS (status_provider_telepathy_parent_class)->dispose (object);
 
177
        return;
 
178
}
 
179
 
 
180
static void
 
181
status_provider_telepathy_finalize (GObject *object)
 
182
{
 
183
 
 
184
        G_OBJECT_CLASS (status_provider_telepathy_parent_class)->finalize (object);
 
185
        return;
 
186
}
 
187
 
 
188
/**
 
189
        status_provider_telepathy_new:
 
190
 
 
191
        Creates a new #StatusProviderTelepathy object.  No parameters or anything
 
192
        like that.  Just a convience function.
 
193
 
 
194
        Return value: A new instance of #StatusProviderTelepathy
 
195
*/
 
196
StatusProvider *
 
197
status_provider_telepathy_new (void)
 
198
{
 
199
        return STATUS_PROVIDER(g_object_new(STATUS_PROVIDER_TELEPATHY_TYPE, NULL));
 
200
}
 
201
 
 
202
static void
 
203
set_status (StatusProvider * sp, StatusProviderStatus status)
 
204
{
 
205
        StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(sp);
 
206
        if (priv->proxy == NULL) {
 
207
                priv->mc_status = MC_STATUS_OFFLINE;
 
208
                return;
 
209
        }
 
210
 
 
211
        priv->mc_status = sp_to_mc_map[status]; 
 
212
 
 
213
        guint mcstatus = MC_STATUS_UNSET;
 
214
        gboolean ret = FALSE;
 
215
        GError * error = NULL;
 
216
 
 
217
        ret = dbus_g_proxy_call(priv->proxy,
 
218
                                "GetPresence", &error,
 
219
                                G_TYPE_INVALID,
 
220
                                G_TYPE_UINT, &priv->mc_status,
 
221
                                G_TYPE_INVALID);
 
222
 
 
223
        /* If we can't get the  get call to work, let's not set */
 
224
        if (!ret) {
 
225
                if (error != NULL) {
 
226
                        g_error_free(error);
 
227
                }
 
228
                return;
 
229
        }
 
230
        
 
231
        /* If the get call doesn't return a status, that means that there
 
232
           are no clients connected.  We don't want to connect them by telling
 
233
           MC that we're going online -- we'd like to be more passive than that. */
 
234
        if (mcstatus == MC_STATUS_UNSET) {
 
235
                return;
 
236
        }
 
237
 
 
238
        ret = dbus_g_proxy_call(priv->proxy,
 
239
                                "SetPresence", &error,
 
240
                                G_TYPE_UINT, priv->mc_status,
 
241
                                G_TYPE_STRING, "",
 
242
                                G_TYPE_INVALID,
 
243
                                G_TYPE_INVALID);
 
244
 
 
245
        if (!ret) {
 
246
                if (error != NULL) {
 
247
                        g_warning("Unable to set Mission Control Presence: %s", error->message);
 
248
                        g_error_free(error);
 
249
                } else {
 
250
                        g_warning("Unable to set Mission Control Presence");
 
251
                }
 
252
                return;
 
253
        }
 
254
 
 
255
        return;
 
256
}
 
257
 
 
258
static StatusProviderStatus
 
259
get_status (StatusProvider * sp)
 
260
{
 
261
        StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(sp);
 
262
 
 
263
        if (priv->proxy == NULL) {
 
264
                return mc_to_sp_map[MC_STATUS_OFFLINE];
 
265
        }
 
266
 
 
267
        return mc_to_sp_map[priv->mc_status];
 
268
}
 
269
 
 
270
static void
 
271
changed_status (DBusGProxy * proxy, guint status, gchar * message, StatusProvider * sp)
 
272
{
 
273
        StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(sp);
 
274
        priv->mc_status = status;
 
275
        g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, mc_to_sp_map[priv->mc_status], TRUE);
 
276
}
 
277
 
 
278
static void
 
279
proxy_destroy (DBusGProxy * proxy, StatusProvider * sp)
 
280
{
 
281
        g_debug("Signal: Mission Control proxy destroyed");
 
282
        g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, STATUS_PROVIDER_STATUS_OFFLINE, TRUE);
 
283
        return;
 
284
}
 
285
 
 
286
static void
 
287
get_status_async (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
 
288
{
 
289
        GError * error = NULL;
 
290
        guint status = 0;
 
291
        if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_UINT, &status, G_TYPE_INVALID)) {
 
292
                g_warning("Unable to get type from Mission Control: %s", error->message);
 
293
                g_error_free(error);
 
294
                return;
 
295
        }
 
296
 
 
297
        StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(userdata);
 
298
 
 
299
        gboolean changed = FALSE;
 
300
        if (status != priv->mc_status) {
 
301
                changed = TRUE;
 
302
        }
 
303
 
 
304
        priv->mc_status = status;
 
305
 
 
306
        if (changed) {
 
307
                g_signal_emit(G_OBJECT(userdata), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, mc_to_sp_map[priv->mc_status], TRUE);
 
308
        }
 
309
 
 
310
        return;
 
311
}