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>
47 static DBusConnection *connection;
48 static dbus_uint32_t dbus_serial;
50 static char *service_name = "org.navit_project.navit";
51 static char *object_path = "/org/navit_project/navit";
52 char *navitintrospectxml_head1 = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
53 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
56 char *navitintrospectxml_head2 = "\">\n"
57 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
58 " <method name=\"Introspect\">\n"
59 " <arg direction=\"out\" type=\"s\" />\n"
65 GHashTable *object_hash;
66 GHashTable *object_hash_rev;
67 GHashTable *object_count;
69 struct dbus_callback {
70 struct callback *callback;
75 object_new(char *type, void *object)
79 dbg(1,"enter %s\n", type);
80 if ((ret=g_hash_table_lookup(object_hash_rev, object)))
82 id=GPOINTER_TO_INT(g_hash_table_lookup(object_count, type));
83 g_hash_table_insert(object_count, type, GINT_TO_POINTER((id+1)));
84 ret=g_strdup_printf("%s/%s/%d", object_path, type, id);
85 g_hash_table_insert(object_hash, ret, object);
86 g_hash_table_insert(object_hash_rev, object, ret);
87 dbg(1,"return %s\n", ret);
92 object_get(const char *path)
94 return g_hash_table_lookup(object_hash, path);
98 object_destroy(const char *path, void *object)
100 if (!path && !object)
103 object=g_hash_table_lookup(object_hash, path);
105 path=g_hash_table_lookup(object_hash_rev, object);
106 g_hash_table_remove(object_hash, path);
107 g_hash_table_remove(object_hash_rev, object);
111 resolve_object(const char *opath, char *type)
116 char *def_navit="/default_navit";
117 char *def_gui="/default_gui";
118 char *def_graphics="/default_graphics";
119 char *def_vehicle="/default_vehicle";
120 char *def_mapset="/default_mapset";
121 char *def_map="/default_map";
124 if (strncmp(opath, object_path, strlen(object_path))) {
125 dbg(0,"wrong object path %s\n",opath);
128 prefix=g_strdup_printf("%s/%s/", object_path, type);
129 if (!strncmp(prefix, opath, strlen(prefix))) {
130 ret=object_get(opath);
135 oprefix=opath+strlen(object_path);
136 if (!strncmp(oprefix,def_navit,strlen(def_navit))) {
137 oprefix+=strlen(def_navit);
139 if (!config_get_attr(config, attr_navit, &navit, NULL))
142 dbg(0,"default_navit\n");
143 return navit.u.navit;
145 if (!strncmp(oprefix,def_graphics,strlen(def_graphics))) {
146 if (navit_get_attr(navit.u.navit, attr_graphics, &attr, NULL)) {
147 return attr.u.graphics;
151 if (!strncmp(oprefix,def_gui,strlen(def_gui))) {
152 if (navit_get_attr(navit.u.navit, attr_gui, &attr, NULL)) {
157 if (!strncmp(oprefix,def_vehicle,strlen(def_vehicle))) {
158 if (navit_get_attr(navit.u.navit, attr_vehicle, &attr, NULL)) {
159 return attr.u.vehicle;
163 if (!strncmp(oprefix,def_mapset,strlen(def_mapset))) {
164 oprefix+=strlen(def_mapset);
165 if (navit_get_attr(navit.u.navit, attr_mapset, &attr, NULL)) {
167 return attr.u.mapset;
169 if (!strncmp(oprefix,def_map,strlen(def_map))) {
170 if (mapset_get_attr(attr.u.mapset, attr_map, &attr, NULL)) {
183 object_get_from_message_arg(DBusMessageIter *iter, char *type)
187 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
189 dbus_message_iter_get_basic(iter, &opath);
190 dbus_message_iter_next(iter);
191 return resolve_object(opath, type);
195 object_get_from_message(DBusMessage *message, char *type)
197 return resolve_object(dbus_message_get_path(message), type);
200 static enum attr_type
201 attr_type_get_from_message(DBusMessageIter *iter)
205 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
207 dbus_message_iter_get_basic(iter, &attr_type);
208 dbus_message_iter_next(iter);
209 return attr_from_name(attr_type);
213 encode_variant_string(DBusMessageIter *iter, char *str)
215 DBusMessageIter variant;
216 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
217 dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &str);
218 dbus_message_iter_close_container(iter, &variant);
222 encode_dict_string_variant_string(DBusMessageIter *iter, char *key, char *value)
224 DBusMessageIter dict;
225 dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
226 dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
227 encode_variant_string(&dict, value);
228 dbus_message_iter_close_container(iter, &dict);
232 encode_attr(DBusMessage *message, struct attr *attr)
234 char *name=attr_to_name(attr->type);
235 DBusMessageIter iter1,iter2;
236 dbus_message_iter_init_append(message, &iter1);
237 dbus_message_iter_append_basic(&iter1, DBUS_TYPE_STRING, &name);
238 if (attr->type >= attr_type_int_begin && attr->type < attr_type_boolean_begin) {
239 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &iter2);
240 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_INT32, &attr->u.num);
241 dbus_message_iter_close_container(&iter1, &iter2);
243 if (attr->type >= attr_type_boolean_begin && attr->type <= attr_type_int_end) {
244 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING, &iter2);
245 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_BOOLEAN, &attr->u.num);
246 dbus_message_iter_close_container(&iter1, &iter2);
248 if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) {
249 encode_variant_string(&iter1, attr->u.str);
251 if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) {
252 char *object=object_new(attr_to_name(attr->type), attr->u.data);
253 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter2);
254 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_OBJECT_PATH, &object);
255 dbus_message_iter_close_container(&iter1, &iter2);
261 static DBusHandlerResult
262 empty_reply(DBusConnection *connection, DBusMessage *message)
266 reply = dbus_message_new_method_return(message);
267 dbus_connection_send (connection, reply, NULL);
268 dbus_message_unref (reply);
270 return DBUS_HANDLER_RESULT_HANDLED;
274 static DBusHandlerResult
275 dbus_error(DBusConnection *connection, DBusMessage *message, char *error, char *msg)
279 reply = dbus_message_new_error(message, error, msg);
280 dbus_connection_send (connection, reply, NULL);
281 dbus_message_unref (reply);
282 return DBUS_HANDLER_RESULT_HANDLED;
285 static DBusHandlerResult
286 dbus_error_invalid_attr_type(DBusConnection *connection, DBusMessage *message)
288 return dbus_error(connection, message, DBUS_ERROR_INVALID_ARGS, "attribute type invalid");
291 static DBusHandlerResult
292 dbus_error_invalid_parameter(DBusConnection *connection, DBusMessage *message)
294 return dbus_error(connection, message, DBUS_ERROR_INVALID_ARGS, "parameter invalid");
297 static DBusHandlerResult
298 dbus_error_invalid_object_path(DBusConnection *connection, DBusMessage *message)
300 return dbus_error(connection, message, DBUS_ERROR_BAD_ADDRESS, "object path invalid");
303 static DBusHandlerResult
304 dbus_error_invalid_object_path_parameter(DBusConnection *connection, DBusMessage *message)
306 return dbus_error(connection, message, DBUS_ERROR_BAD_ADDRESS, "object path parameter invalid");
311 dbus_dump_iter(char *prefix, DBusMessageIter *iter)
315 DBusMessageIter iterr;
316 while ((arg=dbus_message_iter_get_arg_type(iter)) != DBUS_TYPE_INVALID) {
318 case DBUS_TYPE_INT32:
319 dbus_message_iter_get_basic(iter, &vali);
320 dbg(0,"%sDBUS_TYPE_INT32: %d\n",prefix,vali);
322 case DBUS_TYPE_STRING:
323 dbus_message_iter_get_basic(iter, &vals);
324 dbg(0,"%sDBUS_TYPE_STRING: %s\n",prefix,vals);
326 case DBUS_TYPE_STRUCT:
327 dbg(0,"%sDBUS_TYPE_STRUCT:\n",prefix);
328 prefixr=g_strdup_printf("%s ",prefix);
329 dbus_message_iter_recurse(iter, &iterr);
330 dbus_dump_iter(prefixr, &iterr);
333 case DBUS_TYPE_VARIANT:
334 dbg(0,"%sDBUS_TYPE_VARIANT:\n",prefix);
335 prefixr=g_strdup_printf("%s ",prefix);
336 dbus_message_iter_recurse(iter, &iterr);
337 dbus_dump_iter(prefixr, &iterr);
340 case DBUS_TYPE_DICT_ENTRY:
341 dbg(0,"%sDBUS_TYPE_DICT_ENTRY:\n",prefix);
342 prefixr=g_strdup_printf("%s ",prefix);
343 dbus_message_iter_recurse(iter, &iterr);
344 dbus_dump_iter(prefixr, &iterr);
347 case DBUS_TYPE_ARRAY:
348 dbg(0,"%sDBUS_TYPE_ARRAY:\n",prefix);
349 prefixr=g_strdup_printf("%s ",prefix);
350 dbus_message_iter_recurse(iter, &iterr);
351 dbus_dump_iter(prefixr, &iterr);
357 dbus_message_iter_next(iter);
362 dbus_dump(DBusMessage *message)
364 DBusMessageIter iter;
366 dbus_message_iter_init(message, &iter);
367 dbus_dump_iter("",&iter);
373 * Extracts a struct pcoord from a DBus message
375 * @param message The DBus message
376 * @param iter Sort of pointer that points on that (iii)-object in the message
377 * @param pc Pointer where the data should get stored
378 * @returns Returns 1 when everything went right, otherwise 0
381 pcoord_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct pcoord *pc)
384 if(!strcmp(dbus_message_iter_get_signature(iter), "s")) {
387 dbus_message_iter_get_basic(iter, &coordstring);
388 if(!pcoord_parse(coordstring, projection_mg, pc))
394 DBusMessageIter iter2;
395 dbus_message_iter_recurse(iter, &iter2);
396 if(!strcmp(dbus_message_iter_get_signature(iter), "(is)")) {
400 dbus_message_iter_get_basic(&iter2, &projection);
402 dbus_message_iter_next(&iter2);
403 dbus_message_iter_get_basic(&iter2, &coordstring);
405 if(!pcoord_parse(coordstring, projection, pc))
409 } else if(!strcmp(dbus_message_iter_get_signature(iter), "(iii)")) {
411 dbus_message_iter_get_basic(&iter2, &pc->pro);
413 dbus_message_iter_next(&iter2);
414 dbus_message_iter_get_basic(&iter2, &pc->x);
416 dbus_message_iter_next(&iter2);
417 dbus_message_iter_get_basic(&iter2, &pc->y);
427 pcoord_encode(DBusMessageIter *iter, struct pcoord *pc)
429 DBusMessageIter iter2;
430 dbus_message_iter_open_container(iter,DBUS_TYPE_STRUCT,NULL,&iter2);
432 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_INT32, &pc->pro);
433 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_INT32, &pc->x);
434 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_INT32, &pc->y);
437 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_INT32, &n);
438 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_INT32, &n);
439 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_INT32, &n);
441 dbus_message_iter_close_container(iter, &iter2);
444 static enum attr_type
445 decode_attr_type_from_iter(DBusMessageIter *iter)
450 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
452 dbus_message_iter_get_basic(iter, &attr_type);
453 dbus_message_iter_next(iter);
454 ret=attr_from_name(attr_type);
455 dbg(1, "attr value: 0x%x string: %s\n", ret, attr_type);
460 decode_attr_from_iter(DBusMessageIter *iter, struct attr *attr)
462 DBusMessageIter iterattr, iterstruct;
466 attr->type=decode_attr_type_from_iter(iter);
467 if (attr->type == attr_none)
470 dbus_message_iter_recurse(iter, &iterattr);
471 dbus_message_iter_next(iter);
472 dbg(1, "seems valid. signature: %s\n", dbus_message_iter_get_signature(&iterattr));
474 if (attr->type >= attr_type_item_begin && attr->type <= attr_type_item_end)
477 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_boolean_begin) {
478 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_INT32) {
479 dbus_message_iter_get_basic(&iterattr, &attr->u.num);
484 if(attr->type >= attr_type_boolean_begin && attr->type <= attr_type_int_end) {
485 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_BOOLEAN) {
486 dbus_message_iter_get_basic(&iterattr, &attr->u.num);
491 if(attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) {
492 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_STRING) {
493 dbus_message_iter_get_basic(&iterattr, &attr->u.str);
498 if(attr->type >= attr_type_double_begin && attr->type <= attr_type_double_end) {
499 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_DOUBLE) {
500 attr->u.numd=g_new(typeof(*attr->u.numd),1);
501 dbus_message_iter_get_basic(&iterattr, attr->u.numd);
505 if(attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end) {
506 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_STRUCT) {
507 attr->u.coord_geo=g_new(typeof(*attr->u.coord_geo),1);
508 dbus_message_iter_recurse(&iterattr, &iterstruct);
509 if (dbus_message_iter_get_arg_type(&iterstruct) == DBUS_TYPE_DOUBLE) {
510 dbus_message_iter_get_basic(&iterstruct, &d);
511 dbus_message_iter_next(&iterstruct);
512 attr->u.coord_geo->lng=d;
515 if (dbus_message_iter_get_arg_type(&iterstruct) == DBUS_TYPE_DOUBLE) {
516 dbus_message_iter_get_basic(&iterstruct, &d);
517 attr->u.coord_geo->lat=d;
521 g_free(attr->u.coord_geo);
522 attr->u.coord_geo=NULL;
527 if (attr->type == attr_callback) {
528 struct dbus_callback *callback=object_get_from_message_arg(&iterattr, "callback");
530 attr->u.callback=callback->callback;
538 decode_attr(DBusMessage *message, struct attr *attr)
540 DBusMessageIter iter;
542 dbus_message_iter_init(message, &iter);
543 return decode_attr_from_iter(&iter, attr);
547 destroy_attr(struct attr *attr)
549 if(attr->type > attr_type_double_begin && attr->type < attr_type_double_end) {
550 g_free(attr->u.numd);
555 get_iter_name(char *type)
557 return g_strdup_printf("%s_attr_iter",type);
560 static DBusHandlerResult
561 request_attr_iter(DBusConnection *connection, DBusMessage *message, char *type, struct attr_iter *(*func)(void))
566 struct attr_iter *attr_iter;
569 iter_name=get_iter_name(type);
570 opath=object_new(iter_name,attr_iter);
572 reply = dbus_message_new_method_return(message);
573 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
574 dbus_connection_send (connection, reply, NULL);
575 dbus_message_unref (reply);
577 return DBUS_HANDLER_RESULT_HANDLED;
580 static DBusHandlerResult
581 request_attr_iter_destroy(DBusConnection *connection, DBusMessage *message, char *type, void (*func)(struct attr_iter *))
583 struct attr_iter *attr_iter;
584 DBusMessageIter iter;
587 dbus_message_iter_init(message, &iter);
588 iter_name=get_iter_name(type);
589 attr_iter=object_get_from_message_arg(&iter, iter_name);
592 return dbus_error_invalid_object_path_parameter(connection, message);
593 object_destroy(NULL, attr_iter);
596 return empty_reply(connection, message);
599 static DBusHandlerResult
600 request_destroy(DBusConnection *connection, DBusMessage *message, char *type, void *data, void (*func)(void *))
603 data=object_get_from_message(message, type);
605 return dbus_error_invalid_object_path(connection, message);
606 object_destroy(NULL, data);
609 return empty_reply(connection, message);
613 static DBusHandlerResult
614 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))
617 DBusMessageIter iter;
619 enum attr_type attr_type;
620 struct attr_iter *attr_iter;
624 data = object_get_from_message(message, type);
626 return dbus_error_invalid_object_path(connection, message);
628 dbus_message_iter_init(message, &iter);
629 attr_type=attr_type_get_from_message(&iter);
630 if (attr_type == attr_none)
631 return dbus_error_invalid_attr_type(connection, message);
632 iter_name=get_iter_name(type);
633 attr_iter=object_get_from_message_arg(&iter, iter_name);
635 if (func(data, attr_type, &attr, attr_iter)) {
636 reply = dbus_message_new_method_return(message);
637 encode_attr(reply, &attr);
638 dbus_connection_send (connection, reply, NULL);
639 dbus_message_unref (reply);
640 return DBUS_HANDLER_RESULT_HANDLED;
642 return empty_reply(connection, message);
646 static DBusHandlerResult
647 request_command(DBusConnection *connection, DBusMessage *message, char *type, void *data, int (*func)(void *data, enum attr_type type, struct attr *attr, struct attr_iter *iter))
649 DBusMessageIter iter;
654 data = object_get_from_message(message, type);
656 return dbus_error_invalid_object_path(connection, message);
658 dbus_message_iter_init(message, &iter);
659 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
660 return dbus_error_invalid_parameter(connection, message);
661 dbus_message_iter_get_basic(&iter, &command);
662 dbus_message_iter_next(&iter);
663 if (func(data, attr_callback_list, &attr, NULL)) {
665 callback_list_call_attr_4(attr.u.callback_list, attr_command, command, NULL, NULL, &valid);
667 return empty_reply(connection, message);
671 static DBusHandlerResult
672 request_set_add_remove_attr(DBusConnection *connection, DBusMessage *message, char *type, void *data, int (*func)(void *data, struct attr *attr))
678 data = object_get_from_message(message, type);
680 return dbus_error_invalid_object_path(connection, message);
682 if (decode_attr(message, &attr)) {
683 ret=(*func)(data, &attr);
686 return empty_reply(connection, message);
688 return dbus_error_invalid_parameter(connection, message);
695 dbus_callback_emit_signal(struct dbus_callback *dbus_callback)
698 msg = dbus_message_new_signal(object_path, service_name, dbus_callback->signal);
700 dbus_connection_send(connection, msg, &dbus_serial);
701 dbus_connection_flush(connection);
702 dbus_message_unref(msg);
707 request_callback_destroy_do(struct dbus_callback *data)
709 callback_destroy(data->callback);
710 g_free(data->signal);
714 static DBusHandlerResult
715 request_callback_destroy(DBusConnection *connection, DBusMessage *message)
717 return request_destroy(connection, message, "search_list", NULL, (void (*)(void *)) request_callback_destroy_do);
720 static DBusHandlerResult
721 request_callback_new(DBusConnection *connection, DBusMessage *message)
723 DBusMessageIter iter;
725 struct dbus_callback *callback;
729 dbus_message_iter_init(message, &iter);
730 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
731 return dbus_error_invalid_parameter(connection, message);
732 dbus_message_iter_get_basic(&iter, &signal);
733 dbus_message_iter_next(&iter);
734 callback=g_new0(struct dbus_callback, 1);
735 callback->signal=g_strdup(signal);
737 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
738 type=attr_type_get_from_message(&iter);
739 callback->callback=callback_new_attr_1(callback_cast(dbus_callback_emit_signal), type, callback);
741 callback->callback=callback_new_1(callback_cast(dbus_callback_emit_signal), callback);
742 opath=object_new("callback", callback);
743 reply = dbus_message_new_method_return(message);
744 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
745 dbus_connection_send (connection, reply, NULL);
746 dbus_message_unref (reply);
747 return DBUS_HANDLER_RESULT_HANDLED;
751 static DBusHandlerResult
752 request_config_get_attr(DBusConnection *connection, DBusMessage *message)
754 return request_get_attr(connection, message, "config", config, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))config_get_attr);
757 static DBusHandlerResult
758 request_config_attr_iter(DBusConnection *connection, DBusMessage *message)
760 return request_attr_iter(connection, message, "config", (struct attr_iter * (*)(void))config_attr_iter_new);
763 static DBusHandlerResult
764 request_config_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
766 return request_attr_iter_destroy(connection, message, "config", (void (*)(struct attr_iter *))config_attr_iter_destroy);
773 static DBusHandlerResult
774 request_graphics_get_data(DBusConnection *connection, DBusMessage *message)
776 struct graphics *graphics;
778 struct graphics_data_image *image;
781 graphics = object_get_from_message(message, "graphics");
783 return dbus_error_invalid_object_path(connection, message);
785 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &data, DBUS_TYPE_INVALID))
786 return dbus_error_invalid_parameter(connection, message);
787 image=graphics_get_data(graphics, data);
789 DBusMessageIter iter1,iter2;
790 reply = dbus_message_new_method_return(message);
792 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
794 dbus_message_iter_init_append(reply, &iter1);
795 dbus_message_iter_open_container(&iter1, DBUS_TYPE_ARRAY, "y", &iter2);
796 if (image->data && image->size)
797 dbus_message_iter_append_fixed_array(&iter2, DBUS_TYPE_BYTE, &image->data, image->size);
798 dbus_message_iter_close_container(&iter1, &iter2);
799 dbus_connection_send (connection, reply, NULL);
800 dbus_message_unref (reply);
801 return DBUS_HANDLER_RESULT_HANDLED;
803 return empty_reply(connection, message);
808 static DBusHandlerResult
809 request_gui_get_attr(DBusConnection *connection, DBusMessage *message)
811 return request_get_attr(connection, message, "gui", NULL, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))gui_get_attr);
814 static DBusHandlerResult
815 request_gui_command(DBusConnection *connection, DBusMessage *message)
817 return request_command(connection, message, "gui", NULL, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))gui_get_attr);
822 static DBusHandlerResult
823 request_graphics_set_attr(DBusConnection *connection, DBusMessage *message)
825 return request_set_add_remove_attr(connection, message, "graphics", NULL, (int (*)(void *, struct attr *))graphics_set_attr);
830 static DBusHandlerResult
831 request_map_get_attr(DBusConnection *connection, DBusMessage *message)
833 return request_get_attr(connection, message, "map", NULL, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))map_get_attr);
837 static DBusHandlerResult
838 request_map_set_attr(DBusConnection *connection, DBusMessage *message)
840 return request_set_add_remove_attr(connection, message, "map", NULL, (int (*)(void *, struct attr *))map_set_attr);
845 static DBusHandlerResult
846 request_mapset_attr_iter(DBusConnection *connection, DBusMessage *message)
848 return request_attr_iter(connection, message, "mapset", (struct attr_iter * (*)(void))mapset_attr_iter_new);
851 static DBusHandlerResult
852 request_mapset_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
854 return request_attr_iter_destroy(connection, message, "mapset", (void (*)(struct attr_iter *))mapset_attr_iter_destroy);
857 static DBusHandlerResult
858 request_mapset_get_attr(DBusConnection *connection, DBusMessage *message)
860 return request_get_attr(connection, message, "mapset", NULL, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))mapset_get_attr);
865 static DBusHandlerResult
866 request_navit_draw(DBusConnection *connection, DBusMessage *message)
870 navit=object_get_from_message(message, "navit");
872 return dbus_error_invalid_object_path(connection, message);
876 return empty_reply(connection, message);
881 * Extracts a struct point from a DBus message
883 * @param message The DBus message
884 * @param iter Sort of pointer that points on that (ii)-object in the message
885 * @param p Pointer where the data should get stored
886 * @returns Returns 1 when everything went right, otherwise 0
889 point_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct point *p)
891 DBusMessageIter iter2;
893 dbg(0,"%s\n", dbus_message_iter_get_signature(iter));
895 dbus_message_iter_recurse(iter, &iter2);
897 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
899 dbus_message_iter_get_basic(&iter2, &p->x);
901 dbus_message_iter_next(&iter2);
903 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
905 dbus_message_iter_get_basic(&iter2, &p->y);
907 dbg(0, " x -> %x y -> %x\n", p->x, p->y);
909 dbus_message_iter_next(&iter2);
911 if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INVALID)
918 * @brief Shows up a message
919 * @param connection The DBusConnection object through which \a message arrived
920 * @param message The DBusMessage containing the coordinates
921 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
924 static DBusHandlerResult
925 request_navit_add_message(DBusConnection *connection, DBusMessage *message)
930 DBusMessageIter iter;
932 navit=object_get_from_message(message, "navit");
934 return dbus_error_invalid_object_path(connection, message);
936 dbus_message_iter_init(message, &iter);
937 dbus_message_iter_get_basic(&iter, &usermessage);
939 navit_add_message(navit, usermessage);
941 return empty_reply(connection, message);
946 * @brief Centers the screen on a specified position \a pc on the world
947 * @param connection The DBusConnection object through which \a message arrived
948 * @param message The DBusMessage containing the coordinates
949 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
952 static DBusHandlerResult
953 request_navit_set_center(DBusConnection *connection, DBusMessage *message)
957 DBusMessageIter iter;
959 navit=object_get_from_message(message, "navit");
961 return dbus_error_invalid_object_path(connection, message);
963 dbus_message_iter_init(message, &iter);
965 if (!pcoord_get_from_message(message, &iter, &pc))
966 return dbus_error_invalid_parameter(connection, message);
968 navit_set_center(navit, &pc, 0);
969 return empty_reply(connection, message);
973 * @brief Centers the screen on a specified position \a p shown on the screen
974 * @param connection The DBusConnection object through which \a message arrived
975 * @param message The DBusMessage containing the x and y value
976 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
978 static DBusHandlerResult
979 request_navit_set_center_screen(DBusConnection *connection, DBusMessage *message)
983 DBusMessageIter iter;
985 navit=object_get_from_message(message, "navit");
987 return dbus_error_invalid_object_path(connection, message);
989 dbus_message_iter_init(message, &iter);
991 if (!point_get_from_message(message, &iter, &p))
992 return dbus_error_invalid_parameter(connection, message);
993 navit_set_center_screen(navit, &p, 0);
994 return empty_reply(connection, message);
998 * @brief Sets the layout to \a new_layout_name extracted from \a message
999 * @param connection The DBusConnection object through which \a message arrived
1000 * @param message The DBusMessage containing the name of the layout
1001 * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
1003 static DBusHandlerResult
1004 request_navit_set_layout(DBusConnection *connection, DBusMessage *message)
1006 char *new_layout_name;
1007 struct navit *navit;
1009 struct attr_iter *iter;
1011 navit=object_get_from_message(message, "navit");
1013 return dbus_error_invalid_object_path(connection, message);
1015 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &new_layout_name, DBUS_TYPE_INVALID))
1016 return dbus_error_invalid_parameter(connection, message);
1018 iter=navit_attr_iter_new();
1019 while(navit_get_attr(navit, attr_layout, &attr, iter)) {
1020 if (strcmp(attr.u.layout->name, new_layout_name) == 0) {
1021 navit_set_attr(navit, &attr);
1024 return empty_reply(connection, message);
1027 static DBusHandlerResult
1028 request_navit_zoom(DBusConnection *connection, DBusMessage *message)
1031 struct point p, *pp=NULL;
1032 struct navit *navit;
1033 DBusMessageIter iter;
1035 navit = object_get_from_message(message, "navit");
1037 return dbus_error_invalid_object_path(connection, message);
1039 dbus_message_iter_init(message, &iter);
1040 dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
1042 dbus_message_iter_get_basic(&iter, &factor);
1044 if (dbus_message_iter_has_next(&iter))
1046 dbus_message_iter_next(&iter);
1047 if (!point_get_from_message(message, &iter, &p))
1048 return dbus_error_invalid_parameter(connection, message);
1053 navit_zoom_in(navit, factor, pp);
1054 else if (factor < -1)
1055 navit_zoom_out(navit, 0-factor, pp);
1057 return empty_reply(connection, message);
1061 static DBusHandlerResult
1062 request_navit_resize(DBusConnection *connection, DBusMessage *message)
1064 struct navit *navit;
1066 DBusMessageIter iter;
1068 navit = object_get_from_message(message, "navit");
1070 return dbus_error_invalid_object_path(connection, message);
1072 dbus_message_iter_init(message, &iter);
1073 dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
1075 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
1076 return dbus_error_invalid_parameter(connection, message);
1077 dbus_message_iter_get_basic(&iter, &w);
1079 dbus_message_iter_next(&iter);
1081 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
1082 return dbus_error_invalid_parameter(connection, message);
1083 dbus_message_iter_get_basic(&iter, &h);
1085 dbg(0, " w -> %i h -> %i\n", w, h);
1087 navit_handle_resize(navit, w, h);
1089 return empty_reply(connection, message);
1093 static DBusHandlerResult
1094 request_navit_get_attr(DBusConnection *connection, DBusMessage *message)
1097 DBusMessageIter iter;
1099 enum attr_type attr_type;
1100 struct attr_iter *attr_iter;
1101 struct navit *navit;
1103 navit = object_get_from_message(message, "navit");
1105 return dbus_error_invalid_object_path(connection, message);
1107 dbus_message_iter_init(message, &iter);
1108 attr_type=attr_type_get_from_message(&iter);
1109 if (attr_type == attr_none)
1110 return dbus_error_invalid_attr_type(connection, message);
1111 attr_iter=object_get_from_message_arg(&iter, "navit_attr_iter");
1112 if (navit_get_attr(navit, attr_type, &attr, attr_iter)) {
1113 reply = dbus_message_new_method_return(message);
1114 encode_attr(reply, &attr);
1115 dbus_connection_send (connection, reply, NULL);
1116 dbus_message_unref (reply);
1117 return DBUS_HANDLER_RESULT_HANDLED;
1119 return empty_reply(connection, message);
1122 static DBusHandlerResult
1123 request_navit_attr_iter(DBusConnection *connection, DBusMessage *message)
1126 struct attr_iter *attr_iter=navit_attr_iter_new();
1127 char *opath=object_new("navit_attr_iter",attr_iter);
1128 reply = dbus_message_new_method_return(message);
1129 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
1130 dbus_connection_send (connection, reply, NULL);
1131 dbus_message_unref (reply);
1133 return DBUS_HANDLER_RESULT_HANDLED;
1136 static DBusHandlerResult
1137 request_navit_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
1139 struct attr_iter *attr_iter;
1140 DBusMessageIter iter;
1142 dbus_message_iter_init(message, &iter);
1143 attr_iter=object_get_from_message_arg(&iter, "navit_attr_iter");
1145 return dbus_error_invalid_object_path_parameter(connection, message);
1146 navit_attr_iter_destroy(attr_iter);
1148 return empty_reply(connection, message);
1152 static DBusHandlerResult
1153 request_navit_set_attr(DBusConnection *connection, DBusMessage *message)
1155 return request_set_add_remove_attr(connection, message, "navit", NULL, (int (*)(void *, struct attr *))navit_set_attr);
1158 static DBusHandlerResult
1159 request_navit_add_attr(DBusConnection *connection, DBusMessage *message)
1161 return request_set_add_remove_attr(connection, message, "navit", NULL, (int (*)(void *, struct attr *))navit_add_attr);
1164 static DBusHandlerResult
1165 request_navit_remove_attr(DBusConnection *connection, DBusMessage *message)
1167 return request_set_add_remove_attr(connection, message, "navit", NULL, (int (*)(void *, struct attr *))navit_remove_attr);
1170 static DBusHandlerResult
1171 request_navit_set_position(DBusConnection *connection, DBusMessage *message)
1174 struct navit *navit;
1175 DBusMessageIter iter;
1177 navit = object_get_from_message(message, "navit");
1179 return dbus_error_invalid_object_path(connection, message);
1181 dbus_message_iter_init(message, &iter);
1182 if (!pcoord_get_from_message(message, &iter, &pc))
1183 return dbus_error_invalid_parameter(connection, message);
1185 navit_set_position(navit, &pc);
1186 return empty_reply(connection, message);
1189 static DBusHandlerResult
1190 request_navit_set_destination(DBusConnection *connection, DBusMessage *message)
1193 struct navit *navit;
1194 DBusMessageIter iter;
1197 navit = object_get_from_message(message, "navit");
1199 return dbus_error_invalid_object_path(connection, message);
1201 dbus_message_iter_init(message, &iter);
1202 if (!pcoord_get_from_message(message, &iter, &pc))
1203 return dbus_error_invalid_parameter(connection, message);
1205 dbus_message_iter_next(&iter);
1206 dbus_message_iter_get_basic(&iter, &description);
1207 dbg(0, " destination -> %s\n", description);
1209 navit_set_destination(navit, &pc, description, 1);
1210 return empty_reply(connection, message);
1213 static DBusHandlerResult
1214 request_navit_evaluate(DBusConnection *connection, DBusMessage *message)
1216 struct navit *navit;
1223 navit = object_get_from_message(message, "navit");
1225 return dbus_error_invalid_object_path(connection, message);
1227 attr.type=attr_navit;
1229 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &command, DBUS_TYPE_INVALID))
1230 return dbus_error_invalid_parameter(connection, message);
1231 result=command_evaluate_to_string(&attr, command, &error);
1232 reply = dbus_message_new_method_return(message);
1234 dbus_message_append_args(reply, DBUS_TYPE_INT32, &error, DBUS_TYPE_INVALID);
1236 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
1237 dbus_connection_send (connection, reply, NULL);
1238 dbus_message_unref (reply);
1239 return DBUS_HANDLER_RESULT_HANDLED;
1244 static DBusHandlerResult
1245 request_search_list_destroy(DBusConnection *connection, DBusMessage *message)
1247 return request_destroy(connection, message, "search_list", NULL, (void (*)(void *)) search_list_destroy);
1250 static DBusHandlerResult
1251 request_search_list_get_result(DBusConnection *connection, DBusMessage *message)
1253 struct search_list *search_list;
1254 struct search_list_result *result;
1256 DBusMessageIter iter,iter2,iter3,iter4;
1257 char *country="country";
1259 char *street="street";
1261 search_list = object_get_from_message(message, "search_list");
1263 return dbus_error_invalid_object_path(connection, message);
1264 result=search_list_get_result(search_list);
1266 return empty_reply(connection, message);
1267 reply = dbus_message_new_method_return(message);
1268 dbus_message_iter_init_append(reply, &iter);
1269 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &result->id);
1270 pcoord_encode(&iter, result->c);
1271 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sa{sv}}", &iter2);
1272 if (result->country && (result->country->car || result->country->iso2 || result->country->iso3 || result->country->name)) {
1273 dbus_message_iter_open_container(&iter2, DBUS_TYPE_DICT_ENTRY, NULL, &iter3);
1274 dbus_message_iter_append_basic(&iter3, DBUS_TYPE_STRING, &country);
1275 dbus_message_iter_open_container(&iter3, DBUS_TYPE_ARRAY, "{sv}", &iter4);
1276 if (result->country->car)
1277 encode_dict_string_variant_string(&iter4, "car", result->country->car);
1278 if (result->country->iso2)
1279 encode_dict_string_variant_string(&iter4, "iso2", result->country->iso2);
1280 if (result->country->iso3)
1281 encode_dict_string_variant_string(&iter4, "iso3", result->country->iso3);
1282 if (result->country->name)
1283 encode_dict_string_variant_string(&iter4, "name", result->country->name);
1284 dbus_message_iter_close_container(&iter3, &iter4);
1285 dbus_message_iter_close_container(&iter2, &iter3);
1287 if (result->town && (result->town->common.district_name || result->town->common.town_name)) {
1288 dbus_message_iter_open_container(&iter2, DBUS_TYPE_DICT_ENTRY, NULL, &iter3);
1289 dbus_message_iter_append_basic(&iter3, DBUS_TYPE_STRING, &town);
1290 dbus_message_iter_open_container(&iter3, DBUS_TYPE_ARRAY, "{sv}", &iter4);
1291 if (result->town->common.district_name)
1292 encode_dict_string_variant_string(&iter4, "district", result->town->common.district_name);
1293 if (result->town->common.town_name)
1294 encode_dict_string_variant_string(&iter4, "name", result->town->common.town_name);
1295 dbus_message_iter_close_container(&iter3, &iter4);
1296 dbus_message_iter_close_container(&iter2, &iter3);
1298 if (result->street && result->street->name) {
1299 dbus_message_iter_open_container(&iter2, DBUS_TYPE_DICT_ENTRY, NULL, &iter3);
1300 dbus_message_iter_append_basic(&iter3, DBUS_TYPE_STRING, &street);
1301 dbus_message_iter_open_container(&iter3, DBUS_TYPE_ARRAY, "{sv}", &iter4);
1302 if (result->street->name)
1303 encode_dict_string_variant_string(&iter4, "name", result->street->name);
1304 dbus_message_iter_close_container(&iter3, &iter4);
1305 dbus_message_iter_close_container(&iter2, &iter3);
1307 dbus_message_iter_close_container(&iter, &iter2);
1308 dbus_connection_send (connection, reply, NULL);
1309 dbus_message_unref (reply);
1310 return DBUS_HANDLER_RESULT_HANDLED;
1313 static DBusHandlerResult
1314 request_search_list_new(DBusConnection *connection, DBusMessage *message)
1316 DBusMessageIter iter;
1318 struct mapset *mapset;
1319 struct search_list *search_list;
1322 dbus_message_iter_init(message, &iter);
1323 mapset=object_get_from_message_arg(&iter, "mapset");
1325 return dbus_error_invalid_object_path_parameter(connection, message);
1326 search_list=search_list_new(mapset);
1327 opath=object_new("search_list", search_list);
1328 reply = dbus_message_new_method_return(message);
1329 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
1330 dbus_connection_send (connection, reply, NULL);
1331 dbus_message_unref (reply);
1332 return DBUS_HANDLER_RESULT_HANDLED;
1335 static DBusHandlerResult
1336 request_search_list_search(DBusConnection *connection, DBusMessage *message)
1338 DBusMessageIter iter;
1339 struct search_list *search_list;
1343 search_list = object_get_from_message(message, "search_list");
1345 return dbus_error_invalid_object_path(connection, message);
1347 dbus_message_iter_init(message, &iter);
1348 if (!decode_attr_from_iter(&iter, &attr))
1349 return dbus_error_invalid_parameter(connection, message);
1350 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
1351 return dbus_error_invalid_parameter(connection, message);
1352 dbus_message_iter_get_basic(&iter, &partial);
1353 search_list_search(search_list, &attr, partial);
1354 return empty_reply(connection, message);
1357 static DBusHandlerResult
1358 request_search_list_select(DBusConnection *connection, DBusMessage *message)
1360 DBusMessageIter iter;
1361 struct search_list *search_list;
1363 enum attr_type attr_type;
1365 search_list = object_get_from_message(message, "search_list");
1367 return dbus_error_invalid_object_path(connection, message);
1369 dbus_message_iter_init(message, &iter);
1370 attr_type=decode_attr_type_from_iter(&iter);
1371 if (attr_type == attr_none)
1372 return dbus_error_invalid_parameter(connection, message);
1373 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
1374 return dbus_error_invalid_parameter(connection, message);
1375 dbus_message_iter_get_basic(&iter, &id);
1376 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
1377 return dbus_error_invalid_parameter(connection, message);
1378 dbus_message_iter_get_basic(&iter, &mode);
1379 search_list_select(search_list, attr_type, id, mode);
1380 return empty_reply(connection, message);
1385 static DBusHandlerResult
1386 request_vehicle_set_attr(DBusConnection *connection, DBusMessage *message)
1388 struct vehicle *vehicle;
1392 vehicle = object_get_from_message(message, "vehicle");
1394 return dbus_error_invalid_object_path(connection, message);
1395 if (decode_attr(message, &attr)) {
1396 ret=vehicle_set_attr(vehicle, &attr);
1397 destroy_attr(&attr);
1399 return empty_reply(connection, message);
1401 return dbus_error_invalid_parameter(connection, message);
1405 struct dbus_method {
1409 char *signature_name;
1411 char *response_name;
1412 DBusHandlerResult(*func)(DBusConnection *connection, DBusMessage *message);
1413 } dbus_methods[] = {
1414 {"", "attr_iter", "", "", "o", "attr_iter", request_config_attr_iter},
1415 {"", "attr_iter_destroy", "o", "attr_iter", "", "", request_config_attr_iter_destroy},
1416 {"", "get_attr", "s", "attrname", "sv", "attrname,value",request_config_get_attr},
1417 {"", "get_attr_wi", "so", "attrname,attr_iter", "sv", "attrname,value",request_config_get_attr},
1418 {"", "callback_new", "s", "signalname", "o", "callback",request_callback_new},
1419 {"", "callback_attr_new", "ss", "signalname,attribute", "o", "callback",request_callback_new},
1420 {"", "search_list_new", "o", "mapset", "o", "search",request_search_list_new},
1421 {".callback","destroy", "", "", "", "", request_callback_destroy},
1422 {".graphics","get_data", "s", "type", "ay", "data", request_graphics_get_data},
1423 {".graphics","set_attr", "sv", "attribute,value", "", "", request_graphics_set_attr},
1424 {".gui", "get_attr", "s", "attribute", "sv", "attrname,value", request_gui_get_attr},
1425 {".gui", "command_parameter", "sa{sa{sv}}","command,parameter", "a{sa{sv}}", "return", request_gui_command},
1426 {".gui", "command", "s", "command", "a{sa{sv}}", "return", request_gui_command},
1427 {".navit", "draw", "", "", "", "", request_navit_draw},
1428 {".navit", "add_message", "s", "message", "", "", request_navit_add_message},
1429 {".navit", "set_center", "s", "(coordinates)", "", "", request_navit_set_center},
1430 {".navit", "set_center", "(is)", "(projection,coordinates)", "", "", request_navit_set_center},
1431 {".navit", "set_center", "(iii)", "(projection,longitude,latitude)", "", "", request_navit_set_center},
1432 {".navit", "set_center_screen", "(ii)", "(pixel_x,pixel_y)", "", "", request_navit_set_center_screen},
1433 {".navit", "set_layout", "s", "layoutname", "", "", request_navit_set_layout},
1434 {".navit", "zoom", "i(ii)", "factor(pixel_x,pixel_y)", "", "", request_navit_zoom},
1435 {".navit", "zoom", "i", "factor", "", "", request_navit_zoom},
1436 {".navit", "resize", "ii", "upperleft,lowerright", "", "", request_navit_resize},
1437 {".navit", "attr_iter", "", "", "o", "attr_iter", request_navit_attr_iter},
1438 {".navit", "attr_iter_destroy", "o", "attr_iter", "", "", request_navit_attr_iter_destroy},
1439 {".navit", "get_attr", "s", "attribute", "sv", "attrname,value", request_navit_get_attr},
1440 {".navit", "get_attr_wi", "so", "attribute,attr_iter", "sv", "attrname,value", request_navit_get_attr},
1441 {".navit", "set_attr", "sv", "attribute,value", "", "", request_navit_set_attr},
1442 {".navit", "add_attr", "sv", "attribute,value", "", "", request_navit_add_attr},
1443 {".navit", "remove_attr", "sv", "attribute,value", "", "", request_navit_remove_attr},
1444 {".navit", "set_position", "s", "(coordinates)", "", "", request_navit_set_position},
1445 {".navit", "set_position", "(is)", "(projection,coordinated)", "", "", request_navit_set_position},
1446 {".navit", "set_position", "(iii)", "(projection,longitude,latitude)", "", "", request_navit_set_position},
1447 {".navit", "set_destination", "ss", "coordinates,comment", "", "", request_navit_set_destination},
1448 {".navit", "set_destination", "(is)s", "(projection,coordinates)comment", "", "", request_navit_set_destination},
1449 {".navit", "set_destination", "(iii)s", "(projection,longitude,latitude)comment", "", "", request_navit_set_destination},
1450 {".navit", "evaluate", "s", "command", "s", "", request_navit_evaluate},
1451 {".map", "get_attr", "s", "attribute", "sv", "attrname,value", request_map_get_attr},
1452 {".map", "set_attr", "sv", "attribute,value", "", "", request_map_set_attr},
1453 {".mapset", "attr_iter", "", "", "o", "attr_iter", request_mapset_attr_iter},
1454 {".mapset", "attr_iter_destroy", "o", "attr_iter", "", "", request_mapset_attr_iter_destroy},
1455 {".mapset", "get_attr", "s", "attribute", "sv", "attrname,value", request_mapset_get_attr},
1456 {".mapset", "get_attr_wi", "so", "attribute,attr_iter", "sv", "attrname,value", request_mapset_get_attr},
1457 {".search_list","destroy", "", "", "", "", request_search_list_destroy},
1458 {".search_list","get_result", "", "", "i(iii)a{sa{sv}}", "id,coord,dict", request_search_list_get_result},
1459 {".search_list","search", "svi", "attribute,value,partial", "", "", request_search_list_search},
1460 {".search_list","select", "sii", "attribute_type,id,mode", "", "", request_search_list_select},
1461 {".vehicle","set_attr", "sv", "attribute,value", "", "", request_vehicle_set_attr},
1465 introspect_path(const char *object)
1469 char *def=".default_";
1470 int def_len=strlen(def);
1471 if (strncmp(object, object_path, strlen(object_path)))
1473 ret=g_strdup(object+strlen(object_path));
1474 dbg(1,"path=%s\n",ret);
1475 for (i = strlen(ret)-1 ; i >= 0 ; i--) {
1476 if (ret[i] == '/' || (ret[i] >= '0' && ret[i] <= '9'))
1481 for (i = 0 ; i < strlen(ret); i++)
1485 for (i = strlen(ret)-1 ; i >= 0 ; i--) {
1486 if (!strncmp(ret+i, def, def_len)) {
1487 memmove(ret+1,ret+i+def_len,strlen(ret+i+def_len)+1);
1495 generate_navitintrospectxml(const char *object)
1497 int i,methods_size,n=0;
1498 char *navitintrospectxml;
1499 char *path=introspect_path(object);
1502 dbg(1,"path=%s\n",path);
1504 // write header and make navit introspectable
1505 navitintrospectxml = g_strdup_printf("%s%s%s\n", navitintrospectxml_head1, object, navitintrospectxml_head2);
1507 methods_size=sizeof(dbus_methods)/sizeof(struct dbus_method);
1508 for (i = 0 ; i < methods_size ; i++) {
1509 // start new interface if it's the first method or it changed
1510 if (strcmp(dbus_methods[i].path, path))
1512 if ((n == 0) || strcmp(dbus_methods[i-1].path, dbus_methods[i].path))
1513 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <interface name=\"%s%s\">\n", service_name, dbus_methods[i].path);
1516 // start the new method
1517 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <method name=\"%s\">\n", dbus_methods[i].method);
1519 // set input signature if existent
1520 if (strcmp(dbus_methods[i].signature, ""))
1521 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <arg direction=\"in\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].signature_name, dbus_methods[i].signature);
1523 // set response signature if existent
1524 if (strcmp(dbus_methods[i].response, ""))
1525 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " <arg direction=\"out\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].response_name, dbus_methods[i].response);
1528 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " </method>\n");
1530 // close the interface if we reached the last method or the interface changes
1531 if ((methods_size == i+1) || ((methods_size > i+1) && strcmp(dbus_methods[i+1].path, dbus_methods[i].path)))
1532 navitintrospectxml = g_strconcat_printf(navitintrospectxml, " </interface>\n\n");
1534 // close the "mother tag"
1535 navitintrospectxml = g_strconcat_printf(navitintrospectxml, "</node>\n");
1537 return navitintrospectxml;
1540 static DBusHandlerResult
1541 navit_handler_func(DBusConnection *connection, DBusMessage *message, void *user_data)
1545 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));
1546 if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1548 char *navitintrospectxml = generate_navitintrospectxml(dbus_message_get_path(message));
1549 dbg(1,"Introspect %s:Result:%s\n",dbus_message_get_path(message), navitintrospectxml);
1550 if (navitintrospectxml) {
1551 reply = dbus_message_new_method_return(message);
1552 dbus_message_append_args(reply, DBUS_TYPE_STRING, &navitintrospectxml, DBUS_TYPE_INVALID);
1553 dbus_connection_send (connection, reply, NULL);
1554 dbus_message_unref (reply);
1555 g_free(navitintrospectxml);
1556 return DBUS_HANDLER_RESULT_HANDLED;
1558 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1561 for (i = 0 ; i < sizeof(dbus_methods)/sizeof(struct dbus_method) ; i++) {
1562 path=g_strdup_printf("%s%s", service_name, dbus_methods[i].path);
1563 if (dbus_message_is_method_call(message, path, dbus_methods[i].method) &&
1564 dbus_message_has_signature(message, dbus_methods[i].signature)) {
1566 return dbus_methods[i].func(connection, message);
1570 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1573 static DBusObjectPathVTable dbus_navit_vtable = {
1581 filter(DBusConnection *connection, DBusMessage *message, void *user_data)
1583 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));
1584 if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
1586 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1591 dbus_cmd_send_signal(struct navit *navit, char *command, struct attr **in, struct attr ***out)
1594 char *opath=object_new("navit",navit);
1595 char *interface=g_strdup_printf("%s%s", service_name, ".navit");
1596 dbg(0,"enter %s %s %s\n",opath,command,interface);
1597 msg = dbus_message_new_signal(opath, interface, "signal");
1601 encode_attr(msg, *in);
1605 dbus_connection_send(connection, msg, &dbus_serial);
1606 dbus_connection_flush(connection);
1607 dbus_message_unref(msg);
1614 static struct command_table commands[] = {
1615 {"dbus_send_signal",command_cast(dbus_cmd_send_signal)},
1620 dbus_main_navit(struct navit *navit, int added)
1624 command_add_table_attr(commands, sizeof(commands)/sizeof(struct command_table), navit, &attr);
1625 navit_add_attr(navit, &attr);
1629 void plugin_init(void)
1633 struct attr callback;
1634 object_hash=g_hash_table_new(g_str_hash, g_str_equal);
1635 object_hash_rev=g_hash_table_new(NULL, NULL);
1636 object_count=g_hash_table_new(g_str_hash, g_str_equal);
1638 dbus_error_init(&error);
1639 connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
1641 dbg(0,"Failed to open connection to session message bus: %s\n", error.message);
1642 dbus_error_free(&error);
1645 dbus_connection_setup_with_g_main(connection, NULL);
1647 dbus_connection_add_filter(connection, filter, NULL, NULL);
1648 dbus_bus_add_match(connection, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
1650 dbus_connection_register_fallback(connection, object_path, &dbus_navit_vtable, NULL);
1651 dbus_bus_request_name(connection, service_name, 0, &error);
1652 if (dbus_error_is_set(&error)) {
1653 dbg(0,"Failed to request name: %s", error.message);
1654 dbus_error_free (&error);
1656 callback.type=attr_callback;
1657 callback.u.callback=callback_new_attr_0(callback_cast(dbus_main_navit),attr_navit);
1658 config_add_attr(config, &callback);