c7160315a92f05ebc9fcb9fe88d1b5c7fff05b4a
[claws.git] / src / plugins / vcalendar / vcal_dbus.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2011 Colin Leroy <colin@colino.net> and 
4  * the Claws Mail team
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #  include "config.h"
23 #include "claws-features.h"
24 #endif
25
26 #include <stddef.h>
27 #include <glib.h>
28 #include <glib/gi18n.h>
29
30 #include <libical/ical.h>
31 #include <gtk/gtk.h>
32
33 #include "utils.h"
34 #include "vcal_manager.h"
35 #include "vcal_folder.h"
36
37 #if(GLIB_CHECK_VERSION(2,26,0))
38
39 static guint dbus_own_id;
40
41 static void add_event_to_builder_if_match(VCalEvent *event, GVariantBuilder *array,
42                                           time_t start, time_t end)
43 {
44         time_t evt_start = icaltime_as_timet((icaltime_from_string(event->dtstart)));
45         time_t evt_end = icaltime_as_timet((icaltime_from_string(event->dtend)));
46         if ((evt_start >= start && evt_start <= end)
47          || (evt_end >= start && evt_end <= end)) {
48                 g_variant_builder_open(array, 
49                         G_VARIANT_TYPE("(sssbxxa{sv})"));
50                         g_variant_builder_add(array, "s", event->uid);
51                         g_variant_builder_add(array, "s", event->summary);
52                         g_variant_builder_add(array, "s", event->description);
53                         g_variant_builder_add(array, "b", FALSE);
54                         g_variant_builder_add(array, "x", (gint64)evt_start);
55                         g_variant_builder_add(array, "x", (gint64)evt_end);
56                         g_variant_builder_open(array, G_VARIANT_TYPE("a{sv}"));
57                                 /* We don't put stuff there. */
58                         g_variant_builder_close(array);
59                 g_variant_builder_close(array);
60          }
61 }
62
63 static void handle_method_call (GDBusConnection       *connection,
64                                 const gchar           *sender,
65                                 const gchar           *object_path,
66                                 const gchar           *interface_name,
67                                 const gchar           *method_name,
68                                 GVariant              *parameters,
69                                 GDBusMethodInvocation *invocation,
70                                 gpointer               user_data)
71 {
72         time_t start, end;
73         gboolean refresh;
74         GSList *list, *cur;
75         int i;
76         GVariantBuilder *array = g_variant_builder_new(
77                         G_VARIANT_TYPE("(a(sssbxxa{sv}))"));
78         GVariant *value;
79
80         if (g_strcmp0(method_name, "GetEvents") != 0) {
81                 debug_print("Unknown method %s\n", method_name);
82         }
83         
84         g_variant_get(parameters, "(xxb)", &start, &end, &refresh);
85
86         
87         g_variant_builder_open(array, G_VARIANT_TYPE("a(sssbxxa{sv})"));
88
89         /* First our own calendar */
90         list = vcal_folder_get_waiting_events();
91         for (cur = list, i = 0; cur; cur = cur->next, i++) {
92                 VCalEvent *event = (VCalEvent *)cur->data;
93
94                 add_event_to_builder_if_match(event, array, start, end);
95
96                 g_free(event);
97         }
98         g_slist_free(list);
99
100         /* Then subs. */
101         list = vcal_folder_get_webcal_events();
102         for (cur = list; cur; cur = cur->next) {
103                 /* Don't free that, it's done when subscriptions are
104                  * fetched */
105                 icalcomponent *ical = (icalcomponent *)cur->data;
106                 if (ical != NULL) {
107                         VCalEvent *event = vcal_get_event_from_ical(
108                                 icalcomponent_as_ical_string(ical), NULL);
109                         if (event != NULL) {
110                                 add_event_to_builder_if_match(
111                                         event, array, start, end);
112                                 g_free(event);
113                         }
114                 }
115         }
116         g_slist_free(list);
117
118         g_variant_builder_close(array);
119         
120         value = g_variant_builder_end(array);
121         g_variant_builder_unref(array);
122
123         g_dbus_method_invocation_return_value (invocation, value);
124         g_variant_unref(value);
125 }
126
127
128 static GDBusInterfaceVTable* interface_vtable = NULL;
129
130 static GDBusNodeInfo *introspection_data = NULL;
131 static GDBusInterfaceInfo *interface_info = NULL;
132
133 static const gchar introspection_xml[] =
134   "<node>"
135   "  <interface name='org.gnome.Shell.CalendarServer'>"
136   "    <method name='GetEvents'>"
137   "      <arg type='x' name='greeting' direction='in'/>"
138   "      <arg type='x' name='greeting' direction='in'/>"
139   "      <arg type='b' name='greeting' direction='in'/>"
140   "      <arg type='a(sssbxxa{sv})' name='events' direction='out'/>"
141   "    </method>"
142   "  </interface>"
143   "</node>";
144
145 static void name_acquired (GDBusConnection *connection,
146                            const gchar     *name,
147                            gpointer         user_data)
148 {
149         debug_print("Acquired DBUS name %s\n", name);
150 }
151
152 static void name_lost (GDBusConnection *connection,
153                        const gchar     *name,
154                        gpointer         user_data)
155 {
156         debug_print("Lost DBUS name %s\n", name);
157 }
158
159 static void bus_acquired(GDBusConnection *connection,
160                          const gchar     *name,
161                          gpointer         user_data)
162 {
163         GError *err = NULL;
164
165         cm_return_if_fail(interface_vtable);
166
167         g_dbus_connection_register_object(connection,
168                 "/org/gnome/Shell/CalendarServer",
169                 introspection_data->interfaces[0],
170                 (const GDBusInterfaceVTable *)interface_vtable, NULL, NULL, &err);
171         if (err != NULL)
172                 debug_print("Error: %s\n", err->message);
173 }
174
175 void connect_dbus(void)
176 {
177         debug_print("connect_dbus() invoked\n");
178
179         interface_vtable = g_malloc0(sizeof(GDBusInterfaceVTable));
180         cm_return_if_fail(interface_vtable);
181         interface_vtable->method_call = (GDBusInterfaceMethodCallFunc)handle_method_call;
182
183         introspection_data = g_dbus_node_info_new_for_xml(
184                                 introspection_xml, NULL);
185         if (introspection_data == NULL) {
186                 debug_print("Couldn't figure out XML.\n");
187                 return;
188         }
189
190         interface_info = g_dbus_node_info_lookup_interface(
191                                 introspection_data,
192                                 "org.gnome.Shell.CalendarServer");
193         dbus_own_id = g_bus_own_name(G_BUS_TYPE_SESSION,
194                         "org.gnome.Shell.CalendarServer",
195                         G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
196                         | G_BUS_NAME_OWNER_FLAGS_REPLACE,
197                         bus_acquired,
198                         name_acquired,
199                         name_lost,
200                         NULL, NULL);
201 }
202
203 void disconnect_dbus(void)
204 {
205         debug_print("disconnect_dbus() invoked\n");
206         g_bus_unown_name(dbus_own_id);
207
208         g_free(interface_vtable);
209         interface_vtable = NULL;
210 }
211
212 #else
213 void connect_dbus(void)
214 {
215         debug_print("DBUS calendar export is not supported with Glib < 2.26\n");
216 }
217 void disconnect_dbus(void)
218 {
219         debug_print("DBUS calendar export is not supported with Glib < 2.26\n");
220 }
221 #endif