]> git.itanic.dy.fi Git - maemo-mapper/blob - src/main.c
5ce2abf349c819d5205b9880722a8b48e04bd96c
[maemo-mapper] / src / main.c
1 /*
2  * Copyright (C) 2006, 2007 John Costigan.
3  *
4  * POI and GPS-Info code originally written by Cezary Jackiewicz.
5  *
6  * Default map data provided by http://www.openstreetmap.org/
7  *
8  * This file is part of Maemo Mapper.
9  *
10  * Maemo Mapper is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * Maemo Mapper is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Maemo Mapper.  If not, see <http://www.gnu.org/licenses/>.
22  */
23
24 #define _GNU_SOURCE
25
26 #ifdef HAVE_CONFIG_H
27 #    include "config.h"
28 #endif
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 #include <dbus/dbus-glib.h>
34 #include <locale.h>
35
36 #include <gconf/gconf-client.h>
37
38 #ifdef MAEMO_CHANGES /* probably not the best macro to check for here */
39 #    include <device_symbols.h>
40 #endif
41
42 #ifdef CONIC
43 #    include <conicconnection.h>
44 #    include <conicconnectionevent.h>
45 #endif
46
47 #ifndef LEGACY
48 #    include <hildon/hildon-program.h>
49 #    include <hildon/hildon-banner.h>
50 #else
51 #    include <hildon-widgets/hildon-program.h>
52 #    include <hildon-widgets/hildon-banner.h>
53 #endif
54
55 #include "types.h"
56 #include "data.h"
57 #include "defines.h"
58
59 #include "cmenu.h"
60 #include "dbus-ifc.h"
61 #include "display.h"
62 #include "gps.h"
63 #include "gpx.h"
64 #include "input.h"
65 #include "main.h"
66 #include "maps.h"
67 #include "menu.h"
68 #include "path.h"
69 #include "poi.h"
70 #include "settings.h"
71 #include "util.h"
72
73 static void osso_cb_hw_state(osso_hw_state_t *state, gpointer data);
74
75 static HildonProgram *_program = NULL;
76
77 #ifdef CONIC
78 static ConIcConnection *_conic_conn = NULL;
79 static gboolean _conic_is_connecting = FALSE;
80 static gboolean _conic_conn_failed = FALSE;
81 static GMutex *_conic_connection_mutex = NULL;
82 static GCond *_conic_connection_cond = NULL;
83 #endif
84
85 /* Dynamically-sized in-memory map cache. */
86 static size_t _map_cache_size = (32*1024*1024);
87 static gboolean _map_cache_enabled = TRUE;
88
89 #ifdef CONIC
90 static void
91 conic_conn_event(ConIcConnection *connection, ConIcConnectionEvent *event)
92 {
93     ConIcConnectionStatus status;
94     printf("%s()\n", __PRETTY_FUNCTION__);
95
96     g_mutex_lock(_conic_connection_mutex);
97
98     status = con_ic_connection_event_get_status(event);
99
100     if((_conic_is_connected = (status == CON_IC_STATUS_CONNECTED)))
101     {
102         /* We're connected. */
103         _conic_conn_failed = FALSE;
104         if(_download_banner != NULL)
105             gtk_widget_show(_download_banner);
106     }
107     else
108     {
109         /* We're not connected. */
110         /* Mark as a failed connection, if we had been trying to connect. */
111         _conic_conn_failed = _conic_is_connecting;
112         if(_download_banner != NULL)
113             gtk_widget_hide(_download_banner);
114     }
115
116     _conic_is_connecting = FALSE; /* No longer trying to connect. */
117     g_cond_broadcast(_conic_connection_cond);
118     g_mutex_unlock(_conic_connection_mutex);
119
120     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
121 }
122 #endif
123
124 void
125 conic_recommend_connected()
126 {
127     printf("%s()\n", __PRETTY_FUNCTION__);
128
129 #if defined(__arm__) && defined(CONIC)
130     g_mutex_lock(_conic_connection_mutex);
131     if(!_conic_is_connecting)
132     {
133         /* Fire up a connection request. */
134         con_ic_connection_connect(_conic_conn, CON_IC_CONNECT_FLAG_NONE);
135         _conic_is_connecting = TRUE;
136     }
137     g_mutex_unlock(_conic_connection_mutex);
138 #endif
139
140     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
141 }
142
143 gboolean
144 conic_ensure_connected()
145 {
146     printf("%s()\n", __PRETTY_FUNCTION__);
147
148 #if defined(__arm__) && defined(CONIC)
149     while(_window && !_conic_is_connected)
150     {   
151         g_mutex_lock(_conic_connection_mutex);
152         /* If we're not connected, and if we're not connecting, and if we're
153          * not in the wake of a connection failure, then try to connect. */
154         if(!_conic_is_connected && !_conic_is_connecting &&!_conic_conn_failed)
155         {
156             /* Fire up a connection request. */
157             con_ic_connection_connect(_conic_conn, CON_IC_CONNECT_FLAG_NONE);
158             _conic_is_connecting = TRUE;
159         }
160         g_cond_wait(_conic_connection_cond, _conic_connection_mutex);
161         g_mutex_unlock(_conic_connection_mutex);
162     }
163 #else
164     _conic_is_connected = TRUE;
165 #endif
166
167     vprintf("%s(): return %d\n", __PRETTY_FUNCTION__,
168             _window && _conic_is_connected);
169     return _window && _conic_is_connected;
170 }
171
172 /**
173  * Save state and destroy all non-UI elements created by this program in
174  * preparation for exiting.
175  */
176 static void
177 maemo_mapper_destroy()
178 {
179     printf("%s()\n", __PRETTY_FUNCTION__);
180
181     /* _program and widgets have already been destroyed. */
182     _window = NULL;
183
184     gps_destroy(FALSE);
185
186     path_destroy();
187
188     settings_save();
189
190     poi_destroy();
191
192     g_mutex_lock(_mut_priority_mutex);
193     _mut_priority_tree = g_tree_new((GCompareFunc)mut_priority_comparefunc);
194     g_mutex_unlock(_mut_priority_mutex);
195
196     /* Allow remaining downloads to finish. */
197 #ifdef CONIC
198     g_mutex_lock(_conic_connection_mutex);
199     g_cond_broadcast(_conic_connection_cond);
200     g_mutex_unlock(_conic_connection_mutex);
201 #endif
202     g_thread_pool_free(_mut_thread_pool, TRUE, TRUE);
203
204     if(_curr_repo->db)
205     {
206         RepoData* repo_p;
207 #ifdef MAPDB_SQLITE
208         g_mutex_lock(_mapdb_mutex);
209         sqlite3_close(_curr_repo->db);
210         _curr_repo->db = NULL;
211         g_mutex_unlock(_mapdb_mutex);
212 #else
213         g_mutex_lock(_mapdb_mutex);
214         repo_p = _curr_repo;
215         while (repo_p) {
216             if (repo_p->db) {
217 /*                 /\* perform reorganization for layers which are auto refreshed *\/ */
218 /*                 if (repo_p->layer_level && repo_p->layer_refresh_interval) */
219 /*                     gdbm_reorganize (repo_p->db); */
220                 gdbm_close(repo_p->db);
221             }
222             repo_p->db = NULL;
223             repo_p = repo_p->layers;
224         }
225         g_mutex_unlock(_mapdb_mutex);
226 #endif
227     }
228     map_cache_destroy();
229
230     gps_destroy(TRUE);
231
232     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
233 }
234
235 /**
236  * Initialize everything required in preparation for calling gtk_main().
237  */
238 static void
239 maemo_mapper_init(gint argc, gchar **argv)
240 {
241     GtkWidget *hbox, *label, *vbox;
242     printf("%s()\n", __PRETTY_FUNCTION__);
243
244     /* Set enum-based constants. */
245     UNITS_ENUM_TEXT[UNITS_KM] = _("km");
246     UNITS_ENUM_TEXT[UNITS_MI] = _("mi.");
247     UNITS_ENUM_TEXT[UNITS_NM] = _("n.m.");
248
249     ROTATE_DIR_ENUM_TEXT[ROTATE_DIR_UP] = _("Up");
250     ROTATE_DIR_ENUM_TEXT[ROTATE_DIR_RIGHT] = _("Right");
251     ROTATE_DIR_ENUM_TEXT[ROTATE_DIR_DOWN] = _("Down");
252     ROTATE_DIR_ENUM_TEXT[ROTATE_DIR_LEFT] = _("Left");
253
254     UNBLANK_ENUM_TEXT[UNBLANK_WITH_GPS] = _("When Receiving Any GPS Data");
255     UNBLANK_ENUM_TEXT[UNBLANK_WHEN_MOVING] = _("When Moving");
256     UNBLANK_ENUM_TEXT[UNBLANK_FULLSCREEN] = _("When Moving (Full Screen Only)");
257     UNBLANK_ENUM_TEXT[UNBLANK_WAYPOINT] = _("When Approaching a Waypoint");
258     UNBLANK_ENUM_TEXT[UNBLANK_NEVER] = _("Never");
259
260     INFO_FONT_ENUM_TEXT[INFO_FONT_XXSMALL] = "xx-small";
261     INFO_FONT_ENUM_TEXT[INFO_FONT_XSMALL] = "x-small";
262     INFO_FONT_ENUM_TEXT[INFO_FONT_SMALL] = "small";
263     INFO_FONT_ENUM_TEXT[INFO_FONT_MEDIUM] = "medium";
264     INFO_FONT_ENUM_TEXT[INFO_FONT_LARGE] = "large";
265     INFO_FONT_ENUM_TEXT[INFO_FONT_XLARGE] = "x-large";
266     INFO_FONT_ENUM_TEXT[INFO_FONT_XXLARGE] = "xx-large";
267
268 #ifdef MAEMO_CHANGES /* probably not the best macro to check for here */
269     CUSTOM_KEY_ICON[CUSTOM_KEY_UP] = HWK_BUTTON_UP;
270     CUSTOM_KEY_ICON[CUSTOM_KEY_LEFT] = HWK_BUTTON_LEFT;
271     CUSTOM_KEY_ICON[CUSTOM_KEY_DOWN] = HWK_BUTTON_DOWN;
272     CUSTOM_KEY_ICON[CUSTOM_KEY_RIGHT] = HWK_BUTTON_RIGHT;
273     CUSTOM_KEY_ICON[CUSTOM_KEY_SELECT] = HWK_BUTTON_SELECT;
274     CUSTOM_KEY_ICON[CUSTOM_KEY_INCREASE] = HWK_BUTTON_INCREASE;
275     CUSTOM_KEY_ICON[CUSTOM_KEY_DECREASE] = HWK_BUTTON_DECREASE;
276     CUSTOM_KEY_ICON[CUSTOM_KEY_FULLSCREEN] = HWK_BUTTON_VIEW;
277     CUSTOM_KEY_ICON[CUSTOM_KEY_ESC] = HWK_BUTTON_CANCEL;
278 #else
279     CUSTOM_KEY_ICON[CUSTOM_KEY_UP] = "Up";
280     CUSTOM_KEY_ICON[CUSTOM_KEY_LEFT] = "Left";
281     CUSTOM_KEY_ICON[CUSTOM_KEY_DOWN] = "Down";
282     CUSTOM_KEY_ICON[CUSTOM_KEY_RIGHT] = "Right";
283     CUSTOM_KEY_ICON[CUSTOM_KEY_SELECT] = "Enter";
284     CUSTOM_KEY_ICON[CUSTOM_KEY_INCREASE] = "F7";
285     CUSTOM_KEY_ICON[CUSTOM_KEY_DECREASE] = "F8";
286     CUSTOM_KEY_ICON[CUSTOM_KEY_FULLSCREEN] = "F6";
287     CUSTOM_KEY_ICON[CUSTOM_KEY_ESC] = "Esc";
288 #endif
289
290     CUSTOM_KEY_DEFAULT[CUSTOM_KEY_UP] = CUSTOM_ACTION_RESET_VIEW_ANGLE;
291     CUSTOM_KEY_DEFAULT[CUSTOM_KEY_LEFT] =CUSTOM_ACTION_ROTATE_COUNTERCLOCKWISE;
292     CUSTOM_KEY_DEFAULT[CUSTOM_KEY_DOWN] = CUSTOM_ACTION_TOGGLE_AUTOROTATE;
293     CUSTOM_KEY_DEFAULT[CUSTOM_KEY_RIGHT] = CUSTOM_ACTION_ROTATE_CLOCKWISE;
294     CUSTOM_KEY_DEFAULT[CUSTOM_KEY_SELECT] = CUSTOM_ACTION_TOGGLE_AUTOCENTER;
295     CUSTOM_KEY_DEFAULT[CUSTOM_KEY_INCREASE] = CUSTOM_ACTION_ZOOM_IN;
296     CUSTOM_KEY_DEFAULT[CUSTOM_KEY_DECREASE] = CUSTOM_ACTION_ZOOM_OUT;
297     CUSTOM_KEY_DEFAULT[CUSTOM_KEY_FULLSCREEN]= CUSTOM_ACTION_TOGGLE_FULLSCREEN;
298     CUSTOM_KEY_DEFAULT[CUSTOM_KEY_ESC] = CUSTOM_ACTION_TOGGLE_TRACKS;
299
300     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_NORTH] = _("Pan North");
301     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_WEST] = _("Pan West");
302     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_SOUTH] = _("Pan South");
303     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_EAST] = _("Pan East");
304     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_UP] = _("Pan Up");
305     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_DOWN] = _("Pan Down");
306     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_LEFT] = _("Pan Left");
307     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_RIGHT] = _("Pan Right");
308     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_RESET_VIEW_ANGLE]
309         = _("Reset Viewing Angle");
310     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ROTATE_CLOCKWISE]
311         = _("Rotate View Clockwise");
312     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ROTATE_COUNTERCLOCKWISE]
313         = _("Rotate View Counter-Clockwise");
314     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_AUTOCENTER]
315         = _("Toggle Auto-Center");
316     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_AUTOROTATE]
317         = _("Toggle Auto-Rotate");
318     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_FULLSCREEN]
319         = _("Toggle Fullscreen");
320     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ZOOM_IN] = _("Zoom In");
321     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ZOOM_OUT] = _("Zoom Out");
322     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_TRACKING]
323         = _("Toggle Tracking");
324     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_TRACKS]
325         = _("Toggle Tracks/Routes");
326     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_SCALE] = _("Toggle Scale");
327     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_POI] = _("Toggle POIs");
328     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_CHANGE_REPO]
329         = _("Select Next Repository");
330     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ROUTE_DISTNEXT]
331         = _("Show Distance to Next Waypoint");
332     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ROUTE_DISTLAST]
333         = _("Show Distance to End of Route");
334     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TRACK_BREAK]=_("Insert Track Break");
335     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TRACK_CLEAR] = _("Clear Track");
336     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TRACK_DISTLAST]
337         = _("Show Distance from Last Break");
338     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TRACK_DISTFIRST]
339         = _("Show Distance from Beginning");
340     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_GPS] = _("Toggle GPS");
341     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_GPSINFO]=_("Toggle GPS Info");
342     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_SPEEDLIMIT]
343         = _("Toggle Speed Limit");
344     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_RESET_BLUETOOTH]
345         = _("Reset Bluetooth");
346     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_LAYERS] = _("Toggle Layers");
347
348     DEG_FORMAT_ENUM_TEXT[DDPDDDDD] = "-dd.ddddd°";
349     DEG_FORMAT_ENUM_TEXT[DD_MMPMMM] = "-dd°mm.mmm'";
350     DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS] = "-dd°mm'ss.s\"";
351     DEG_FORMAT_ENUM_TEXT[DDPDDDDD_NSEW] = "dd.ddddd° S";
352     DEG_FORMAT_ENUM_TEXT[DD_MMPMMM_NSEW] = "dd°mm.mmm' S";
353     DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS_NSEW] = "dd°mm'ss.s\" S";
354     DEG_FORMAT_ENUM_TEXT[NSEW_DDPDDDDD] = "S dd.ddddd°";
355     DEG_FORMAT_ENUM_TEXT[NSEW_DD_MMPMMM] = "S dd° mm.mmm'";
356     DEG_FORMAT_ENUM_TEXT[NSEW_DD_MM_SSPS] = "S dd° mm' ss.s\"";
357
358     SPEED_LOCATION_ENUM_TEXT[SPEED_LOCATION_TOP_LEFT] = _("Top-Left");
359     SPEED_LOCATION_ENUM_TEXT[SPEED_LOCATION_TOP_RIGHT] = _("Top-Right");
360     SPEED_LOCATION_ENUM_TEXT[SPEED_LOCATION_BOTTOM_RIGHT] = _("Bottom-Right");
361     SPEED_LOCATION_ENUM_TEXT[SPEED_LOCATION_BOTTOM_LEFT] = _("Bottom-Left");
362
363     GPS_RCVR_ENUM_TEXT[GPS_RCVR_BT] = _("Bluetooth");
364     GPS_RCVR_ENUM_TEXT[GPS_RCVR_GPSD] = _("GPSD");
365     GPS_RCVR_ENUM_TEXT[GPS_RCVR_FILE] = _("File");
366
367     /* Set up track array (must be done before config). */
368     memset(&_track, 0, sizeof(_track));
369     memset(&_route, 0, sizeof(_route));
370     /* initialisation of paths is done in path_init() */
371
372     _mapdb_mutex = g_mutex_new();
373     _mut_priority_mutex = g_mutex_new();
374     _mouse_mutex = g_mutex_new();
375
376 #ifdef CONIC
377     _conic_connection_mutex = g_mutex_new();
378     _conic_connection_cond = g_cond_new();
379 #endif
380
381     settings_init();
382     map_cache_init(_map_cache_size);
383
384     /* Initialize _program. */
385     _program = HILDON_PROGRAM(hildon_program_get_instance());
386     g_set_application_name("Maemo Mapper");
387
388     /* Initialize _window. */
389     _window = GTK_WIDGET(hildon_window_new());
390     hildon_program_add_window(_program, HILDON_WINDOW(_window));
391
392     gtk_window_set_default_size(GTK_WINDOW(_window), 800, 480);
393
394     /* Lets go fullscreen if so requested in saved config */
395     if (_fullscreen) {
396       gtk_window_fullscreen(GTK_WINDOW(_window));
397     }
398
399     /* Create and add widgets and supporting data. */
400     hbox = gtk_hbox_new(FALSE, 0);
401     gtk_container_add(GTK_CONTAINER(_window), hbox);
402
403     _gps_widget = gtk_frame_new("GPS Info");
404     gtk_container_add(GTK_CONTAINER(_gps_widget),
405             vbox = gtk_vbox_new(FALSE, 0));
406     gtk_widget_set_size_request(GTK_WIDGET(_gps_widget), 180, 0);
407     gtk_box_pack_start(GTK_BOX(hbox), _gps_widget, FALSE, TRUE, 0);
408
409     label = gtk_label_new(" ");
410     gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10);
411     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
412
413     _text_lat = gtk_label_new(" --- ");
414     gtk_widget_set_size_request(GTK_WIDGET(_text_lat), -1, 30);
415     gtk_box_pack_start(GTK_BOX(vbox), _text_lat, FALSE, TRUE, 0);
416
417     _text_lon = gtk_label_new(" --- ");
418     gtk_widget_set_size_request(GTK_WIDGET(_text_lon), -1, 30);
419     gtk_box_pack_start(GTK_BOX(vbox), _text_lon, FALSE, TRUE, 0);
420
421     _text_speed = gtk_label_new(" --- ");
422     gtk_widget_set_size_request(GTK_WIDGET(_text_speed), -1, 30);
423     gtk_box_pack_start(GTK_BOX(vbox), _text_speed, FALSE, TRUE, 0);
424
425     _text_alt = gtk_label_new(" --- ");
426     gtk_widget_set_size_request(GTK_WIDGET(_text_alt), -1, 30);
427     gtk_box_pack_start(GTK_BOX(vbox), _text_alt, FALSE, TRUE, 0);
428
429     label = gtk_label_new(" ");
430     gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10);
431     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
432
433     _sat_panel = gtk_drawing_area_new ();
434     gtk_widget_set_size_request (_sat_panel, -1, 100);
435     gtk_box_pack_start(GTK_BOX(vbox), _sat_panel, TRUE, TRUE, 0);
436
437     label = gtk_label_new(" ");
438     gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10);
439     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
440
441     _text_time = gtk_label_new("--:--:--");
442     gtk_widget_set_size_request(GTK_WIDGET(_text_time), -1, 30);
443     gtk_box_pack_start(GTK_BOX(vbox), _text_time, FALSE, TRUE, 0);
444
445     _heading_panel = gtk_drawing_area_new ();
446     gtk_widget_set_size_request (_heading_panel, -1, 100);
447     gtk_box_pack_start(GTK_BOX(vbox), _heading_panel, TRUE, TRUE, 0);
448
449     _map_widget = gtk_drawing_area_new();
450
451     gtk_box_pack_start(GTK_BOX(hbox), _map_widget, TRUE, TRUE, 0);
452
453     gtk_widget_show_all(hbox);
454     gps_show_info(); /* hides info, if necessary. */
455
456     gtk_widget_realize(_map_widget);
457
458     /* Tweak the foreground and background colors a little bit... */
459     {
460         GdkColor color;
461         GdkGCValues values;
462         GdkColormap *colormap = gtk_widget_get_colormap(_map_widget);
463
464         gdk_gc_get_values(
465                 _map_widget->style->fg_gc[GTK_STATE_NORMAL],
466                 &values);
467         gdk_colormap_query_color(colormap, values.foreground.pixel, &color);
468         gtk_widget_modify_fg(_map_widget, GTK_STATE_ACTIVE, &color);
469
470         gdk_gc_get_values(
471                 _map_widget->style->bg_gc[GTK_STATE_NORMAL],
472                 &values);
473         gdk_colormap_query_color(colormap, values.foreground.pixel, &color);
474         gtk_widget_modify_bg(_map_widget, GTK_STATE_ACTIVE, &color);
475
476         /* Use a black background for _map_widget, since missing tiles are
477          * also drawn with a black background. */
478         color.red = 0; color.green = 0; color.blue = 0;
479         gtk_widget_modify_bg(_map_widget,
480                 GTK_STATE_NORMAL, &color);
481     }
482
483     _map_pixmap = gdk_pixmap_new(_map_widget->window, 1, 1, -1);
484     /* -1: use bit depth of widget->window. */
485
486     _map_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 1, 1);
487
488     _mut_exists_table = g_hash_table_new(
489             (GHashFunc)mut_exists_hashfunc, (GEqualFunc)mut_exists_equalfunc);
490     _mut_priority_tree = g_tree_new((GCompareFunc)mut_priority_comparefunc);
491
492     _mut_thread_pool = g_thread_pool_new(
493             (GFunc)thread_proc_mut, NULL, NUM_DOWNLOAD_THREADS, FALSE, NULL);
494     _mrt_thread_pool = g_thread_pool_new(
495             (GFunc)thread_render_map, NULL, 1, FALSE, NULL);
496
497     /* Connect signals. */
498     g_signal_connect(G_OBJECT(_window), "destroy",
499             G_CALLBACK(gtk_main_quit), NULL);
500
501     memset(&_autoroute_data, 0, sizeof(_autoroute_data));
502
503     latlon2unit(_gps.lat, _gps.lon, _pos.unitx, _pos.unity);
504
505     /* Initialize our line styles. */
506     update_gcs();
507
508     menu_init();
509     cmenu_init();
510     path_init();
511     gps_init();
512     input_init();
513     poi_db_connect();
514     display_init();
515     dbus_ifc_init();
516
517     /* If present, attempt to load the file specified on the command line. */
518     if(argc > 1)
519     {
520         GnomeVFSResult vfs_result;
521         gint size;
522         gchar *buffer;
523         gchar *file_uri;
524
525         /* Get the selected filename. */
526         file_uri = gnome_vfs_make_uri_from_shell_arg(argv[1]);
527
528         if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
529                         file_uri, &size, &buffer)))
530         {
531             gchar buffer[BUFFER_SIZE];
532             snprintf(buffer, sizeof(buffer),
533                     "%s:\n%s", _("Failed to open file for reading"),
534                     gnome_vfs_result_to_string(vfs_result));
535             popup_error(_window, buffer);
536         }
537         else
538         {
539             if(gpx_path_parse(&_route, buffer, size, 0))
540             {
541                 path_save_route_to_db();
542                 MACRO_BANNER_SHOW_INFO(_window, _("Route Opened"));
543             }
544             else
545                 popup_error(_window, _("Error parsing GPX file."));
546             g_free(buffer);
547         }
548         g_free(file_uri);
549     }
550
551     /* If we have a route, calculate the next point. */
552     route_find_nearest_point();
553
554 #ifdef CONIC
555     _conic_conn = con_ic_connection_new();
556     g_object_set(_conic_conn, "automatic-connection-events", TRUE, NULL);
557     g_signal_connect(G_OBJECT(_conic_conn), "connection-event",
558             G_CALLBACK(conic_conn_event), NULL);
559 #endif
560
561     g_idle_add((GSourceFunc)window_present, NULL);
562
563
564     osso_hw_set_event_cb(_osso, NULL, osso_cb_hw_state, NULL);
565
566     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
567 }
568
569 static gboolean
570 osso_cb_hw_state_idle(osso_hw_state_t *state)
571 {
572     static gboolean _must_save_data = FALSE;
573     printf("%s(inact=%d, save=%d, shut=%d, memlow=%d, state=%d)\n",
574             __PRETTY_FUNCTION__, state->system_inactivity_ind,
575             state->save_unsaved_data_ind, state->shutdown_ind,
576             state->memory_low_ind, state->sig_device_mode_ind);
577
578     if(state->shutdown_ind)
579     {
580         maemo_mapper_destroy();
581         exit(1);
582     }
583
584     if(state->save_unsaved_data_ind)
585     {
586         settings_save();
587         _must_save_data = TRUE;
588     }
589
590     if(state->memory_low_ind)
591     {
592         // Disable the map cache and set the next max cache size to
593         // slightly less than the current cache size.
594         _map_cache_size = map_cache_resize(0) * 0.8;
595         _map_cache_enabled = FALSE;
596     }
597     else
598     {
599         if(!_map_cache_enabled)
600         {
601             // Restore the map cache.
602             map_cache_resize(_map_cache_size);
603             _map_cache_enabled = TRUE;
604         }
605     }
606
607     g_free(state);
608
609     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
610     return FALSE;
611 }
612
613 static void
614 osso_cb_hw_state(osso_hw_state_t *state, gpointer data)
615 {
616     printf("%s()\n", __PRETTY_FUNCTION__);
617     osso_hw_state_t *state_copy = g_new(osso_hw_state_t, 1);
618     memcpy(state_copy, state, sizeof(osso_hw_state_t));
619     g_idle_add((GSourceFunc)osso_cb_hw_state_idle, state_copy);
620     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
621 }
622
623 gint
624 main(gint argc, gchar *argv[])
625 {
626     printf("%s()\n", __PRETTY_FUNCTION__);
627
628     /* Initialize localization. */
629     setlocale(LC_ALL, "");
630     bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
631     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
632     textdomain(GETTEXT_PACKAGE);
633
634     g_thread_init(NULL);
635
636     /* Initialize _osso. */
637     _osso = osso_initialize("com.gnuite.maemo_mapper", VERSION, TRUE, NULL);
638     if(!_osso)
639     {
640         g_printerr("osso_initialize failed.\n");
641         return 1;
642     }
643
644     gtk_init(&argc, &argv);
645
646     /* Init gconf. */
647     g_type_init();
648     gconf_init(argc, argv, NULL);
649
650     /* Init Gnome-VFS. */
651     gnome_vfs_init();
652
653 #ifdef DEBUG
654     /* This is just some helpful DBUS testing code. */
655     if(argc >= 3)
656     {
657         /* Try to set the center to a new lat/lon. */
658         GError *error = NULL;
659         gchar *error_check;
660         gdouble lat, lon;
661         DBusGConnection *bus;
662         DBusGProxy *proxy;
663         
664         bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
665         if(!bus || error)
666         {
667             g_printerr("Error: %s\n", error->message);
668             return -1;
669         }
670
671         proxy = dbus_g_proxy_new_for_name(bus,
672                         MM_DBUS_SERVICE, MM_DBUS_PATH, MM_DBUS_INTERFACE);
673
674         lat = g_ascii_strtod((argv[1]), &error_check);
675         if(error_check == argv[1])
676         {
677             g_printerr("Failed to parse string as float: %s\n", argv[1]);
678             return 1;
679         }
680
681         lon = g_ascii_strtod((argv[2]), &error_check);
682         if(error_check == argv[2])
683         {
684             g_printerr("Failed to parse string as float: %s\n", argv[2]);
685             return 2;
686         }
687
688         error = NULL;
689         if(argc >= 4)
690         {
691             /* We are specifying a zoom. */
692             gint zoom;
693
694             zoom = g_ascii_strtod((argv[3]), &error_check);
695             if(error_check == argv[3])
696             {
697                 g_printerr("Failed to parse string as integer: %s\n", argv[3]);
698                 return 3;
699             }
700             if(!dbus_g_proxy_call(proxy, MM_DBUS_METHOD_SET_VIEW_POSITION,
701                         &error,
702                         G_TYPE_DOUBLE, lat, G_TYPE_DOUBLE, lon,
703                         G_TYPE_INT, zoom, G_TYPE_INVALID,
704                         G_TYPE_INVALID)
705                     || error)
706             {
707                 g_printerr("Error: %s\n", error->message);
708                 return 4;
709             }
710         }
711         else
712         {
713             /* Not specifying a zoom. */
714             if(!dbus_g_proxy_call(proxy, MM_DBUS_METHOD_SET_VIEW_POSITION,
715                         &error,
716                         G_TYPE_DOUBLE, lat, G_TYPE_DOUBLE, lon, G_TYPE_INVALID,
717                         G_TYPE_INVALID)
718                     || error)
719             {
720                 g_printerr("Error: %s\n", error->message);
721                 return -2;
722             }
723         }
724
725         g_object_unref(proxy);
726         dbus_g_connection_unref(bus);
727
728         return 0;
729     }
730 #endif
731
732     maemo_mapper_init(argc, argv);
733
734     gtk_main();
735
736     maemo_mapper_destroy();
737
738     osso_deinitialize(_osso);
739
740     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
741     exit(0);
742 }
743