Fix:core:Fixed various compiler warnings
[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 "main.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 "graphics.h"
37 #include "util.h"
38
39
40 static DBusConnection *connection;
41
42 static char *service_name = "org.navit_project.navit";
43 static char *object_path = "/org/navit_project/navit";
44 char *navitintrospectxml_head1 = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
45                                  "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
46                                  "<node name=\"";
47
48 char *navitintrospectxml_head2 = "\">\n"
49                                  "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
50                                  "    <method name=\"Introspect\">\n"
51                                  "      <arg direction=\"out\" type=\"s\" />\n"
52                                  "    </method>\n"
53                                  "  </interface>\n";
54
55
56
57 GHashTable *object_hash;
58 GHashTable *object_count;
59
60 static char *
61 object_new(char *type, void *object)
62 {
63         int id;
64         char *ret;
65         dbg(0,"enter %s\n", type);
66         id=GPOINTER_TO_INT(g_hash_table_lookup(object_count, type));
67         g_hash_table_insert(object_count, type, GINT_TO_POINTER((id+1)));
68         ret=g_strdup_printf("%s/%s/%d", object_path, type, id);
69         g_hash_table_insert(object_hash, ret, object);
70         dbg(0,"return %s\n", ret);
71         return (ret);
72 }
73
74 static void *
75 object_get(const char *path)
76 {
77         return g_hash_table_lookup(object_hash, path);
78 }
79
80 static void *
81 resolve_object(const char *opath, char *type)
82 {
83         char *prefix;
84         void *ret=NULL;
85         char *def_navit="/default_navit";
86         char *def_graphics="/default_graphics";
87         struct attr attr;
88
89         if (strncmp(opath, object_path, strlen(object_path))) {
90                 dbg(0,"wrong object path %s\n",opath);
91                 return NULL;
92         }
93         prefix=g_strdup_printf("%s/%s/", object_path, type);
94         if (!strncmp(prefix, opath, strlen(prefix))) {
95                 ret=object_get(opath);
96                 g_free(prefix);
97                 return ret;
98         }
99         g_free(prefix);
100         prefix=opath+strlen(object_path);
101         if (!strncmp(prefix,def_navit,strlen(def_navit))) {
102                 prefix+=strlen(def_navit);
103                 struct navit *navit=main_get_navit(NULL);
104                 if (!prefix[0]) {
105                         dbg(0,"default_navit\n");
106                         return navit;
107                 }
108                 if (!strncmp(prefix,def_graphics,strlen(def_graphics))) {
109                         if (navit_get_attr(navit, attr_graphics, &attr, NULL)) {
110                                 return attr.u.graphics;
111                         }
112                         return NULL;
113                 }
114         }
115         return NULL;
116 }
117
118 static void *
119 object_get_from_message_arg(DBusMessage *message, char *type)
120 {
121         char *opath;
122         DBusError error;
123
124         dbus_error_init(&error);
125         if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID)) {
126                 dbus_error_free(&error);
127                 dbg(0,"wrong arg type\n");
128                 return NULL;
129         }
130         return resolve_object(opath, type);
131 }
132
133 static void *
134 object_get_from_message(DBusMessage *message, char *type)
135 {
136         return resolve_object(dbus_message_get_path(message), type);
137 }
138
139 static DBusHandlerResult
140 reply_simple_as_variant(DBusConnection *connection, DBusMessage *message, int value, int dbus_type)
141 {
142         DBusMessage *reply;
143     
144         reply = dbus_message_new_method_return(message);
145     dbus_message_append_args(reply,
146                              dbus_type, &value,
147                              DBUS_TYPE_INVALID);
148         dbus_connection_send (connection, reply, NULL);
149         dbus_message_unref (reply);
150
151         return DBUS_HANDLER_RESULT_HANDLED;
152 }
153
154 static DBusHandlerResult
155 empty_reply(DBusConnection *connection, DBusMessage *message)
156 {
157         DBusMessage *reply;
158
159         reply = dbus_message_new_method_return(message);
160         dbus_connection_send (connection, reply, NULL);
161         dbus_message_unref (reply);
162
163         return DBUS_HANDLER_RESULT_HANDLED;
164 }
165
166 static DBusHandlerResult
167 request_main_get_navit(DBusConnection *connection, DBusMessage *message)
168 {
169         DBusMessage *reply;
170         DBusError error;
171         struct iter *iter;
172         struct navit *navit;
173         char *opath;
174
175         dbus_error_init(&error);
176
177         if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID)) {
178                 dbg(0,"Error parsing\n");
179                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
180         }
181         dbg(0,"opath=%s\n", opath);
182         iter=object_get(opath);
183         navit=main_get_navit(iter);
184         if (navit) {
185                 reply = dbus_message_new_method_return(message);
186                 opath=object_new("navit",navit);
187                 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
188                 dbus_connection_send (connection, reply, NULL);
189                 dbus_message_unref (reply);
190                 return DBUS_HANDLER_RESULT_HANDLED;
191         }
192         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
193 }
194
195 static DBusHandlerResult
196 request_main_iter(DBusConnection *connection, DBusMessage *message)
197 {
198         DBusMessage *reply;
199         struct iter *iter=main_iter_new();
200         dbg(0,"iter=%p\n", iter);
201         char *opath=object_new("main_iter",iter);
202         reply = dbus_message_new_method_return(message);
203         dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID);
204         dbus_connection_send (connection, reply, NULL);
205         dbus_message_unref (reply);
206
207         return DBUS_HANDLER_RESULT_HANDLED;
208 }
209
210 static DBusHandlerResult
211 request_main_iter_destroy(DBusConnection *connection, DBusMessage *message)
212 {
213         struct iter *iter;
214         
215         iter=object_get_from_message_arg(message, "main_iter");
216         if (! iter)
217                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
218         main_iter_destroy(iter);
219
220         return empty_reply(connection, message);
221 }
222
223 /**
224  * Extracts a struct pcoord from a DBus message
225  *
226  * @param message The DBus message
227  * @param iter Sort of pointer that points on that (iii)-object in the message
228  * @param pc Pointer where the data should get stored
229  * @returns Returns 1 when everything went right, otherwise 0
230  */
231 static int
232 pcoord_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct pcoord *pc)
233 {
234
235     if(!strcmp(dbus_message_iter_get_signature(iter), "s")) {
236         char *coordstring;
237
238         dbus_message_iter_get_basic(iter, &coordstring);
239         if(!pcoord_parse(coordstring, projection_mg, pc))
240             return 0;
241         
242         return 1;
243     } else {
244         
245         DBusMessageIter iter2;
246         dbus_message_iter_recurse(iter, &iter2);
247         if(!strcmp(dbus_message_iter_get_signature(iter), "(is)")) {
248             char *coordstring;
249             int projection;
250             
251             dbus_message_iter_get_basic(&iter2, &projection);
252
253             dbus_message_iter_next(&iter2);
254             dbus_message_iter_get_basic(&iter2, &coordstring);
255
256             if(!pcoord_parse(coordstring, projection, pc))
257                 return 0;
258
259             return 1;
260         } else if(!strcmp(dbus_message_iter_get_signature(iter), "(iii)")) {
261             
262             dbus_message_iter_get_basic(&iter2, &pc->pro);
263             
264             dbus_message_iter_next(&iter2);
265             dbus_message_iter_get_basic(&iter2, &pc->x);
266             
267             dbus_message_iter_next(&iter2);
268             dbus_message_iter_get_basic(&iter2, &pc->y);
269
270             return 1;
271         }
272     }
273     return 0;
274     
275 }
276
277 static DBusHandlerResult
278 request_navit_draw(DBusConnection *connection, DBusMessage *message)
279 {
280         struct navit *navit;
281
282         navit=object_get_from_message(message, "navit");
283         if (! navit)
284                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
285
286         navit_draw(navit);
287         
288     return empty_reply(connection, message);
289 }
290
291
292 /**
293  * Extracts a struct point from a DBus message
294  *
295  * @param message The DBus message
296  * @param iter Sort of pointer that points on that (ii)-object in the message
297  * @param p Pointer where the data should get stored
298  * @returns Returns 1 when everything went right, otherwise 0
299  */
300 static int
301 point_get_from_message(DBusMessage *message, DBusMessageIter *iter, struct point *p)
302 {
303         DBusMessageIter iter2;
304
305         dbg(0,"%s\n", dbus_message_iter_get_signature(iter));
306         
307         dbus_message_iter_recurse(iter, &iter2);
308
309         if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
310                 return 0;
311         dbus_message_iter_get_basic(&iter2, &p->x);
312         
313         dbus_message_iter_next(&iter2);
314         
315         if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INT32)
316                 return 0;
317         dbus_message_iter_get_basic(&iter2, &p->y);
318
319         dbg(0, " x -> %x  y -> %x\n", p->x, p->y);
320         
321         dbus_message_iter_next(&iter2);
322
323         if (dbus_message_iter_get_arg_type(&iter2) != DBUS_TYPE_INVALID)
324                 return 0;
325         
326         return 1;
327 }
328
329 /**
330  * @brief Shows up a message
331  * @param connection The DBusConnection object through which \a message arrived
332  * @param message The DBusMessage containing the coordinates
333  * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
334  */
335
336 static DBusHandlerResult
337 request_navit_add_message(DBusConnection *connection, DBusMessage *message)
338 {
339         struct navit *navit;
340         char *usermessage;
341     
342     DBusMessageIter iter;
343
344         navit=object_get_from_message(message, "navit");
345         if (! navit)
346                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
347
348         dbus_message_iter_init(message, &iter);
349         dbus_message_iter_get_basic(&iter, &usermessage);
350         
351     navit_add_message(navit, usermessage);
352         
353     return empty_reply(connection, message);
354 }
355
356
357 /**
358  * @brief Centers the screen on a specified position \a pc on the world
359  * @param connection The DBusConnection object through which \a message arrived
360  * @param message The DBusMessage containing the coordinates
361  * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
362  */
363
364 static DBusHandlerResult
365 request_navit_set_center(DBusConnection *connection, DBusMessage *message)
366 {
367         struct pcoord pc;
368         struct navit *navit;
369         DBusMessageIter iter;
370
371         navit=object_get_from_message(message, "navit");
372         if (! navit)
373                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
374
375         dbus_message_iter_init(message, &iter);
376
377         if (!pcoord_get_from_message(message, &iter, &pc))
378                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
379     
380         navit_set_center(navit, &pc, 0);
381         return empty_reply(connection, message);
382 }
383
384 /**
385  * @brief Centers the screen on a specified position \a p shown on the screen
386  * @param connection The DBusConnection object through which \a message arrived
387  * @param message The DBusMessage containing the x and y value
388  * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
389  */
390 static DBusHandlerResult
391 request_navit_set_center_screen(DBusConnection *connection, DBusMessage *message)
392 {
393         struct point p;
394         struct navit *navit;
395         DBusMessageIter iter;
396
397         navit=object_get_from_message(message, "navit");
398         if (! navit)
399                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
400
401         dbus_message_iter_init(message, &iter);
402
403         if (!point_get_from_message(message, &iter, &p))
404                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
405         navit_set_center_screen(navit, &p, 0);
406         return empty_reply(connection, message);
407 }
408
409 /**
410  * @brief Sets the layout to \a new_layout_name extracted from \a message
411  * @param connection The DBusConnection object through which \a message arrived
412  * @param message The DBusMessage containing the name of the layout
413  * @returns An empty reply if everything went right, otherwise DBUS_HANDLER_RESULT_NOT_YET_HANDLED
414  */
415 static DBusHandlerResult
416 request_navit_set_layout(DBusConnection *connection, DBusMessage *message)
417 {
418         char *new_layout_name;
419         struct navit *navit;
420         struct attr attr;
421         struct attr_iter *iter;
422
423         navit=object_get_from_message(message, "navit");
424         if (! navit)
425                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
426         
427     if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &new_layout_name, DBUS_TYPE_INVALID))
428                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
429         
430     iter=navit_attr_iter_new();
431         while(navit_get_attr(navit, attr_layout, &attr, iter)) {
432                 if (strcmp(attr.u.layout->name, new_layout_name) == 0) {
433                         navit_set_attr(navit, &attr);
434                 }
435         }
436         return empty_reply(connection, message);
437 }
438
439 static DBusHandlerResult
440 request_navit_zoom(DBusConnection *connection, DBusMessage *message)
441 {
442         int factor;
443         struct point p;
444         struct navit *navit;
445         DBusMessageIter iter;
446
447         navit = object_get_from_message(message, "navit");
448         if (! navit)
449                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
450
451         dbus_message_iter_init(message, &iter);
452         dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
453         
454         dbus_message_iter_get_basic(&iter, &factor);
455         
456         if (dbus_message_iter_has_next(&iter))
457         {
458                 dbus_message_iter_next(&iter);
459                 if (!point_get_from_message(message, &iter, &p))
460                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
461         }
462
463         if (factor > 1)
464                 navit_zoom_in(navit, factor, &p);
465         else if (factor < -1)
466                 navit_zoom_out(navit, 0-factor, &p);
467
468         return empty_reply(connection, message);
469
470 }
471
472 static DBusHandlerResult
473 request_navit_resize(DBusConnection *connection, DBusMessage *message)
474 {
475         struct navit *navit;
476         int w, h;
477         DBusMessageIter iter;
478
479         navit = object_get_from_message(message, "navit");
480         if (! navit)
481                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
482
483         dbus_message_iter_init(message, &iter);
484         dbg(0,"%s\n", dbus_message_iter_get_signature(&iter));
485         
486         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
487                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
488         dbus_message_iter_get_basic(&iter, &w);
489         
490         dbus_message_iter_next(&iter);
491         
492         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
493                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
494         dbus_message_iter_get_basic(&iter, &h);
495
496         dbg(0, " w -> %i  h -> %i\n", w, h);
497         
498         navit_handle_resize(navit, w, h);
499
500         return empty_reply(connection, message);
501
502 }
503
504 static DBusHandlerResult
505 request_navit_get_attr(DBusConnection *connection, DBusMessage *message)
506 {
507     struct navit *navit;
508     DBusMessageIter iter;
509     char * attr_type = NULL;
510     struct attr attr;
511     navit = object_get_from_message(message, "navit");
512     if (! navit)
513         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
514
515     dbus_message_iter_init(message, &iter);
516     dbus_message_iter_get_basic(&iter, &attr_type);
517     attr.type = attr_from_name(attr_type); 
518     dbg(0, "attr value: 0x%x string: %s\n", attr.type, attr_type);
519
520     if (attr.type == attr_none)
521         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
522     
523     if (attr.type > attr_type_item_begin && attr.type < attr_type_item_end)
524         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
525
526     else if (attr.type > attr_type_int_begin && attr.type < attr_type_boolean_begin)
527     {
528         dbg(0, "int detected\n");
529         if(navit_get_attr(navit, attr.type, &attr, NULL)) {
530             dbg(0, "%s = %i\n", attr_type, attr.u.num);
531             return reply_simple_as_variant(connection, message, attr.u.num, DBUS_TYPE_INT32);
532         }
533     }
534
535     else if(attr.type > attr_type_boolean_begin && attr.type < attr_type_int_end)
536     {
537         dbg(0, "bool detected\n");
538         if(navit_get_attr(navit, attr.type, &attr, NULL)) {
539             dbg(0, "%s = %i\n", attr_type, attr.u.num);
540             return reply_simple_as_variant(connection, message, attr.u.num, DBUS_TYPE_BOOLEAN);
541         }
542     }
543
544     else if(attr.type > attr_type_string_begin && attr.type < attr_type_string_end)
545     {
546         dbg(0, "string detected\n");
547         if(navit_get_attr(navit, attr.type, &attr, NULL)) {
548             dbg(0, "%s = %s\n", attr_type, &attr.u.layout);
549             return reply_simple_as_variant(connection, message, GPOINTER_TO_INT(&attr.u.layout), DBUS_TYPE_STRING);
550         }
551     }
552
553 #if 0
554     else if(attr.type > attr_type_special_begin && attr.type < attr_type_special_end)
555         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
556
557     else if(attr.type > attr_type_double_begin && attr.type < attr_type_double_end)
558         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
559
560     else if(attr.type > attr_type_coord_geo_begin && attr.type < attr_type_coord_geo_end)
561         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
562
563     else if(attr.type > attr_type_color_begin && attr.type < attr_type_color_end)
564         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
565
566     else if(attr.type > attr_type_object_begin && attr.type < attr_type_object_end)
567         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
568
569     else if(attr.type > attr_type_coord_begin && attr.type < attr_type_coord_end)
570         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
571
572     else if(attr.type > attr_type_pcoord_begin && attr.type < attr_type_pcoord_end)
573         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
574
575     else if(attr.type > attr_type_callback_begin && attr.type < attr_type_callback_end)
576         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
577 #endif
578     else {
579         dbg(0, "zomg really unhandled111\n");
580         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
581     }
582
583     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
584 }
585
586
587 static DBusHandlerResult
588 request_navit_set_attr(DBusConnection *connection, DBusMessage *message)
589 {
590     struct navit *navit;
591         DBusMessageIter iter, iterattr;
592     struct attr attr;
593     char *attr_type;
594
595         navit = object_get_from_message(message, "navit");
596         if (! navit)
597                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
598
599     dbus_message_iter_init(message, &iter);
600     dbus_message_iter_get_basic(&iter, &attr_type);
601     attr.type = attr_from_name(attr_type); 
602     dbg(0, "attr value: 0x%x string: %s\n", attr.type, attr_type);
603     
604     if (attr.type == attr_none)
605         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
606     
607     dbus_message_iter_next(&iter);
608     dbus_message_iter_recurse(&iter, &iterattr);
609     dbg(0, "seems valid. signature: %s\n", dbus_message_iter_get_signature(&iterattr));
610     
611     if (attr.type > attr_type_item_begin && attr.type < attr_type_item_end)
612         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
613
614     else if (attr.type > attr_type_int_begin && attr.type < attr_type_boolean_begin) {
615         if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_INT32)
616         {
617             dbus_message_iter_get_basic(&iterattr, &attr.u.num);
618             if (navit_set_attr(navit, &attr))
619                 return empty_reply(connection, message);
620         }
621     }
622     else if(attr.type > attr_type_boolean_begin && attr.type < attr_type_int_end) {
623         if (dbus_message_iter_get_arg_type(&iterattr) == DBUS_TYPE_BOOLEAN)
624         {
625             dbus_message_iter_get_basic(&iterattr, &attr.u.num);
626             if (navit_set_attr(navit, &attr))
627                 return empty_reply(connection, message);
628         }
629     }
630 #if 0
631     else if(attr.type > attr_type_string_begin && attr.type < attr_type_string_end)
632         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
633
634     else if(attr.type > attr_type_special_begin && attr.type < attr_type_special_end)
635         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
636
637     else if(attr.type > attr_type_double_begin && attr.type < attr_type_double_end)
638         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
639
640     else if(attr.type > attr_type_coord_geo_begin && attr.type < attr_type_coord_geo_end)
641         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
642
643     else if(attr.type > attr_type_color_begin && attr.type < attr_type_color_end)
644         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
645
646     else if(attr.type > attr_type_object_begin && attr.type < attr_type_object_end)
647         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
648
649     else if(attr.type > attr_type_coord_begin && attr.type < attr_type_coord_end)
650         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
651
652     else if(attr.type > attr_type_pcoord_begin && attr.type < attr_type_pcoord_end)
653         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
654
655     else if(attr.type > attr_type_callback_begin && attr.type < attr_type_callback_end)
656         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
657 #endif
658     else {
659         dbg(0, "zomg really unhandled111\n");
660         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
661     }
662     
663     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
664 }
665
666 static DBusHandlerResult
667 request_navit_set_position(DBusConnection *connection, DBusMessage *message)
668 {
669         struct pcoord pc;
670         struct navit *navit;
671         DBusMessageIter iter;
672
673         navit = object_get_from_message(message, "navit");
674         if (! navit)
675                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
676
677         dbus_message_iter_init(message, &iter);
678         if (!pcoord_get_from_message(message, &iter, &pc))
679         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
680         
681         navit_set_position(navit, &pc);
682         return empty_reply(connection, message);
683 }
684
685 static DBusHandlerResult
686 request_navit_set_destination(DBusConnection *connection, DBusMessage *message)
687 {
688         struct pcoord pc;
689         struct navit *navit;
690         DBusMessageIter iter;
691         char *description;
692
693         navit = object_get_from_message(message, "navit");
694         if (! navit)
695                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
696
697         dbus_message_iter_init(message, &iter);
698         if (!pcoord_get_from_message(message, &iter, &pc))
699             return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
700         
701     dbus_message_iter_next(&iter);
702         dbus_message_iter_get_basic(&iter, &description);
703         dbg(0, " destination -> %s\n", description);
704         
705         navit_set_destination(navit, &pc, description, 1);
706         return empty_reply(connection, message);
707 }
708
709 static DBusHandlerResult
710 request_navit_evaluate(DBusConnection *connection, DBusMessage *message)
711 {
712         struct navit *navit;
713         char *command;
714         char *result;
715         struct attr attr;
716         DBusMessage *reply;
717         int *error;
718
719         navit = object_get_from_message(message, "navit");
720         if (! navit)
721                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
722
723         attr.type=attr_navit;
724         attr.u.navit=navit;
725         if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &command, DBUS_TYPE_INVALID))
726                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
727         result=command_evaluate_to_string(&attr, command, &error);
728         reply = dbus_message_new_method_return(message);
729         if (error)
730                 dbus_message_append_args(reply, DBUS_TYPE_INT32, error, DBUS_TYPE_INVALID);
731         else
732                 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
733         dbus_connection_send (connection, reply, NULL);
734         dbus_message_unref (reply);
735         return DBUS_HANDLER_RESULT_HANDLED;
736 }
737
738 static DBusHandlerResult
739 request_graphics_get_data(DBusConnection *connection, DBusMessage *message)
740 {
741         struct graphics *graphics;
742         char *data;
743         struct graphics_data_image *image;
744         DBusMessage *reply;
745
746         graphics = object_get_from_message(message, "graphics");
747         if (! graphics)
748                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
749
750         if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &data, DBUS_TYPE_INVALID))
751                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
752         image=graphics_get_data(graphics, data);
753         if (image) {
754                 DBusMessageIter iter1,iter2;
755                 reply = dbus_message_new_method_return(message);
756 #if 0
757                 dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID);
758 #endif
759                 dbus_message_iter_init_append(reply, &iter1);
760                 dbus_message_iter_open_container(&iter1, DBUS_TYPE_ARRAY, "y", &iter2);
761                 if (image->data && image->size) 
762                         dbus_message_iter_append_fixed_array(&iter2, DBUS_TYPE_BYTE, &image->data, image->size);
763                 dbus_message_iter_close_container(&iter1, &iter2);
764                 dbus_connection_send (connection, reply, NULL);
765                 dbus_message_unref (reply);
766                 return DBUS_HANDLER_RESULT_HANDLED;
767         }
768         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
769 }
770
771 struct dbus_method {
772         char *path;
773         char *method;
774         char *signature;
775     char *signature_name;
776     char *response;
777     char *response_name;
778         DBusHandlerResult(*func)(DBusConnection *connection, DBusMessage *message);
779 } dbus_methods[] = {
780         {"",        "iter",                "",        "",                                        "o",  "navit", request_main_iter},
781         {"",        "iter_destroy",        "o",       "navit",                                   "",   "",      request_main_iter_destroy},
782         {"",        "get_navit",           "o",       "navit",                                   "o",  "",      request_main_get_navit},
783         {".navit",  "draw",                "",        "",                                        "",   "",      request_navit_draw},
784         {".navit",  "add_message",         "s",       "message",                                 "",   "",      request_navit_add_message},
785         {".navit",  "set_center",          "s",       "(coordinates)",                           "",   "",      request_navit_set_center},
786         {".navit",  "set_center",          "(is)",    "(projection,coordinates)",                "",   "",      request_navit_set_center},
787         {".navit",  "set_center",          "(iii)",   "(projection,longitude,latitude)",         "",   "",      request_navit_set_center},
788         {".navit",  "set_center_screen",   "(ii)",    "(pixel_x,pixel_y)",                       "",   "",      request_navit_set_center_screen},
789         {".navit",  "set_layout",          "s",       "layoutname",                              "",   "",      request_navit_set_layout},
790         {".navit",  "zoom",                "i(ii)",   "factor(pixel_x,pixel_y)",                 "",   "",      request_navit_zoom},
791         {".navit",  "zoom",                "i",       "factor",                                  "",   "",      request_navit_zoom},
792         {".navit",  "resize",              "ii",      "upperleft,lowerright",                    "",   "",      request_navit_resize},
793         {".navit",  "get_attr",            "s",       "attribute",                               "v",  "value", request_navit_get_attr},
794         {".navit",  "set_attr",            "sv",      "attribute,value",                         "",   "",      request_navit_set_attr},
795         {".navit",  "set_position",        "s",       "(coordinates)",                           "",   "",      request_navit_set_position},
796         {".navit",  "set_position",        "(is)",    "(projection,coordinated)",                "",   "",      request_navit_set_position},
797         {".navit",  "set_position",        "(iii)",   "(projection,longitude,latitude)",         "",   "",      request_navit_set_position},
798         {".navit",  "set_destination",     "ss",      "coordinates,comment",                     "",   "",      request_navit_set_destination},
799         {".navit",  "set_destination",     "(is)s",   "(projection,coordinates)comment",         "",   "",      request_navit_set_destination},
800         {".navit",  "set_destination",     "(iii)s",  "(projection,longitude,latitude)comment",  "",   "",      request_navit_set_destination},
801         {".navit",  "evaluate",            "s",       "command",                                 "s",  "",     request_navit_evaluate},
802         {".graphics","get_data",           "s",       "type",                                    "ay",  "data", request_graphics_get_data},
803 #if 0
804     {".navit",  "toggle_announcer",    "",        "",                                        "",   "",      request_navit_toggle_announcer},
805         {".navit",  "toggle_announcer",    "i",       "",                                        "",   "",      request_navit_toggle_announcer},
806 #endif
807 };
808
809 static char *
810 introspect_path(char *object)
811 {
812         char *ret;
813         int i;
814         char *def=".default_";
815         int def_len=strlen(def);
816         if (strncmp(object, object_path, strlen(object_path)))
817                 return NULL;
818         ret=g_strdup(object+strlen(object_path));
819         dbg(0,"path=%s\n",ret);
820         for (i = strlen(ret)-1 ; i >= 0 ; i--) {
821                 if (ret[i] == '/' || (ret[i] >= '0' && ret[i] <= '9'))
822                         ret[i]='\0';
823                 else
824                         break;
825         }
826         for (i = 0 ; i < strlen(ret); i++)
827                 if (ret[i] == '/')
828                         ret[i]='.';
829         
830         for (i = strlen(ret)-1 ; i >= 0 ; i--) {
831                 if (!strncmp(ret+i, def, def_len)) {
832                         memmove(ret+1,ret+i+def_len,strlen(ret+i+def_len)+1);
833                         break;
834                 }
835         }
836         return ret;
837 }
838
839 static char *
840 generate_navitintrospectxml(char *object)
841 {
842     int i,methods_size,n=0;
843     char *navitintrospectxml;
844     char *path=introspect_path(object);
845     if (!path)
846         return NULL;
847     dbg(0,"path=%s\n",path);
848     
849     // write header and make navit introspectable
850     navitintrospectxml = g_strdup_printf("%s%s%s\n", navitintrospectxml_head1, object, navitintrospectxml_head2);
851     
852     methods_size=sizeof(dbus_methods)/sizeof(struct dbus_method);
853     for (i = 0 ; i < methods_size ; i++) {
854         // start new interface if it's the first method or it changed
855         if (strcmp(dbus_methods[i].path, path))
856                 continue;
857         if ((n == 0) || strcmp(dbus_methods[i-1].path, dbus_methods[i].path))
858             navitintrospectxml = g_strconcat_printf(navitintrospectxml, "  <interface name=\"%s%s\">\n", service_name, dbus_methods[i].path);
859         n++;
860         
861         // start the new method
862         navitintrospectxml = g_strconcat_printf(navitintrospectxml, "    <method name=\"%s\">\n", dbus_methods[i].method);
863
864         // set input signature if existent
865         if (strcmp(dbus_methods[i].signature, ""))
866             navitintrospectxml = g_strconcat_printf(navitintrospectxml, "      <arg direction=\"in\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].signature_name, dbus_methods[i].signature);
867         
868         // set response signature if existent
869         if (strcmp(dbus_methods[i].response, ""))
870             navitintrospectxml = g_strconcat_printf(navitintrospectxml, "      <arg direction=\"out\" name=\"%s\" type=\"%s\" />\n", dbus_methods[i].response_name, dbus_methods[i].response);
871         
872         // close the method
873         navitintrospectxml = g_strconcat_printf(navitintrospectxml, "    </method>\n");
874         
875         // close the interface if we reached the last method or the interface changes
876         if ((methods_size == i+1) || ((methods_size > i+1) && strcmp(dbus_methods[i+1].path, dbus_methods[i].path)))
877             navitintrospectxml = g_strconcat_printf(navitintrospectxml, "  </interface>\n\n");
878     }
879     // close the "mother tag"
880     navitintrospectxml = g_strconcat_printf(navitintrospectxml, "</node>\n");
881     
882     return navitintrospectxml;
883 }
884
885 static DBusHandlerResult
886 navit_handler_func(DBusConnection *connection, DBusMessage *message, void *user_data)
887 {
888         int i;
889         char *path;
890         dbg(0,"type=%s interface=%s path=%s member=%s signature=%s\n", dbus_message_type_to_string(dbus_message_get_type(message)), dbus_message_get_interface(message), dbus_message_get_path(message), dbus_message_get_member(message), dbus_message_get_signature(message));
891         if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
892                 DBusMessage *reply;
893                 char *navitintrospectxml = generate_navitintrospectxml(dbus_message_get_path(message));
894                 dbg(0,"Introspect %s:Result:%s\n",dbus_message_get_path(message), navitintrospectxml);
895                 if (navitintrospectxml) {
896                         reply = dbus_message_new_method_return(message);
897                         dbus_message_append_args(reply, DBUS_TYPE_STRING, &navitintrospectxml, DBUS_TYPE_INVALID);
898                         dbus_connection_send (connection, reply, NULL);
899                         dbus_message_unref (reply);
900                         g_free(navitintrospectxml);
901                         return DBUS_HANDLER_RESULT_HANDLED;
902                 }
903                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
904         }
905         
906     for (i = 0 ; i < sizeof(dbus_methods)/sizeof(struct dbus_method) ; i++) {
907                 path=g_strdup_printf("%s%s", service_name, dbus_methods[i].path);
908                 if (dbus_message_is_method_call(message, path, dbus_methods[i].method) &&
909                     dbus_message_has_signature(message, dbus_methods[i].signature)) {
910                         g_free(path);
911                         return dbus_methods[i].func(connection, message);
912                 }
913                 g_free(path);
914         }
915         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
916 }
917
918 static DBusObjectPathVTable dbus_navit_vtable = {
919         NULL,
920         navit_handler_func,
921         NULL
922 };
923
924 #if 0
925 DBusHandlerResult
926 filter(DBusConnection *connection, DBusMessage *message, void *user_data)
927 {
928         dbg(0,"type=%s interface=%s path=%s member=%s signature=%s\n", dbus_message_type_to_string(dbus_message_get_type(message)), dbus_message_get_interface(message), dbus_message_get_path(message), dbus_message_get_member(message), dbus_message_get_signature(message));
929         if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
930         }
931         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
932 }
933 #endif
934
935 void plugin_init(void)
936 {
937         DBusError error;
938
939     object_hash=g_hash_table_new(g_str_hash, g_str_equal);
940         object_count=g_hash_table_new(g_str_hash, g_str_equal);
941         dbg(0,"enter 1\n");
942         dbus_error_init(&error);
943         connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
944         if (!connection) {
945                 dbg(0,"Failed to open connection to session message bus: %s\n", error.message);
946                 dbus_error_free(&error);
947                 return;
948         }
949         dbus_connection_setup_with_g_main(connection, NULL);
950 #if 0
951         dbus_connection_add_filter(connection, filter, NULL, NULL);
952         dbus_bus_add_match(connection, "type='signal',""interface='" DBUS_INTERFACE_DBUS  "'", &error);
953 #endif
954         dbus_connection_register_fallback(connection, object_path, &dbus_navit_vtable, NULL);
955         dbus_bus_request_name(connection, service_name, 0, &error);
956         if (dbus_error_is_set(&error)) {
957                 dbg(0,"Failed to request name: %s", error.message);
958                 dbus_error_free (&error);
959         }
960 }