Code cleanup around glib version check (2.28 minimum).
[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 static guint dbus_own_id;
38
39 static void add_event_to_builder_if_match(VCalEvent *event, GVariantBuilder *array,
40                                           time_t start, time_t end)
41 {
42         time_t evt_start = icaltime_as_timet((icaltime_from_string(event->dtstart)));
43         time_t evt_end = icaltime_as_timet((icaltime_from_string(event->dtend)));
44         if ((evt_start >= start && evt_start <= end)
45          || (evt_end >= start && evt_end <= end)) {
46                 g_variant_builder_open(array, 
47                         G_VARIANT_TYPE("(sssbxxa{sv})"));
48                         g_variant_builder_add(array, "s", event->uid);
49                         g_variant_builder_add(array, "s", event->summary);
50                         g_variant_builder_add(array, "s", event->description);
51                         g_variant_builder_add(array, "b", FALSE);
52                         g_variant_builder_add(array, "x", (gint64)evt_start);
53                         g_variant_builder_add(array, "x", (gint64)evt_end);
54                         g_variant_builder_open(array, G_VARIANT_TYPE("a{sv}"));
55                                 /* We don't put stuff there. */
56                         g_variant_builder_close(array);
57                 g_variant_builder_close(array);
58          }
59 }
60
61 static void handle_method_call (GDBusConnection       *connection,
62                                 const gchar           *sender,
63                                 const gchar           *object_path,
64                                 const gchar           *interface_name,
65                                 const gchar           *method_name,
66                                 GVariant              *parameters,
67                                 GDBusMethodInvocation *invocation,
68                                 gpointer               user_data)
69 {
70         time_t start, end;
71         gboolean refresh;
72         GSList *list, *cur;
73         int i;
74         GVariantBuilder *array = g_variant_builder_new(
75                         G_VARIANT_TYPE("(a(sssbxxa{sv}))"));
76         GVariant *value;
77
78         if (g_strcmp0(method_name, "GetEvents") != 0) {
79                 debug_print("Unknown method %s\n", method_name);
80         }
81         
82         g_variant_get(parameters, "(xxb)", &start, &end, &refresh);
83
84         
85         g_variant_builder_open(array, G_VARIANT_TYPE("a(sssbxxa{sv})"));
86
87         /* First our own calendar */
88         list = vcal_folder_get_waiting_events();
89         for (cur = list, i = 0; cur; cur = cur->next, i++) {
90                 VCalEvent *event = (VCalEvent *)cur->data;
91
92                 add_event_to_builder_if_match(event, array, start, end);
93
94                 g_free(event);
95         }
96         g_slist_free(list);
97
98         /* Then subs. */
99         list = vcal_folder_get_webcal_events();
100         for (cur = list; cur; cur = cur->next) {
101                 /* Don't free that, it's done when subscriptions are
102                  * fetched */
103                 icalcomponent *ical = (icalcomponent *)cur->data;
104                 if (ical != NULL) {
105                         VCalEvent *event = vcal_get_event_from_ical(
106                                 icalcomponent_as_ical_string(ical), NULL);
107                         if (event != NULL) {
108                                 add_event_to_builder_if_match(
109                                         event, array, start, end);
110                                 g_free(event);
111                         }
112                 }
113         }
114         g_slist_free(list);
115
116         g_variant_builder_close(array);
117         
118         value = g_variant_builder_end(array);
119         g_variant_builder_unref(array);
120
121         g_dbus_method_invocation_return_value (invocation, value);
122         g_variant_unref(value);
123 }
124
125
126 static GDBusInterfaceVTable* interface_vtable = NULL;
127
128 static GDBusNodeInfo *introspection_data = NULL;
129 static GDBusInterfaceInfo *interface_info = NULL;
130
131 static const gchar introspection_xml[] =
132   "<node>"
133   "  <interface name='org.gnome.Shell.CalendarServer'>"
134   "    <method name='GetEvents'>"
135   "      <arg type='x' name='greeting' direction='in'/>"
136   "      <arg type='x' name='greeting' direction='in'/>"
137   "      <arg type='b' name='greeting' direction='in'/>"
138   "      <arg type='a(sssbxxa{sv})' name='events' direction='out'/>"
139   "    </method>"
140   "  </interface>"
141   "</node>";
142
143 static void name_acquired (GDBusConnection *connection,
144                            const gchar     *name,
145                            gpointer         user_data)
146 {
147         debug_print("Acquired DBUS name %s\n", name);
148 }
149
150 static void name_lost (GDBusConnection *connection,
151                        const gchar     *name,
152                        gpointer         user_data)
153 {
154         debug_print("Lost DBUS name %s\n", name);
155 }
156
157 static void bus_acquired(GDBusConnection *connection,
158                          const gchar     *name,
159                          gpointer         user_data)
160 {
161         GError *err = NULL;
162
163         cm_return_if_fail(interface_vtable);
164
165         g_dbus_connection_register_object(connection,
166                 "/org/gnome/Shell/CalendarServer",
167                 introspection_data->interfaces[0],
168                 (const GDBusInterfaceVTable *)interface_vtable, NULL, NULL, &err);
169         if (err != NULL)
170                 debug_print("Error: %s\n", err->message);
171 }
172
173 void connect_dbus(void)
174 {
175         debug_print("connect_dbus() invoked\n");
176
177         interface_vtable = g_malloc0(sizeof(GDBusInterfaceVTable));
178         cm_return_if_fail(interface_vtable);
179         interface_vtable->method_call = (GDBusInterfaceMethodCallFunc)handle_method_call;
180
181         introspection_data = g_dbus_node_info_new_for_xml(
182                                 introspection_xml, NULL);
183         if (introspection_data == NULL) {
184                 debug_print("Couldn't figure out XML.\n");
185                 return;
186         }
187
188         interface_info = g_dbus_node_info_lookup_interface(
189                                 introspection_data,
190                                 "org.gnome.Shell.CalendarServer");
191         dbus_own_id = g_bus_own_name(G_BUS_TYPE_SESSION,
192                         "org.gnome.Shell.CalendarServer",
193                         G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
194                         | G_BUS_NAME_OWNER_FLAGS_REPLACE,
195                         bus_acquired,
196                         name_acquired,
197                         name_lost,
198                         NULL, NULL);
199 }
200
201 void disconnect_dbus(void)
202 {
203         debug_print("disconnect_dbus() invoked\n");
204         g_bus_unown_name(dbus_own_id);
205
206         g_free(interface_vtable);
207         interface_vtable = NULL;
208 }