Fix:binding_dbus:Cleanup
[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 "util.h"
42
43
44 static DBusConnection *connection;
45 static dbus_uint32_t dbus_serial;
46
47 static char *service_name = "org.navit_project.navit";
48 static char *object_path = "/org/navit_project/navit";
49 char *navitintrospectxml_head1 = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
50                                  "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
51                                  "<node name=\"";
52
53 char *navitintrospectxml_head2 = "\">\n"
54                                  "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
55                                  "    <method name=\"Introspect\">\n"
56                                  "      <arg direction=\"out\" type=\"s\" />\n"
57                                  "    </method>\n"
58                                  "  </interface>\n";
59
60
61
62 GHashTable *object_hash;
63 GHashTable *object_hash_rev;
64 GHashTable *object_count;
65
66 static char *
67 object_new(char *type, void *object)
68 {
69         int id;
70         char *ret;
71         dbg(0,"enter %s\n", type);
72         if ((ret=g_hash_table_lookup(object_hash_rev, object)))
73                 return ret;
74         id=GPOINTER_TO_INT(g_hash_table_lookup(object_count, type));
75         g_hash_table_insert(object_count, type, GINT_TO_POINTER((id+1)));
76         ret=g_strdup_printf("%s/%s/%d", object_path, type, id);
77         g_hash_table_insert(object_hash, ret, object);
78         g_hash_table_insert(object_hash_rev, object, ret);
79         dbg(0,"return %s\n", ret);
80         return (ret);
81 }
82
83 static void *
84 object_get(const char *path)
85 {
86         return g_hash_table_lookup(object_hash, path);
87 }
88
89 static void *
90 resolve_object(const char *opath, char *type)
91 {
92         char *prefix;
93         const char *oprefix;
94         void *ret=NULL;
95         char *def_navit="/default_navit";
96         char *def_graphics="/default_graphics";
97         char *def_vehicle="/default_vehicle";
98         char *def_mapset="/default_mapset";
99         char *def_map="/default_map";
100         struct attr attr;
101
102         if (strncmp(opath, object_path, strlen(object_path))) {
103                 dbg(0,"wrong object path %s\n",opath);
104                 return NULL;
105         }
106         prefix=g_strdup_printf("%s/%s/", object_path, type);
107         if (!strncmp(prefix, opath, strlen(prefix))) {
108                 ret=object_get(opath);
109                 g_free(prefix);
110                 return ret;
111         }
112         g_free(prefix);
113         oprefix=opath+strlen(object_path);
114         if (!strncmp(oprefix,def_navit,strlen(def_navit))) {
115                 oprefix+=strlen(def_navit);
116                 struct attr navit;
117                 if (!config_get_attr(config, attr_navit, &navit, NULL))
118                         return NULL;
119                 if (!oprefix[0]) {
120                         dbg(0,"default_navit\n");
121                         return navit.u.navit;
122                 }
123                 if (!strncmp(oprefix,def_graphics,strlen(def_graphics))) {
124                         if (navit_get_attr(navit.u.navit, attr_graphics, &attr, NULL)) {
125                                 return attr.u.graphics;
126                         }
127                         return NULL;
128                 }
129                 if (!strncmp(oprefix,def_vehicle,strlen(def_vehicle))) {
130                         if (navit_get_attr(navit.u.navit, attr_vehicle, &attr, NULL)) {
131                                 return attr.u.vehicle;
132                         }
133                         return NULL;
134                 }
135                 if (!strncmp(oprefix,def_mapset,strlen(def_mapset))) {
136                         oprefix+=strlen(def_mapset);
137                         if (navit_get_attr(navit.u.navit, attr_mapset, &attr, NULL)) {
138                                 if (!oprefix[0]) {
139                                         return attr.u.mapset;
140                                 }       
141                                 if (!strncmp(oprefix,def_map,strlen(def_map))) {
142                                         if (mapset_get_attr(attr.u.mapset, attr_map, &attr, NULL)) {
143                                                 return attr.u.map;
144                                         }
145                                         return NULL;
146                                 }
147                         }
148                         return NULL;
149                 }
150         }
151         return NULL;
152 }
153
154 static void *
155 object_get_from_message_arg(DBusMessageIter *iter, char *type)
156 {
157         char *opath;
158
159         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
160                 return NULL;
161         dbus_message_iter_get_basic(iter, &opath);
162         dbus_message_iter_next(iter);
163         return resolve_object(opath, type);
164 }
165
166 static void *
167 object_get_from_message(DBusMessage *message, char *type)
168 {
169         return resolve_object(dbus_message_get_path(message), type);
170 }
171
172 static enum attr_type 
173 attr_type_get_from_message(DBusMessageIter *iter)
174 {
175         char *attr_type;
176
177         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) 
178                 return attr_none;
179         dbus_message_iter_get_basic(iter, &attr_type);
180         dbus_message_iter_next(iter);
181         return attr_from_name(attr_type); 
182 }
183
184 static int
185 encode_attr(DBusMessage *message, struct attr *attr)
186 {
187         char *name=attr_to_name(attr->type);
188         DBusMessageIter iter1,iter2;
189         dbus_message_iter_init_append(message, &iter1);
190         dbus_message_iter_append_basic(&iter1, DBUS_TYPE_STRING, &name);
191         if (attr->type >= attr_type_int_begin && attr->type < attr_type_boolean_begin) {
192                 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &iter2);
193                 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_INT32, &attr->u.num);
194                 dbus_message_iter_close_container(&iter1, &iter2);
195         }
196         if (attr->type >= attr_type_boolean_begin && attr->type <= attr_type_int_end) {
197                 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING, &iter2);
198                 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_BOOLEAN, &attr->u.num);
199                 dbus_message_iter_close_container(&iter1, &iter2);
200         }
201         if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) {
202                 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &iter2);
203                 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_STRING, &attr->u.str);
204                 dbus_message_iter_close_container(&iter1, &iter2);
205         }
206         if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) {
207                 char *object=object_new(attr_to_name(attr->type), attr->u.data);
208                 dbus_message_iter_open_container(&iter1, DBUS_TYPE_VARIANT, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter2);
209                 dbus_message_iter_append_basic(&iter2, DBUS_TYPE_OBJECT_PATH, &object);
210                 dbus_message_iter_close_container(&iter1, &iter2);
211         }
212         return 1;
213 }
214
215
216 static DBusHandlerResult
217 empty_reply(DBusConnection *connection, DBusMessage *message)
218 {
219         DBusMessage *reply;
220
221         reply = dbus_message_new_method_return(message);
222         dbus_connection_send (connection, reply, NULL);
223         dbus_message_unref (reply);
224
225         return DBUS_HANDLER_RESULT_HANDLED;
226 }
227
228
229 static DBusHandlerResult
230 dbus_error(DBusConnection *connection, DBusMessage *message, char *error, char *msg)
231 {
232         DBusMessage *reply;
233
234         reply = dbus_message_new_error(message, error, msg);
235         dbus_connection_send (connection, reply, NULL);
236         dbus_message_unref (reply);
237         return DBUS_HANDLER_RESULT_HANDLED;
238 }
239
240 static DBusHandlerResult
241 dbus_error_invalid_attr_type(DBusConnection *connection, DBusMessage *message)
242 {
243         return dbus_error(connection, message, DBUS_ERROR_INVALID_ARGS, "attribute type invalid");
244 }
245
246 static DBusHandlerResult
247 dbus_error_invalid_parameter(DBusConnection *connection, DBusMessage *message)
248 {
249         return dbus_error(connection, message, DBUS_ERROR_INVALID_ARGS, "parameter invalid");
250 }
251
252 static DBusHandlerResult
253 dbus_error_invalid_object_path(DBusConnection *connection, DBusMessage *message)
254 {
255         return dbus_error(connection, message, DBUS_ERROR_BAD_ADDRESS, "object path invalid");
256 }
257
258 static DBusHandlerResult
259 dbus_error_invalid_object_path_parameter(DBusConnection *connection, DBusMessage *message)
260 {
261         return dbus_error(connection, message, DBUS_ERROR_BAD_ADDRESS, "object path parameter invalid");
262 }
263
264 /**
265  * Extracts a struct pcoord from a DBus message
266  *
267  * @param message The DBus message
268  * @param iter Sort of pointer that points on that (iii)-object in the message
269  * @param pc Pointer where the data should get stored
270  * @returns Returns 1 when everything went right, otherwise 0
271  */
272 static int
273 pcoord_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct pcoord *pc)
274 {
275
276     if(!strcmp(dbus_message_iter_get_signature(iter), "s")) {
277         char *coordstring;
278
279         dbus_message_iter_get_basic(iter, &coordstring);
280         if(!pcoord_parse(coordstring, projection_mg, pc))
281             return 0;
282         
283         return 1;
284     } else {
285         
286         DBusMessageIter iter2;
287         dbus_message_iter_recurse(iter, &iter2);
288         if(!strcmp(dbus_message_iter_get_signature(iter), "(is)")) {
289             char *coordstring;
290             int projection;
291             
292             dbus_message_iter_get_basic(&iter2, &projection);
293
294             dbus_message_iter_next(&iter2);
295             dbus_message_iter_get_basic(&iter2, &coordstring);
296
297             if(!pcoord_parse(coordstring, projection, pc))
298                 return 0;
299
300             return 1;
301         } else if(!strcmp(dbus_message_iter_get_signature(iter), "(iii)")) {
302             
303             dbus_message_iter_get_basic(&iter2, &pc->pro);
304             
305             dbus_message_iter_next(&iter2);
306             dbus_message_iter_get_basic(&iter2, &pc->x);
307             
308             dbus_message_iter_next(&iter2);
309             dbus_message_iter_get_basic(&iter2, &pc->y);
310
311             return 1;
312         }
313     }
314     return 0;
315     
316 }
317
318 static int
319 decode_attr(DBusMessage *message, struct attr *attr)
320 {
321         DBusMessageIter iter, iterattr, iterstruct;
322         char *attr_type;
323         int ret=1;
324         double d;
325
326         dbus_message_iter_init(message, &iter);
327         dbus_message_iter_get_basic(&iter, &attr_type);
328         attr->type = attr_from_name(attr_type); 
329         dbg(0, "attr value: 0x%x string: %s\n", attr->type, attr_type);
330     
331         if (attr->type == attr_none)
332                 return 0;
333     
334         dbus_message_iter_next(&iter);
335         dbus_message_iter_recurse(&iter, &iterattr);
336         dbg(0, "seems valid. signature: %s\n", dbus_message_iter_get_signature(&iterattr));
337     
338         if (attr->type >= attr_type_item_begin && attr->type <= attr_type_item_end)
339                 return 0;
340
341         if (attr->type >= attr_type_int_begin && attr->type <= attr_type_boolean_begin) {
342                 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_INT32) {
343                         dbus_message_iter_get_basic(&iterattr, &attr->u.num);
344                         return 1;
345                 }
346                 return 0;
347         }
348         if(attr->type >= attr_type_boolean_begin && attr->type <= attr_type_int_end) {
349                 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_BOOLEAN) {
350                         dbus_message_iter_get_basic(&iterattr, &attr->u.num);
351                         return 1;
352                 }
353                 return 0;
354         }
355         if(attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) {
356                 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_STRING) {
357                         dbus_message_iter_get_basic(&iterattr, &attr->u.str);
358                         return 1;
359                 }
360                 return 0;
361         }
362         if(attr->type >= attr_type_double_begin && attr->type <= attr_type_double_end) {
363                 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_DOUBLE) {
364                         attr->u.numd=g_new(typeof(*attr->u.numd),1);
365                         dbus_message_iter_get_basic(&iterattr, attr->u.numd);
366                         return 1;
367                 }
368         }
369         if(attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end) {
370                 if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_STRUCT) {
371                         attr->u.coord_geo=g_new(typeof(*attr->u.coord_geo),1);
372                         dbus_message_iter_recurse(&iterattr, &iterstruct);
373                         if (dbus_message_iter_get_arg_type(&iterstruct) == DBUS_TYPE_DOUBLE) {
374                                 dbus_message_iter_get_basic(&iterstruct, &d);
375                                 dbus_message_iter_next(&iterstruct);
376                                 attr->u.coord_geo->lng=d;
377                         } else
378                                 ret=0;
379                         if (dbus_message_iter_get_arg_type(&iterstruct) == DBUS_TYPE_DOUBLE) {
380                                 dbus_message_iter_get_basic(&iterstruct, &d);
381                                 attr->u.coord_geo->lat=d;
382                         } else
383                                 ret=0;
384                         if (!ret) {
385                                 g_free(attr->u.coord_geo);
386                                 attr->u.coord_geo=NULL;
387                         }
388                         return ret;
389                 }
390         }
391         return 0;
392 }
393
394 static void
395 destroy_attr(struct attr *attr)
396 {
397         if(attr->type > attr_type_double_begin && attr->type < attr_type_double_end) {
398                 g_free(attr->u.numd);
399         }
400 }
401
402 static char *
403 get_iter_name(char *type)
404 {
405         return g_strdup_printf("%s_attr_iter",type);
406 }
407
408 static DBusHandlerResult
409 request_attr_iter(DBusConnection *connection, DBusMessage *message, char *type, struct attr_iter *(*func)(void))
410 {
411         DBusMessage *reply;
412         char *iter_name;
413         char *opath;
414         struct attr_iter *attr_iter;
415
416         attr_iter=(*func)();
417         iter_name=get_iter_name(type);
418         opath=object_new(iter_name,attr_iter);
419         g_free(iter_name);
420         reply = dbus_message_new_method_return(message);
421         dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
422         dbus_connection_send (connection, reply, NULL);
423         dbus_message_unref (reply);
424
425         return DBUS_HANDLER_RESULT_HANDLED;
426 }
427
428 static DBusHandlerResult
429 request_attr_iter_destroy(DBusConnection *connection, DBusMessage *message, char *type, void (*func)(struct attr_iter *))
430 {
431         struct attr_iter *attr_iter;
432         DBusMessageIter iter;
433         char *iter_name;
434
435         dbus_message_iter_init(message, &iter);
436         iter_name=get_iter_name(type);
437         attr_iter=object_get_from_message_arg(&iter, iter_name);
438         g_free(iter_name);
439         if (! attr_iter)
440                 return dbus_error_invalid_object_path_parameter(connection, message);
441         func(attr_iter);
442
443         return empty_reply(connection, message);
444 }
445
446
447 static DBusHandlerResult
448 request_get_attr(DBusConnection *connection, DBusMessage *message, char *type, int (*func)(void *data, enum attr_type type, struct attr *attr, struct attr_iter *iter))
449 {
450         DBusMessage *reply;
451         DBusMessageIter iter;
452         struct attr attr;
453         enum attr_type attr_type;
454         struct attr_iter *attr_iter;
455         void *data;
456         char *iter_name;
457
458         data = object_get_from_message(message, type);
459         if (! data)
460                 return dbus_error_invalid_object_path(connection, message);
461
462         dbus_message_iter_init(message, &iter);
463         attr_type=attr_type_get_from_message(&iter);
464         if (attr_type == attr_none)
465                 return dbus_error_invalid_attr_type(connection, message);
466         iter_name=get_iter_name(type);  
467         attr_iter=object_get_from_message_arg(&iter, iter_name);
468         g_free(iter_name);
469         if (func(data, attr_type, &attr, attr_iter)) {
470                 reply = dbus_message_new_method_return(message);
471                 encode_attr(reply, &attr);
472                 dbus_connection_send (connection, reply, NULL);
473                 dbus_message_unref (reply);
474                 return DBUS_HANDLER_RESULT_HANDLED;
475         }
476         return empty_reply(connection, message);
477         
478 }
479
480
481 /* config */
482 static DBusHandlerResult
483 request_config_get_attr(DBusConnection *connection, DBusMessage *message)
484 {
485         DBusMessage *reply;
486         DBusMessageIter iter;
487         struct attr attr;
488         enum attr_type attr_type;
489         struct attr_iter *attr_iter;
490
491         dbus_message_iter_init(message, &iter);
492         attr_type=attr_type_get_from_message(&iter);
493         attr_iter=object_get_from_message_arg(&iter, "config_attr_iter");
494         if (attr_type == attr_none)
495                 return dbus_error_invalid_attr_type(connection, message);
496         if (config_get_attr(config, attr_type, &attr, attr_iter)) {
497                 reply = dbus_message_new_method_return(message);
498                 encode_attr(reply, &attr);
499                 dbus_connection_send (connection, reply, NULL);
500                 dbus_message_unref (reply);
501                 return DBUS_HANDLER_RESULT_HANDLED;
502         }
503         return empty_reply(connection, message);
504 }
505
506 static DBusHandlerResult
507 request_config_attr_iter(DBusConnection *connection, DBusMessage *message)
508 {
509         DBusMessage *reply;
510         struct attr_iter *attr_iter=config_attr_iter_new();
511         char *opath=object_new("config_attr_iter",attr_iter);
512         reply = dbus_message_new_method_return(message);
513         dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
514         dbus_connection_send (connection, reply, NULL);
515         dbus_message_unref (reply);
516
517         return DBUS_HANDLER_RESULT_HANDLED;
518 }
519
520 static DBusHandlerResult
521 request_config_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
522 {
523         struct attr_iter *attr_iter;
524         DBusMessageIter iter;
525
526         dbus_message_iter_init(message, &iter);
527         attr_iter=object_get_from_message_arg(&iter, "config_attr_iter");
528         if (! attr_iter)
529                 return dbus_error_invalid_object_path_parameter(connection, message);
530         config_attr_iter_destroy(attr_iter);
531
532         return empty_reply(connection, message);
533 }
534
535 /* graphics */
536
537 static DBusHandlerResult
538 request_graphics_get_data(DBusConnection *connection, DBusMessage *message)
539 {
540         struct graphics *graphics;
541         char *data;
542         struct graphics_data_image *image;
543         DBusMessage *reply;
544
545         graphics = object_get_from_message(message, "graphics");
546         if (! graphics)
547                 return dbus_error_invalid_object_path(connection, message);
548
549         if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &data, DBUS_TYPE_INVALID))
550                 return dbus_error_invalid_parameter(connection, message);
551         image=graphics_get_data(graphics, data);
552         if (image) {
553                 DBusMessageIter iter1,iter2;
554                 reply = dbus_message_new_method_return(message);
555 #if 0
556                 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
557 #endif
558                 dbus_message_iter_init_append(reply, &iter1);
559                 dbus_message_iter_open_container(&iter1, DBUS_TYPE_ARRAY, "y", &iter2);
560                 if (image->data && image->size) 
561                         dbus_message_iter_append_fixed_array(&iter2, DBUS_TYPE_BYTE, &image->data, image->size);
562                 dbus_message_iter_close_container(&iter1, &iter2);
563                 dbus_connection_send (connection, reply, NULL);
564                 dbus_message_unref (reply);
565                 return DBUS_HANDLER_RESULT_HANDLED;
566         }
567         return empty_reply(connection, message);
568 }
569
570 static DBusHandlerResult
571 request_graphics_set_attr(DBusConnection *connection, DBusMessage *message)
572 {
573         struct graphics *graphics;
574         struct attr attr;
575         int ret;
576         
577         graphics = object_get_from_message(message, "graphics");
578         if (! graphics)
579                 return dbus_error_invalid_object_path(connection, message);
580         if (decode_attr(message, &attr)) {
581                 ret=graphics_set_attr(graphics, &attr);
582                 destroy_attr(&attr);
583                 if (ret)
584                         return empty_reply(connection, message);
585         }
586         return dbus_error_invalid_parameter(connection, message);
587 }
588
589 /* map */
590
591 static DBusHandlerResult
592 request_map_set_attr(DBusConnection *connection, DBusMessage *message)
593 {
594         struct map *map;
595         struct attr attr;
596         int ret;
597         
598         map = object_get_from_message(message, "map");
599         if (! map)
600                 return dbus_error_invalid_object_path(connection, message);
601         if (decode_attr(message, &attr)) {
602                 ret=map_set_attr(map, &attr);
603                 destroy_attr(&attr);
604                 if (ret)        
605                         return empty_reply(connection, message);
606         }
607         return dbus_error_invalid_parameter(connection, message);
608 }
609
610 static DBusHandlerResult
611 request_map_get_attr(DBusConnection *connection, DBusMessage *message)
612 {
613         return request_get_attr(connection, message, "map", (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))map_get_attr);
614 }
615
616 /* mapset */
617
618 static DBusHandlerResult
619 request_mapset_attr_iter(DBusConnection *connection, DBusMessage *message)
620 {
621         return request_attr_iter(connection, message, "mapset", (struct attr_iter * (*)(void))mapset_attr_iter_new);
622 }
623
624 static DBusHandlerResult
625 request_mapset_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
626 {
627         return request_attr_iter_destroy(connection, message, "mapset", (void (*)(struct attr_iter *))mapset_attr_iter_destroy);
628 }
629
630 static DBusHandlerResult
631 request_mapset_get_attr(DBusConnection *connection, DBusMessage *message)
632 {
633         return request_get_attr(connection, message, "mapset", (int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))mapset_get_attr);
634 }
635
636 /* navit */
637
638 static DBusHandlerResult
639 request_navit_draw(DBusConnection *connection, DBusMessage *message)
640 {
641         struct navit *navit;
642
643         navit=object_get_from_message(message, "navit");
644         if (! navit)
645                 return dbus_error_invalid_object_path(connection, message);
646
647         navit_draw(navit);
648         
649         return empty_reply(connection, message);
650 }
651
652
653 /**
654  * Extracts a struct point from a DBus message
655  *
656  * @param message The DBus message
657  * @param iter Sort of pointer that points on that (ii)-object in the message
658  * @param p Pointer where the data should get stored
659  * @returns Returns 1 when everything went right, otherwise 0
660  */
661 static int
662 point_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct point *p)
663 {
664         DBusMessageIter iter2;
665
666         dbg(0,"%s\n", dbus_message_iter_get_signature(iter));
667         
668         dbus_message_iter_recurse(iter, &iter2);
669
670         if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
671                 return 0;
672         dbus_message_iter_get_basic(&iter2, &p->x);
673         
674         dbus_message_iter_next(&iter2);
675         
676         if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
677                 return 0;
678         dbus_message_iter_get_basic(&iter2, &p->y);
679
680         dbg(0, " x -> %x  y -> %x\n", p->x, p->y);
681         
682         dbus_message_iter_next(&iter2);
683
684         if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INVALID)
685                 return 0;
686         
687         return 1;
688 }
689
690 /**
691  * @brief Shows up a message
692  * @param connection The DBusConnection object through which \a message arrived
693  * @param message The DBusMessage containing the coordinates
694  * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
695  */
696
697 static DBusHandlerResult
698 request_navit_add_message(DBusConnection *connection, DBusMessage *message)
699 {
700         struct navit *navit;
701         char *usermessage;
702     
703     DBusMessageIter iter;
704
705         navit=object_get_from_message(message, "navit");
706         if (! navit)
707                 return dbus_error_invalid_object_path(connection, message);
708
709         dbus_message_iter_init(message, &iter);
710         dbus_message_iter_get_basic(&iter, &usermessage);
711         
712     navit_add_message(navit, usermessage);
713         
714     return empty_reply(connection, message);
715 }
716
717
718 /**
719  * @brief Centers the screen on a specified position \a pc on the world
720  * @param connection The DBusConnection object through which \a message arrived
721  * @param message The DBusMessage containing the coordinates
722  * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
723  */
724
725 static DBusHandlerResult
726 request_navit_set_center(DBusConnection *connection, DBusMessage *message)
727 {
728         struct pcoord pc;
729         struct navit *navit;
730         DBusMessageIter iter;
731
732         navit=object_get_from_message(message, "navit");
733         if (! navit)
734                 return dbus_error_invalid_object_path(connection, message);
735
736         dbus_message_iter_init(message, &iter);
737
738         if (!pcoord_get_from_message(message, &iter, &pc))
739                 return dbus_error_invalid_parameter(connection, message);
740     
741         navit_set_center(navit, &pc, 0);
742         return empty_reply(connection, message);
743 }
744
745 /**
746  * @brief Centers the screen on a specified position \a p shown on the screen
747  * @param connection The DBusConnection object through which \a message arrived
748  * @param message The DBusMessage containing the x and y value
749  * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
750  */
751 static DBusHandlerResult
752 request_navit_set_center_screen(DBusConnection *connection, DBusMessage *message)
753 {
754         struct point p;
755         struct navit *navit;
756         DBusMessageIter iter;
757
758         navit=object_get_from_message(message, "navit");
759         if (! navit)
760                 return dbus_error_invalid_object_path(connection, message);
761
762         dbus_message_iter_init(message, &iter);
763
764         if (!point_get_from_message(message, &iter, &p))
765                 return dbus_error_invalid_parameter(connection, message);
766         navit_set_center_screen(navit, &p, 0);
767         return empty_reply(connection, message);
768 }
769
770 /**
771  * @brief Sets the layout to \a new_layout_name extracted from \a message
772  * @param connection The DBusConnection object through which \a message arrived
773  * @param message The DBusMessage containing the name of the layout
774  * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
775  */
776 static DBusHandlerResult
777 request_navit_set_layout(DBusConnection *connection, DBusMessage *message)
778 {
779         char *new_layout_name;
780         struct navit *navit;
781         struct attr attr;
782         struct attr_iter *iter;
783
784         navit=object_get_from_message(message, "navit");
785         if (! navit)
786                 return dbus_error_invalid_object_path(connection, message);
787         
788         if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &new_layout_name, DBUS_TYPE_INVALID))
789                 return dbus_error_invalid_parameter(connection, message);
790         
791         iter=navit_attr_iter_new();
792         while(navit_get_attr(navit, attr_layout, &attr, iter)) {
793                 if (strcmp(attr.u.layout->name, new_layout_name) == 0) {
794                         navit_set_attr(navit, &attr);
795                 }
796         }
797         return empty_reply(connection, message);
798 }
799
800 static DBusHandlerResult
801 request_navit_zoom(DBusConnection *connection, DBusMessage *message)
802 {
803         int factor;
804         struct point p;
805         struct navit *navit;
806         DBusMessageIter iter;
807
808         navit = object_get_from_message(message, "navit");
809         if (! navit)
810                 return dbus_error_invalid_object_path(connection, message);
811
812         dbus_message_iter_init(message, &iter);
813         dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
814         
815         dbus_message_iter_get_basic(&iter, &factor);
816         
817         if (dbus_message_iter_has_next(&iter))
818         {
819                 dbus_message_iter_next(&iter);
820                 if (!point_get_from_message(message, &iter, &p))
821                         return dbus_error_invalid_parameter(connection, message);
822         }
823
824         if (factor > 1)
825                 navit_zoom_in(navit, factor, &p);
826         else if (factor < -1)
827                 navit_zoom_out(navit, 0-factor, &p);
828
829         return empty_reply(connection, message);
830
831 }
832
833 static DBusHandlerResult
834 request_navit_resize(DBusConnection *connection, DBusMessage *message)
835 {
836         struct navit *navit;
837         int w, h;
838         DBusMessageIter iter;
839
840         navit = object_get_from_message(message, "navit");
841         if (! navit)
842                 return dbus_error_invalid_object_path(connection, message);
843
844         dbus_message_iter_init(message, &iter);
845         dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
846         
847         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
848                 return dbus_error_invalid_parameter(connection, message);
849         dbus_message_iter_get_basic(&iter, &w);
850         
851         dbus_message_iter_next(&iter);
852         
853         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
854                 return dbus_error_invalid_parameter(connection, message);
855         dbus_message_iter_get_basic(&iter, &h);
856
857         dbg(0, " w -> %i  h -> %i\n", w, h);
858         
859         navit_handle_resize(navit, w, h);
860
861         return empty_reply(connection, message);
862
863 }
864
865 static DBusHandlerResult
866 request_navit_get_attr(DBusConnection *connection, DBusMessage *message)
867 {
868         DBusMessage *reply;
869         DBusMessageIter iter;
870         struct attr attr;
871         enum attr_type attr_type;
872         struct attr_iter *attr_iter;
873         struct navit *navit;
874
875         navit = object_get_from_message(message, "navit");
876         if (! navit)
877                 return dbus_error_invalid_object_path(connection, message);
878
879         dbus_message_iter_init(message, &iter);
880         attr_type=attr_type_get_from_message(&iter);
881         if (attr_type == attr_none)
882                 return dbus_error_invalid_attr_type(connection, message);
883         attr_iter=object_get_from_message_arg(&iter, "navit_attr_iter");
884         if (navit_get_attr(navit, attr_type, &attr, attr_iter)) {
885                 reply = dbus_message_new_method_return(message);
886                 encode_attr(reply, &attr);
887                 dbus_connection_send (connection, reply, NULL);
888                 dbus_message_unref (reply);
889                 return DBUS_HANDLER_RESULT_HANDLED;
890         }
891         return empty_reply(connection, message);
892 }
893
894 static DBusHandlerResult
895 request_navit_attr_iter(DBusConnection *connection, DBusMessage *message)
896 {
897         DBusMessage *reply;
898         struct attr_iter *attr_iter=navit_attr_iter_new();
899         char *opath=object_new("navit_attr_iter",attr_iter);
900         reply = dbus_message_new_method_return(message);
901         dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
902         dbus_connection_send (connection, reply, NULL);
903         dbus_message_unref (reply);
904
905         return DBUS_HANDLER_RESULT_HANDLED;
906 }
907
908 static DBusHandlerResult
909 request_navit_attr_iter_destroy(DBusConnection *connection, DBusMessage *message)
910 {
911         struct attr_iter *attr_iter;
912         DBusMessageIter iter;
913
914         dbus_message_iter_init(message, &iter);
915         attr_iter=object_get_from_message_arg(&iter, "navit_attr_iter");
916         if (! attr_iter)
917                 return dbus_error_invalid_object_path_parameter(connection, message);
918         navit_attr_iter_destroy(attr_iter);
919
920         return empty_reply(connection, message);
921 }
922
923
924 static DBusHandlerResult
925 request_navit_set_attr(DBusConnection *connection, DBusMessage *message)
926 {
927         struct navit *navit;
928         struct attr attr;
929         int ret;
930
931         navit = object_get_from_message(message, "navit");
932         if (! navit)
933                 return dbus_error_invalid_object_path(connection, message);
934         if (decode_attr(message, &attr)) {
935                 ret=navit_set_attr(navit, &attr);
936                 destroy_attr(&attr);
937                 if (ret)
938                         return empty_reply(connection, message);
939         }
940         return dbus_error_invalid_parameter(connection, message);
941 }
942
943 static DBusHandlerResult
944 request_navit_set_position(DBusConnection *connection, DBusMessage *message)
945 {
946         struct pcoord pc;
947         struct navit *navit;
948         DBusMessageIter iter;
949
950         navit = object_get_from_message(message, "navit");
951         if (! navit)
952                 return dbus_error_invalid_object_path(connection, message);
953
954         dbus_message_iter_init(message, &iter);
955         if (!pcoord_get_from_message(message, &iter, &pc))
956                 return dbus_error_invalid_parameter(connection, message);
957         
958         navit_set_position(navit, &pc);
959         return empty_reply(connection, message);
960 }
961
962 static DBusHandlerResult
963 request_navit_set_destination(DBusConnection *connection, DBusMessage *message)
964 {
965         struct pcoord pc;
966         struct navit *navit;
967         DBusMessageIter iter;
968         char *description;
969
970         navit = object_get_from_message(message, "navit");
971         if (! navit)
972                 return dbus_error_invalid_object_path(connection, message);
973
974         dbus_message_iter_init(message, &iter);
975         if (!pcoord_get_from_message(message, &iter, &pc))
976                 return dbus_error_invalid_parameter(connection, message);
977         
978         dbus_message_iter_next(&iter);
979         dbus_message_iter_get_basic(&iter, &description);
980         dbg(0, " destination -> %s\n", description);
981         
982         navit_set_destination(navit, &pc, description, 1);
983         return empty_reply(connection, message);
984 }
985
986 static DBusHandlerResult
987 request_navit_evaluate(DBusConnection *connection, DBusMessage *message)
988 {
989         struct navit *navit;
990         char *command;
991         char *result;
992         struct attr attr;
993         DBusMessage *reply;
994         int *error;
995
996         navit = object_get_from_message(message, "navit");
997         if (! navit)
998                 return dbus_error_invalid_object_path(connection, message);
999
1000         attr.type=attr_navit;
1001         attr.u.navit=navit;
1002         if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &command, DBUS_TYPE_INVALID))
1003                 return dbus_error_invalid_parameter(connection, message);
1004         result=command_evaluate_to_string(&attr, command, &error);
1005         reply = dbus_message_new_method_return(message);
1006         if (error)
1007                 dbus_message_append_args(reply, DBUS_TYPE_INT32, error, DBUS_TYPE_INVALID);
1008         else
1009                 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
1010         dbus_connection_send (connection, reply, NULL);
1011         dbus_message_unref (reply);
1012         return DBUS_HANDLER_RESULT_HANDLED;
1013 }
1014
1015
1016
1017 /* vehicle */
1018
1019 static DBusHandlerResult
1020 request_vehicle_set_attr(DBusConnection *connection, DBusMessage *message)
1021 {
1022         struct vehicle *vehicle;
1023         struct attr attr;
1024         int ret;
1025         
1026         vehicle = object_get_from_message(message, "vehicle");
1027         if (! vehicle)
1028                 return dbus_error_invalid_object_path(connection, message);
1029         if (decode_attr(message, &attr)) {
1030                 ret=vehicle_set_attr(vehicle, &attr);
1031                 destroy_attr(&attr);
1032                 if (ret)        
1033                         return empty_reply(connection, message);
1034         }
1035         return dbus_error_invalid_parameter(connection, message);
1036 }
1037
1038
1039 struct dbus_method {
1040         char *path;
1041         char *method;
1042         char *signature;
1043     char *signature_name;
1044     char *response;
1045     char *response_name;
1046         DBusHandlerResult(*func)(DBusConnection *connection, DBusMessage *message);
1047 } dbus_methods[] = {
1048         {"",        "attr_iter",           "",        "",                                        "o",  "attr_iter",  request_config_attr_iter},
1049         {"",        "attr_iter_destroy",   "o",       "attr_iter",                               "",   "",      request_config_attr_iter_destroy},
1050         {"",        "get_attr",            "s",       "attrname",                                "sv", "attrname,value",request_config_get_attr},
1051         {"",        "get_attr_wi",         "so",      "attrname,attr_iter",                      "sv", "attrname,value",request_config_get_attr},
1052         {".graphics","get_data",           "s",       "type",                                    "ay",  "data", request_graphics_get_data},
1053         {".graphics","set_attr",           "sv",      "attribute,value",                         "",   "",      request_graphics_set_attr},
1054         {".navit",  "draw",                "",        "",                                        "",   "",      request_navit_draw},
1055         {".navit",  "add_message",         "s",       "message",                                 "",   "",      request_navit_add_message},
1056         {".navit",  "set_center",          "s",       "(coordinates)",                           "",   "",      request_navit_set_center},
1057         {".navit",  "set_center",          "(is)",    "(projection,coordinates)",                "",   "",      request_navit_set_center},
1058         {".navit",  "set_center",          "(iii)",   "(projection,longitude,latitude)",         "",   "",      request_navit_set_center},
1059         {".navit",  "set_center_screen",   "(ii)",    "(pixel_x,pixel_y)",                       "",   "",      request_navit_set_center_screen},
1060         {".navit",  "set_layout",          "s",       "layoutname",                              "",   "",      request_navit_set_layout},
1061         {".navit",  "zoom",                "i(ii)",   "factor(pixel_x,pixel_y)",                 "",   "",      request_navit_zoom},
1062         {".navit",  "zoom",                "i",       "factor",                                  "",   "",      request_navit_zoom},
1063         {".navit",  "resize",              "ii",      "upperleft,lowerright",                    "",   "",      request_navit_resize},
1064         {".navit",  "attr_iter",           "",        "",                                        "o",  "attr_iter",  request_navit_attr_iter},
1065         {".navit",  "attr_iter_destroy",   "o",       "attr_iter",                               "",   "",      request_navit_attr_iter_destroy},
1066         {".navit",  "get_attr",            "s",       "attribute",                               "sv",  "attrname,value", request_navit_get_attr},
1067         {".navit",  "get_attr_wi",         "so",      "attribute,attr_iter",                     "sv",  "attrname,value", request_navit_get_attr},
1068         {".navit",  "set_attr",            "sv",      "attribute,value",                         "",   "",      request_navit_set_attr},
1069         {".navit",  "set_position",        "s",       "(coordinates)",                           "",   "",      request_navit_set_position},
1070         {".navit",  "set_position",        "(is)",    "(projection,coordinated)",                "",   "",      request_navit_set_position},
1071         {".navit",  "set_position",        "(iii)",   "(projection,longitude,latitude)",         "",   "",      request_navit_set_position},
1072         {".navit",  "set_destination",     "ss",      "coordinates,comment",                     "",   "",      request_navit_set_destination},
1073         {".navit",  "set_destination",     "(is)s",   "(projection,coordinates)comment",         "",   "",      request_navit_set_destination},
1074         {".navit",  "set_destination",     "(iii)s",  "(projection,longitude,latitude)comment",  "",   "",      request_navit_set_destination},
1075         {".navit",  "evaluate",            "s",       "command",                                 "s",  "",      request_navit_evaluate},
1076         {".map",    "get_attr",            "s",       "attribute",                               "sv",  "attrname,value", request_map_get_attr},
1077         {".map",    "set_attr",            "sv",      "attribute,value",                         "",   "",      request_map_set_attr},
1078         {".mapset", "attr_iter",           "",        "",                                        "o",  "attr_iter",  request_mapset_attr_iter},
1079         {".mapset", "attr_iter_destroy",   "o",       "attr_iter",                               "",   "",      request_mapset_attr_iter_destroy},
1080         {".mapset", "get_attr",            "s",       "attribute",                               "sv",  "attrname,value", request_mapset_get_attr},
1081         {".mapset", "get_attr_wi",         "so",      "attribute,attr_iter",                     "sv",  "attrname,value", request_mapset_get_attr},
1082         {".vehicle","set_attr",            "sv",      "attribute,value",                         "",   "",      request_vehicle_set_attr},
1083 };
1084
1085 static char *
1086 introspect_path(const char *object)
1087 {
1088         char *ret;
1089         int i;
1090         char *def=".default_";
1091         int def_len=strlen(def);
1092         if (strncmp(object, object_path, strlen(object_path)))
1093                 return NULL;
1094         ret=g_strdup(object+strlen(object_path));
1095         dbg(0,"path=%s\n",ret);
1096         for (i = strlen(ret)-1 ; i >= 0 ; i--) {
1097                 if (ret[i] == '/' || (ret[i] >= '0' && ret[i] <= '9'))
1098                         ret[i]='\0';
1099                 else
1100                         break;
1101         }
1102         for (i = 0 ; i < strlen(ret); i++)
1103                 if (ret[i] == '/')
1104                         ret[i]='.';
1105         
1106         for (i = strlen(ret)-1 ; i >= 0 ; i--) {
1107                 if (!strncmp(ret+i, def, def_len)) {
1108                         memmove(ret+1,ret+i+def_len,strlen(ret+i+def_len)+1);
1109                         break;
1110                 }
1111         }
1112         return ret;
1113 }
1114
1115 static char *
1116 generate_navitintrospectxml(const char *object)
1117 {
1118     int i,methods_size,n=0;
1119     char *navitintrospectxml;
1120     char *path=introspect_path(object);
1121     if (!path)
1122         return NULL;
1123     dbg(0,"path=%s\n",path);
1124     
1125     // write header and make navit introspectable
1126     navitintrospectxml = g_strdup_printf("%s%s%s\n", navitintrospectxml_head1, object, navitintrospectxml_head2);
1127     
1128     methods_size=sizeof(dbus_methods)/sizeof(struct dbus_method);
1129     for (i = 0 ; i < methods_size ; i++) {
1130         // start new interface if it's the first method or it changed
1131         if (strcmp(dbus_methods[i].path, path))
1132                 continue;
1133         if ((n == 0) || strcmp(dbus_methods[i-1].path, dbus_methods[i].path))
1134             navitintrospectxml = g_strconcat_printf(navitintrospectxml, "  <interface name=\"%s%s\">\n", service_name, dbus_methods[i].path);
1135         n++;
1136         
1137         // start the new method
1138         navitintrospectxml = g_strconcat_printf(navitintrospectxml, "    <method name=\"%s\">\n", dbus_methods[i].method);
1139
1140         // set input signature if existent
1141         if (strcmp(dbus_methods[i].signature, ""))
1142             navitintrospectxml = g_strconcat_printf(navitintrospectxml, "      <arg direction=\"in\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].signature_name, dbus_methods[i].signature);
1143         
1144         // set response signature if existent
1145         if (strcmp(dbus_methods[i].response, ""))
1146             navitintrospectxml = g_strconcat_printf(navitintrospectxml, "      <arg direction=\"out\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].response_name, dbus_methods[i].response);
1147         
1148         // close the method
1149         navitintrospectxml = g_strconcat_printf(navitintrospectxml, "    </method>\n");
1150         
1151         // close the interface if we reached the last method or the interface changes
1152         if ((methods_size == i+1) || ((methods_size > i+1) && strcmp(dbus_methods[i+1].path, dbus_methods[i].path)))
1153             navitintrospectxml = g_strconcat_printf(navitintrospectxml, "  </interface>\n\n");
1154     }
1155     // close the "mother tag"
1156     navitintrospectxml = g_strconcat_printf(navitintrospectxml, "</node>\n");
1157     
1158     return navitintrospectxml;
1159 }
1160
1161 static DBusHandlerResult
1162 navit_handler_func(DBusConnection *connection, DBusMessage *message, void *user_data)
1163 {
1164         int i;
1165         char *path;
1166         dbg(0,"type=%s interface=%s path=%s member=%s signature=%s\n", dbus_message_type_to_string(dbus_message_get_type(message)), dbus_message_get_interface(message), dbus_message_get_path(message), dbus_message_get_member(message), dbus_message_get_signature(message));
1167         if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1168                 DBusMessage *reply;
1169                 char *navitintrospectxml = generate_navitintrospectxml(dbus_message_get_path(message));
1170                 dbg(0,"Introspect %s:Result:%s\n",dbus_message_get_path(message), navitintrospectxml);
1171                 if (navitintrospectxml) {
1172                         reply = dbus_message_new_method_return(message);
1173                         dbus_message_append_args(reply, DBUS_TYPE_STRING, &navitintrospectxml, DBUS_TYPE_INVALID);
1174                         dbus_connection_send (connection, reply, NULL);
1175                         dbus_message_unref (reply);
1176                         g_free(navitintrospectxml);
1177                         return DBUS_HANDLER_RESULT_HANDLED;
1178                 }
1179                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1180         }
1181         
1182     for (i = 0 ; i < sizeof(dbus_methods)/sizeof(struct dbus_method) ; i++) {
1183                 path=g_strdup_printf("%s%s", service_name, dbus_methods[i].path);
1184                 if (dbus_message_is_method_call(message, path, dbus_methods[i].method) &&
1185                     dbus_message_has_signature(message, dbus_methods[i].signature)) {
1186                         g_free(path);
1187                         return dbus_methods[i].func(connection, message);
1188                 }
1189                 g_free(path);
1190         }
1191         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1192 }
1193
1194 static DBusObjectPathVTable dbus_navit_vtable = {
1195         NULL,
1196         navit_handler_func,
1197         NULL
1198 };
1199
1200 #if 0
1201 DBusHandlerResult
1202 filter(DBusConnection *connection, DBusMessage *message, void *user_data)
1203 {
1204         dbg(0,"type=%s interface=%s path=%s member=%s signature=%s\n", dbus_message_type_to_string(dbus_message_get_type(message)), dbus_message_get_interface(message), dbus_message_get_path(message), dbus_message_get_member(message), dbus_message_get_signature(message));
1205         if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
1206         }
1207         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1208 }
1209 #endif
1210
1211 static int
1212 dbus_cmd_send_signal(struct navit *navit, char *command, struct attr **in, struct attr ***out)
1213 {
1214         DBusMessage* msg;
1215         char *opath=object_new("navit",navit);
1216         char *interface=g_strdup_printf("%s%s", service_name, ".navit");
1217         dbg(0,"enter %s %s %s\n",opath,command,interface);
1218         msg = dbus_message_new_signal(opath, interface, "signal");
1219         if (msg) {
1220                 if (in && in[0]) {
1221                         encode_attr(msg, in[0]);
1222                 }
1223                 dbus_connection_send(connection, msg, &dbus_serial);
1224                 dbus_connection_flush(connection);
1225                 dbus_message_unref(msg);
1226         }
1227         g_free(interface);
1228         return 0;
1229 }
1230      
1231
1232 static struct command_table commands[] = {
1233         {"dbus_send_signal",command_cast(dbus_cmd_send_signal)},
1234 };
1235
1236
1237 static void
1238 dbus_main_navit(struct navit *navit, int added)
1239 {
1240         struct attr attr;
1241         if (added) {
1242                 command_add_table_attr(commands, sizeof(commands)/sizeof(struct command_table), navit, &attr);
1243                 navit_add_attr(navit, &attr);
1244         }
1245 }
1246
1247 void plugin_init(void)
1248 {
1249         DBusError error;
1250
1251         struct attr callback;
1252         object_hash=g_hash_table_new(g_str_hash, g_str_equal);
1253         object_hash_rev=g_hash_table_new(NULL, NULL);
1254         object_count=g_hash_table_new(g_str_hash, g_str_equal);
1255         dbg(0,"enter 1\n");
1256         dbus_error_init(&error);
1257         connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
1258         if (!connection) {
1259                 dbg(0,"Failed to open connection to session message bus: %s\n", error.message);
1260                 dbus_error_free(&error);
1261                 return;
1262         }
1263         dbus_connection_setup_with_g_main(connection, NULL);
1264 #if 0
1265         dbus_connection_add_filter(connection, filter, NULL, NULL);
1266         dbus_bus_add_match(connection, "type='signal',""interface='" DBUS_INTERFACE_DBUS  "'", &error);
1267 #endif
1268         dbus_connection_register_fallback(connection, object_path, &dbus_navit_vtable, NULL);
1269         dbus_bus_request_name(connection, service_name, 0, &error);
1270         if (dbus_error_is_set(&error)) {
1271                 dbg(0,"Failed to request name: %s", error.message);
1272                 dbus_error_free (&error);
1273         }
1274         callback.type=attr_callback;
1275         callback.u.callback=callback_new_0(callback_cast(dbus_main_navit));
1276         config_add_attr(config, &callback);
1277 }