~indicator-applet-developers/indicator-session/trunk.0.1

« back to all changes in this revision

Viewing changes to src/session-service.c

  • Committer: Ted Gould
  • Date: 2009-07-27 04:47:27 UTC
  • mfrom: (9.1.94 fusa.libindicator)
  • Revision ID: ted@canonical.com-20090727044727-m04ul5d8sxqt2pd4
Merging in the branch to port everything to libindicator and fleshing thigns out.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include <glib/gi18n.h>
 
3
 
 
4
#include <dbus/dbus-glib.h>
 
5
#include <dbus/dbus-glib-bindings.h>
 
6
 
 
7
#include <libdbusmenu-glib/server.h>
 
8
#include <libdbusmenu-glib/menuitem.h>
 
9
 
 
10
#include "dbus-shared-names.h"
 
11
 
 
12
#define DKP_ADDRESS    "org.freedesktop.DeviceKit.Power"
 
13
#define DKP_OBJECT     "/org/freedesktop/DeviceKit/Power"
 
14
#define DKP_INTERFACE  "org.freedesktop.DeviceKit.Power"
 
15
 
 
16
static DbusmenuMenuitem * root_menuitem = NULL;
 
17
static GMainLoop * mainloop = NULL;
 
18
static DBusGProxy * dkp_main_proxy = NULL;
 
19
static DBusGProxy * dkp_prop_proxy = NULL;
 
20
 
 
21
static DBusGProxyCall * suspend_call = NULL;
 
22
static DBusGProxyCall * hibernate_call = NULL;
 
23
 
 
24
static DbusmenuMenuitem * hibernate_mi = NULL;
 
25
static DbusmenuMenuitem * suspend_mi = NULL;
 
26
 
 
27
/* Let's put this machine to sleep, with some info on how
 
28
   it should sleep.  */
 
29
static void
 
30
sleep (DbusmenuMenuitem * mi, gpointer userdata)
 
31
{
 
32
        gchar * type = (gchar *)userdata;
 
33
 
 
34
        if (dkp_main_proxy == NULL) {
 
35
                g_warning("Can not %s as no DeviceKit Power Proxy", type);
 
36
        }
 
37
 
 
38
        dbus_g_proxy_call_no_reply(dkp_main_proxy,
 
39
                                   type,
 
40
                                   G_TYPE_INVALID,
 
41
                                   G_TYPE_INVALID);
 
42
 
 
43
        return;
 
44
}
 
45
 
 
46
/* A response to getting the suspend property */
 
47
static void
 
48
suspend_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
 
49
{
 
50
        suspend_call = NULL;
 
51
 
 
52
        GValue candoit = {0};
 
53
        GError * error = NULL;
 
54
        dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &candoit, G_TYPE_INVALID);
 
55
        if (error != NULL) {
 
56
                g_warning("Unable to check suspend: %s", error->message);
 
57
                g_error_free(error);
 
58
                return;
 
59
        }
 
60
        g_debug("Got Suspend: %s", g_value_get_boolean(&candoit) ? "true" : "false");
 
61
 
 
62
        if (suspend_mi != NULL) {
 
63
                dbusmenu_menuitem_property_set(suspend_mi, "visible", g_value_get_boolean(&candoit) ? "true" : "false");
 
64
        }
 
65
 
 
66
        return;
 
67
}
 
68
 
 
69
/* Response to getting the hibernate property */
 
70
static void
 
71
hibernate_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
 
72
{
 
73
        hibernate_call = NULL;
 
74
 
 
75
        GValue candoit = {0};
 
76
        GError * error = NULL;
 
77
        dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &candoit, G_TYPE_INVALID);
 
78
        if (error != NULL) {
 
79
                g_warning("Unable to check hibernate: %s", error->message);
 
80
                g_error_free(error);
 
81
                return;
 
82
        }
 
83
        g_debug("Got Hibernate: %s", g_value_get_boolean(&candoit) ? "true" : "false");
 
