2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 #define DBUS_API_SUBJECT_TO_CHANGE
22 #include <dbus/dbus.h>
23 #include <dbus/dbus-glib.h>
24 #include <dbus/dbus-glib-lowlevel.h>
37 static DBusConnection *connection;
39 static char *service_name="org.navit-project.navit";
40 static char *object_path="/org/navit_project/navit";
42 GHashTable *object_hash;
43 GHashTable *object_count;
46 object_new(char *type, void *object)
50 dbg(0,"enter %s\n", type);
51 id=(int)g_hash_table_lookup(object_count, type);
52 g_hash_table_insert(object_count, type, (void *)(id+1));
53 ret=g_strdup_printf("%s/%s/%d", object_path, type, id);
54 g_hash_table_insert(object_hash, ret, object);
55 dbg(0,"return %s\n", ret);
60 object_get(const char *path)
62 return g_hash_table_lookup(object_hash, path);
66 object_get_from_message_arg(DBusMessage *message, char *type)
73 dbus_error_init(&error);
74 if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID)) {
75 dbus_error_free(&error);
76 dbg(0,"wrong arg type\n");
79 prefix=g_strdup_printf("%s/%s/", object_path, type);
80 if (!strncmp(prefix, opath, strlen(prefix)))
81 ret=object_get(opath);
83 dbg(0,"wrong object type\n");
89 object_get_from_message(DBusMessage *message, char *type)
91 const char *opath=dbus_message_get_path(message);
95 prefix=g_strdup_printf("%s/%s/", object_path, type);
96 if (!strncmp(prefix, opath, strlen(prefix)))
97 ret=object_get(opath);
99 dbg(0,"wrong object type\n");
104 static DBusHandlerResult
105 empty_reply(DBusConnection *connection, DBusMessage *message)
109 reply = dbus_message_new_method_return(message);
110 dbus_connection_send (connection, reply, NULL);
111 dbus_message_unref (reply);
113 return DBUS_HANDLER_RESULT_HANDLED;
116 static DBusHandlerResult
117 request_main_get_navit(DBusConnection *connection, DBusMessage *message)
125 dbus_error_init(&error);
127 if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID)) {
128 dbg(0,"Error parsing\n");
129 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
131 dbg(0,"opath=%s\n", opath);
132 iter=object_get(opath);
133 navit=main_get_navit(iter);
135 reply = dbus_message_new_method_return(message);
136 opath=object_new("navit",navit);
137 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
138 dbus_connection_send (connection, reply, NULL);
139 dbus_message_unref (reply);
140 return DBUS_HANDLER_RESULT_HANDLED;
142 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
145 static DBusHandlerResult
146 request_main_iter(DBusConnection *connection, DBusMessage *message)
149 struct iter *iter=main_iter_new();
150 dbg(0,"iter=%p\n", iter);
151 char *opath=object_new("main_iter",iter);
152 reply = dbus_message_new_method_return(message);
153 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
154 dbus_connection_send (connection, reply, NULL);
155 dbus_message_unref (reply);
157 return DBUS_HANDLER_RESULT_HANDLED;
160 static DBusHandlerResult
161 request_main_iter_destroy(DBusConnection *connection, DBusMessage *message)
165 iter=object_get_from_message_arg(message, "main_iter");
167 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
168 main_iter_destroy(iter);
170 return empty_reply(connection, message);
174 * Extracts a struct pcoord from a DBus message
176 * @param message The DBus message
177 * @param iter Sort of pointer that points on that (iii)-object in the message
178 * @param pc Pointer where the data should get stored
181 pcoord_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct pcoord *pc)
183 DBusMessageIter iter2;
185 dbg(0,"%s\n", dbus_message_iter_get_signature(iter));
187 dbus_message_iter_recurse(iter, &iter2);
189 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
191 dbus_message_iter_get_basic(&iter2, &pc->pro);
193 dbus_message_iter_next(&iter2);
195 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
197 dbus_message_iter_get_basic(&iter2, &pc->x);
199 dbus_message_iter_next(&iter2);
201 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
203 dbus_message_iter_get_basic(&iter2, &pc->y);
205 dbg(0, " pro -> %i x -> %i y -> %i\n", &pc->pro, &pc->x, &pc->y);
207 dbus_message_iter_next(&iter2);
209 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INVALID)
216 * Extracts a struct point from a DBus message
218 * @param message The DBus message
219 * @param iter Sort of pointer that points on that (ii)-object in the message
220 * @param p Pointer where the data should get stored
223 point_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct point *p)
225 DBusMessageIter iter2;
227 dbg(0,"%s\n", dbus_message_iter_get_signature(iter));
229 dbus_message_iter_recurse(iter, &iter2);
231 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
233 dbus_message_iter_get_basic(&iter2, &p->x);
235 dbus_message_iter_next(&iter2);
237 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
239 dbus_message_iter_get_basic(&iter2, &p->y);
241 dbg(0, " x -> %i y -> %i\n", p->x, p->y);
243 dbus_message_iter_next(&iter2);
245 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INVALID)
251 static DBusHandlerResult
252 request_navit_set_center(DBusConnection *connection, DBusMessage *message)
256 DBusMessageIter iter;
258 navit=object_get_from_message(message, "navit");
260 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
262 dbus_message_iter_init(message, &iter);
264 if (!pcoord_get_from_message(message, &iter, &pc))
265 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
266 navit_set_center(navit, &pc);
267 return empty_reply(connection, message);
270 static DBusHandlerResult
271 request_navit_set_center_screen(DBusConnection *connection, DBusMessage *message)
275 DBusMessageIter iter;
277 navit=object_get_from_message(message, "navit");
279 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
281 dbus_message_iter_init(message, &iter);
283 if (!point_get_from_message(message, &iter, &p))
284 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
285 navit_set_center_screen(navit, &p);
286 return empty_reply(connection, message);
289 static DBusHandlerResult
290 request_navit_set_layout(DBusConnection *connection, DBusMessage *message)
292 char *new_layout_name;
295 struct attr_iter *iter;
297 navit=object_get_from_message(message, "navit");
299 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
301 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &new_layout_name, DBUS_TYPE_INVALID))
302 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
304 iter=navit_attr_iter_new();
305 while(navit_get_attr(navit, attr_layout, &attr, iter)) {
306 if (strcmp(attr.u.layout->name, new_layout_name) == 0) {
307 navit_set_attr(navit, &attr);
310 return empty_reply(connection, message);
313 static DBusHandlerResult
314 request_navit_zoom(DBusConnection *connection, DBusMessage *message)
317 struct point *p = malloc(sizeof(struct point));
319 DBusMessageIter iter;
321 navit = object_get_from_message(message, "navit");
323 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
325 dbus_message_iter_init(message, &iter);
326 dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
328 dbus_message_iter_get_basic(&iter, &factor);
330 if (dbus_message_iter_has_next(&iter))
332 dbus_message_iter_next(&iter);
333 if (!point_get_from_message(message, &iter, p))
334 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
338 navit_zoom_in(navit, factor, p);
339 else if (factor < -1)
340 navit_zoom_out(navit, 0-factor, p);
342 return empty_reply(connection, message);
346 static DBusHandlerResult
347 request_navit_resize(DBusConnection *connection, DBusMessage *message)
351 DBusMessageIter iter;
353 navit = object_get_from_message(message, "navit");
355 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
357 dbus_message_iter_init(message, &iter);
358 dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
360 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
361 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
362 dbus_message_iter_get_basic(&iter, &w);
364 dbus_message_iter_next(&iter);
366 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
367 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
368 dbus_message_iter_get_basic(&iter, &h);
370 dbg(0, " w -> %i h -> %i\n", w, h);
372 navit_resize(navit, w, h);
374 return empty_reply(connection, message);
378 static DBusHandlerResult
379 request_navit_set_position(DBusConnection *connection, DBusMessage *message)
384 DBusMessageIter iter;
386 navit = object_get_from_message(message, "navit");
388 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
390 dbus_message_iter_init(message, &iter);
391 pcoord_get_from_message(message, &iter, &c);
393 navit_set_position(navit, &c);
394 return empty_reply(connection, message);
397 static DBusHandlerResult
398 request_navit_set_destination(DBusConnection *connection, DBusMessage *message)
404 DBusMessageIter iter;
406 navit = object_get_from_message(message, "navit");
408 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
410 dbus_message_iter_init(message, &iter);
411 pcoord_get_from_message(message, &iter, &c);
413 dbus_message_iter_next(&iter);
414 dbus_message_iter_get_basic(&iter, &description);
415 dbg(0, " destination -> %s\n", description);
417 navit_set_destination(navit, &c, description);
418 return empty_reply(connection, message);
425 DBusHandlerResult(*func)(DBusConnection *connection, DBusMessage *message);
427 {"", "iter", "", request_main_iter},
428 {".navit", "set_center", "(iii)", request_navit_set_center},
431 static DBusHandlerResult
432 navit_handler_func(DBusConnection *connection, DBusMessage *message, void *user_data)
436 dbg(0,"type=%s interface=%s path=%s member=%s signature=%s\n", dbus_message_type_to_string(dbus_message_get_type(message)), dbus_message_get_interface(message), dbus_message_get_path(message), dbus_message_get_member(message), dbus_message_get_signature(message));
438 if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
441 dbg(0,"Introspect\n");
442 if (! strcmp(dbus_message_get_path(message), "/org/navit_project/navit")) {
443 g_file_get_contents("binding/dbus/navit.introspect", &idata, NULL, NULL);
444 reply = dbus_message_new_method_return(message);
445 dbus_message_append_args(reply, DBUS_TYPE_STRING, &idata, DBUS_TYPE_INVALID);
446 dbus_connection_send (connection, reply, NULL);
447 dbus_message_unref (reply);
449 return DBUS_HANDLER_RESULT_HANDLED;
453 for (i = 0 ; i < sizeof(dbus_methods)/sizeof(struct dbus_method) ; i++) {
454 path=g_strdup_printf("org.navit_project.navit%s", dbus_methods[i].path);
455 if (dbus_message_is_method_call(message, path, dbus_methods[i].method) &&
456 dbus_message_has_signature(message, dbus_methods[i].signature)) {
458 return dbus_methods[i].func(connection, message);
462 if (dbus_message_is_method_call (message, "org.navit_project.navit", "iter_destroy") &&
463 dbus_message_has_signature(message, "o"))
464 return request_main_iter_destroy(connection, message);
465 if (dbus_message_is_method_call (message, "org.navit_project.navit", "get_navit") &&
466 dbus_message_has_signature(message,"o"))
467 return request_main_get_navit(connection, message);
468 if (dbus_message_is_method_call (message, "org.navit_project.navit.navit", "set_center_screen") &&
469 dbus_message_has_signature(message,"(ii)"))
470 return request_navit_set_center_screen(connection, message);
471 if (dbus_message_is_method_call (message, "org.navit_project.navit.navit", "set_layout") &&
472 dbus_message_has_signature(message,"s"))
473 return request_navit_set_layout(connection, message);
474 if (dbus_message_is_method_call (message, "org.navit_project.navit.navit", "zoom") &&
475 dbus_message_has_signature(message, "i(ii)"))
476 return request_navit_zoom(connection, message);
477 if (dbus_message_is_method_call (message, "org.navit_project.navit.navit", "zoom") &&
478 dbus_message_has_signature(message, "i"))
479 return request_navit_zoom(connection, message);
480 if (dbus_message_is_method_call (message, "org.navit_project.navit.navit", "resize") &&
481 dbus_message_has_signature(message, "ii"))
482 return request_navit_resize(connection, message);
483 if (dbus_message_is_method_call (message, "org.navit_project.navit.navit", "set_position") &&
484 dbus_message_has_signature(message, "(iii)"))
485 return request_navit_set_position(connection, message);
486 if (dbus_message_is_method_call (message, "org.navit_project.navit.navit", "set_destination") &&
487 dbus_message_has_signature(message, "(iii)s"))
488 return request_navit_set_destination(connection, message);
489 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
492 static DBusObjectPathVTable dbus_navit_vtable = {
500 filter(DBusConnection *connection, DBusMessage *message, void *user_data)
502 dbg(0,"type=%s interface=%s path=%s member=%s signature=%s\n", dbus_message_type_to_string(dbus_message_get_type(message)), dbus_message_get_interface(message), dbus_message_get_path(message), dbus_message_get_member(message), dbus_message_get_signature(message));
503 if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
505 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
509 void plugin_init(void)
513 object_hash=g_hash_table_new(g_str_hash, g_str_equal);
514 object_count=g_hash_table_new(g_str_hash, g_str_equal);
516 dbus_error_init(&error);
517 connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
519 dbg(0,"Failed to open connection to session message bus: %s\n", error.message);
520 dbus_error_free(&error);
523 dbus_connection_setup_with_g_main(connection, NULL);
525 dbus_connection_add_filter(connection, filter, NULL, NULL);
526 dbus_bus_add_match(connection, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
528 dbus_connection_register_fallback(connection, object_path, &dbus_navit_vtable, NULL);
529 dbus_bus_request_name(connection, service_name, 0, &error);
530 if (dbus_error_is_set(&error)) {
531 dbg(0,"Failed to request name: %s", error.message);
532 dbus_error_free (&error);