/* * Copyright (C) 2006, 2007 John Costigan. * * POI and GPS-Info code originally written by Cezary Jackiewicz. * * Default map data provided by http://www.openstreetmap.org/ * * This file is part of Maemo Mapper. * * Maemo Mapper is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Maemo Mapper is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Maemo Mapper. If not, see . */ #define _GNU_SOURCE #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #ifdef MAEMO_CHANGES /* probably not the best macro to check for here */ # include #endif #ifdef CONIC # include # include #endif #ifndef LEGACY # include # include #else # include # include #endif #include "types.h" #include "data.h" #include "defines.h" #include "cmenu.h" #include "dbus-ifc.h" #include "display.h" #include "gps.h" #include "aprs.h" #include "gpx.h" #include "input.h" #include "main.h" #include "maps.h" #include "menu.h" #include "path.h" #include "poi.h" #include "settings.h" #include "util.h" static void osso_cb_hw_state(osso_hw_state_t *state, gpointer data); static HildonProgram *_program = NULL; #ifdef CONIC static ConIcConnection *_conic_conn = NULL; static gboolean _conic_is_connecting = FALSE; static gboolean _conic_conn_failed = FALSE; static GMutex *_conic_connection_mutex = NULL; static GCond *_conic_connection_cond = NULL; #endif /* Dynamically-sized in-memory map cache. */ static size_t _map_cache_size = (32*1024*1024); static gboolean _map_cache_enabled = TRUE; #ifdef CONIC static void conic_conn_event(ConIcConnection *connection, ConIcConnectionEvent *event) { ConIcConnectionStatus status; printf("%s()\n", __PRETTY_FUNCTION__); g_mutex_lock(_conic_connection_mutex); status = con_ic_connection_event_get_status(event); if((_conic_is_connected = (status == CON_IC_STATUS_CONNECTED))) { /* We're connected. */ _conic_conn_failed = FALSE; if(_download_banner != NULL) gtk_widget_show(_download_banner); } else { /* We're not connected. */ /* Mark as a failed connection, if we had been trying to connect. */ _conic_conn_failed = _conic_is_connecting; if(_download_banner != NULL) gtk_widget_hide(_download_banner); } _conic_is_connecting = FALSE; /* No longer trying to connect. */ g_cond_broadcast(_conic_connection_cond); g_mutex_unlock(_conic_connection_mutex); vprintf("%s(): return\n", __PRETTY_FUNCTION__); } #endif void conic_recommend_connected() { printf("%s()\n", __PRETTY_FUNCTION__); #if defined(__arm__) && defined(CONIC) g_mutex_lock(_conic_connection_mutex); if(!_conic_is_connecting) { /* Fire up a connection request. */ con_ic_connection_connect(_conic_conn, CON_IC_CONNECT_FLAG_NONE); _conic_is_connecting = TRUE; } g_mutex_unlock(_conic_connection_mutex); #endif vprintf("%s(): return\n", __PRETTY_FUNCTION__); } gboolean conic_ensure_connected() { printf("%s()\n", __PRETTY_FUNCTION__); #if defined(__arm__) && defined(CONIC) while(_window && !_conic_is_connected) { g_mutex_lock(_conic_connection_mutex); /* If we're not connected, and if we're not connecting, and if we're * not in the wake of a connection failure, then try to connect. */ if(!_conic_is_connected && !_conic_is_connecting &&!_conic_conn_failed) { /* Fire up a connection request. */ con_ic_connection_connect(_conic_conn, CON_IC_CONNECT_FLAG_NONE); _conic_is_connecting = TRUE; } g_cond_wait(_conic_connection_cond, _conic_connection_mutex); g_mutex_unlock(_conic_connection_mutex); } #else _conic_is_connected = TRUE; #endif vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, _window && _conic_is_connected); return _window && _conic_is_connected; } /** * Save state and destroy all non-UI elements created by this program in * preparation for exiting. */ static void maemo_mapper_destroy() { printf("%s()\n", __PRETTY_FUNCTION__); /* _program and widgets have already been destroyed. */ _window = NULL; gps_destroy(FALSE); path_destroy(); settings_save(); poi_destroy(); g_mutex_lock(_mut_priority_mutex); _mut_priority_tree = g_tree_new((GCompareFunc)mut_priority_comparefunc); g_mutex_unlock(_mut_priority_mutex); /* Allow remaining downloads to finish. */ #ifdef CONIC g_mutex_lock(_conic_connection_mutex); g_cond_broadcast(_conic_connection_cond); g_mutex_unlock(_conic_connection_mutex); #endif g_thread_pool_free(_mut_thread_pool, TRUE, TRUE); maps_destroy(); gps_destroy(TRUE); vprintf("%s(): return\n", __PRETTY_FUNCTION__); } /** * Initialize everything required in preparation for calling gtk_main(). */ static void maemo_mapper_init(gint argc, gchar **argv) { GtkWidget *hbox, *label, *vbox; printf("%s()\n", __PRETTY_FUNCTION__); /* Set enum-based constants. */ UNITS_ENUM_TEXT[UNITS_KM] = _("km"); UNITS_ENUM_TEXT[UNITS_MI] = _("mi."); UNITS_ENUM_TEXT[UNITS_NM] = _("n.m."); ROTATE_DIR_ENUM_TEXT[ROTATE_DIR_UP] = _("Up"); ROTATE_DIR_ENUM_TEXT[ROTATE_DIR_RIGHT] = _("Right"); ROTATE_DIR_ENUM_TEXT[ROTATE_DIR_DOWN] = _("Down"); ROTATE_DIR_ENUM_TEXT[ROTATE_DIR_LEFT] = _("Left"); UNBLANK_ENUM_TEXT[UNBLANK_WITH_GPS] = _("When Receiving Any GPS Data"); UNBLANK_ENUM_TEXT[UNBLANK_WHEN_MOVING] = _("When Moving"); UNBLANK_ENUM_TEXT[UNBLANK_FULLSCREEN] = _("When Moving (Full Screen Only)"); UNBLANK_ENUM_TEXT[UNBLANK_WAYPOINT] = _("When Approaching a Waypoint"); UNBLANK_ENUM_TEXT[UNBLANK_NEVER] = _("Never"); INFO_FONT_ENUM_TEXT[INFO_FONT_XXSMALL] = "xx-small"; INFO_FONT_ENUM_TEXT[INFO_FONT_XSMALL] = "x-small"; INFO_FONT_ENUM_TEXT[INFO_FONT_SMALL] = "small"; INFO_FONT_ENUM_TEXT[INFO_FONT_MEDIUM] = "medium"; INFO_FONT_ENUM_TEXT[INFO_FONT_LARGE] = "large"; INFO_FONT_ENUM_TEXT[INFO_FONT_XLARGE] = "x-large"; INFO_FONT_ENUM_TEXT[INFO_FONT_XXLARGE] = "xx-large"; #ifdef MAEMO_CHANGES /* probably not the best macro to check for here */ CUSTOM_KEY_ICON[CUSTOM_KEY_UP] = HWK_BUTTON_UP; CUSTOM_KEY_ICON[CUSTOM_KEY_LEFT] = HWK_BUTTON_LEFT; CUSTOM_KEY_ICON[CUSTOM_KEY_DOWN] = HWK_BUTTON_DOWN; CUSTOM_KEY_ICON[CUSTOM_KEY_RIGHT] = HWK_BUTTON_RIGHT; CUSTOM_KEY_ICON[CUSTOM_KEY_SELECT] = HWK_BUTTON_SELECT; CUSTOM_KEY_ICON[CUSTOM_KEY_INCREASE] = HWK_BUTTON_INCREASE; CUSTOM_KEY_ICON[CUSTOM_KEY_DECREASE] = HWK_BUTTON_DECREASE; CUSTOM_KEY_ICON[CUSTOM_KEY_FULLSCREEN] = HWK_BUTTON_VIEW; CUSTOM_KEY_ICON[CUSTOM_KEY_ESC] = HWK_BUTTON_CANCEL; #else CUSTOM_KEY_ICON[CUSTOM_KEY_UP] = "Up"; CUSTOM_KEY_ICON[CUSTOM_KEY_LEFT] = "Left"; CUSTOM_KEY_ICON[CUSTOM_KEY_DOWN] = "Down"; CUSTOM_KEY_ICON[CUSTOM_KEY_RIGHT] = "Right"; CUSTOM_KEY_ICON[CUSTOM_KEY_SELECT] = "Enter"; CUSTOM_KEY_ICON[CUSTOM_KEY_INCREASE] = "F7"; CUSTOM_KEY_ICON[CUSTOM_KEY_DECREASE] = "F8"; CUSTOM_KEY_ICON[CUSTOM_KEY_FULLSCREEN] = "F6"; CUSTOM_KEY_ICON[CUSTOM_KEY_ESC] = "Esc"; #endif CUSTOM_KEY_DEFAULT[CUSTOM_KEY_UP] = CUSTOM_ACTION_RESET_VIEW_ANGLE; CUSTOM_KEY_DEFAULT[CUSTOM_KEY_LEFT] =CUSTOM_ACTION_ROTATE_COUNTERCLOCKWISE; CUSTOM_KEY_DEFAULT[CUSTOM_KEY_DOWN] = CUSTOM_ACTION_TOGGLE_AUTOROTATE; CUSTOM_KEY_DEFAULT[CUSTOM_KEY_RIGHT] = CUSTOM_ACTION_ROTATE_CLOCKWISE; CUSTOM_KEY_DEFAULT[CUSTOM_KEY_SELECT] = CUSTOM_ACTION_TOGGLE_AUTOCENTER; CUSTOM_KEY_DEFAULT[CUSTOM_KEY_INCREASE] = CUSTOM_ACTION_ZOOM_IN; CUSTOM_KEY_DEFAULT[CUSTOM_KEY_DECREASE] = CUSTOM_ACTION_ZOOM_OUT; CUSTOM_KEY_DEFAULT[CUSTOM_KEY_FULLSCREEN]= CUSTOM_ACTION_TOGGLE_FULLSCREEN; CUSTOM_KEY_DEFAULT[CUSTOM_KEY_ESC] = CUSTOM_ACTION_TOGGLE_TRACKS; CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_NORTH] = _("Pan North"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_WEST] = _("Pan West"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_SOUTH] = _("Pan South"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_EAST] = _("Pan East"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_UP] = _("Pan Up"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_DOWN] = _("Pan Down"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_LEFT] = _("Pan Left"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_PAN_RIGHT] = _("Pan Right"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_RESET_VIEW_ANGLE] = _("Reset Viewing Angle"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ROTATE_CLOCKWISE] = _("Rotate View Clockwise"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ROTATE_COUNTERCLOCKWISE] = _("Rotate View Counter-Clockwise"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_AUTOCENTER] = _("Toggle Auto-Center"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_AUTOROTATE] = _("Toggle Auto-Rotate"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_FULLSCREEN] = _("Toggle Fullscreen"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ZOOM_IN] = _("Zoom In"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ZOOM_OUT] = _("Zoom Out"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_TRACKING] = _("Toggle Tracking"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_TRACKS] = _("Toggle Tracks/Routes"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_SCALE] = _("Toggle Scale"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_POI] = _("Toggle POIs"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_CHANGE_REPO] = _("Select Next Repository"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ROUTE_DISTNEXT] = _("Show Distance to Next Waypoint"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_ROUTE_DISTLAST] = _("Show Distance to End of Route"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TRACK_BREAK]=_("Insert Track Break"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TRACK_CLEAR] = _("Clear Track"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TRACK_DISTLAST] = _("Show Distance from Last Break"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TRACK_DISTFIRST] = _("Show Distance from Beginning"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_GPS] = _("Toggle GPS"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_GPSINFO]=_("Toggle GPS Info"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_SPEEDLIMIT] = _("Toggle Speed Limit"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_RESET_BLUETOOTH] = _("Reset Bluetooth"); CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_TOGGLE_LAYERS] = _("Toggle Layers"); DEG_FORMAT_ENUM_TEXT[DDPDDDDD].name = "-dd.ddddd°"; DEG_FORMAT_ENUM_TEXT[DDPDDDDD].short_field_1 = "Lat"; DEG_FORMAT_ENUM_TEXT[DDPDDDDD].long_field_1 = "Latitude"; DEG_FORMAT_ENUM_TEXT[DDPDDDDD].short_field_2 = "Lon"; DEG_FORMAT_ENUM_TEXT[DDPDDDDD].long_field_2 = "Longitude"; DEG_FORMAT_ENUM_TEXT[DDPDDDDD].field_2_in_use = TRUE; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM].name = "-dd°mm.mmm'"; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM].short_field_1 = "Lat"; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM].long_field_1 = "Latitude"; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM].short_field_2 = "Lon"; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM].long_field_2 = "Longitude"; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM].field_2_in_use = TRUE; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS].name = "-dd°mm'ss.s\""; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS].short_field_1 = "Lat"; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS].long_field_1 = "Latitude"; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS].short_field_2 = "Lon"; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS].long_field_2 = "Longitude"; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS].field_2_in_use = TRUE; DEG_FORMAT_ENUM_TEXT[DDPDDDDD_NSEW].name = "dd.ddddd° S"; DEG_FORMAT_ENUM_TEXT[DDPDDDDD_NSEW].short_field_1 = "Lat"; DEG_FORMAT_ENUM_TEXT[DDPDDDDD_NSEW].long_field_1 = "Latitude"; DEG_FORMAT_ENUM_TEXT[DDPDDDDD_NSEW].short_field_2 = "Lon"; DEG_FORMAT_ENUM_TEXT[DDPDDDDD_NSEW].long_field_2 = "Longitude"; DEG_FORMAT_ENUM_TEXT[DDPDDDDD_NSEW].field_2_in_use = TRUE; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM_NSEW].name = "dd°mm.mmm' S"; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM_NSEW].short_field_1 = "Lat"; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM_NSEW].long_field_1 = "Latitude"; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM_NSEW].short_field_2 = "Lon"; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM_NSEW].long_field_2 = "Longitude"; DEG_FORMAT_ENUM_TEXT[DD_MMPMMM_NSEW].field_2_in_use = TRUE; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS_NSEW].name = "dd°mm'ss.s\" S"; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS_NSEW].short_field_1 = "Lat"; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS_NSEW].long_field_1 = "Latitude"; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS_NSEW].short_field_2 = "Lon"; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS_NSEW].long_field_2 = "Longitude"; DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS_NSEW].field_2_in_use = TRUE; DEG_FORMAT_ENUM_TEXT[NSEW_DDPDDDDD].name = "S dd.ddddd°"; DEG_FORMAT_ENUM_TEXT[NSEW_DDPDDDDD].short_field_1 = "Lat"; DEG_FORMAT_ENUM_TEXT[NSEW_DDPDDDDD].long_field_1 = "Latitude"; DEG_FORMAT_ENUM_TEXT[NSEW_DDPDDDDD].short_field_2 = "Lon"; DEG_FORMAT_ENUM_TEXT[NSEW_DDPDDDDD].long_field_2 = "Longitude"; DEG_FORMAT_ENUM_TEXT[NSEW_DDPDDDDD].field_2_in_use = TRUE; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MMPMMM].name = "S dd° mm.mmm'"; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MMPMMM].short_field_1 = "Lat"; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MMPMMM].long_field_1 = "Latitude"; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MMPMMM].short_field_2 = "Lon"; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MMPMMM].long_field_2 = "Longitude"; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MMPMMM].field_2_in_use = TRUE; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MM_SSPS].name = "S dd° mm' ss.s\""; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MM_SSPS].short_field_1 = "Lat"; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MM_SSPS].long_field_1 = "Latitude"; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MM_SSPS].short_field_2 = "Lon"; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MM_SSPS].long_field_2 = "Longitude"; DEG_FORMAT_ENUM_TEXT[NSEW_DD_MM_SSPS].field_2_in_use = TRUE; // Used by Radio Amateurs DEG_FORMAT_ENUM_TEXT[IARU_LOC].name = "IARU Locator"; DEG_FORMAT_ENUM_TEXT[IARU_LOC].short_field_1 = "Locator"; DEG_FORMAT_ENUM_TEXT[IARU_LOC].long_field_1 = "Locator"; DEG_FORMAT_ENUM_TEXT[IARU_LOC].short_field_2 = ""; DEG_FORMAT_ENUM_TEXT[IARU_LOC].long_field_2 = ""; DEG_FORMAT_ENUM_TEXT[IARU_LOC].field_2_in_use = FALSE; DEG_FORMAT_ENUM_TEXT[UK_OSGB].name = "OSGB X,Y Grid"; DEG_FORMAT_ENUM_TEXT[UK_OSGB].short_field_1 = "X"; DEG_FORMAT_ENUM_TEXT[UK_OSGB].long_field_1 = "OS X"; DEG_FORMAT_ENUM_TEXT[UK_OSGB].short_field_2 = "Y"; DEG_FORMAT_ENUM_TEXT[UK_OSGB].long_field_2 = "OS Y"; DEG_FORMAT_ENUM_TEXT[UK_OSGB].field_2_in_use = TRUE; DEG_FORMAT_ENUM_TEXT[UK_NGR].name = "OSGB Landranger Grid (8)"; DEG_FORMAT_ENUM_TEXT[UK_NGR].short_field_1 = "GR"; DEG_FORMAT_ENUM_TEXT[UK_NGR].long_field_1 = "OS Grid"; DEG_FORMAT_ENUM_TEXT[UK_NGR].short_field_2 = ""; DEG_FORMAT_ENUM_TEXT[UK_NGR].long_field_2 = ""; DEG_FORMAT_ENUM_TEXT[UK_NGR].field_2_in_use = FALSE; DEG_FORMAT_ENUM_TEXT[UK_NGR6].name = "OSGB Landranger Grid (6)"; DEG_FORMAT_ENUM_TEXT[UK_NGR6].short_field_1 = "GR"; DEG_FORMAT_ENUM_TEXT[UK_NGR6].long_field_1 = "OS Grid"; DEG_FORMAT_ENUM_TEXT[UK_NGR6].short_field_2 = ""; DEG_FORMAT_ENUM_TEXT[UK_NGR6].long_field_2 = ""; DEG_FORMAT_ENUM_TEXT[UK_NGR6].field_2_in_use = FALSE; SPEED_LOCATION_ENUM_TEXT[SPEED_LOCATION_TOP_LEFT] = _("Top-Left"); SPEED_LOCATION_ENUM_TEXT[SPEED_LOCATION_TOP_RIGHT] = _("Top-Right"); SPEED_LOCATION_ENUM_TEXT[SPEED_LOCATION_BOTTOM_RIGHT] = _("Bottom-Right"); SPEED_LOCATION_ENUM_TEXT[SPEED_LOCATION_BOTTOM_LEFT] = _("Bottom-Left"); GPS_RCVR_ENUM_TEXT[GPS_RCVR_BT] = _("Bluetooth"); GPS_RCVR_ENUM_TEXT[GPS_RCVR_GPSD] = _("GPSD"); GPS_RCVR_ENUM_TEXT[GPS_RCVR_FILE] = _("File"); /* Set up track array (must be done before config). */ memset(&_track, 0, sizeof(_track)); memset(&_route, 0, sizeof(_route)); /* initialisation of paths is done in path_init() */ _mapdb_mutex = g_mutex_new(); _mut_priority_mutex = g_mutex_new(); _mouse_mutex = g_mutex_new(); #ifdef CONIC _conic_connection_mutex = g_mutex_new(); _conic_connection_cond = g_cond_new(); #endif settings_init(); maps_init(_map_cache_size); /* Initialize _program. */ _program = HILDON_PROGRAM(hildon_program_get_instance()); g_set_application_name("Maemo Mapper"); /* Initialize _window. */ _window = GTK_WIDGET(hildon_window_new()); hildon_program_add_window(_program, HILDON_WINDOW(_window)); gtk_window_set_default_size(GTK_WINDOW(_window), 800, 480); /* Create and add widgets and supporting data. */ hbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(_window), hbox); _gps_widget = gtk_frame_new("GPS Info"); gtk_container_add(GTK_CONTAINER(_gps_widget), vbox = gtk_vbox_new(FALSE, 0)); gtk_widget_set_size_request(GTK_WIDGET(_gps_widget), 180, 0); gtk_box_pack_start(GTK_BOX(hbox), _gps_widget, FALSE, TRUE, 0); label = gtk_label_new(" "); gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0); _text_lat = gtk_label_new(" --- "); gtk_widget_set_size_request(GTK_WIDGET(_text_lat), -1, 30); gtk_box_pack_start(GTK_BOX(vbox), _text_lat, FALSE, TRUE, 0); _text_lon = gtk_label_new(" --- "); gtk_widget_set_size_request(GTK_WIDGET(_text_lon), -1, 30); gtk_box_pack_start(GTK_BOX(vbox), _text_lon, FALSE, TRUE, 0); _text_speed = gtk_label_new(" --- "); gtk_widget_set_size_request(GTK_WIDGET(_text_speed), -1, 30); gtk_box_pack_start(GTK_BOX(vbox), _text_speed, FALSE, TRUE, 0); _text_alt = gtk_label_new(" --- "); gtk_widget_set_size_request(GTK_WIDGET(_text_alt), -1, 30); gtk_box_pack_start(GTK_BOX(vbox), _text_alt, FALSE, TRUE, 0); label = gtk_label_new(" "); gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0); _sat_panel = gtk_drawing_area_new (); gtk_widget_set_size_request (_sat_panel, -1, 100); gtk_box_pack_start(GTK_BOX(vbox), _sat_panel, TRUE, TRUE, 0); label = gtk_label_new(" "); gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0); _text_time = gtk_label_new("--:--:--"); gtk_widget_set_size_request(GTK_WIDGET(_text_time), -1, 30); gtk_box_pack_start(GTK_BOX(vbox), _text_time, FALSE, TRUE, 0); _heading_panel = gtk_drawing_area_new (); gtk_widget_set_size_request (_heading_panel, -1, 100); gtk_box_pack_start(GTK_BOX(vbox), _heading_panel, TRUE, TRUE, 0); _map_widget = gtk_drawing_area_new(); gtk_box_pack_start(GTK_BOX(hbox), _map_widget, TRUE, TRUE, 0); gtk_widget_show_all(hbox); gps_show_info(); /* hides info, if necessary. */ gtk_widget_realize(_map_widget); /* Tweak the foreground and background colors a little bit... */ { GdkColor color; GdkGCValues values; GdkColormap *colormap = gtk_widget_get_colormap(_map_widget); gdk_gc_get_values( _map_widget->style->fg_gc[GTK_STATE_NORMAL], &values); gdk_colormap_query_color(colormap, values.foreground.pixel, &color); gtk_widget_modify_fg(_map_widget, GTK_STATE_ACTIVE, &color); gdk_gc_get_values( _map_widget->style->bg_gc[GTK_STATE_NORMAL], &values); gdk_colormap_query_color(colormap, values.foreground.pixel, &color); gtk_widget_modify_bg(_map_widget, GTK_STATE_ACTIVE, &color); /* Use a black background for _map_widget, since missing tiles are * also drawn with a black background. */ color.red = 0; color.green = 0; color.blue = 0; gtk_widget_modify_bg(_map_widget, GTK_STATE_NORMAL, &color); } _map_pixmap = gdk_pixmap_new(_map_widget->window, 1, 1, -1); /* -1: use bit depth of widget->window. */ _map_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 1, 1); _mut_exists_table = g_hash_table_new( (GHashFunc)mut_exists_hashfunc, (GEqualFunc)mut_exists_equalfunc); _mut_priority_tree = g_tree_new((GCompareFunc)mut_priority_comparefunc); _mut_thread_pool = g_thread_pool_new( (GFunc)thread_proc_mut, NULL, NUM_DOWNLOAD_THREADS, FALSE, NULL); _mrt_thread_pool = g_thread_pool_new( (GFunc)thread_render_map, NULL, 1, FALSE, NULL); /* Connect signals. */ g_signal_connect(G_OBJECT(_window), "destroy", G_CALLBACK(gtk_main_quit), NULL); memset(&_autoroute_data, 0, sizeof(_autoroute_data)); latlon2unit(_gps.lat, _gps.lon, _pos.unitx, _pos.unity); /* Initialize our line styles. */ update_gcs(); menu_init(); cmenu_init(); path_init(); gps_init(); input_init(); poi_db_connect(); display_init(); dbus_ifc_init(); #ifdef INCLUDE_APRS aprs_init(); #endif //INCLUDE_APRS /* If present, attempt to load the file specified on the command line. */ if(argc > 1) { GnomeVFSResult vfs_result; gint size; gchar *buffer; gchar *file_uri; /* Get the selected filename. */ file_uri = gnome_vfs_make_uri_from_shell_arg(argv[1]); if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file( file_uri, &size, &buffer))) { gchar buffer[BUFFER_SIZE]; snprintf(buffer, sizeof(buffer), "%s:\n%s", _("Failed to open file for reading"), gnome_vfs_result_to_string(vfs_result)); popup_error(_window, buffer); } else { if(gpx_path_parse(&_route, buffer, size, 0)) { path_save_route_to_db(); MACRO_BANNER_SHOW_INFO(_window, _("Route Opened")); } else popup_error(_window, _("Error parsing GPX file.")); g_free(buffer); } g_free(file_uri); } /* If we have a route, calculate the next point. */ route_find_nearest_point(); #ifdef CONIC _conic_conn = con_ic_connection_new(); g_object_set(_conic_conn, "automatic-connection-events", TRUE, NULL); g_signal_connect(G_OBJECT(_conic_conn), "connection-event", G_CALLBACK(conic_conn_event), NULL); #endif g_idle_add((GSourceFunc)window_present, NULL); osso_hw_set_event_cb(_osso, NULL, osso_cb_hw_state, NULL); /* Lets go fullscreen if so requested in saved config */ if (_fullscreen) { gtk_window_fullscreen(GTK_WINDOW(_window)); } vprintf("%s(): return\n", __PRETTY_FUNCTION__); } static gboolean osso_cb_hw_state_idle(osso_hw_state_t *state) { static gboolean _must_save_data = FALSE; printf("%s(inact=%d, save=%d, shut=%d, memlow=%d, state=%d)\n", __PRETTY_FUNCTION__, state->system_inactivity_ind, state->save_unsaved_data_ind, state->shutdown_ind, state->memory_low_ind, state->sig_device_mode_ind); if(state->shutdown_ind) { maemo_mapper_destroy(); exit(1); } if(state->save_unsaved_data_ind) { settings_save(); _must_save_data = TRUE; } if(state->memory_low_ind) { // Disable the map cache and set the next max cache size to // slightly less than the current cache size. _map_cache_size = map_cache_resize(0) * 0.8; _map_cache_enabled = FALSE; } else { if(!_map_cache_enabled) { // Restore the map cache. map_cache_resize(_map_cache_size); _map_cache_enabled = TRUE; } } g_free(state); vprintf("%s(): return\n", __PRETTY_FUNCTION__); return FALSE; } static void osso_cb_hw_state(osso_hw_state_t *state, gpointer data) { printf("%s()\n", __PRETTY_FUNCTION__); osso_hw_state_t *state_copy = g_new(osso_hw_state_t, 1); memcpy(state_copy, state, sizeof(osso_hw_state_t)); g_idle_add((GSourceFunc)osso_cb_hw_state_idle, state_copy); vprintf("%s(): return\n", __PRETTY_FUNCTION__); } gint main(gint argc, gchar *argv[]) { printf("%s()\n", __PRETTY_FUNCTION__); /* Initialize localization. */ setlocale(LC_ALL, ""); bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); g_thread_init(NULL); /* Initialize _osso. */ _osso = osso_initialize("com.gnuite.maemo_mapper", VERSION, TRUE, NULL); if(!_osso) { g_printerr("osso_initialize failed.\n"); return 1; } gtk_init(&argc, &argv); /* Init gconf. */ g_type_init(); gconf_init(argc, argv, NULL); /* Init Gnome-VFS. */ gnome_vfs_init(); #ifdef DEBUG /* This is just some helpful DBUS testing code. */ if(argc >= 3) { /* Try to set the center to a new lat/lon. */ GError *error = NULL; gchar *error_check; gdouble lat, lon; DBusGConnection *bus; DBusGProxy *proxy; bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error); if(!bus || error) { g_printerr("Error: %s\n", error->message); return -1; } proxy = dbus_g_proxy_new_for_name(bus, MM_DBUS_SERVICE, MM_DBUS_PATH, MM_DBUS_INTERFACE); lat = g_ascii_strtod((argv[1]), &error_check); if(error_check == argv[1]) { g_printerr("Failed to parse string as float: %s\n", argv[1]); return 1; } lon = g_ascii_strtod((argv[2]), &error_check); if(error_check == argv[2]) { g_printerr("Failed to parse string as float: %s\n", argv[2]); return 2; } error = NULL; if(argc >= 4) { /* We are specifying a zoom. */ gint zoom; zoom = g_ascii_strtod((argv[3]), &error_check); if(error_check == argv[3]) { g_printerr("Failed to parse string as integer: %s\n", argv[3]); return 3; } if(!dbus_g_proxy_call(proxy, MM_DBUS_METHOD_SET_VIEW_POSITION, &error, G_TYPE_DOUBLE, lat, G_TYPE_DOUBLE, lon, G_TYPE_INT, zoom, G_TYPE_INVALID, G_TYPE_INVALID) || error) { g_printerr("Error: %s\n", error->message); return 4; } } else { /* Not specifying a zoom. */ if(!dbus_g_proxy_call(proxy, MM_DBUS_METHOD_SET_VIEW_POSITION, &error, G_TYPE_DOUBLE, lat, G_TYPE_DOUBLE, lon, G_TYPE_INVALID, G_TYPE_INVALID) || error) { g_printerr("Error: %s\n", error->message); return -2; } } g_object_unref(proxy); dbus_g_connection_unref(bus); return 0; } #endif maemo_mapper_init(argc, argv); gtk_main(); maemo_mapper_destroy(); osso_deinitialize(_osso); vprintf("%s(): return\n", __PRETTY_FUNCTION__); exit(0); }