84
 
 
85
        if (suspend_mi != NULL) {
 
86
                dbusmenu_menuitem_property_set(hibernate_mi, "visible", g_value_get_boolean(&candoit) ? "true" : "false");
 
87
        }
 
88
 
 
89
        return;
 
90
}
 
91
 
 
92
/* A signal that we need to recheck to ensure we can still
 
93
   hibernate and/or suspend */
 
94
static void
 
95
dpk_changed_cb (DBusGProxy * proxy, gpointer user_data)
 
96
{
 
97
        /* Start Async call to see if we can hibernate */
 
98
        if (suspend_call == NULL) {
 
99
                suspend_call = dbus_g_proxy_begin_call(dkp_prop_proxy,
 
100
                                                       "Get",
 
101
                                                       suspend_prop_cb,
 
102
                                                       NULL,
 
103
                                                       NULL,
 
104
                                                       G_TYPE_STRING,
 
105
                                                       DKP_INTERFACE,
 
106
                                                       G_TYPE_STRING,
 
107
                                                       "can-suspend",
 
108
                                                       G_TYPE_INVALID,
 
109
                                                       G_TYPE_VALUE,
 
110
                                                       G_TYPE_INVALID);
 
111
        }
 
112
 
 
113
        /* Start Async call to see if we can suspend */
 
114
        if (hibernate_call == NULL) {
 
115
                hibernate_call = dbus_g_proxy_begin_call(dkp_prop_proxy,
 
116
                                                         "Get",
 
117
                                                         hibernate_prop_cb,
 
118
                                                         NULL,
 
119
                                                         NULL,
 
120
                                                         G_TYPE_STRING,
 
121
                                                         DKP_INTERFACE,
 
122
                                                         G_TYPE_STRING,
 
123
                                                         "can-hibernate",
 
124
                                                         G_TYPE_INVALID,
 
125
                                                         G_TYPE_VALUE,
 
126
                                                         G_TYPE_INVALID);
 
127
        }
 
128
 
 
129
        return;
 
130
}
 
131
 
 
132
/* This function goes through and sets up what we need for
 
133
   DKp checking.  We're even setting up the calls for the props
 
134
   we need */
 
135
static void
 
136
setup_dkp (void) {
 
137
        DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
 
138
        g_return_if_fail(bus != NULL);
 
139
 
 
140
        if (dkp_main_proxy == NULL) {
 
141
                dkp_main_proxy = dbus_g_proxy_new_for_name(bus,
 
142
                                                           DKP_ADDRESS,
 
143
                                                           DKP_OBJECT,
 
144
                                                           DKP_INTERFACE);
 
145
        }
 
146
        g_return_if_fail(dkp_main_proxy != NULL);
 
147
 
 
148
        if (dkp_prop_proxy == NULL) {
 
149
                dkp_prop_proxy = dbus_g_proxy_new_for_name(bus,
 
150
                                                           DKP_ADDRESS,
 
151
                                                           DKP_OBJECT,
 
152
                                                           DBUS_INTERFACE_PROPERTIES);
 
153
        }
 
154
        g_return_if_fail(dkp_prop_proxy != NULL);
 
155
 
 
156
        /* Connect to changed signal */
 
157
        dbus_g_proxy_add_signal(dkp_main_proxy,
 
158
                                "Changed",
 
159
                                G_TYPE_INVALID);
 
160
 
 
161
        dbus_g_proxy_connect_signal(dkp_main_proxy,
 
162
                                    "Changed",
 
163
                                    G_CALLBACK(dpk_changed_cb),
 
164
                                    NULL,
 
165
                                    NULL);
 
166
 
 
167
        /* Force an original "changed" event */
 
168
        dpk_changed_cb(dkp_main_proxy, NULL);
 
169
 
 
170
        return;
 
171
}
 
172
 
 
173
/* This is the function to show a dialog on actions that
 
174
   can destroy data.  Currently it just calls the GTK version
 
175
   but it seems that in the future it should figure out
 
176
   what's going on and something better. */
 
177
static void
 
178
show_dialog (DbusmenuMenuitem * mi, gchar * type)
 
