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>
44 static DBusConnection *connection;
45 static dbus_uint32_t dbus_serial;
47 static char *service_name = "org.navit_project.navit";
48 static char *object_path = "/org/navit_project/navit";
49 char *navitintrospectxml_head1 = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
50 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
53 char *navitintrospectxml_head2 = "\">\n"
54 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
55 " <method name=\"Introspect\">\n"
56 " <arg direction=\"out\" type=\"s\" />\n"
62 GHashTable *object_hash;
63 GHashTable *object_hash_rev;
64 GHashTable *object_count;
67 object_new(char *type, void *object)
71 dbg(0,"enter %s\n", type);
72 if ((ret=g_hash_table_lookup(object_hash_rev, object)))
74 id=GPOINTER_TO_INT(g_hash_table_lookup(object_count, type));
75 g_hash_table_insert(object_count, type, GINT_TO_POINTER((id+1)));
76 ret=g_strdup_printf("%s/%s/%d", object_path, type, id);
77 g_hash_table_insert(object_hash, ret, object);
78 g_hash_table_insert(object_hash_rev, object, ret);
79 dbg(0,"return %s\n", ret);
84 object_get(const char *path)
86 return g_hash_table_lookup(object_hash, path);
90 resolve_object(const char *opath, char *type)
95 char *def_navit="/default_navit";
96 char *def_graphics="/default_graphics";
97 char *def_vehicle="/default_vehicle";
98 char *def_mapset="/default_mapset";
99 char *def_map="/default_map";
102 if (strncmp(opath, object_path, strlen(object_path))) {
103 dbg(0,"wrong object path %s\n",opath);
106 prefix=g_strdup_printf("%s/%s/", object_path, type);
107 if (!strncmp(prefix, opath, strlen(prefix))) {
108 ret=object_get(opath);
113 oprefix=opath+strlen(object_path);
114 if (!strncmp(oprefix,def_navit,strlen(def_navit))) {
115 oprefix+=strlen(def_navit);
117 if (!config_get_attr(config, attr_navit, &navit, NULL))
120 dbg(0,"default_navit\n");
121 return navit.u.navit;
123 if (!strncmp(oprefix,def_graphics,strlen(def_graphics))) {
124 if (navit_get_attr(navit.u.navit, attr_graphics, &attr, NULL)) {
125 return attr.u.graphics;
129 if (!strncmp(oprefix,def_vehicle,strlen(def_vehicle))) {
130 if (navit_get_attr(navit.u.navit, attr_vehicle, &attr, NULL)) {
131 return attr.u.vehicle;
135 if (!strncmp(oprefix,def_mapset,strlen(def_mapset))) {
136 oprefix+=strlen(def_mapset);
137 if (navit_get_attr(navit.u.navit, attr_mapset, &attr, NULL)) {
139 return attr.u.mapset;
141 if (!strncmp(oprefix,def_map,strlen(def_map))) {
142 if (mapset_get_attr(attr.u.mapset, attr_map, &attr, NULL)) {
155 object_get_from_message_arg(DBusMessageIter *iter, char *type)
159 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
161 dbus_message_iter_get_basic(iter, &opath);
162 dbus_message_iter_next(iter);
163 return resolve_object(opath, type);
167 object_get_from_message(DBusMessage *message, char *type)
169 return resolve_object(dbus_message_get_path(message), type);
172 static enum attr_type
173 attr_type_get_from_message(DBusMessageIter *iter)
177 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
179 dbus_message_iter_get_basic(iter, &attr_type);
180 dbus_message_iter_next(iter);
181 return attr_from_name(attr_type);
185 encode_attr(DBusMessage *message, struct attr *attr)
187 char *name=attr_to_name(attr->type);
188 DBusMessageIter iter1,iter2;
189 dbus_message_iter_init_append(message, &iter1);
190 dbus_message_iter_append_basic(&iter1, DBUS_TYPE_STRING, &name);
191 if (attr->type >= attr_type_int_begin && attr->type < attr_type_boolean_begin) {
192 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &iter2);
193 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_INT32, &attr->u.num);
194 dbus_message_iter_close_container(&iter1, &iter2);
196 if (attr->type >= attr_type_boolean_begin && attr->type <= attr_type_int_end) {
197 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING, &iter2);
198 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_BOOLEAN, &attr->u.num);
199 dbus_message_iter_close_container(&iter1, &iter2);
201 if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) {
202 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &iter2);
203 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_STRING, &attr->u.str);
204 dbus_message_iter_close_container(&iter1, &iter2);
206 if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) {
207 char *object=object_new(attr_to_name(attr->type), attr->u.data);
208 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter2);
209 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_OBJECT_PATH, &object);
210 dbus_message_iter_close_container(&iter1, &iter2);
216 static DBusHandlerResult
217 empty_reply(DBusConnection *connection, DBusMessage *message)
221 reply = dbus_message_new_method_return(message);
222 dbus_connection_send (connection, reply, NULL);
223 dbus_message_unref (reply);
225 return DBUS_HANDLER_RESULT_HANDLED;
229 static DBusHandlerResult
230 dbus_error(DBusConnection *connection, DBusMessage *message, char *error, char *msg)
234 reply = dbus_message_new_error(message, error, msg);
235 dbus_connection_send (connection, reply, NULL);
236 dbus_message_unref (reply);
237 return DBUS_HANDLER_RESULT_HANDLED;
240 static DBusHandlerResult
241 dbus_error_invalid_attr_type(DBusConnection *connection, DBusMessage *message)
243 return dbus_error(connection, message, DBUS_ERROR_INVALID_ARGS, "attribute type invalid");
246 static DBusHandlerResult
247 dbus_error_invalid_parameter(DBusConnection *connection, DBusMessage *message)
249 return dbus_error(connection, message, DBUS_ERROR_INVALID_ARGS, "parameter invalid");
252 static DBusHandlerResult
253 dbus_error_invalid_object_path(DBusConnection *connection, DBusMessage *message)
255 return dbus_error(connection, message, DBUS_ERROR_BAD_ADDRESS, "object path invalid");
258 static DBusHandlerResult
259 dbus_error_invalid_object_path_parameter(DBusConnection *connection, DBusMessage *message)
261 return dbus_error(connection, message, DBUS_ERROR_BAD_ADDRESS, "object path parameter invalid");
265 * Extracts a struct pcoord from a DBus message
267 * @param message The DBus message
268 * @param iter Sort of pointer that points on that (iii)-object in the message
269 * @param pc Pointer where the data should get stored
270 * @returns Returns 1 when everything went right, otherwise 0
273 pcoord_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct pcoord *pc)
276 if(!strcmp(dbus_message_iter_get_signature(iter), "s")) {
279 dbus_message_iter_get_basic(iter, &coordstring);
280 if(!pcoord_parse(coordstring, projection_mg, pc))
286 DBusMessageIter iter2;
287 dbus_message_iter_recurse(iter, &iter2);
288 if(!strcmp(dbus_message_iter_get_signature(iter), "(is)")) {
292 dbus_message_iter_get_basic(&iter2, &projection);
294 dbus_message_iter_next(&iter2);
295 dbus_message_iter_get_basic(&iter2, &coordstring);
297 if(!pcoord_parse(coordstring, projection, pc))
301 } else if(!strcmp(dbus_message_iter_get_signature(iter), "(iii)")) {
303 dbus_message_iter_get_basic(&iter2, &pc->pro);
305 dbus_message_iter_next(&iter2);
306 dbus_message_iter_get_basic(&iter2, &pc->x);
308 dbus_message_iter_next(&iter2);
309 dbus_message_iter_get_basic(&iter2, &pc->y);
319 decode_attr(DBusMessage *message, struct attr *attr)
321 DBusMessageIter iter, iterattr, iterstruct;
326 dbus_message_iter_init(message, &iter);
327 dbus_message_iter_get_basic(&iter, &attr_type);
328 attr->type = attr_from_name(attr_type);
329 dbg(0, "attr value: 0x%x string: %s\n", attr->type, attr_type);
331 if (attr->type == attr_none)
334 dbus_message_iter_next(&iter);
335 dbus_message_iter_recurse(&iter, &iterattr);
336 dbg(0, "seems valid. signature: %s\n", dbus_message_iter_get_signature(&iterattr));
338 if (attr->type >= attr_type_item_begin && attr->type <= attr_type_item_end)
341 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_boolean_begin) {
342 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_INT32) {
343 dbus_message_iter_get_basic(&iterattr, &attr->u.num);
348 if(attr->type >= attr_type_boolean_begin && attr->type <= attr_type_int_end) {
349 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_BOOLEAN) {
350 dbus_message_iter_get_basic(&iterattr, &attr->u.num);
355 if(attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) {
356 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_STRING) {
357 dbus_message_iter_get_basic(&iterattr, &attr->u.str);
362 if(attr->type >= attr_type_double_begin && attr->type <= attr_type_double_end) {
363 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_DOUBLE) {
364 attr->u.numd=g_new(typeof(*attr->u.numd),1);
365 dbus_message_iter_get_basic(&iterattr, attr->u.numd);
369 if(attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end) {
370 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_STRUCT) {
371 attr->u.coord_geo=g_new(typeof(*attr->u.coord_geo),1);
372 dbus_message_iter_recurse(&iterattr, &iterstruct);
373 if (dbus_message_iter_get_arg_type(&iterstruct) == DBUS_TYPE_DOUBLE) {
374 dbus_message_iter_get_basic(&iterstruct, &d);
375 dbus_message_iter_next(&iterstruct);
376 attr->u.coord_geo->lng=d;
379 if (dbus_message_iter_get_arg_type(&iterstruct) == DBUS_TYPE_DOUBLE) {
380 dbus_message_iter_get_basic(&iterstruct, &d);
381 attr->u.coord_geo->lat=d;
385 g_free(attr->u.coord_geo);
386 attr->u.coord_geo=NULL;
395 destroy_attr(struct attr *attr)
397 if(attr->type > attr_type_double_begin && attr->type < attr_type_double_end) {
398 g_free(attr->u.numd);
403 get_iter_name(char *type)
405 return g_strdup_printf("%s_attr_iter",type);
408 static DBusHandlerResult
409 request_attr_iter(DBusConnection *connection, DBusMessage *message, char *type, struct attr_iter *(*func)(void))
414 struct attr_iter *attr_iter;
417 iter_name=get_iter_name(type);
418 opath=object_new(iter_name,attr_iter);
420 reply = dbus_message_new_method_return(message);
421 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
422 dbus_connection_send (connection, reply, NULL);
423 dbus_message_unref (reply);
425 return DBUS_HANDLER_RESULT_HANDLED;
428 static DBusHandlerResult
429 request_attr_iter_destroy(DBusConnection *connection, DBusMessage *message, char *type, void (*func)(struct attr_iter *))
431 struct attr_iter *attr_iter;
432 DBusMessageIter iter;
435 dbus_message_iter_init(message, &iter);
436 iter_name=get_iter_name(type);
437 attr_iter=object_get_from_message_arg(&iter, iter_name);
440 return dbus_error_invalid_object_path_parameter(connection, message);
443 return empty_reply(connection, message);
447 static DBusHandlerResult
448 request_get_attr(DBusConnection *connection, DBusMessage *message, char *type, int (*func)(void *data, enum attr_type type, struct attr *attr, struct attr_iter *iter))
451 DBusMessageIter iter;
453 enum attr_type attr_type;
454 struct attr_iter *attr_iter;
458 data = object_get_from_message(message, type);
460 return dbus_error_invalid_object_path(connection, message);
462 dbus_message_iter_init(message, &iter);
463 attr_type=attr_type_get_from_message(&iter);
464 if (attr_type == attr_none)
465 return dbus_error_invalid_attr_type(connection, message);
466 iter_name=get_iter_name(type);
467 attr_iter=object_get_from_message_arg(&iter, iter_name);
469 if (func(data, attr_type, &attr, attr_iter)) {
470 reply = dbus_message_new_method_return(message);
471 encode_attr(reply, &attr);
472 dbus_connection_send (connection, reply, NULL);
473 dbus_message_unref (reply);
474 return DBUS_HANDLER_RESULT_HANDLED;
476 return empty_reply(connection, message);
482 static DBusHandlerResult
483 request_config_get_attr(DBusConnection *connection, DBusMessage *message)
486 DBusMessageIter iter;
488 enum attr_type attr_type;
489 struct attr_iter *attr_iter;
491 dbus_message_iter_init(message, &iter);
492 attr_type=attr_type_get_from_message(&iter);
493 attr_iter=object_get_from_message_arg(&iter, "config_attr_iter");
494 if (attr_type == attr_none)
495 return dbus_error_invalid_attr_type(connection, message);
496 if (config_get_attr(config, attr_type, &attr, attr_iter)) {
497 reply = dbus_message_new_method_return(message);
498 encode_attr(reply, &attr);
499 dbus_connection_send (connection, reply, NULL);
500 dbus_message_unref (reply);
501 return DBUS_HANDLER_RESULT_HANDLED;
503 return empty_reply(connection, message);
506 static DBusHandlerResult
507 request_config_attr_iter(DBusConnection *connection, DBusMessage *message)
510 struct attr_iter *attr_iter=config_attr_iter_new();
511 char *opath=object_new("config_attr_iter",attr_iter);
512 reply = dbus_message_new_method_return(message);
513 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
514 dbus_connection_send (connection, reply, NULL);
515 dbus_message_unref (reply);
517 return DBUS_HANDLER_RESULT_HANDLED;
520 static DBusHandlerResult
521 request_config_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
523 struct attr_iter *attr_iter;
524 DBusMessageIter iter;
526 dbus_message_iter_init(message, &iter);
527 attr_iter=object_get_from_message_arg(&iter, "config_attr_iter");
529 return dbus_error_invalid_object_path_parameter(connection, message);
530 config_attr_iter_destroy(attr_iter);
532 return empty_reply(connection, message);
537 static DBusHandlerResult
538 request_graphics_get_data(DBusConnection *connection, DBusMessage *message)
540 struct graphics *graphics;
542 struct graphics_data_image *image;
545 graphics = object_get_from_message(message, "graphics");
547 return dbus_error_invalid_object_path(connection, message);
549 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &data, DBUS_TYPE_INVALID))
550 return dbus_error_invalid_parameter(connection, message);
551 image=graphics_get_data(graphics, data);
553 DBusMessageIter iter1,iter2;
554 reply = dbus_message_new_method_return(message);
556 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
558 dbus_message_iter_init_append(reply, &iter1);
559 dbus_message_iter_open_container(&iter1, DBUS_TYPE_ARRAY, "y", &iter2);
560 if (image->data && image->size)
561 dbus_message_iter_append_fixed_array(&iter2, DBUS_TYPE_BYTE, &image->data, image->size);
562 dbus_message_iter_close_container(&iter1, &iter2);
563 dbus_connection_send (connection, reply, NULL);
564 dbus_message_unref (reply);
565 return DBUS_HANDLER_RESULT_HANDLED;
567 return empty_reply(connection, message);
570 static DBusHandlerResult
571 request_graphics_set_attr(DBusConnection *connection, DBusMessage *message)
573 struct graphics *graphics;
577 graphics = object_get_from_message(message, "graphics");
579 return dbus_error_invalid_object_path(connection, message);
580 if (decode_attr(message, &attr)) {
581 ret=graphics_set_attr(graphics, &attr);
584 return empty_reply(connection, message);
586 return dbus_error_invalid_parameter(connection, message);
591 static DBusHandlerResult
592 request_map_set_attr(DBusConnection *connection, DBusMessage *message)
598 map = object_get_from_message(message, "map");
600 return dbus_error_invalid_object_path(connection, message);
601 if (decode_attr(message, &attr)) {
602 ret=map_set_attr(map, &attr);
605 return empty_reply(connection, message);
607 return dbus_error_invalid_parameter(connection, message);
610 static DBusHandlerResult
611 request_map_get_attr(DBusConnection *connection, DBusMessage *message)
613 return request_get_attr(connection, message, "map", (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))map_get_attr);
618 static DBusHandlerResult
619 request_mapset_attr_iter(DBusConnection *connection, DBusMessage *message)
621 return request_attr_iter(connection, message, "mapset", (struct attr_iter * (*)(void))mapset_attr_iter_new);
624 static DBusHandlerResult
625 request_mapset_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
627 return request_attr_iter_destroy(connection, message, "mapset", (void (*)(struct attr_iter *))mapset_attr_iter_destroy);
630 static DBusHandlerResult
631 request_mapset_get_attr(DBusConnection *connection, DBusMessage *message)
633 return request_get_attr(connection, message, "mapset", (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))mapset_get_attr);
638 static DBusHandlerResult
639 request_navit_draw(DBusConnection *connection, DBusMessage *message)
643 navit=object_get_from_message(message, "navit");
645 return dbus_error_invalid_object_path(connection, message);
649 return empty_reply(connection, message);
654 * Extracts a struct point from a DBus message
656 * @param message The DBus message
657 * @param iter Sort of pointer that points on that (ii)-object in the message
658 * @param p Pointer where the data should get stored
659 * @returns Returns 1 when everything went right, otherwise 0
662 point_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct point *p)
664 DBusMessageIter iter2;
666 dbg(0,"%s\n", dbus_message_iter_get_signature(iter));
668 dbus_message_iter_recurse(iter, &iter2);
670 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
672 dbus_message_iter_get_basic(&iter2, &p->x);
674 dbus_message_iter_next(&iter2);
676 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
678 dbus_message_iter_get_basic(&iter2, &p->y);
680 dbg(0, " x -> %x y -> %x\n", p->x, p->y);
682 dbus_message_iter_next(&iter2);
684 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INVALID)
691 * @brief Shows up a message
692 * @param connection The DBusConnection object through which \a message arrived
693 * @param message The DBusMessage containing the coordinates
694 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
697 static DBusHandlerResult
698 request_navit_add_message(DBusConnection *connection, DBusMessage *message)
703 DBusMessageIter iter;
705 navit=object_get_from_message(message, "navit");
707 return dbus_error_invalid_object_path(connection, message);
709 dbus_message_iter_init(message, &iter);
710 dbus_message_iter_get_basic(&iter, &usermessage);
712 navit_add_message(navit, usermessage);
714 return empty_reply(connection, message);
719 * @brief Centers the screen on a specified position \a pc on the world
720 * @param connection The DBusConnection object through which \a message arrived
721 * @param message The DBusMessage containing the coordinates
722 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
725 static DBusHandlerResult
726 request_navit_set_center(DBusConnection *connection, DBusMessage *message)
730 DBusMessageIter iter;
732 navit=object_get_from_message(message, "navit");
734 return dbus_error_invalid_object_path(connection, message);
736 dbus_message_iter_init(message, &iter);
738 if (!pcoord_get_from_message(message, &iter, &pc))
739 return dbus_error_invalid_parameter(connection, message);
741 navit_set_center(navit, &pc, 0);
742 return empty_reply(connection, message);
746 * @brief Centers the screen on a specified position \a p shown on the screen
747 * @param connection The DBusConnection object through which \a message arrived
748 * @param message The DBusMessage containing the x and y value
749 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
751 static DBusHandlerResult
752 request_navit_set_center_screen(DBusConnection *connection, DBusMessage *message)
756 DBusMessageIter iter;
758 navit=object_get_from_message(message, "navit");
760 return dbus_error_invalid_object_path(connection, message);
762 dbus_message_iter_init(message, &iter);
764 if (!point_get_from_message(message, &iter, &p))
765 return dbus_error_invalid_parameter(connection, message);
766 navit_set_center_screen(navit, &p, 0);
767 return empty_reply(connection, message);
771 * @brief Sets the layout to \a new_layout_name extracted from \a message
772 * @param connection The DBusConnection object through which \a message arrived
773 * @param message The DBusMessage containing the name of the layout
774 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
776 static DBusHandlerResult
777 request_navit_set_layout(DBusConnection *connection, DBusMessage *message)
779 char *new_layout_name;
782 struct attr_iter *iter;
784 navit=object_get_from_message(message, "navit");
786 return dbus_error_invalid_object_path(connection, message);
788 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &new_layout_name, DBUS_TYPE_INVALID))
789 return dbus_error_invalid_parameter(connection, message);
791 iter=navit_attr_iter_new();
792 while(navit_get_attr(navit, attr_layout, &attr, iter)) {
793 if (strcmp(attr.u.layout->name, new_layout_name) == 0) {
794 navit_set_attr(navit, &attr);
797 return empty_reply(connection, message);
800 static DBusHandlerResult
801 request_navit_zoom(DBusConnection *connection, DBusMessage *message)
806 DBusMessageIter iter;
808 navit = object_get_from_message(message, "navit");
810 return dbus_error_invalid_object_path(connection, message);
812 dbus_message_iter_init(message, &iter);
813 dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
815 dbus_message_iter_get_basic(&iter, &factor);
817 if (dbus_message_iter_has_next(&iter))
819 dbus_message_iter_next(&iter);
820 if (!point_get_from_message(message, &iter, &p))
821 return dbus_error_invalid_parameter(connection, message);
825 navit_zoom_in(navit, factor, &p);
826 else if (factor < -1)
827 navit_zoom_out(navit, 0-factor, &p);
829 return empty_reply(connection, message);
833 static DBusHandlerResult
834 request_navit_resize(DBusConnection *connection, DBusMessage *message)
838 DBusMessageIter iter;
840 navit = object_get_from_message(message, "navit");
842 return dbus_error_invalid_object_path(connection, message);
844 dbus_message_iter_init(message, &iter);
845 dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
847 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
848 return dbus_error_invalid_parameter(connection, message);
849 dbus_message_iter_get_basic(&iter, &w);
851 dbus_message_iter_next(&iter);
853 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
854 return dbus_error_invalid_parameter(connection, message);
855 dbus_message_iter_get_basic(&iter, &h);
857 dbg(0, " w -> %i h -> %i\n", w, h);
859 navit_handle_resize(navit, w, h);
861 return empty_reply(connection, message);
865 static DBusHandlerResult
866 request_navit_get_attr(DBusConnection *connection, DBusMessage *message)
869 DBusMessageIter iter;
871 enum attr_type attr_type;
872 struct attr_iter *attr_iter;
875 navit = object_get_from_message(message, "navit");
877 return dbus_error_invalid_object_path(connection, message);
879 dbus_message_iter_init(message, &iter);
880 attr_type=attr_type_get_from_message(&iter);
881 if (attr_type == attr_none)
882 return dbus_error_invalid_attr_type(connection, message);
883 attr_iter=object_get_from_message_arg(&iter, "navit_attr_iter");
884 if (navit_get_attr(navit, attr_type, &attr, attr_iter)) {
885 reply = dbus_message_new_method_return(message);
886 encode_attr(reply, &attr);
887 dbus_connection_send (connection, reply, NULL);
888 dbus_message_unref (reply);
889 return DBUS_HANDLER_RESULT_HANDLED;
891 return empty_reply(connection, message);
894 static DBusHandlerResult
895 request_navit_attr_iter(DBusConnection *connection, DBusMessage *message)
898 struct attr_iter *attr_iter=navit_attr_iter_new();
899 char *opath=object_new("navit_attr_iter",attr_iter);
900 reply = dbus_message_new_method_return(message);
901 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
902 dbus_connection_send (connection, reply, NULL);
903 dbus_message_unref (reply);
905 return DBUS_HANDLER_RESULT_HANDLED;
908 static DBusHandlerResult
909 request_navit_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
911 struct attr_iter *attr_iter;
912 DBusMessageIter iter;
914 dbus_message_iter_init(message, &iter);
915 attr_iter=object_get_from_message_arg(&iter, "navit_attr_iter");
917 return dbus_error_invalid_object_path_parameter(connection, message);
918 navit_attr_iter_destroy(attr_iter);
920 return empty_reply(connection, message);
924 static DBusHandlerResult
925 request_navit_set_attr(DBusConnection *connection, DBusMessage *message)
931 navit = object_get_from_message(message, "navit");
933 return dbus_error_invalid_object_path(connection, message);
934 if (decode_attr(message, &attr)) {
935 ret=navit_set_attr(navit, &attr);
938 return empty_reply(connection, message);
940 return dbus_error_invalid_parameter(connection, message);
943 static DBusHandlerResult
944 request_navit_set_position(DBusConnection *connection, DBusMessage *message)
948 DBusMessageIter iter;
950 navit = object_get_from_message(message, "navit");
952 return dbus_error_invalid_object_path(connection, message);
954 dbus_message_iter_init(message, &iter);
955 if (!pcoord_get_from_message(message, &iter, &pc))
956 return dbus_error_invalid_parameter(connection, message);
958 navit_set_position(navit, &pc);
959 return empty_reply(connection, message);
962 static DBusHandlerResult
963 request_navit_set_destination(DBusConnection *connection, DBusMessage *message)
967 DBusMessageIter iter;
970 navit = object_get_from_message(message, "navit");
972 return dbus_error_invalid_object_path(connection, message);
974 dbus_message_iter_init(message, &iter);
975 if (!pcoord_get_from_message(message, &iter, &pc))
976 return dbus_error_invalid_parameter(connection, message);
978 dbus_message_iter_next(&iter);
979 dbus_message_iter_get_basic(&iter, &description);
980 dbg(0, " destination -> %s\n", description);
982 navit_set_destination(navit, &pc, description, 1);
983 return empty_reply(connection, message);
986 static DBusHandlerResult
987 request_navit_evaluate(DBusConnection *connection, DBusMessage *message)
996 navit = object_get_from_message(message, "navit");
998 return dbus_error_invalid_object_path(connection, message);
1000 attr.type=attr_navit;
1002 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &command, DBUS_TYPE_INVALID))
1003 return dbus_error_invalid_parameter(connection, message);
1004 result=command_evaluate_to_string(&attr, command, &error);
1005 reply = dbus_message_new_method_return(message);
1007 dbus_message_append_args(reply, DBUS_TYPE_INT32, error, DBUS_TYPE_INVALID);
1009 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
1010 dbus_connection_send (connection, reply, NULL);
1011 dbus_message_unref (reply);
1012 return DBUS_HANDLER_RESULT_HANDLED;
1019 static DBusHandlerResult
1020 request_vehicle_set_attr(DBusConnection *connection, DBusMessage *message)
1022 struct vehicle *vehicle;
1026 vehicle = object_get_from_message(message, "vehicle");
1028 return dbus_error_invalid_object_path(connection, message);
1029 if (decode_attr(message, &attr)) {
1030 ret=vehicle_set_attr(vehicle, &attr);
1031 destroy_attr(&attr);
1033 return empty_reply(connection, message);
1035 return dbus_error_invalid_parameter(connection, message);
1039 struct dbus_method {
1043 char *signature_name;
1045 char *response_name;
1046 DBusHandlerResult(*func)(DBusConnection *connection, DBusMessage *message);
1047 } dbus_methods[] = {
1048 {"", "attr_iter", "", "", "o", "attr_iter", request_config_attr_iter},
1049 {"", "attr_iter_destroy", "o", "attr_iter", "", "", request_config_attr_iter_destroy},
1050 {"", "get_attr", "s", "attrname", "sv", "attrname,value",request_config_get_attr},
1051 {"", "get_attr_wi", "so", "attrname,attr_iter", "sv", "attrname,value",request_config_get_attr},
1052 {".graphics","get_data", "s", "type", "ay", "data", request_graphics_get_data},
1053 {".graphics","set_attr", "sv", "attribute,value", "", "", request_graphics_set_attr},
1054 {".navit", "draw", "", "", "", "", request_navit_draw},
1055 {".navit", "add_message", "s", "message", "", "", request_navit_add_message},
1056 {".navit", "set_center", "s", "(coordinates)", "", "", request_navit_set_center},
1057 {".navit", "set_center", "(is)", "(projection,coordinates)", "", "", request_navit_set_center},
1058 {".navit", "set_center", "(iii)", "(projection,longitude,latitude)", "", "", request_navit_set_center},
1059 {".navit", "set_center_screen", "(ii)", "(pixel_x,pixel_y)", "", "", request_navit_set_center_screen},
1060 {".navit", "set_layout", "s", "layoutname", "", "", request_navit_set_layout},
1061 {".navit", "zoom", "i(ii)", "factor(pixel_x,pixel_y)", "", "", request_navit_zoom},
1062 {".navit", "zoom", "i", "factor", "", "", request_navit_zoom},
1063 {".navit", "resize", "ii", "upperleft,lowerright", "", "", request_navit_resize},
1064 {".navit", "attr_iter", "", "", "o", "attr_iter", request_navit_attr_iter},
1065 {".navit", "attr_iter_destroy", "o", "attr_iter", "", "", request_navit_attr_iter_destroy},
1066 {".navit", "get_attr", "s", "attribute", "sv", "attrname,value", request_navit_get_attr},
1067 {".navit", "get_attr_wi", "so", "attribute,attr_iter", "sv", "attrname,value", request_navit_get_attr},
1068 {".navit", "set_attr", "sv", "attribute,value", "", "", request_navit_set_attr},
1069 {".navit", "set_position", "s", "(coordinates)", "", "", request_navit_set_position},
1070 {".navit", "set_position", "(is)", "(projection,coordinated)", "", "", request_navit_set_position},
1071 {".navit", "set_position", "(iii)", "(projection,longitude,latitude)", "", "", request_navit_set_position},
1072 {".navit", "set_destination", "ss", "coordinates,comment", "", "", request_navit_set_destination},
1073 {".navit", "set_destination", "(is)s", "(projection,coordinates)comment", "", "", request_navit_set_destination},
1074 {".navit", "set_destination", "(iii)s", "(projection,longitude,latitude)comment", "", "", request_navit_set_destination},
1075 {".navit", "evaluate", "s", "command", "s", "", request_navit_evaluate},
1076 {".map", "get_attr", "s", "attribute", "sv", "attrname,value", request_map_get_attr},
1077 {".map", "set_attr", "sv", "attribute,value", "", "", request_map_set_attr},
1078 {".mapset", "attr_iter", "", "", "o", "attr_iter", request_mapset_attr_iter},
1079 {".mapset", "attr_iter_destroy", "o", "attr_iter", "", "", request_mapset_attr_iter_destroy},
1080 {".mapset", "get_attr", "s", "attribute", "sv", "attrname,value", request_mapset_get_attr},
1081 {".mapset", "get_attr_wi", "so", "attribute,attr_iter", "sv", "attrname,value", request_mapset_get_attr},
1082 {".vehicle","set_attr", "sv", "attribute,value", "", "", request_vehicle_set_attr},
1086 introspect_path(const char *object)
1090 char *def=".default_";
1091 int def_len=strlen(def);
1092 if (strncmp(object, object_path, strlen(object_path)))
1094 ret=g_strdup(object+strlen(object_path));
1095 dbg(0,"path=%s\n",ret);
1096 for (i = strlen(ret)-1 ; i >= 0 ; i--) {
1097 if (ret[i] == '/' || (ret[i] >= '0' && ret[i] <= '9'))
1102 for (i = 0 ; i < strlen(ret); i++)
1106 for (i = strlen(ret)-1 ; i >= 0 ; i--) {
1107 if (!strncmp(ret+i, def, def_len)) {
1108 memmove(ret+1,ret+i+def_len,strlen(ret+i+def_len)+1);
1116 generate_navitintrospectxml(const char *object)
1118 int i,methods_size,n=0;
1119 char *navitintrospectxml;
1120 char *path=introspect_path(object);
1123 dbg(0,"path=%s\n",path);
1125 // write header and make navit introspectable
1126 navitintrospectxml = g_strdup_printf("%s%s%s\n", navitintrospectxml_head1, object, navitintrospectxml_head2);
1128 methods_size=sizeof(dbus_methods)/sizeof(struct dbus_method);
1129 for (i = 0 ; i < methods_size ; i++) {
1130 // start new interface if it's the first method or it changed
1131 if (strcmp(dbus_methods[i].path, path))
1133 if ((n == 0) || strcmp(dbus_methods[i-1].path, dbus_methods[i].path))
1134 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <interface name=\"%s%s\">\n", service_name, dbus_methods[i].path);
1137 // start the new method
1138 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <method name=\"%s\">\n", dbus_methods[i].method);
1140 // set input signature if existent
1141 if (strcmp(dbus_methods[i].signature, ""))
1142 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <arg direction=\"in\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].signature_name, dbus_methods[i].signature);
1144 // set response signature if existent
1145 if (strcmp(dbus_methods[i].response, ""))
1146 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <arg direction=\"out\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].response_name, dbus_methods[i].response);
1149 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " </method>\n");
1151 // close the interface if we reached the last method or the interface changes
1152 if ((methods_size == i+1) || ((methods_size > i+1) && strcmp(dbus_methods[i+1].path, dbus_methods[i].path)))
1153 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " </interface>\n\n");
1155 // close the "mother tag"
1156 navitintrospectxml = g_strconcat_printf(navitintrospectxml, "</node>\n");
1158 return navitintrospectxml;
1161 static DBusHandlerResult
1162 navit_handler_func(DBusConnection *connection, DBusMessage *message, void *user_data)
1166 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));
1167 if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1169 char *navitintrospectxml = generate_navitintrospectxml(dbus_message_get_path(message));
1170 dbg(0,"Introspect %s:Result:%s\n",dbus_message_get_path(message), navitintrospectxml);
1171 if (navitintrospectxml) {
1172 reply = dbus_message_new_method_return(message);
1173 dbus_message_append_args(reply, DBUS_TYPE_STRING, &navitintrospectxml, DBUS_TYPE_INVALID);
1174 dbus_connection_send (connection, reply, NULL);
1175 dbus_message_unref (reply);
1176 g_free(navitintrospectxml);
1177 return DBUS_HANDLER_RESULT_HANDLED;
1179 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1182 for (i = 0 ; i < sizeof(dbus_methods)/sizeof(struct dbus_method) ; i++) {
1183 path=g_strdup_printf("%s%s", service_name, dbus_methods[i].path);
1184 if (dbus_message_is_method_call(message, path, dbus_methods[i].method) &&
1185 dbus_message_has_signature(message, dbus_methods[i].signature)) {
1187 return dbus_methods[i].func(connection, message);
1191 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1194 static DBusObjectPathVTable dbus_navit_vtable = {
1202 filter(DBusConnection *connection, DBusMessage *message, void *user_data)
1204 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));
1205 if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
1207 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1212 dbus_cmd_send_signal(struct navit *navit, char *command, struct attr **in, struct attr ***out)
1215 char *opath=object_new("navit",navit);
1216 char *interface=g_strdup_printf("%s%s", service_name, ".navit");
1217 dbg(0,"enter %s %s %s\n",opath,command,interface);
1218 msg = dbus_message_new_signal(opath, interface, "signal");
1221 encode_attr(msg, in[0]);
1223 dbus_connection_send(connection, msg, &dbus_serial);
1224 dbus_connection_flush(connection);
1225 dbus_message_unref(msg);
1232 static struct command_table commands[] = {
1233 {"dbus_send_signal",command_cast(dbus_cmd_send_signal)},
1238 dbus_main_navit(struct navit *navit, int added)
1242 command_add_table_attr(commands, sizeof(commands)/sizeof(struct command_table), navit, &attr);
1243 navit_add_attr(navit, &attr);
1247 void plugin_init(void)
1251 struct attr callback;
1252 object_hash=g_hash_table_new(g_str_hash, g_str_equal);
1253 object_hash_rev=g_hash_table_new(NULL, NULL);
1254 object_count=g_hash_table_new(g_str_hash, g_str_equal);
1256 dbus_error_init(&error);
1257 connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
1259 dbg(0,"Failed to open connection to session message bus: %s\n", error.message);
1260 dbus_error_free(&error);
1263 dbus_connection_setup_with_g_main(connection, NULL);
1265 dbus_connection_add_filter(connection, filter, NULL, NULL);
1266 dbus_bus_add_match(connection, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
1268 dbus_connection_register_fallback(connection, object_path, &dbus_navit_vtable, NULL);
1269 dbus_bus_request_name(connection, service_name, 0, &error);
1270 if (dbus_error_is_set(&error)) {
1271 dbg(0,"Failed to request name: %s", error.message);
1272 dbus_error_free (&error);
1274 callback.type=attr_callback;
1275 callback.u.callback=callback_new_0(callback_cast(dbus_main_navit));
1276 config_add_attr(config, &callback);