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>
40 static DBusConnection *connection;
42 static char *service_name = "org.navit_project.navit";
43 static char *object_path = "/org/navit_project/navit";
44 char *navitintrospectxml_head1 = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
45 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
48 char *navitintrospectxml_head2 = "\">\n"
49 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
50 " <method name=\"Introspect\">\n"
51 " <arg direction=\"out\" type=\"s\" />\n"
57 GHashTable *object_hash;
58 GHashTable *object_count;
61 object_new(char *type, void *object)
65 dbg(0,"enter %s\n", type);
66 id=GPOINTER_TO_INT(g_hash_table_lookup(object_count, type));
67 g_hash_table_insert(object_count, type, GINT_TO_POINTER((id+1)));
68 ret=g_strdup_printf("%s/%s/%d", object_path, type, id);
69 g_hash_table_insert(object_hash, ret, object);
70 dbg(0,"return %s\n", ret);
75 object_get(const char *path)
77 return g_hash_table_lookup(object_hash, path);
81 resolve_object(const char *opath, char *type)
85 char *def_navit="/default_navit";
86 char *def_graphics="/default_graphics";
89 if (strncmp(opath, object_path, strlen(object_path))) {
90 dbg(0,"wrong object path %s\n",opath);
93 prefix=g_strdup_printf("%s/%s/", object_path, type);
94 if (!strncmp(prefix, opath, strlen(prefix))) {
95 ret=object_get(opath);
100 prefix=opath+strlen(object_path);
101 if (!strncmp(prefix,def_navit,strlen(def_navit))) {
102 prefix+=strlen(def_navit);
103 struct navit *navit=main_get_navit(NULL);
105 dbg(0,"default_navit\n");
108 if (!strncmp(prefix,def_graphics,strlen(def_graphics))) {
109 if (navit_get_attr(navit, attr_graphics, &attr, NULL)) {
110 return attr.u.graphics;
119 object_get_from_message_arg(DBusMessage *message, char *type)
124 dbus_error_init(&error);
125 if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID)) {
126 dbus_error_free(&error);
127 dbg(0,"wrong arg type\n");
130 return resolve_object(opath, type);
134 object_get_from_message(DBusMessage *message, char *type)
136 return resolve_object(dbus_message_get_path(message), type);
139 static DBusHandlerResult
140 reply_simple_as_variant(DBusConnection *connection, DBusMessage *message, int value, int dbus_type)
144 reply = dbus_message_new_method_return(message);
145 dbus_message_append_args(reply,
148 dbus_connection_send (connection, reply, NULL);
149 dbus_message_unref (reply);
151 return DBUS_HANDLER_RESULT_HANDLED;
154 static DBusHandlerResult
155 empty_reply(DBusConnection *connection, DBusMessage *message)
159 reply = dbus_message_new_method_return(message);
160 dbus_connection_send (connection, reply, NULL);
161 dbus_message_unref (reply);
163 return DBUS_HANDLER_RESULT_HANDLED;
166 static DBusHandlerResult
167 request_main_get_navit(DBusConnection *connection, DBusMessage *message)
175 dbus_error_init(&error);
177 if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID)) {
178 dbg(0,"Error parsing\n");
179 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
181 dbg(0,"opath=%s\n", opath);
182 iter=object_get(opath);
183 navit=main_get_navit(iter);
185 reply = dbus_message_new_method_return(message);
186 opath=object_new("navit",navit);
187 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
188 dbus_connection_send (connection, reply, NULL);
189 dbus_message_unref (reply);
190 return DBUS_HANDLER_RESULT_HANDLED;
192 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
195 static DBusHandlerResult
196 request_main_iter(DBusConnection *connection, DBusMessage *message)
199 struct iter *iter=main_iter_new();
200 dbg(0,"iter=%p\n", iter);
201 char *opath=object_new("main_iter",iter);
202 reply = dbus_message_new_method_return(message);
203 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
204 dbus_connection_send (connection, reply, NULL);
205 dbus_message_unref (reply);
207 return DBUS_HANDLER_RESULT_HANDLED;
210 static DBusHandlerResult
211 request_main_iter_destroy(DBusConnection *connection, DBusMessage *message)
215 iter=object_get_from_message_arg(message, "main_iter");
217 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
218 main_iter_destroy(iter);
220 return empty_reply(connection, message);
224 * Extracts a struct pcoord from a DBus message
226 * @param message The DBus message
227 * @param iter Sort of pointer that points on that (iii)-object in the message
228 * @param pc Pointer where the data should get stored
229 * @returns Returns 1 when everything went right, otherwise 0
232 pcoord_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct pcoord *pc)
235 if(!strcmp(dbus_message_iter_get_signature(iter), "s")) {
238 dbus_message_iter_get_basic(iter, &coordstring);
239 if(!pcoord_parse(coordstring, projection_mg, pc))
245 DBusMessageIter iter2;
246 dbus_message_iter_recurse(iter, &iter2);
247 if(!strcmp(dbus_message_iter_get_signature(iter), "(is)")) {
251 dbus_message_iter_get_basic(&iter2, &projection);
253 dbus_message_iter_next(&iter2);
254 dbus_message_iter_get_basic(&iter2, &coordstring);
256 if(!pcoord_parse(coordstring, projection, pc))
260 } else if(!strcmp(dbus_message_iter_get_signature(iter), "(iii)")) {
262 dbus_message_iter_get_basic(&iter2, &pc->pro);
264 dbus_message_iter_next(&iter2);
265 dbus_message_iter_get_basic(&iter2, &pc->x);
267 dbus_message_iter_next(&iter2);
268 dbus_message_iter_get_basic(&iter2, &pc->y);
277 static DBusHandlerResult
278 request_navit_draw(DBusConnection *connection, DBusMessage *message)
282 navit=object_get_from_message(message, "navit");
284 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
288 return empty_reply(connection, message);
293 * Extracts a struct point from a DBus message
295 * @param message The DBus message
296 * @param iter Sort of pointer that points on that (ii)-object in the message
297 * @param p Pointer where the data should get stored
298 * @returns Returns 1 when everything went right, otherwise 0
301 point_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct point *p)
303 DBusMessageIter iter2;
305 dbg(0,"%s\n", dbus_message_iter_get_signature(iter));
307 dbus_message_iter_recurse(iter, &iter2);
309 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
311 dbus_message_iter_get_basic(&iter2, &p->x);
313 dbus_message_iter_next(&iter2);
315 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
317 dbus_message_iter_get_basic(&iter2, &p->y);
319 dbg(0, " x -> %x y -> %x\n", p->x, p->y);
321 dbus_message_iter_next(&iter2);
323 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INVALID)
330 * @brief Shows up a message
331 * @param connection The DBusConnection object through which \a message arrived
332 * @param message The DBusMessage containing the coordinates
333 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
336 static DBusHandlerResult
337 request_navit_add_message(DBusConnection *connection, DBusMessage *message)
342 DBusMessageIter iter;
344 navit=object_get_from_message(message, "navit");
346 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
348 dbus_message_iter_init(message, &iter);
349 dbus_message_iter_get_basic(&iter, &usermessage);
351 navit_add_message(navit, usermessage);
353 return empty_reply(connection, message);
358 * @brief Centers the screen on a specified position \a pc on the world
359 * @param connection The DBusConnection object through which \a message arrived
360 * @param message The DBusMessage containing the coordinates
361 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
364 static DBusHandlerResult
365 request_navit_set_center(DBusConnection *connection, DBusMessage *message)
369 DBusMessageIter iter;
371 navit=object_get_from_message(message, "navit");
373 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
375 dbus_message_iter_init(message, &iter);
377 if (!pcoord_get_from_message(message, &iter, &pc))
378 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
380 navit_set_center(navit, &pc, 0);
381 return empty_reply(connection, message);
385 * @brief Centers the screen on a specified position \a p shown on the screen
386 * @param connection The DBusConnection object through which \a message arrived
387 * @param message The DBusMessage containing the x and y value
388 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
390 static DBusHandlerResult
391 request_navit_set_center_screen(DBusConnection *connection, DBusMessage *message)
395 DBusMessageIter iter;
397 navit=object_get_from_message(message, "navit");
399 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
401 dbus_message_iter_init(message, &iter);
403 if (!point_get_from_message(message, &iter, &p))
404 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
405 navit_set_center_screen(navit, &p, 0);
406 return empty_reply(connection, message);
410 * @brief Sets the layout to \a new_layout_name extracted from \a message
411 * @param connection The DBusConnection object through which \a message arrived
412 * @param message The DBusMessage containing the name of the layout
413 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
415 static DBusHandlerResult
416 request_navit_set_layout(DBusConnection *connection, DBusMessage *message)
418 char *new_layout_name;
421 struct attr_iter *iter;
423 navit=object_get_from_message(message, "navit");
425 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
427 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &new_layout_name, DBUS_TYPE_INVALID))
428 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
430 iter=navit_attr_iter_new();
431 while(navit_get_attr(navit, attr_layout, &attr, iter)) {
432 if (strcmp(attr.u.layout->name, new_layout_name) == 0) {
433 navit_set_attr(navit, &attr);
436 return empty_reply(connection, message);
439 static DBusHandlerResult
440 request_navit_zoom(DBusConnection *connection, DBusMessage *message)
445 DBusMessageIter iter;
447 navit = object_get_from_message(message, "navit");
449 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
451 dbus_message_iter_init(message, &iter);
452 dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
454 dbus_message_iter_get_basic(&iter, &factor);
456 if (dbus_message_iter_has_next(&iter))
458 dbus_message_iter_next(&iter);
459 if (!point_get_from_message(message, &iter, &p))
460 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
464 navit_zoom_in(navit, factor, &p);
465 else if (factor < -1)
466 navit_zoom_out(navit, 0-factor, &p);
468 return empty_reply(connection, message);
472 static DBusHandlerResult
473 request_navit_resize(DBusConnection *connection, DBusMessage *message)
477 DBusMessageIter iter;
479 navit = object_get_from_message(message, "navit");
481 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
483 dbus_message_iter_init(message, &iter);
484 dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
486 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
487 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
488 dbus_message_iter_get_basic(&iter, &w);
490 dbus_message_iter_next(&iter);
492 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
493 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
494 dbus_message_iter_get_basic(&iter, &h);
496 dbg(0, " w -> %i h -> %i\n", w, h);
498 navit_handle_resize(navit, w, h);
500 return empty_reply(connection, message);
504 static DBusHandlerResult
505 request_navit_get_attr(DBusConnection *connection, DBusMessage *message)
508 DBusMessageIter iter;
509 char * attr_type = NULL;
511 navit = object_get_from_message(message, "navit");
513 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
515 dbus_message_iter_init(message, &iter);
516 dbus_message_iter_get_basic(&iter, &attr_type);
517 attr.type = attr_from_name(attr_type);
518 dbg(0, "attr value: 0x%x string: %s\n", attr.type, attr_type);
520 if (attr.type == attr_none)
521 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
523 if (attr.type > attr_type_item_begin && attr.type < attr_type_item_end)
524 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
526 else if (attr.type > attr_type_int_begin && attr.type < attr_type_boolean_begin)
528 dbg(0, "int detected\n");
529 if(navit_get_attr(navit, attr.type, &attr, NULL)) {
530 dbg(0, "%s = %i\n", attr_type, attr.u.num);
531 return reply_simple_as_variant(connection, message, attr.u.num, DBUS_TYPE_INT32);
535 else if(attr.type > attr_type_boolean_begin && attr.type < attr_type_int_end)
537 dbg(0, "bool detected\n");
538 if(navit_get_attr(navit, attr.type, &attr, NULL)) {
539 dbg(0, "%s = %i\n", attr_type, attr.u.num);
540 return reply_simple_as_variant(connection, message, attr.u.num, DBUS_TYPE_BOOLEAN);
544 else if(attr.type > attr_type_string_begin && attr.type < attr_type_string_end)
546 dbg(0, "string detected\n");
547 if(navit_get_attr(navit, attr.type, &attr, NULL)) {
548 dbg(0, "%s = %s\n", attr_type, &attr.u.layout);
549 return reply_simple_as_variant(connection, message, GPOINTER_TO_INT(&attr.u.layout), DBUS_TYPE_STRING);
554 else if(attr.type > attr_type_special_begin && attr.type < attr_type_special_end)
555 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
557 else if(attr.type > attr_type_double_begin && attr.type < attr_type_double_end)
558 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
560 else if(attr.type > attr_type_coord_geo_begin && attr.type < attr_type_coord_geo_end)
561 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
563 else if(attr.type > attr_type_color_begin && attr.type < attr_type_color_end)
564 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
566 else if(attr.type > attr_type_object_begin && attr.type < attr_type_object_end)
567 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
569 else if(attr.type > attr_type_coord_begin && attr.type < attr_type_coord_end)
570 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
572 else if(attr.type > attr_type_pcoord_begin && attr.type < attr_type_pcoord_end)
573 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
575 else if(attr.type > attr_type_callback_begin && attr.type < attr_type_callback_end)
576 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
579 dbg(0, "zomg really unhandled111\n");
580 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
583 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
587 static DBusHandlerResult
588 request_navit_set_attr(DBusConnection *connection, DBusMessage *message)
591 DBusMessageIter iter, iterattr;
595 navit = object_get_from_message(message, "navit");
597 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
599 dbus_message_iter_init(message, &iter);
600 dbus_message_iter_get_basic(&iter, &attr_type);
601 attr.type = attr_from_name(attr_type);
602 dbg(0, "attr value: 0x%x string: %s\n", attr.type, attr_type);
604 if (attr.type == attr_none)
605 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
607 dbus_message_iter_next(&iter);
608 dbus_message_iter_recurse(&iter, &iterattr);
609 dbg(0, "seems valid. signature: %s\n", dbus_message_iter_get_signature(&iterattr));
611 if (attr.type > attr_type_item_begin && attr.type < attr_type_item_end)
612 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
614 else if (attr.type > attr_type_int_begin && attr.type < attr_type_boolean_begin) {
615 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_INT32)
617 dbus_message_iter_get_basic(&iterattr, &attr.u.num);
618 if (navit_set_attr(navit, &attr))
619 return empty_reply(connection, message);
622 else if(attr.type > attr_type_boolean_begin && attr.type < attr_type_int_end) {
623 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_BOOLEAN)
625 dbus_message_iter_get_basic(&iterattr, &attr.u.num);
626 if (navit_set_attr(navit, &attr))
627 return empty_reply(connection, message);
631 else if(attr.type > attr_type_string_begin && attr.type < attr_type_string_end)
632 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
634 else if(attr.type > attr_type_special_begin && attr.type < attr_type_special_end)
635 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
637 else if(attr.type > attr_type_double_begin && attr.type < attr_type_double_end)
638 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
640 else if(attr.type > attr_type_coord_geo_begin && attr.type < attr_type_coord_geo_end)
641 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
643 else if(attr.type > attr_type_color_begin && attr.type < attr_type_color_end)
644 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
646 else if(attr.type > attr_type_object_begin && attr.type < attr_type_object_end)
647 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
649 else if(attr.type > attr_type_coord_begin && attr.type < attr_type_coord_end)
650 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
652 else if(attr.type > attr_type_pcoord_begin && attr.type < attr_type_pcoord_end)
653 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
655 else if(attr.type > attr_type_callback_begin && attr.type < attr_type_callback_end)
656 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
659 dbg(0, "zomg really unhandled111\n");
660 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
663 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
666 static DBusHandlerResult
667 request_navit_set_position(DBusConnection *connection, DBusMessage *message)
671 DBusMessageIter iter;
673 navit = object_get_from_message(message, "navit");
675 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
677 dbus_message_iter_init(message, &iter);
678 if (!pcoord_get_from_message(message, &iter, &pc))
679 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
681 navit_set_position(navit, &pc);
682 return empty_reply(connection, message);
685 static DBusHandlerResult
686 request_navit_set_destination(DBusConnection *connection, DBusMessage *message)
690 DBusMessageIter iter;
693 navit = object_get_from_message(message, "navit");
695 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
697 dbus_message_iter_init(message, &iter);
698 if (!pcoord_get_from_message(message, &iter, &pc))
699 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
701 dbus_message_iter_next(&iter);
702 dbus_message_iter_get_basic(&iter, &description);
703 dbg(0, " destination -> %s\n", description);
705 navit_set_destination(navit, &pc, description, 1);
706 return empty_reply(connection, message);
709 static DBusHandlerResult
710 request_navit_evaluate(DBusConnection *connection, DBusMessage *message)
719 navit = object_get_from_message(message, "navit");
721 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
723 attr.type=attr_navit;
725 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &command, DBUS_TYPE_INVALID))
726 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
727 result=command_evaluate_to_string(&attr, command, &error);
728 reply = dbus_message_new_method_return(message);
730 dbus_message_append_args(reply, DBUS_TYPE_INT32, error, DBUS_TYPE_INVALID);
732 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
733 dbus_connection_send (connection, reply, NULL);
734 dbus_message_unref (reply);
735 return DBUS_HANDLER_RESULT_HANDLED;
738 static DBusHandlerResult
739 request_graphics_get_data(DBusConnection *connection, DBusMessage *message)
741 struct graphics *graphics;
743 struct graphics_data_image *image;
746 graphics = object_get_from_message(message, "graphics");
748 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
750 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &data, DBUS_TYPE_INVALID))
751 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
752 image=graphics_get_data(graphics, data);
754 DBusMessageIter iter1,iter2;
755 reply = dbus_message_new_method_return(message);
757 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
759 dbus_message_iter_init_append(reply, &iter1);
760 dbus_message_iter_open_container(&iter1, DBUS_TYPE_ARRAY, "y", &iter2);
761 if (image->data && image->size)
762 dbus_message_iter_append_fixed_array(&iter2, DBUS_TYPE_BYTE, &image->data, image->size);
763 dbus_message_iter_close_container(&iter1, &iter2);
764 dbus_connection_send (connection, reply, NULL);
765 dbus_message_unref (reply);
766 return DBUS_HANDLER_RESULT_HANDLED;
768 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
775 char *signature_name;
778 DBusHandlerResult(*func)(DBusConnection *connection, DBusMessage *message);
780 {"", "iter", "", "", "o", "navit", request_main_iter},
781 {"", "iter_destroy", "o", "navit", "", "", request_main_iter_destroy},
782 {"", "get_navit", "o", "navit", "o", "", request_main_get_navit},
783 {".navit", "draw", "", "", "", "", request_navit_draw},
784 {".navit", "add_message", "s", "message", "", "", request_navit_add_message},
785 {".navit", "set_center", "s", "(coordinates)", "", "", request_navit_set_center},
786 {".navit", "set_center", "(is)", "(projection,coordinates)", "", "", request_navit_set_center},
787 {".navit", "set_center", "(iii)", "(projection,longitude,latitude)", "", "", request_navit_set_center},
788 {".navit", "set_center_screen", "(ii)", "(pixel_x,pixel_y)", "", "", request_navit_set_center_screen},
789 {".navit", "set_layout", "s", "layoutname", "", "", request_navit_set_layout},
790 {".navit", "zoom", "i(ii)", "factor(pixel_x,pixel_y)", "", "", request_navit_zoom},
791 {".navit", "zoom", "i", "factor", "", "", request_navit_zoom},
792 {".navit", "resize", "ii", "upperleft,lowerright", "", "", request_navit_resize},
793 {".navit", "get_attr", "s", "attribute", "v", "value", request_navit_get_attr},
794 {".navit", "set_attr", "sv", "attribute,value", "", "", request_navit_set_attr},
795 {".navit", "set_position", "s", "(coordinates)", "", "", request_navit_set_position},
796 {".navit", "set_position", "(is)", "(projection,coordinated)", "", "", request_navit_set_position},
797 {".navit", "set_position", "(iii)", "(projection,longitude,latitude)", "", "", request_navit_set_position},
798 {".navit", "set_destination", "ss", "coordinates,comment", "", "", request_navit_set_destination},
799 {".navit", "set_destination", "(is)s", "(projection,coordinates)comment", "", "", request_navit_set_destination},
800 {".navit", "set_destination", "(iii)s", "(projection,longitude,latitude)comment", "", "", request_navit_set_destination},
801 {".navit", "evaluate", "s", "command", "s", "", request_navit_evaluate},
802 {".graphics","get_data", "s", "type", "ay", "data", request_graphics_get_data},
804 {".navit", "toggle_announcer", "", "", "", "", request_navit_toggle_announcer},
805 {".navit", "toggle_announcer", "i", "", "", "", request_navit_toggle_announcer},
810 introspect_path(char *object)
814 char *def=".default_";
815 int def_len=strlen(def);
816 if (strncmp(object, object_path, strlen(object_path)))
818 ret=g_strdup(object+strlen(object_path));
819 dbg(0,"path=%s\n",ret);
820 for (i = strlen(ret)-1 ; i >= 0 ; i--) {
821 if (ret[i] == '/' || (ret[i] >= '0' && ret[i] <= '9'))
826 for (i = 0 ; i < strlen(ret); i++)
830 for (i = strlen(ret)-1 ; i >= 0 ; i--) {
831 if (!strncmp(ret+i, def, def_len)) {
832 memmove(ret+1,ret+i+def_len,strlen(ret+i+def_len)+1);
840 generate_navitintrospectxml(char *object)
842 int i,methods_size,n=0;
843 char *navitintrospectxml;
844 char *path=introspect_path(object);
847 dbg(0,"path=%s\n",path);
849 // write header and make navit introspectable
850 navitintrospectxml = g_strdup_printf("%s%s%s\n", navitintrospectxml_head1, object, navitintrospectxml_head2);
852 methods_size=sizeof(dbus_methods)/sizeof(struct dbus_method);
853 for (i = 0 ; i < methods_size ; i++) {
854 // start new interface if it's the first method or it changed
855 if (strcmp(dbus_methods[i].path, path))
857 if ((n == 0) || strcmp(dbus_methods[i-1].path, dbus_methods[i].path))
858 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <interface name=\"%s%s\">\n", service_name, dbus_methods[i].path);
861 // start the new method
862 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <method name=\"%s\">\n", dbus_methods[i].method);
864 // set input signature if existent
865 if (strcmp(dbus_methods[i].signature, ""))
866 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <arg direction=\"in\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].signature_name, dbus_methods[i].signature);
868 // set response signature if existent
869 if (strcmp(dbus_methods[i].response, ""))
870 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <arg direction=\"out\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].response_name, dbus_methods[i].response);
873 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " </method>\n");
875 // close the interface if we reached the last method or the interface changes
876 if ((methods_size == i+1) || ((methods_size > i+1) && strcmp(dbus_methods[i+1].path, dbus_methods[i].path)))
877 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " </interface>\n\n");
879 // close the "mother tag"
880 navitintrospectxml = g_strconcat_printf(navitintrospectxml, "</node>\n");
882 return navitintrospectxml;
885 static DBusHandlerResult
886 navit_handler_func(DBusConnection *connection, DBusMessage *message, void *user_data)
890 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));
891 if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
893 char *navitintrospectxml = generate_navitintrospectxml(dbus_message_get_path(message));
894 dbg(0,"Introspect %s:Result:%s\n",dbus_message_get_path(message), navitintrospectxml);
895 if (navitintrospectxml) {
896 reply = dbus_message_new_method_return(message);
897 dbus_message_append_args(reply, DBUS_TYPE_STRING, &navitintrospectxml, DBUS_TYPE_INVALID);
898 dbus_connection_send (connection, reply, NULL);
899 dbus_message_unref (reply);
900 g_free(navitintrospectxml);
901 return DBUS_HANDLER_RESULT_HANDLED;
903 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
906 for (i = 0 ; i < sizeof(dbus_methods)/sizeof(struct dbus_method) ; i++) {
907 path=g_strdup_printf("%s%s", service_name, dbus_methods[i].path);
908 if (dbus_message_is_method_call(message, path, dbus_methods[i].method) &&
909 dbus_message_has_signature(message, dbus_methods[i].signature)) {
911 return dbus_methods[i].func(connection, message);
915 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
918 static DBusObjectPathVTable dbus_navit_vtable = {
926 filter(DBusConnection *connection, DBusMessage *message, void *user_data)
928 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));
929 if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
931 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
935 void plugin_init(void)
939 object_hash=g_hash_table_new(g_str_hash, g_str_equal);
940 object_count=g_hash_table_new(g_str_hash, g_str_equal);
942 dbus_error_init(&error);
943 connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
945 dbg(0,"Failed to open connection to session message bus: %s\n", error.message);
946 dbus_error_free(&error);
949 dbus_connection_setup_with_g_main(connection, NULL);
951 dbus_connection_add_filter(connection, filter, NULL, NULL);
952 dbus_bus_add_match(connection, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
954 dbus_connection_register_fallback(connection, object_path, &dbus_navit_vtable, NULL);
955 dbus_bus_request_name(connection, service_name, 0, &error);
956 if (dbus_error_is_set(&error)) {
957 dbg(0,"Failed to request name: %s", error.message);
958 dbus_error_free (&error);