179
{
 
180
        gchar * helper = g_build_filename(LIBEXECDIR, "gtk-logout-helper", NULL);
 
181
        gchar * dialog_line = g_strdup_printf("%s --%s", helper, type);
 
182
        g_free(helper);
 
183
 
 
184
        g_debug("Showing dialog '%s'", dialog_line);
 
185
 
 
186
        GError * error = NULL;
 
187
        if (!g_spawn_command_line_async(dialog_line, &error)) {
 
188
                g_warning("Unable to show dialog: %s", error->message);
 
189
                g_error_free(error);
 
190
        }
 
191
 
 
192
        g_free(dialog_line);
 
193
 
 
194
        return;
 
195
}
 
196
 
 
197
/* This function creates all of the menuitems that the service
 
198
   provides in the UI.  It also connects them to the callbacks. */
 
199
static void
 
200
create_items (DbusmenuMenuitem * root) {
 
201
        DbusmenuMenuitem * mi = NULL;
 
202
 
 
203
        mi = dbusmenu_menuitem_new();
 
204
        dbusmenu_menuitem_property_set(mi, "label", _("Log Out"));
 
205
        dbusmenu_menuitem_child_append(root, mi);
 
206
        g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "logout");
 
207
 
 
208
        suspend_mi = dbusmenu_menuitem_new();
 
209
        dbusmenu_menuitem_property_set(suspend_mi, "visible", "false");
 
210
        dbusmenu_menuitem_property_set(suspend_mi, "label", _("Suspend"));
 
211
        dbusmenu_menuitem_child_append(root, suspend_mi);
 
212
        g_signal_connect(G_OBJECT(suspend_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(sleep), "Suspend");
 
213
 
 
214
        hibernate_mi = dbusmenu_menuitem_new();
 
215
        dbusmenu_menuitem_property_set(hibernate_mi, "visible", "false");
 
216
        dbusmenu_menuitem_property_set(hibernate_mi, "label", _("Hibernate"));
 
217
        dbusmenu_menuitem_child_append(root, hibernate_mi);
 
218
        g_signal_connect(G_OBJECT(hibernate_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(sleep), "Hibernate");
 
219
 
 
220
        mi = dbusmenu_menuitem_new();
 
221
        dbusmenu_menuitem_property_set(mi, "label", _("Restart"));
 
222
        dbusmenu_menuitem_child_append(root, mi);
 
223
        g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "restart");
 
224
 
 
225
        mi = dbusmenu_menuitem_new();
 
226
        dbusmenu_menuitem_property_set(mi, "label", _("Shutdown"));
 
227
        dbusmenu_menuitem_child_append(root, mi);
 
228
        g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "shutdown");
 
229
 
 
230
        return;
 
231
}
 
232
 
 
233
/* Main, is well, main.  It brings everything up and throws
 
234
   us into the mainloop of no return. */
 
235
int
 
236
main (int argc, char ** argv)
 
237
{
 
238
    g_type_init();
 
239
 
 
240
    DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
 
241
    DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
 
242
    GError * error = NULL;
 
243
    guint nameret = 0;
 
244
 
 
245
    if (!org_freedesktop_DBus_request_name(bus_proxy, INDICATOR_SESSION_DBUS_NAME, 0, &nameret, &error)) {
 
246
        g_error("Unable to call to request name");
 
247
        return 1;
 
248
    }   
 
249
 
 
250
    if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
 
251
        g_error("Unable to get name");
 
252
        return 1;
 
253
    }   
 
254
 
 
255
    root_menuitem = dbusmenu_menuitem_new();
 
256
        g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem));
 
257
 
 
258
        create_items(root_menuitem);
 
259
        setup_dkp();
 
260
 
 
261
    DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT);
 
262
    dbusmenu_server_set_root(server, root_menuitem);
 
263
 
 
264
    mainloop = g_main_loop_new(NULL, FALSE);
 
265
    g_main_loop_run(mainloop);
 
266
 
 
267
    return 0;
 
268
}
 
269