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, void *data, 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);
480 static DBusHandlerResult
481 request_set_attr(DBusConnection *connection, DBusMessage *message, char *type, void *data, int (*func)(void *data, struct attr *attr))
487 data = object_get_from_message(message, type);
489 return dbus_error_invalid_object_path(connection, message);
491 if (decode_attr(message, &attr)) {
492 ret=(*func)(data, &attr);
495 return empty_reply(connection, message);
497 return dbus_error_invalid_parameter(connection, message);
502 static DBusHandlerResult
503 request_config_get_attr(DBusConnection *connection, DBusMessage *message)
505 return request_get_attr(connection, message, "config", config, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))config_get_attr);
508 static DBusHandlerResult
509 request_config_attr_iter(DBusConnection *connection, DBusMessage *message)
511 return request_attr_iter(connection, message, "config", (struct attr_iter * (*)(void))config_attr_iter_new);
514 static DBusHandlerResult
515 request_config_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
517 return request_attr_iter_destroy(connection, message, "config", (void (*)(struct attr_iter *))config_attr_iter_destroy);
522 static DBusHandlerResult
523 request_graphics_get_data(DBusConnection *connection, DBusMessage *message)
525 struct graphics *graphics;
527 struct graphics_data_image *image;
530 graphics = object_get_from_message(message, "graphics");
532 return dbus_error_invalid_object_path(connection, message);
534 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &data, DBUS_TYPE_INVALID))
535 return dbus_error_invalid_parameter(connection, message);
536 image=graphics_get_data(graphics, data);
538 DBusMessageIter iter1,iter2;
539 reply = dbus_message_new_method_return(message);
541 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
543 dbus_message_iter_init_append(reply, &iter1);
544 dbus_message_iter_open_container(&iter1, DBUS_TYPE_ARRAY, "y", &iter2);
545 if (image->data && image->size)
546 dbus_message_iter_append_fixed_array(&iter2, DBUS_TYPE_BYTE, &image->data, image->size);
547 dbus_message_iter_close_container(&iter1, &iter2);
548 dbus_connection_send (connection, reply, NULL);
549 dbus_message_unref (reply);
550 return DBUS_HANDLER_RESULT_HANDLED;
552 return empty_reply(connection, message);
555 static DBusHandlerResult
556 request_graphics_set_attr(DBusConnection *connection, DBusMessage *message)
558 return request_set_attr(connection, message, "graphics", NULL, (int (*)(void *, struct attr *))graphics_set_attr);
563 static DBusHandlerResult
564 request_map_get_attr(DBusConnection *connection, DBusMessage *message)
566 return request_get_attr(connection, message, "map", NULL, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))map_get_attr);
570 static DBusHandlerResult
571 request_map_set_attr(DBusConnection *connection, DBusMessage *message)
573 return request_set_attr(connection, message, "map", NULL, (int (*)(void *, struct attr *))map_set_attr);
578 static DBusHandlerResult
579 request_mapset_attr_iter(DBusConnection *connection, DBusMessage *message)
581 return request_attr_iter(connection, message, "mapset", (struct attr_iter * (*)(void))mapset_attr_iter_new);
584 static DBusHandlerResult
585 request_mapset_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
587 return request_attr_iter_destroy(connection, message, "mapset", (void (*)(struct attr_iter *))mapset_attr_iter_destroy);
590 static DBusHandlerResult
591 request_mapset_get_attr(DBusConnection *connection, DBusMessage *message)
593 return request_get_attr(connection, message, "mapset", NULL, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))mapset_get_attr);
598 static DBusHandlerResult
599 request_navit_draw(DBusConnection *connection, DBusMessage *message)
603 navit=object_get_from_message(message, "navit");
605 return dbus_error_invalid_object_path(connection, message);
609 return empty_reply(connection, message);
614 * Extracts a struct point from a DBus message
616 * @param message The DBus message
617 * @param iter Sort of pointer that points on that (ii)-object in the message
618 * @param p Pointer where the data should get stored
619 * @returns Returns 1 when everything went right, otherwise 0
622 point_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct point *p)
624 DBusMessageIter iter2;
626 dbg(0,"%s\n", dbus_message_iter_get_signature(iter));
628 dbus_message_iter_recurse(iter, &iter2);
630 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
632 dbus_message_iter_get_basic(&iter2, &p->x);
634 dbus_message_iter_next(&iter2);
636 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
638 dbus_message_iter_get_basic(&iter2, &p->y);
640 dbg(0, " x -> %x y -> %x\n", p->x, p->y);
642 dbus_message_iter_next(&iter2);
644 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INVALID)
651 * @brief Shows up a message
652 * @param connection The DBusConnection object through which \a message arrived
653 * @param message The DBusMessage containing the coordinates
654 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
657 static DBusHandlerResult
658 request_navit_add_message(DBusConnection *connection, DBusMessage *message)
663 DBusMessageIter iter;
665 navit=object_get_from_message(message, "navit");
667 return dbus_error_invalid_object_path(connection, message);
669 dbus_message_iter_init(message, &iter);
670 dbus_message_iter_get_basic(&iter, &usermessage);
672 navit_add_message(navit, usermessage);
674 return empty_reply(connection, message);
679 * @brief Centers the screen on a specified position \a pc on the world
680 * @param connection The DBusConnection object through which \a message arrived
681 * @param message The DBusMessage containing the coordinates
682 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
685 static DBusHandlerResult
686 request_navit_set_center(DBusConnection *connection, DBusMessage *message)
690 DBusMessageIter iter;
692 navit=object_get_from_message(message, "navit");
694 return dbus_error_invalid_object_path(connection, message);
696 dbus_message_iter_init(message, &iter);
698 if (!pcoord_get_from_message(message, &iter, &pc))
699 return dbus_error_invalid_parameter(connection, message);
701 navit_set_center(navit, &pc, 0);
702 return empty_reply(connection, message);
706 * @brief Centers the screen on a specified position \a p shown on the screen
707 * @param connection The DBusConnection object through which \a message arrived
708 * @param message The DBusMessage containing the x and y value
709 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
711 static DBusHandlerResult
712 request_navit_set_center_screen(DBusConnection *connection, DBusMessage *message)
716 DBusMessageIter iter;
718 navit=object_get_from_message(message, "navit");
720 return dbus_error_invalid_object_path(connection, message);
722 dbus_message_iter_init(message, &iter);
724 if (!point_get_from_message(message, &iter, &p))
725 return dbus_error_invalid_parameter(connection, message);
726 navit_set_center_screen(navit, &p, 0);
727 return empty_reply(connection, message);
731 * @brief Sets the layout to \a new_layout_name extracted from \a message
732 * @param connection The DBusConnection object through which \a message arrived
733 * @param message The DBusMessage containing the name of the layout
734 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
736 static DBusHandlerResult
737 request_navit_set_layout(DBusConnection *connection, DBusMessage *message)
739 char *new_layout_name;
742 struct attr_iter *iter;
744 navit=object_get_from_message(message, "navit");
746 return dbus_error_invalid_object_path(connection, message);
748 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &new_layout_name, DBUS_TYPE_INVALID))
749 return dbus_error_invalid_parameter(connection, message);
751 iter=navit_attr_iter_new();
752 while(navit_get_attr(navit, attr_layout, &attr, iter)) {
753 if (strcmp(attr.u.layout->name, new_layout_name) == 0) {
754 navit_set_attr(navit, &attr);
757 return empty_reply(connection, message);
760 static DBusHandlerResult
761 request_navit_zoom(DBusConnection *connection, DBusMessage *message)
766 DBusMessageIter iter;
768 navit = object_get_from_message(message, "navit");
770 return dbus_error_invalid_object_path(connection, message);
772 dbus_message_iter_init(message, &iter);
773 dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
775 dbus_message_iter_get_basic(&iter, &factor);
777 if (dbus_message_iter_has_next(&iter))
779 dbus_message_iter_next(&iter);
780 if (!point_get_from_message(message, &iter, &p))
781 return dbus_error_invalid_parameter(connection, message);
785 navit_zoom_in(navit, factor, &p);
786 else if (factor < -1)
787 navit_zoom_out(navit, 0-factor, &p);
789 return empty_reply(connection, message);
793 static DBusHandlerResult
794 request_navit_resize(DBusConnection *connection, DBusMessage *message)
798 DBusMessageIter iter;
800 navit = object_get_from_message(message, "navit");
802 return dbus_error_invalid_object_path(connection, message);
804 dbus_message_iter_init(message, &iter);
805 dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
807 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
808 return dbus_error_invalid_parameter(connection, message);
809 dbus_message_iter_get_basic(&iter, &w);
811 dbus_message_iter_next(&iter);
813 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
814 return dbus_error_invalid_parameter(connection, message);
815 dbus_message_iter_get_basic(&iter, &h);
817 dbg(0, " w -> %i h -> %i\n", w, h);
819 navit_handle_resize(navit, w, h);
821 return empty_reply(connection, message);
825 static DBusHandlerResult
826 request_navit_get_attr(DBusConnection *connection, DBusMessage *message)
829 DBusMessageIter iter;
831 enum attr_type attr_type;
832 struct attr_iter *attr_iter;
835 navit = object_get_from_message(message, "navit");
837 return dbus_error_invalid_object_path(connection, message);
839 dbus_message_iter_init(message, &iter);
840 attr_type=attr_type_get_from_message(&iter);
841 if (attr_type == attr_none)
842 return dbus_error_invalid_attr_type(connection, message);
843 attr_iter=object_get_from_message_arg(&iter, "navit_attr_iter");
844 if (navit_get_attr(navit, attr_type, &attr, attr_iter)) {
845 reply = dbus_message_new_method_return(message);
846 encode_attr(reply, &attr);
847 dbus_connection_send (connection, reply, NULL);
848 dbus_message_unref (reply);
849 return DBUS_HANDLER_RESULT_HANDLED;
851 return empty_reply(connection, message);
854 static DBusHandlerResult
855 request_navit_attr_iter(DBusConnection *connection, DBusMessage *message)
858 struct attr_iter *attr_iter=navit_attr_iter_new();
859 char *opath=object_new("navit_attr_iter",attr_iter);
860 reply = dbus_message_new_method_return(message);
861 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
862 dbus_connection_send (connection, reply, NULL);
863 dbus_message_unref (reply);
865 return DBUS_HANDLER_RESULT_HANDLED;
868 static DBusHandlerResult
869 request_navit_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
871 struct attr_iter *attr_iter;
872 DBusMessageIter iter;
874 dbus_message_iter_init(message, &iter);
875 attr_iter=object_get_from_message_arg(&iter, "navit_attr_iter");
877 return dbus_error_invalid_object_path_parameter(connection, message);
878 navit_attr_iter_destroy(attr_iter);
880 return empty_reply(connection, message);
884 static DBusHandlerResult
885 request_navit_set_attr(DBusConnection *connection, DBusMessage *message)
891 navit = object_get_from_message(message, "navit");
893 return dbus_error_invalid_object_path(connection, message);
894 if (decode_attr(message, &attr)) {
895 ret=navit_set_attr(navit, &attr);
898 return empty_reply(connection, message);
900 return dbus_error_invalid_parameter(connection, message);
903 static DBusHandlerResult
904 request_navit_set_position(DBusConnection *connection, DBusMessage *message)
908 DBusMessageIter iter;
910 navit = object_get_from_message(message, "navit");
912 return dbus_error_invalid_object_path(connection, message);
914 dbus_message_iter_init(message, &iter);
915 if (!pcoord_get_from_message(message, &iter, &pc))
916 return dbus_error_invalid_parameter(connection, message);
918 navit_set_position(navit, &pc);
919 return empty_reply(connection, message);
922 static DBusHandlerResult
923 request_navit_set_destination(DBusConnection *connection, DBusMessage *message)
927 DBusMessageIter iter;
930 navit = object_get_from_message(message, "navit");
932 return dbus_error_invalid_object_path(connection, message);
934 dbus_message_iter_init(message, &iter);
935 if (!pcoord_get_from_message(message, &iter, &pc))
936 return dbus_error_invalid_parameter(connection, message);
938 dbus_message_iter_next(&iter);
939 dbus_message_iter_get_basic(&iter, &description);
940 dbg(0, " destination -> %s\n", description);
942 navit_set_destination(navit, &pc, description, 1);
943 return empty_reply(connection, message);
946 static DBusHandlerResult
947 request_navit_evaluate(DBusConnection *connection, DBusMessage *message)
956 navit = object_get_from_message(message, "navit");
958 return dbus_error_invalid_object_path(connection, message);
960 attr.type=attr_navit;
962 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &command, DBUS_TYPE_INVALID))
963 return dbus_error_invalid_parameter(connection, message);
964 result=command_evaluate_to_string(&attr, command, &error);
965 reply = dbus_message_new_method_return(message);
967 dbus_message_append_args(reply, DBUS_TYPE_INT32, error, DBUS_TYPE_INVALID);
969 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
970 dbus_connection_send (connection, reply, NULL);
971 dbus_message_unref (reply);
972 return DBUS_HANDLER_RESULT_HANDLED;
979 static DBusHandlerResult
980 request_vehicle_set_attr(DBusConnection *connection, DBusMessage *message)
982 struct vehicle *vehicle;
986 vehicle = object_get_from_message(message, "vehicle");
988 return dbus_error_invalid_object_path(connection, message);
989 if (decode_attr(message, &attr)) {
990 ret=vehicle_set_attr(vehicle, &attr);
993 return empty_reply(connection, message);
995 return dbus_error_invalid_parameter(connection, message);
1003 char *signature_name;
1005 char *response_name;
1006 DBusHandlerResult(*func)(DBusConnection *connection, DBusMessage *message);
1007 } dbus_methods[] = {
1008 {"", "attr_iter", "", "", "o", "attr_iter", request_config_attr_iter},
1009 {"", "attr_iter_destroy", "o", "attr_iter", "", "", request_config_attr_iter_destroy},
1010 {"", "get_attr", "s", "attrname", "sv", "attrname,value",request_config_get_attr},
1011 {"", "get_attr_wi", "so", "attrname,attr_iter", "sv", "attrname,value",request_config_get_attr},
1012 {".graphics","get_data", "s", "type", "ay", "data", request_graphics_get_data},
1013 {".graphics","set_attr", "sv", "attribute,value", "", "", request_graphics_set_attr},
1014 {".navit", "draw", "", "", "", "", request_navit_draw},
1015 {".navit", "add_message", "s", "message", "", "", request_navit_add_message},
1016 {".navit", "set_center", "s", "(coordinates)", "", "", request_navit_set_center},
1017 {".navit", "set_center", "(is)", "(projection,coordinates)", "", "", request_navit_set_center},
1018 {".navit", "set_center", "(iii)", "(projection,longitude,latitude)", "", "", request_navit_set_center},
1019 {".navit", "set_center_screen", "(ii)", "(pixel_x,pixel_y)", "", "", request_navit_set_center_screen},
1020 {".navit", "set_layout", "s", "layoutname", "", "", request_navit_set_layout},
1021 {".navit", "zoom", "i(ii)", "factor(pixel_x,pixel_y)", "", "", request_navit_zoom},
1022 {".navit", "zoom", "i", "factor", "", "", request_navit_zoom},
1023 {".navit", "resize", "ii", "upperleft,lowerright", "", "", request_navit_resize},
1024 {".navit", "attr_iter", "", "", "o", "attr_iter", request_navit_attr_iter},
1025 {".navit", "attr_iter_destroy", "o", "attr_iter", "", "", request_navit_attr_iter_destroy},
1026 {".navit", "get_attr", "s", "attribute", "sv", "attrname,value", request_navit_get_attr},
1027 {".navit", "get_attr_wi", "so", "attribute,attr_iter", "sv", "attrname,value", request_navit_get_attr},
1028 {".navit", "set_attr", "sv", "attribute,value", "", "", request_navit_set_attr},
1029 {".navit", "set_position", "s", "(coordinates)", "", "", request_navit_set_position},
1030 {".navit", "set_position", "(is)", "(projection,coordinated)", "", "", request_navit_set_position},
1031 {".navit", "set_position", "(iii)", "(projection,longitude,latitude)", "", "", request_navit_set_position},
1032 {".navit", "set_destination", "ss", "coordinates,comment", "", "", request_navit_set_destination},
1033 {".navit", "set_destination", "(is)s", "(projection,coordinates)comment", "", "", request_navit_set_destination},
1034 {".navit", "set_destination", "(iii)s", "(projection,longitude,latitude)comment", "", "", request_navit_set_destination},
1035 {".navit", "evaluate", "s", "command", "s", "", request_navit_evaluate},
1036 {".map", "get_attr", "s", "attribute", "sv", "attrname,value", request_map_get_attr},
1037 {".map", "set_attr", "sv", "attribute,value", "", "", request_map_set_attr},
1038 {".mapset", "attr_iter", "", "", "o", "attr_iter", request_mapset_attr_iter},
1039 {".mapset", "attr_iter_destroy", "o", "attr_iter", "", "", request_mapset_attr_iter_destroy},
1040 {".mapset", "get_attr", "s", "attribute", "sv", "attrname,value", request_mapset_get_attr},
1041 {".mapset", "get_attr_wi", "so", "attribute,attr_iter", "sv", "attrname,value", request_mapset_get_attr},
1042 {".vehicle","set_attr", "sv", "attribute,value", "", "", request_vehicle_set_attr},
1046 introspect_path(const char *object)
1050 char *def=".default_";
1051 int def_len=strlen(def);
1052 if (strncmp(object, object_path, strlen(object_path)))
1054 ret=g_strdup(object+strlen(object_path));
1055 dbg(0,"path=%s\n",ret);
1056 for (i = strlen(ret)-1 ; i >= 0 ; i--) {
1057 if (ret[i] == '/' || (ret[i] >= '0' && ret[i] <= '9'))
1062 for (i = 0 ; i < strlen(ret); i++)
1066 for (i = strlen(ret)-1 ; i >= 0 ; i--) {
1067 if (!strncmp(ret+i, def, def_len)) {
1068 memmove(ret+1,ret+i+def_len,strlen(ret+i+def_len)+1);
1076 generate_navitintrospectxml(const char *object)
1078 int i,methods_size,n=0;
1079 char *navitintrospectxml;
1080 char *path=introspect_path(object);
1083 dbg(0,"path=%s\n",path);
1085 // write header and make navit introspectable
1086 navitintrospectxml = g_strdup_printf("%s%s%s\n", navitintrospectxml_head1, object, navitintrospectxml_head2);
1088 methods_size=sizeof(dbus_methods)/sizeof(struct dbus_method);
1089 for (i = 0 ; i < methods_size ; i++) {
1090 // start new interface if it's the first method or it changed
1091 if (strcmp(dbus_methods[i].path, path))
1093 if ((n == 0) || strcmp(dbus_methods[i-1].path, dbus_methods[i].path))
1094 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <interface name=\"%s%s\">\n", service_name, dbus_methods[i].path);
1097 // start the new method
1098 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <method name=\"%s\">\n", dbus_methods[i].method);
1100 // set input signature if existent
1101 if (strcmp(dbus_methods[i].signature, ""))
1102 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <arg direction=\"in\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].signature_name, dbus_methods[i].signature);
1104 // set response signature if existent
1105 if (strcmp(dbus_methods[i].response, ""))
1106 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <arg direction=\"out\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].response_name, dbus_methods[i].response);
1109 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " </method>\n");
1111 // close the interface if we reached the last method or the interface changes
1112 if ((methods_size == i+1) || ((methods_size > i+1) && strcmp(dbus_methods[i+1].path, dbus_methods[i].path)))
1113 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " </interface>\n\n");
1115 // close the "mother tag"
1116 navitintrospectxml = g_strconcat_printf(navitintrospectxml, "</node>\n");
1118 return navitintrospectxml;
1121 static DBusHandlerResult
1122 navit_handler_func(DBusConnection *connection, DBusMessage *message, void *user_data)
1126 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));
1127 if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1129 char *navitintrospectxml = generate_navitintrospectxml(dbus_message_get_path(message));
1130 dbg(0,"Introspect %s:Result:%s\n",dbus_message_get_path(message), navitintrospectxml);
1131 if (navitintrospectxml) {
1132 reply = dbus_message_new_method_return(message);
1133 dbus_message_append_args(reply, DBUS_TYPE_STRING, &navitintrospectxml, DBUS_TYPE_INVALID);
1134 dbus_connection_send (connection, reply, NULL);
1135 dbus_message_unref (reply);
1136 g_free(navitintrospectxml);
1137 return DBUS_HANDLER_RESULT_HANDLED;
1139 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1142 for (i = 0 ; i < sizeof(dbus_methods)/sizeof(struct dbus_method) ; i++) {
1143 path=g_strdup_printf("%s%s", service_name, dbus_methods[i].path);
1144 if (dbus_message_is_method_call(message, path, dbus_methods[i].method) &&
1145 dbus_message_has_signature(message, dbus_methods[i].signature)) {
1147 return dbus_methods[i].func(connection, message);
1151 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1154 static DBusObjectPathVTable dbus_navit_vtable = {
1162 filter(DBusConnection *connection, DBusMessage *message, void *user_data)
1164 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));
1165 if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
1167 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1172 dbus_cmd_send_signal(struct navit *navit, char *command, struct attr **in, struct attr ***out)
1175 char *opath=object_new("navit",navit);
1176 char *interface=g_strdup_printf("%s%s", service_name, ".navit");
1177 dbg(0,"enter %s %s %s\n",opath,command,interface);
1178 msg = dbus_message_new_signal(opath, interface, "signal");
1181 encode_attr(msg, in[0]);
1183 dbus_connection_send(connection, msg, &dbus_serial);
1184 dbus_connection_flush(connection);
1185 dbus_message_unref(msg);
1192 static struct command_table commands[] = {
1193 {"dbus_send_signal",command_cast(dbus_cmd_send_signal)},
1198 dbus_main_navit(struct navit *navit, int added)
1202 command_add_table_attr(commands, sizeof(commands)/sizeof(struct command_table), navit, &attr);
1203 navit_add_attr(navit, &attr);
1207 void plugin_init(void)
1211 struct attr callback;
1212 object_hash=g_hash_table_new(g_str_hash, g_str_equal);
1213 object_hash_rev=g_hash_table_new(NULL, NULL);
1214 object_count=g_hash_table_new(g_str_hash, g_str_equal);
1216 dbus_error_init(&error);
1217 connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
1219 dbg(0,"Failed to open connection to session message bus: %s\n", error.message);
1220 dbus_error_free(&error);
1223 dbus_connection_setup_with_g_main(connection, NULL);
1225 dbus_connection_add_filter(connection, filter, NULL, NULL);
1226 dbus_bus_add_match(connection, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
1228 dbus_connection_register_fallback(connection, object_path, &dbus_navit_vtable, NULL);
1229 dbus_bus_request_name(connection, service_name, 0, &error);
1230 if (dbus_error_is_set(&error)) {
1231 dbg(0,"Failed to request name: %s", error.message);
1232 dbus_error_free (&error);
1234 callback.type=attr_callback;
1235 callback.u.callback=callback_new_0(callback_cast(dbus_main_navit));
1236 config_add_attr(config, &callback);