Add:Core:speech_dbus
[navit-package] / navit / binding / dbus / binding_dbus.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include <string.h>
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>
25 #include "config.h"
26 #include "config_.h"
27 #include "navit.h"
28 #include "coord.h"
29 #include "point.h"
30 #include "plugin.h"
31 #include "debug.h"
32 #include "item.h"
33 #include "attr.h"
34 #include "layout.h"
35 #include "command.h"
36 #include "callback.h"
37 #include "graphics.h"
38 #include "vehicle.h"
39 #include "map.h"
40 #include "mapset.h"
41 #include "search.h"
42 #include "callback.h"
43 #include "gui.h"
44 #include "util.h"
45
46
47 static DBusConnection *connection;
48 static dbus_uint32_t dbus_serial;
49
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"
54                                  "<node name=\"";
55
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"
60                                  "    </method>\n"
61                                  "  </interface>\n";
62
63
64
65 GHashTable *object_hash;
66 GHashTable *object_hash_rev;
67 GHashTable *object_count;
68
69 struct dbus_callback {
70         struct callback *callback;
71         char *signal;
72 };
73
74 static char *
75 object_new(char *type, void *object)
76 {
77         int id;
78         char *ret;
79         dbg(1,"enter %s\n", type);
80         if ((ret=g_hash_table_lookup(object_hash_rev, object)))
81                 return ret;
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);
88         return (ret);
89 }
90
91 static void *
92 object_get(const char *path)
93 {
94         return g_hash_table_lookup(object_hash, path);
95 }
96
97 static void 
98 object_destroy(const char *path, void *object)
99 {
100         if (!path && !object)
101                 return;
102         if (!object)
103                 object=g_hash_table_lookup(object_hash, path);
104         if (!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);
108 }
109
110 static void *
111 resolve_object(const char *opath, char *type)
112 {
113         char *prefix;
114         const char *oprefix;
115         void *ret=NULL;
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";
122         struct attr attr;
123
124         if (strncmp(opath, object_path, strlen(object_path))) {
125                 dbg(0,"wrong object path %s\n",opath);
126                 return NULL;
127         }
128         prefix=g_strdup_printf("%s/%s/", object_path, type);
129         if (!strncmp(prefix, opath, strlen(prefix))) {
130                 ret=object_get(opath);
131                 g_free(prefix);
132                 return ret;
133         }
134         g_free(prefix);
135         oprefix=opath+strlen(object_path);
136         if (!strncmp(oprefix,def_navit,strlen(def_navit))) {
137                 oprefix+=strlen(def_navit);
138                 struct attr navit;
139                 if (!config_get_attr(config, attr_navit, &navit, NULL))
140                         return NULL;
141                 if (!oprefix[0]) {
142                         dbg(0,"default_navit\n");
143                         return navit.u.navit;
144                 }
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;
148                         }
149                         return NULL;
150                 }
151                 if (!strncmp(oprefix,def_gui,strlen(def_gui))) {
152                         if (navit_get_attr(navit.u.navit, attr_gui, &attr, NULL)) {
153                                 return attr.u.gui;
154                         }
155                         return NULL;
156                 }
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;
160                         }
161                         return NULL;
162                 }
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)) {
166                                 if (!oprefix[0]) {
167                                         return attr.u.mapset;
168                                 }       
169                                 if (!strncmp(oprefix,def_map,strlen(def_map))) {
170                                         if (mapset_get_attr(attr.u.mapset, attr_map, &attr, NULL)) {
171                                                 return attr.u.map;
172                                         }
173                                         return NULL;
174                                 }
175                         }
176                         return NULL;
177                 }
178         }
179         return NULL;
180 }
181
182 static void *
183 object_get_from_message_arg(DBusMessageIter *iter, char *type)
184 {
185         char *opath;
186
187         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
188                 return NULL;
189         dbus_message_iter_get_basic(iter, &opath);
190         dbus_message_iter_next(iter);
191         return resolve_object(opath, type);
192 }
193
194 static void *
195 object_get_from_message(DBusMessage *message, char *type)
196 {
197         return resolve_object(dbus_message_get_path(message), type);
198 }
199
200 static enum attr_type 
201 attr_type_get_from_message(DBusMessageIter *iter)
202 {
203         char *attr_type;
204
205         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) 
206                 return attr_none;
207         dbus_message_iter_get_basic(iter, &attr_type);
208         dbus_message_iter_next(iter);
209         return attr_from_name(attr_type); 
210 }
211
212 static void
213 encode_variant_string(DBusMessageIter *iter, char *str)
214 {
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);
219 }
220
221 static void
222 encode_dict_string_variant_string(DBusMessageIter *iter, char *key, char *value)
223 {
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);
229 }
230
231 static int
232 encode_attr(DBusMessage *message, struct attr *attr)
233 {
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);
242         }
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);
247         }
248         if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) {
249                 encode_variant_string(&iter1, attr->u.str);
250         }
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);
256         }
257         return 1;
258 }
259
260
261 static DBusHandlerResult
262 empty_reply(DBusConnection *connection, DBusMessage *message)
263 {
264         DBusMessage *reply;
265
266         reply = dbus_message_new_method_return(message);
267         dbus_connection_send (connection, reply, NULL);
268         dbus_message_unref (reply);
269
270         return DBUS_HANDLER_RESULT_HANDLED;
271 }
272
273
274 static DBusHandlerResult
275 dbus_error(DBusConnection *connection, DBusMessage *message, char *error, char *msg)
276 {
277         DBusMessage *reply;
278
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;
283 }
284
285 static DBusHandlerResult
286 dbus_error_invalid_attr_type(DBusConnection *connection, DBusMessage *message)
287 {
288         return dbus_error(connection, message, DBUS_ERROR_INVALID_ARGS, "attribute type invalid");
289 }
290
291 static DBusHandlerResult
292 dbus_error_invalid_parameter(DBusConnection *connection, DBusMessage *message)
293 {
294         return dbus_error(connection, message, DBUS_ERROR_INVALID_ARGS, "parameter invalid");
295 }
296
297 static DBusHandlerResult
298 dbus_error_invalid_object_path(DBusConnection *connection, DBusMessage *message)
299 {
300         return dbus_error(connection, message, DBUS_ERROR_BAD_ADDRESS, "object path invalid");
301 }
302
303 static DBusHandlerResult
304 dbus_error_invalid_object_path_parameter(DBusConnection *connection, DBusMessage *message)
305 {
306         return dbus_error(connection, message, DBUS_ERROR_BAD_ADDRESS, "object path parameter invalid");
307 }
308
309 #if 0
310 static void
311 dbus_dump_iter(char *prefix, DBusMessageIter *iter)
312 {
313         char *prefixr,*vals;
314         int arg,vali;
315         DBusMessageIter iterr;
316         while ((arg=dbus_message_iter_get_arg_type(iter)) != DBUS_TYPE_INVALID) {
317                 switch (arg) {
318                 case DBUS_TYPE_INT32:
319                         dbus_message_iter_get_basic(iter, &vali);
320                         dbg(0,"%sDBUS_TYPE_INT32: %d\n",prefix,vali);
321                         break;
322                 case DBUS_TYPE_STRING:
323                         dbus_message_iter_get_basic(iter, &vals);
324                         dbg(0,"%sDBUS_TYPE_STRING: %s\n",prefix,vals);
325                         break;
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);
331                         g_free(prefixr);
332                         break;
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);
338                         g_free(prefixr);
339                         break;
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);
345                         g_free(prefixr);
346                         break;
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);
352                         g_free(prefixr);
353                         break;
354                 default:
355                         dbg(0,"%c\n",arg);
356                 }
357                 dbus_message_iter_next(iter);
358         }
359 }
360
361 static void
362 dbus_dump(DBusMessage *message)
363 {
364         DBusMessageIter iter;
365
366         dbus_message_iter_init(message, &iter);
367         dbus_dump_iter("",&iter);
368                 
369 }
370 #endif
371
372 /**
373  * Extracts a struct pcoord from a DBus message
374  *
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
379  */
380 static int
381 pcoord_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct pcoord *pc)
382 {
383
384     if(!strcmp(dbus_message_iter_get_signature(iter), "s")) {
385         char *coordstring;
386
387         dbus_message_iter_get_basic(iter, &coordstring);
388         if(!pcoord_parse(coordstring, projection_mg, pc))
389             return 0;
390         
391         return 1;
392     } else {
393         
394         DBusMessageIter iter2;
395         dbus_message_iter_recurse(iter, &iter2);
396         if(!strcmp(dbus_message_iter_get_signature(iter), "(is)")) {
397             char *coordstring;
398             int projection;
399             
400             dbus_message_iter_get_basic(&iter2, &projection);
401
402             dbus_message_iter_next(&iter2);
403             dbus_message_iter_get_basic(&iter2, &coordstring);
404
405             if(!pcoord_parse(coordstring, projection, pc))
406                 return 0;
407
408             return 1;
409         } else if(!strcmp(dbus_message_iter_get_signature(iter), "(iii)")) {
410             
411             dbus_message_iter_get_basic(&iter2, &pc->pro);
412             
413             dbus_message_iter_next(&iter2);
414             dbus_message_iter_get_basic(&iter2, &pc->x);
415             
416             dbus_message_iter_next(&iter2);
417             dbus_message_iter_get_basic(&iter2, &pc->y);
418
419             return 1;
420         }
421     }
422     return 0;
423     
424 }
425
426 static void
427 pcoord_encode(DBusMessageIter *iter, struct pcoord *pc)
428 {
429         DBusMessageIter iter2;
430         dbus_message_iter_open_container(iter,DBUS_TYPE_STRUCT,NULL,&iter2);
431         if (pc) {
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);
435         } else {
436                 int n=0;
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);
440         }
441         dbus_message_iter_close_container(iter, &iter2);
442 }
443
444 static enum attr_type
445 decode_attr_type_from_iter(DBusMessageIter *iter)
446 {
447         char *attr_type;
448         enum attr_type ret;
449         
450         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
451                 return attr_none;
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);
456         return ret;
457 }
458
459 static int
460 decode_attr_from_iter(DBusMessageIter *iter, struct attr *attr)
461 {
462         DBusMessageIter iterattr, iterstruct;
463         int ret=1;
464         double d;
465
466         attr->type=decode_attr_type_from_iter(iter);
467         if (attr->type == attr_none)
468                 return 0;
469     
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));
473     
474         if (attr->type >= attr_type_item_begin && attr->type <= attr_type_item_end)
475                 return 0;
476
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);
480                         return 1;
481                 }
482                 return 0;
483         }
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);
487                         return 1;
488                 }
489                 return 0;
490         }
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);
494                         return 1;
495                 }
496                 return 0;
497         }
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);
502                         return 1;
503                 }
504         }
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;
513                         } else
514                                 ret=0;
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;
518                         } else
519                                 ret=0;
520                         if (!ret) {
521                                 g_free(attr->u.coord_geo);
522                                 attr->u.coord_geo=NULL;
523                         }
524                         return ret;
525                 }
526         }
527         if (attr->type == attr_callback) {
528                 struct dbus_callback *callback=object_get_from_message_arg(&iterattr, "callback");
529                 if (callback) {
530                         attr->u.callback=callback->callback;
531                         return 1;
532                 }
533         }
534         return 0;
535 }
536
537 static int
538 decode_attr(DBusMessage *message, struct attr *attr)
539 {
540         DBusMessageIter iter;
541
542         dbus_message_iter_init(message, &iter);
543         return decode_attr_from_iter(&iter, attr);
544 }
545
546 static void
547 destroy_attr(struct attr *attr)
548 {
549         if(attr->type > attr_type_double_begin && attr->type < attr_type_double_end) {
550                 g_free(attr->u.numd);
551         }
552 }
553
554 static char *
555 get_iter_name(char *type)
556 {
557         return g_strdup_printf("%s_attr_iter",type);
558 }
559
560 static DBusHandlerResult
561 request_attr_iter(DBusConnection *connection, DBusMessage *message, char *type, struct attr_iter *(*func)(void))
562 {
563         DBusMessage *reply;
564         char *iter_name;
565         char *opath;
566         struct attr_iter *attr_iter;
567
568         attr_iter=(*func)();
569         iter_name=get_iter_name(type);
570         opath=object_new(iter_name,attr_iter);
571         g_free(iter_name);
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);
576
577         return DBUS_HANDLER_RESULT_HANDLED;
578 }
579
580 static DBusHandlerResult
581 request_attr_iter_destroy(DBusConnection *connection, DBusMessage *message, char *type, void (*func)(struct attr_iter *))
582 {
583         struct attr_iter *attr_iter;
584         DBusMessageIter iter;
585         char *iter_name;
586
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);
590         g_free(iter_name);
591         if (! attr_iter)
592                 return dbus_error_invalid_object_path_parameter(connection, message);
593         object_destroy(NULL, attr_iter);
594         func(attr_iter);
595
596         return empty_reply(connection, message);
597 }
598
599 static DBusHandlerResult
600 request_destroy(DBusConnection *connection, DBusMessage *message, char *type, void *data, void (*func)(void *))
601 {
602         if (!data) 
603                 data=object_get_from_message(message, type);
604         if (!data)
605                 return dbus_error_invalid_object_path(connection, message);
606         object_destroy(NULL, data);
607         func(data);
608
609         return empty_reply(connection, message);
610 }
611
612
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))
615 {
616         DBusMessage *reply;
617         DBusMessageIter iter;
618         struct attr attr;
619         enum attr_type attr_type;
620         struct attr_iter *attr_iter;
621         char *iter_name;
622
623         if (! data)
624                 data = object_get_from_message(message, type);
625         if (! data)
626                 return dbus_error_invalid_object_path(connection, message);
627
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);
634         g_free(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;
641         }
642         return empty_reply(connection, message);
643         
644 }
645
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))
648 {
649         DBusMessageIter iter;
650         struct attr attr;
651         char *command;
652
653         if (! data)
654                 data = object_get_from_message(message, type);
655         if (! data)
656                 return dbus_error_invalid_object_path(connection, message);
657
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)) {
664                 int valid=0;
665                 callback_list_call_attr_4(attr.u.callback_list, attr_command, command, NULL, NULL, &valid);
666         }
667         return empty_reply(connection, message);
668         
669 }
670
671 static DBusHandlerResult
672 request_set_add_remove_attr(DBusConnection *connection, DBusMessage *message, char *type, void *data, int (*func)(void *data, struct attr *attr))
673 {
674         struct attr attr;
675         int ret;
676
677         if (! data)     
678                 data = object_get_from_message(message, type);
679         if (! data)
680                 return dbus_error_invalid_object_path(connection, message);
681
682         if (decode_attr(message, &attr)) {
683                 ret=(*func)(data, &attr);
684                 destroy_attr(&attr);
685                 if (ret)        
686                         return empty_reply(connection, message);
687         }
688         return dbus_error_invalid_parameter(connection, message);
689 }
690
691 /* callback */
692
693
694 static void
695 dbus_callback_emit_signal(struct dbus_callback *dbus_callback)
696 {
697         DBusMessage* msg;
698         msg = dbus_message_new_signal(object_path, service_name, dbus_callback->signal);
699         if (msg) {
700                 dbus_connection_send(connection, msg, &dbus_serial);
701                 dbus_connection_flush(connection);
702                 dbus_message_unref(msg);
703         }
704 }
705
706 static void
707 request_callback_destroy_do(struct dbus_callback *data)
708 {
709         callback_destroy(data->callback);
710         g_free(data->signal);
711         g_free(data);
712 }
713
714 static DBusHandlerResult
715 request_callback_destroy(DBusConnection *connection, DBusMessage *message)
716 {
717         return request_destroy(connection, message, "search_list", NULL, (void (*)(void *)) request_callback_destroy_do);
718 }
719
720 static DBusHandlerResult
721 request_callback_new(DBusConnection *connection, DBusMessage *message)
722 {
723         DBusMessageIter iter;
724         DBusMessage *reply;
725         struct dbus_callback *callback;
726         char *signal,*opath;
727         enum attr_type type;
728
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);
736
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);
740         } else
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;
748 }
749
750 /* config */
751 static DBusHandlerResult
752 request_config_get_attr(DBusConnection *connection, DBusMessage *message)
753 {
754         return request_get_attr(connection, message, "config", config, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))config_get_attr);
755 }
756
757 static DBusHandlerResult
758 request_config_attr_iter(DBusConnection *connection, DBusMessage *message)
759 {
760         return request_attr_iter(connection, message, "config", (struct attr_iter * (*)(void))config_attr_iter_new);
761 }
762
763 static DBusHandlerResult
764 request_config_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
765 {
766         return request_attr_iter_destroy(connection, message, "config", (void (*)(struct attr_iter *))config_attr_iter_destroy);
767 }
768
769
770
771 /* graphics */
772
773 static DBusHandlerResult
774 request_graphics_get_data(DBusConnection *connection, DBusMessage *message)
775 {
776         struct graphics *graphics;
777         char *data;
778         struct graphics_data_image *image;
779         DBusMessage *reply;
780
781         graphics = object_get_from_message(message, "graphics");
782         if (! graphics)
783                 return dbus_error_invalid_object_path(connection, message);
784
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);
788         if (image) {
789                 DBusMessageIter iter1,iter2;
790                 reply = dbus_message_new_method_return(message);
791 #if 0
792                 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
793 #endif
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;
802         }
803         return empty_reply(connection, message);
804 }
805
806 /* gui */
807
808 static DBusHandlerResult
809 request_gui_get_attr(DBusConnection *connection, DBusMessage *message)
810 {
811         return request_get_attr(connection, message, "gui", NULL, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))gui_get_attr);
812 }
813
814 static DBusHandlerResult
815 request_gui_command(DBusConnection *connection, DBusMessage *message)
816 {
817         return request_command(connection, message, "gui", NULL, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))gui_get_attr);
818 }
819
820
821
822 static DBusHandlerResult
823 request_graphics_set_attr(DBusConnection *connection, DBusMessage *message)
824 {
825         return request_set_add_remove_attr(connection, message, "graphics", NULL, (int (*)(void *, struct attr *))graphics_set_attr);
826 }
827
828 /* map */
829
830 static DBusHandlerResult
831 request_map_get_attr(DBusConnection *connection, DBusMessage *message)
832 {
833         return request_get_attr(connection, message, "map", NULL, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))map_get_attr);
834 }
835
836
837 static DBusHandlerResult
838 request_map_set_attr(DBusConnection *connection, DBusMessage *message)
839 {
840         return request_set_add_remove_attr(connection, message, "map", NULL, (int (*)(void *, struct attr *))map_set_attr);
841 }
842
843 /* mapset */
844
845 static DBusHandlerResult
846 request_mapset_attr_iter(DBusConnection *connection, DBusMessage *message)
847 {
848         return request_attr_iter(connection, message, "mapset", (struct attr_iter * (*)(void))mapset_attr_iter_new);
849 }
850
851 static DBusHandlerResult
852 request_mapset_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
853 {
854         return request_attr_iter_destroy(connection, message, "mapset", (void (*)(struct attr_iter *))mapset_attr_iter_destroy);
855 }
856
857 static DBusHandlerResult
858 request_mapset_get_attr(DBusConnection *connection, DBusMessage *message)
859 {
860         return request_get_attr(connection, message, "mapset", NULL, (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))mapset_get_attr);
861 }
862
863 /* navit */
864
865 static DBusHandlerResult
866 request_navit_draw(DBusConnection *connection, DBusMessage *message)
867 {
868         struct navit *navit;
869
870         navit=object_get_from_message(message, "navit");
871         if (! navit)
872                 return dbus_error_invalid_object_path(connection, message);
873
874         navit_draw(navit);
875         
876         return empty_reply(connection, message);
877 }
878
879
880 /**
881  * Extracts a struct point from a DBus message
882  *
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
887  */
888 static int
889 point_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct point *p)
890 {
891         DBusMessageIter iter2;
892
893         dbg(0,"%s\n", dbus_message_iter_get_signature(iter));
894         
895         dbus_message_iter_recurse(iter, &iter2);
896
897         if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
898                 return 0;
899         dbus_message_iter_get_basic(&iter2, &p->x);
900         
901         dbus_message_iter_next(&iter2);
902         
903         if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
904                 return 0;
905         dbus_message_iter_get_basic(&iter2, &p->y);
906
907         dbg(0, " x -> %x  y -> %x\n", p->x, p->y);
908         
909         dbus_message_iter_next(&iter2);
910
911         if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INVALID)
912                 return 0;
913         
914         return 1;
915 }
916
917 /**
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
922  */
923
924 static DBusHandlerResult
925 request_navit_add_message(DBusConnection *connection, DBusMessage *message)
926 {
927         struct navit *navit;
928         char *usermessage;
929     
930     DBusMessageIter iter;
931
932         navit=object_get_from_message(message, "navit");
933         if (! navit)
934                 return dbus_error_invalid_object_path(connection, message);
935
936         dbus_message_iter_init(message, &iter);
937         dbus_message_iter_get_basic(&iter, &usermessage);
938         
939     navit_add_message(navit, usermessage);
940         
941     return empty_reply(connection, message);
942 }
943
944
945 /**
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
950  */
951
952 static DBusHandlerResult
953 request_navit_set_center(DBusConnection *connection, DBusMessage *message)
954 {
955         struct pcoord pc;
956         struct navit *navit;
957         DBusMessageIter iter;
958
959         navit=object_get_from_message(message, "navit");
960         if (! navit)
961                 return dbus_error_invalid_object_path(connection, message);
962
963         dbus_message_iter_init(message, &iter);
964
965         if (!pcoord_get_from_message(message, &iter, &pc))
966                 return dbus_error_invalid_parameter(connection, message);
967     
968         navit_set_center(navit, &pc, 0);
969         return empty_reply(connection, message);
970 }
971
972 /**
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
977  */
978 static DBusHandlerResult
979 request_navit_set_center_screen(DBusConnection *connection, DBusMessage *message)
980 {
981         struct point p;
982         struct navit *navit;
983         DBusMessageIter iter;
984
985         navit=object_get_from_message(message, "navit");
986         if (! navit)
987                 return dbus_error_invalid_object_path(connection, message);
988
989         dbus_message_iter_init(message, &iter);
990
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);
995 }
996
997 /**
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
1002  */
1003 static DBusHandlerResult
1004 request_navit_set_layout(DBusConnection *connection, DBusMessage *message)
1005 {
1006         char *new_layout_name;
1007         struct navit *navit;
1008         struct attr attr;
1009         struct attr_iter *iter;
1010
1011         navit=object_get_from_message(message, "navit");
1012         if (! navit)
1013                 return dbus_error_invalid_object_path(connection, message);
1014         
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);
1017         
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);
1022                 }
1023         }
1024         return empty_reply(connection, message);
1025 }
1026
1027 static DBusHandlerResult
1028 request_navit_zoom(DBusConnection *connection, DBusMessage *message)
1029 {
1030         int factor;
1031         struct point p, *pp=NULL;
1032         struct navit *navit;
1033         DBusMessageIter iter;
1034
1035         navit = object_get_from_message(message, "navit");
1036         if (! navit)
1037                 return dbus_error_invalid_object_path(connection, message);
1038
1039         dbus_message_iter_init(message, &iter);
1040         dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
1041         
1042         dbus_message_iter_get_basic(&iter, &factor);
1043         
1044         if (dbus_message_iter_has_next(&iter))
1045         {
1046                 dbus_message_iter_next(&iter);
1047                 if (!point_get_from_message(message, &iter, &p))
1048                         return dbus_error_invalid_parameter(connection, message);
1049                 pp=&p;
1050         }
1051
1052         if (factor > 1)
1053                 navit_zoom_in(navit, factor, pp);
1054         else if (factor < -1)
1055                 navit_zoom_out(navit, 0-factor, pp);
1056
1057         return empty_reply(connection, message);
1058
1059 }
1060
1061 static DBusHandlerResult
1062 request_navit_resize(DBusConnection *connection, DBusMessage *message)
1063 {
1064         struct navit *navit;
1065         int w, h;
1066         DBusMessageIter iter;
1067
1068         navit = object_get_from_message(message, "navit");
1069         if (! navit)
1070                 return dbus_error_invalid_object_path(connection, message);
1071
1072         dbus_message_iter_init(message, &iter);
1073         dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
1074         
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);
1078         
1079         dbus_message_iter_next(&iter);
1080         
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);
1084
1085         dbg(0, " w -> %i  h -> %i\n", w, h);
1086         
1087         navit_handle_resize(navit, w, h);
1088
1089         return empty_reply(connection, message);
1090
1091 }
1092
1093 static DBusHandlerResult
1094 request_navit_get_attr(DBusConnection *connection, DBusMessage *message)
1095 {
1096         DBusMessage *reply;
1097         DBusMessageIter iter;
1098         struct attr attr;
1099         enum attr_type attr_type;
1100         struct attr_iter *attr_iter;
1101         struct navit *navit;
1102
1103         navit = object_get_from_message(message, "navit");
1104         if (! navit)
1105                 return dbus_error_invalid_object_path(connection, message);
1106
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;
1118         }
1119         return empty_reply(connection, message);
1120 }
1121
1122 static DBusHandlerResult
1123 request_navit_attr_iter(DBusConnection *connection, DBusMessage *message)
1124 {
1125         DBusMessage *reply;
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);
1132
1133         return DBUS_HANDLER_RESULT_HANDLED;
1134 }
1135
1136 static DBusHandlerResult
1137 request_navit_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
1138 {
1139         struct attr_iter *attr_iter;
1140         DBusMessageIter iter;
1141
1142         dbus_message_iter_init(message, &iter);
1143         attr_iter=object_get_from_message_arg(&iter, "navit_attr_iter");
1144         if (! attr_iter)
1145                 return dbus_error_invalid_object_path_parameter(connection, message);
1146         navit_attr_iter_destroy(attr_iter);
1147
1148         return empty_reply(connection, message);
1149 }
1150
1151
1152 static DBusHandlerResult
1153 request_navit_set_attr(DBusConnection *connection, DBusMessage *message)
1154 {
1155         return request_set_add_remove_attr(connection, message, "navit", NULL, (int (*)(void *, struct attr *))navit_set_attr);
1156 }
1157
1158 static DBusHandlerResult
1159 request_navit_add_attr(DBusConnection *connection, DBusMessage *message)
1160 {
1161         return request_set_add_remove_attr(connection, message, "navit", NULL, (int (*)(void *, struct attr *))navit_add_attr);
1162 }
1163
1164 static DBusHandlerResult
1165 request_navit_remove_attr(DBusConnection *connection, DBusMessage *message)
1166 {
1167         return request_set_add_remove_attr(connection, message, "navit", NULL, (int (*)(void *, struct attr *))navit_remove_attr);
1168 }
1169
1170 static DBusHandlerResult
1171 request_navit_set_position(DBusConnection *connection, DBusMessage *message)
1172 {
1173         struct pcoord pc;
1174         struct navit *navit;
1175         DBusMessageIter iter;
1176
1177         navit = object_get_from_message(message, "navit");
1178         if (! navit)
1179                 return dbus_error_invalid_object_path(connection, message);
1180
1181         dbus_message_iter_init(message, &iter);
1182         if (!pcoord_get_from_message(message, &iter, &pc))
1183                 return dbus_error_invalid_parameter(connection, message);
1184         
1185         navit_set_position(navit, &pc);
1186         return empty_reply(connection, message);
1187 }
1188
1189 static DBusHandlerResult
1190 request_navit_set_destination(DBusConnection *connection, DBusMessage *message)
1191 {
1192         struct pcoord pc;
1193         struct navit *navit;
1194         DBusMessageIter iter;
1195         char *description;
1196
1197         navit = object_get_from_message(message, "navit");
1198         if (! navit)
1199                 return dbus_error_invalid_object_path(connection, message);
1200
1201         dbus_message_iter_init(message, &iter);
1202         if (!pcoord_get_from_message(message, &iter, &pc))
1203                 return dbus_error_invalid_parameter(connection, message);
1204         
1205         dbus_message_iter_next(&iter);
1206         dbus_message_iter_get_basic(&iter, &description);
1207         dbg(0, " destination -> %s\n", description);
1208         
1209         navit_set_destination(navit, &pc, description, 1);
1210         return empty_reply(connection, message);
1211 }
1212
1213 static DBusHandlerResult
1214 request_navit_evaluate(DBusConnection *connection, DBusMessage *message)
1215 {
1216         struct navit *navit;
1217         char *command;
1218         char *result;
1219         struct attr attr;
1220         DBusMessage *reply;
1221         int error;
1222
1223         navit = object_get_from_message(message, "navit");
1224         if (! navit)
1225                 return dbus_error_invalid_object_path(connection, message);
1226
1227         attr.type=attr_navit;
1228         attr.u.navit=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);
1233         if (error)
1234                 dbus_message_append_args(reply, DBUS_TYPE_INT32, &error, DBUS_TYPE_INVALID);
1235         else if (result)
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;
1240 }
1241
1242 /* search_list */
1243
1244 static DBusHandlerResult
1245 request_search_list_destroy(DBusConnection *connection, DBusMessage *message)
1246 {
1247         return request_destroy(connection, message, "search_list", NULL, (void (*)(void *)) search_list_destroy);
1248 }
1249
1250 static DBusHandlerResult
1251 request_search_list_get_result(DBusConnection *connection, DBusMessage *message)
1252 {
1253         struct search_list *search_list;
1254         struct search_list_result *result;
1255         DBusMessage *reply;
1256         DBusMessageIter iter,iter2,iter3,iter4;
1257         char *country="country";
1258         char *town="town";
1259         char *street="street";
1260
1261         search_list = object_get_from_message(message, "search_list");
1262         if (! search_list)
1263                 return dbus_error_invalid_object_path(connection, message);
1264         result=search_list_get_result(search_list);
1265         if (!result)
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);
1286         }
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);
1297         }
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);
1306         }
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;
1311 }
1312
1313 static DBusHandlerResult
1314 request_search_list_new(DBusConnection *connection, DBusMessage *message)
1315 {
1316         DBusMessageIter iter;
1317         DBusMessage *reply;
1318         struct mapset *mapset;
1319         struct search_list *search_list;
1320         char *opath;
1321
1322         dbus_message_iter_init(message, &iter);
1323         mapset=object_get_from_message_arg(&iter, "mapset");
1324         if (! 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;
1333 }
1334
1335 static DBusHandlerResult
1336 request_search_list_search(DBusConnection *connection, DBusMessage *message)
1337 {
1338         DBusMessageIter iter;
1339         struct search_list *search_list;
1340         struct attr attr;
1341         int partial;
1342
1343         search_list = object_get_from_message(message, "search_list");
1344         if (! search_list)
1345                 return dbus_error_invalid_object_path(connection, message);
1346
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);
1355 }
1356
1357 static DBusHandlerResult
1358 request_search_list_select(DBusConnection *connection, DBusMessage *message)
1359 {
1360         DBusMessageIter iter;
1361         struct search_list *search_list;
1362         int id, mode;
1363         enum attr_type attr_type;
1364
1365         search_list = object_get_from_message(message, "search_list");
1366         if (! search_list)
1367                 return dbus_error_invalid_object_path(connection, message);
1368
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);
1381 }
1382
1383 /* vehicle */
1384
1385 static DBusHandlerResult
1386 request_vehicle_set_attr(DBusConnection *connection, DBusMessage *message)
1387 {
1388         struct vehicle *vehicle;
1389         struct attr attr;
1390         int ret;
1391         
1392         vehicle = object_get_from_message(message, "vehicle");
1393         if (! 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);
1398                 if (ret)        
1399                         return empty_reply(connection, message);
1400         }
1401         return dbus_error_invalid_parameter(connection, message);
1402 }
1403
1404
1405 struct dbus_method {
1406         char *path;
1407         char *method;
1408         char *signature;
1409     char *signature_name;
1410     char *response;
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},
1462 };
1463
1464 static char *
1465 introspect_path(const char *object)
1466 {
1467         char *ret;
1468         int i;
1469         char *def=".default_";
1470         int def_len=strlen(def);
1471         if (strncmp(object, object_path, strlen(object_path)))
1472                 return NULL;
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'))
1477                         ret[i]='\0';
1478                 else
1479                         break;
1480         }
1481         for (i = 0 ; i < strlen(ret); i++)
1482                 if (ret[i] == '/')
1483                         ret[i]='.';
1484         
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);
1488                         break;
1489                 }
1490         }
1491         return ret;
1492 }
1493
1494 static char *
1495 generate_navitintrospectxml(const char *object)
1496 {
1497     int i,methods_size,n=0;
1498     char *navitintrospectxml;
1499     char *path=introspect_path(object);
1500     if (!path)
1501         return NULL;
1502     dbg(1,"path=%s\n",path);
1503     
1504     // write header and make navit introspectable
1505     navitintrospectxml = g_strdup_printf("%s%s%s\n", navitintrospectxml_head1, object, navitintrospectxml_head2);
1506     
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))
1511                 continue;
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);
1514         n++;
1515         
1516         // start the new method
1517         navitintrospectxml = g_strconcat_printf(navitintrospectxml, "    <method name=\"%s\">\n", dbus_methods[i].method);
1518
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);
1522         
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);
1526         
1527         // close the method
1528         navitintrospectxml = g_strconcat_printf(navitintrospectxml, "    </method>\n");
1529         
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");
1533     }
1534     // close the "mother tag"
1535     navitintrospectxml = g_strconcat_printf(navitintrospectxml, "</node>\n");
1536     
1537     return navitintrospectxml;
1538 }
1539
1540 static DBusHandlerResult
1541 navit_handler_func(DBusConnection *connection, DBusMessage *message, void *user_data)
1542 {
1543         int i;
1544         char *path;
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")) {
1547                 DBusMessage *reply;
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;
1557                 }
1558                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1559         }
1560         
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)) {
1565                         g_free(path);
1566                         return dbus_methods[i].func(connection, message);
1567                 }
1568                 g_free(path);
1569         }
1570         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1571 }
1572
1573 static DBusObjectPathVTable dbus_navit_vtable = {
1574         NULL,
1575         navit_handler_func,
1576         NULL
1577 };
1578
1579 #if 0
1580 DBusHandlerResult
1581 filter(DBusConnection *connection, DBusMessage *message, void *user_data)
1582 {
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")) {
1585         }
1586         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1587 }
1588 #endif
1589
1590 static int
1591 dbus_cmd_send_signal(struct navit *navit, char *command, struct attr **in, struct attr ***out)
1592 {
1593         DBusMessage* msg;
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");
1598         if (msg) {
1599                 if (in) {
1600                         while (*in) {
1601                                 encode_attr(msg, *in);
1602                                 in++;
1603                         }
1604                 }
1605                 dbus_connection_send(connection, msg, &dbus_serial);
1606                 dbus_connection_flush(connection);
1607                 dbus_message_unref(msg);
1608         }
1609         g_free(interface);
1610         return 0;
1611 }
1612      
1613
1614 static struct command_table commands[] = {
1615         {"dbus_send_signal",command_cast(dbus_cmd_send_signal)},
1616 };
1617
1618
1619 static void
1620 dbus_main_navit(struct navit *navit, int added)
1621 {
1622         struct attr attr;
1623         if (added) {
1624                 command_add_table_attr(commands, sizeof(commands)/sizeof(struct command_table), navit, &attr);
1625                 navit_add_attr(navit, &attr);
1626         }
1627 }
1628
1629 void plugin_init(void)
1630 {
1631         DBusError error;
1632
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);
1637         dbg(0,"enter 1\n");
1638         dbus_error_init(&error);
1639         connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
1640         if (!connection) {
1641                 dbg(0,"Failed to open connection to session message bus: %s\n", error.message);
1642                 dbus_error_free(&error);
1643                 return;
1644         }
1645         dbus_connection_setup_with_g_main(connection, NULL);
1646 #if 0
1647         dbus_connection_add_filter(connection, filter, NULL, NULL);
1648         dbus_bus_add_match(connection, "type='signal',""interface='" DBUS_INTERFACE_DBUS  "'", &error);
1649 #endif
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);
1655         }
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);
1659 }