]> git.itanic.dy.fi Git - maemo-mapper/commitdiff
* Added an in-memory map cache to improve pan performance (thanks to Tim
authorgnuite <gnuite@gmail.com>
Sat, 12 Jan 2008 22:46:01 +0000 (22:46 +0000)
committergnuite <gnuite@gmail.com>
Sat, 12 Jan 2008 22:46:01 +0000 (22:46 +0000)
    Terriberry for the patch).
  * Fixed bug with infinitely repeating auto-route-update error messages.
  * Added option to completely disable all announcements.

git-svn-id: svn+ssh://garage/var/lib/gforge/svnroot/maemo-mapper/trunk@144 6c538b50-5814-0410-93ad-8bdf4c0149d1

src/data.c
src/data.h
src/defines.h
src/main.c
src/maps.c
src/maps.h
src/path.c
src/settings.c

index aa34b8fe1c2670b8774eabe832758b024a7441a0..27c9f8090a431fc6461a548961cefb81657decf3 100644 (file)
@@ -182,6 +182,7 @@ gint _draw_width = 5;
 gint _rotate_sens = 5;
 gint _ac_min_speed = 2;
 RotateDir _rotate_dir = ROTATE_DIR_UP;
 gint _rotate_sens = 5;
 gint _ac_min_speed = 2;
 RotateDir _rotate_dir = ROTATE_DIR_UP;
+gboolean _enable_announce = TRUE;
 gint _announce_notice_ratio = 8;
 gboolean _enable_voice = TRUE;
 GSList *_loc_list;
 gint _announce_notice_ratio = 8;
 gboolean _enable_voice = TRUE;
 GSList *_loc_list;
index 92ffbcf4b378e6f1bd0f7501e920b033a1a2b3c8..da3e984fae99348e6f424d4bc4811de061df9c3e 100644 (file)
@@ -161,6 +161,7 @@ extern gint _draw_width;
 extern gint _rotate_sens;
 extern gint _ac_min_speed;
 extern RotateDir _rotate_dir;
 extern gint _rotate_sens;
 extern gint _ac_min_speed;
 extern RotateDir _rotate_dir;
+extern gboolean _enable_announce;
 extern gint _announce_notice_ratio;
 extern gboolean _enable_voice;
 extern GSList *_loc_list;
 extern gint _announce_notice_ratio;
 extern gboolean _enable_voice;
 extern GSList *_loc_list;
index 01caeaed57c423e9e47590d6249f77bcc1ec1b47..6f209aee39fbf1a36379a3f6becc534402f4c224 100644 (file)
 
 #define INITIAL_DOWNLOAD_RETRIES (3)
 
 
 #define INITIAL_DOWNLOAD_RETRIES (3)
 
-#define GCONF_KEY_PREFIX "/apps/maemo/maemo-mapper"
-#define GCONF_KEY_GPS_RCVR_TYPE GCONF_KEY_PREFIX"/gps_rcvr_type"
-#define GCONF_KEY_GPS_BT_MAC GCONF_KEY_PREFIX"/receiver_mac"
-#define GCONF_KEY_GPS_GPSD_HOST GCONF_KEY_PREFIX"/gps_gpsd_host"
-#define GCONF_KEY_GPS_GPSD_PORT GCONF_KEY_PREFIX"/gps_gpsd_port"
-#define GCONF_KEY_GPS_FILE_PATH GCONF_KEY_PREFIX"/gps_file_path"
-#define GCONF_KEY_AUTO_DOWNLOAD GCONF_KEY_PREFIX"/auto_download"
-#define GCONF_KEY_AUTO_DOWNLOAD_PRECACHE \
-                                      GCONF_KEY_PREFIX"/auto_download_precache"
-#define GCONF_KEY_CENTER_SENSITIVITY GCONF_KEY_PREFIX"/center_sensitivity"
-#define GCONF_KEY_ANNOUNCE_NOTICE GCONF_KEY_PREFIX"/announce_notice"
-#define GCONF_KEY_ROTATE_SENSITIVITY GCONF_KEY_PREFIX"/rotate_sensitivity"
-#define GCONF_KEY_AC_MIN_SPEED GCONF_KEY_PREFIX"/autocenter_min_speed"
-#define GCONF_KEY_ROTATE_DIR GCONF_KEY_PREFIX"/rotate_direction"
-#define GCONF_KEY_DRAW_WIDTH GCONF_KEY_PREFIX"/draw_width"
-#define GCONF_KEY_ENABLE_VOICE GCONF_KEY_PREFIX"/enable_voice"
-#define GCONF_KEY_VOICE_SPEED GCONF_KEY_PREFIX"/voice_speed"
-#define GCONF_KEY_VOICE_PITCH GCONF_KEY_PREFIX"/voice_pitch"
-#define GCONF_KEY_FULLSCREEN GCONF_KEY_PREFIX"/fullscreen"
-#define GCONF_KEY_UNITS GCONF_KEY_PREFIX"/units"
-#define GCONF_KEY_SPEED_LIMIT_ON GCONF_KEY_PREFIX"/speed_limit_on"
-#define GCONF_KEY_SPEED_LIMIT GCONF_KEY_PREFIX"/speed_limit"
-#define GCONF_KEY_SPEED_LOCATION GCONF_KEY_PREFIX"/speed_location"
-#define GCONF_KEY_UNBLANK_SIZE GCONF_KEY_PREFIX"/unblank_option"
-#define GCONF_KEY_INFO_FONT_SIZE GCONF_KEY_PREFIX"/info_font_size"
-
-#define GCONF_KEY_POI_DB GCONF_KEY_PREFIX"/poi_db"
-#define GCONF_KEY_POI_ZOOM GCONF_KEY_PREFIX"/poi_zoom"
-
-#define GCONF_KEY_AUTOCENTER_MODE GCONF_KEY_PREFIX"/autocenter_mode"
-#define GCONF_KEY_AUTOCENTER_ROTATE GCONF_KEY_PREFIX"/autocenter_rotate"
-#define GCONF_KEY_LEAD_AMOUNT GCONF_KEY_PREFIX"/lead_amount"
-#define GCONF_KEY_LEAD_IS_FIXED GCONF_KEY_PREFIX"/lead_is_fixed"
-#define GCONF_KEY_LAST_LAT GCONF_KEY_PREFIX"/last_latitude"
-#define GCONF_KEY_LAST_LON GCONF_KEY_PREFIX"/last_longitude"
-#define GCONF_KEY_LAST_ALT GCONF_KEY_PREFIX"/last_altitude"
-#define GCONF_KEY_LAST_SPEED GCONF_KEY_PREFIX"/last_speed"
-#define GCONF_KEY_LAST_HEADING GCONF_KEY_PREFIX"/last_heading"
-#define GCONF_KEY_LAST_TIME GCONF_KEY_PREFIX"/last_timestamp"
-#define GCONF_KEY_CENTER_LAT GCONF_KEY_PREFIX"/center_latitude"
-#define GCONF_KEY_CENTER_LON GCONF_KEY_PREFIX"/center_longitude"
-#define GCONF_KEY_CENTER_ANGLE GCONF_KEY_PREFIX"/center_angle"
-#define GCONF_KEY_ZOOM GCONF_KEY_PREFIX"/zoom"
-#define GCONF_KEY_ROUTEDIR GCONF_KEY_PREFIX"/route_directory"
-#define GCONF_KEY_TRACKFILE GCONF_KEY_PREFIX"/track_file"
-#define GCONF_KEY_SHOWZOOMLEVEL GCONF_KEY_PREFIX"/show_zoomlevel"
-#define GCONF_KEY_SHOWSCALE GCONF_KEY_PREFIX"/show_scale"
-#define GCONF_KEY_SHOWCOMPROSE GCONF_KEY_PREFIX"/show_comprose"
-#define GCONF_KEY_SHOWTRACKS GCONF_KEY_PREFIX"/show_tracks"
-#define GCONF_KEY_SHOWROUTES GCONF_KEY_PREFIX"/show_routes"
-#define GCONF_KEY_SHOWVELVEC GCONF_KEY_PREFIX"/show_velocity_vector"
-#define GCONF_KEY_SHOWPOIS GCONF_KEY_PREFIX"/show_poi"
-#define GCONF_KEY_ENABLE_GPS GCONF_KEY_PREFIX"/enable_gps"
-#define GCONF_KEY_ROUTE_LOCATIONS GCONF_KEY_PREFIX"/route_locations"
-#define GCONF_KEY_REPOSITORIES GCONF_KEY_PREFIX"/repositories"
-#define GCONF_KEY_CURRREPO GCONF_KEY_PREFIX"/curr_repo"
-#define GCONF_KEY_GPS_INFO GCONF_KEY_PREFIX"/gps_info"
-#define GCONF_KEY_ROUTE_DL_URL GCONF_KEY_PREFIX"/route_dl_url"
-#define GCONF_KEY_ROUTE_DL_RADIUS GCONF_KEY_PREFIX"/route_dl_radius"
-#define GCONF_KEY_POI_DL_URL GCONF_KEY_PREFIX"/poi_dl_url"
-#define GCONF_KEY_DEG_FORMAT GCONF_KEY_PREFIX"/deg_format"
-
 #define CONFIG_DIR_NAME "~/.maemo-mapper/"
 #define CONFIG_PATH_DB_FILE "paths.db"
 
 #define CONFIG_DIR_NAME "~/.maemo-mapper/"
 #define CONFIG_PATH_DB_FILE "paths.db"
 
index 93ed9c26ebb08d301b48c9e3e6daf577b3be42f2..efeed6e152f0e54086b78461e4dc98c91596ded7 100644 (file)
@@ -74,6 +74,10 @@ static gboolean _conic_conn_failed = FALSE;
 static GMutex *_conic_connection_mutex = NULL;
 static GCond *_conic_connection_cond = NULL;
 
 static GMutex *_conic_connection_mutex = NULL;
 static GCond *_conic_connection_cond = NULL;
 
+/* Dynamically-sized in-memory map cache. */
+static size_t _map_cache_size = (32*1024*1024);
+static gboolean _map_cache_enabled = TRUE;
+
 static void
 conic_conn_event(ConIcConnection *connection, ConIcConnectionEvent *event)
 {
 static void
 conic_conn_event(ConIcConnection *connection, ConIcConnectionEvent *event)
 {
@@ -192,6 +196,7 @@ maemo_mapper_destroy()
         g_mutex_unlock(_mapdb_mutex);
 #endif
     }
         g_mutex_unlock(_mapdb_mutex);
 #endif
     }
+    map_cache_destroy();
 
     gps_destroy(TRUE);
 
 
     gps_destroy(TRUE);
 
@@ -231,16 +236,6 @@ maemo_mapper_init(gint argc, gchar **argv)
     INFO_FONT_ENUM_TEXT[INFO_FONT_XLARGE] = "x-large";
     INFO_FONT_ENUM_TEXT[INFO_FONT_XXLARGE] = "xx-large";
 
     INFO_FONT_ENUM_TEXT[INFO_FONT_XLARGE] = "x-large";
     INFO_FONT_ENUM_TEXT[INFO_FONT_XXLARGE] = "xx-large";
 
-    CUSTOM_KEY_GCONF[CUSTOM_KEY_UP] = GCONF_KEY_PREFIX"/key_up";
-    CUSTOM_KEY_GCONF[CUSTOM_KEY_DOWN] = GCONF_KEY_PREFIX"/key_down";
-    CUSTOM_KEY_GCONF[CUSTOM_KEY_LEFT] = GCONF_KEY_PREFIX"/key_left";
-    CUSTOM_KEY_GCONF[CUSTOM_KEY_RIGHT] = GCONF_KEY_PREFIX"/key_right";
-    CUSTOM_KEY_GCONF[CUSTOM_KEY_SELECT] = GCONF_KEY_PREFIX"/key_select";
-    CUSTOM_KEY_GCONF[CUSTOM_KEY_INCREASE] = GCONF_KEY_PREFIX"/key_increase";
-    CUSTOM_KEY_GCONF[CUSTOM_KEY_DECREASE] = GCONF_KEY_PREFIX"/key_decrease";
-    CUSTOM_KEY_GCONF[CUSTOM_KEY_FULLSCREEN]= GCONF_KEY_PREFIX"/key_fullscreen";
-    CUSTOM_KEY_GCONF[CUSTOM_KEY_ESC] = GCONF_KEY_PREFIX"/key_esc";
-
     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_UP] = HWK_BUTTON_UP;
     CUSTOM_KEY_ICON[CUSTOM_KEY_LEFT] = HWK_BUTTON_LEFT;
     CUSTOM_KEY_ICON[CUSTOM_KEY_DOWN] = HWK_BUTTON_DOWN;
@@ -305,20 +300,6 @@ maemo_mapper_init(gint argc, gchar **argv)
     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_RESET_BLUETOOTH]
         = _("Reset Bluetooth");
 
     CUSTOM_ACTION_ENUM_TEXT[CUSTOM_ACTION_RESET_BLUETOOTH]
         = _("Reset Bluetooth");
 
-    COLORABLE_GCONF[COLORABLE_MARK] = GCONF_KEY_PREFIX"/color_mark";
-    COLORABLE_GCONF[COLORABLE_MARK_VELOCITY]
-        = GCONF_KEY_PREFIX"/color_mark_velocity";
-    COLORABLE_GCONF[COLORABLE_MARK_OLD] = GCONF_KEY_PREFIX"/color_mark_old";
-    COLORABLE_GCONF[COLORABLE_TRACK] = GCONF_KEY_PREFIX"/color_track";
-    COLORABLE_GCONF[COLORABLE_TRACK_MARK] =GCONF_KEY_PREFIX"/color_track_mark";
-    COLORABLE_GCONF[COLORABLE_TRACK_BREAK]
-        = GCONF_KEY_PREFIX"/color_track_break";
-    COLORABLE_GCONF[COLORABLE_ROUTE] = GCONF_KEY_PREFIX"/color_route";
-    COLORABLE_GCONF[COLORABLE_ROUTE_WAY] = GCONF_KEY_PREFIX"/color_route_way";
-    COLORABLE_GCONF[COLORABLE_ROUTE_BREAK]
-        = GCONF_KEY_PREFIX"/color_route_break";
-    COLORABLE_GCONF[COLORABLE_POI] = GCONF_KEY_PREFIX"/color_poi";
-
     DEG_FORMAT_ENUM_TEXT[DDPDDDDD] = "-dd.ddddd°";
     DEG_FORMAT_ENUM_TEXT[DD_MMPMMM] = "-dd°mm.mmm'";
     DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS] = "-dd°mm'ss.s\"";
     DEG_FORMAT_ENUM_TEXT[DDPDDDDD] = "-dd.ddddd°";
     DEG_FORMAT_ENUM_TEXT[DD_MMPMMM] = "-dd°mm.mmm'";
     DEG_FORMAT_ENUM_TEXT[DD_MM_SSPS] = "-dd°mm'ss.s\"";
@@ -352,6 +333,7 @@ maemo_mapper_init(gint argc, gchar **argv)
     _conic_connection_cond = g_cond_new();
 
     settings_init();
     _conic_connection_cond = g_cond_new();
 
     settings_init();
+    map_cache_init(_map_cache_size);
 
     /* Initialize _program. */
     _program = HILDON_PROGRAM(hildon_program_get_instance());
 
     /* Initialize _program. */
     _program = HILDON_PROGRAM(hildon_program_get_instance());
@@ -543,15 +525,33 @@ osso_cb_hw_state_idle(osso_hw_state_t *state)
             state->save_unsaved_data_ind, state->shutdown_ind,
             state->memory_low_ind, state->sig_device_mode_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->save_unsaved_data_ind)
     {
         settings_save();
         _must_save_data = TRUE;
     }
-    else if(state->shutdown_ind)
+
+    if(state->memory_low_ind)
     {
     {
-        maemo_mapper_destroy();
-        exit(1);
+        // 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);
     }
 
     g_free(state);
index 5ee5c540e161f318beeca8d2c5218d49db95ac03..9d0457afeb95390ac5092f83faac3eba5b848860 100644 (file)
@@ -109,74 +109,62 @@ struct _MapmanInfo {
     GtkWidget *chk_zoom_levels[MAX_ZOOM + 1];
 };
 
     GtkWidget *chk_zoom_levels[MAX_ZOOM + 1];
 };
 
+typedef struct _MapCacheKey MapCacheKey;
+struct _MapCacheKey {
+    RepoData      *repo;
+    gint           zoom;
+    gint           tilex;
+    gint           tiley;
+};
 
 
-gboolean
-mapdb_exists(RepoData *repo, gint zoom, gint tilex, gint tiley)
-{
-    gboolean exists;
-    vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
-            repo->name, zoom, tilex, tiley);
-
-    g_mutex_lock(_mapdb_mutex);
+typedef struct _MapCacheEntry MapCacheEntry;
+struct _MapCacheEntry {
+    MapCacheKey    key;
+    int            list;
+    guint          size;
+    guint          data_sz;
+    gchar         *data;
+    GdkPixbuf     *pixbuf;
+    MapCacheEntry *next;
+    MapCacheEntry *prev;
+};
 
 
-    if(!repo->db)
-    {
-        /* There is no cache.  Return FALSE. */
-        g_mutex_unlock(_mapdb_mutex);
-        vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
-        return FALSE;
-    }
+typedef struct _MapCacheList MapCacheList;
+struct _MapCacheList {
+    MapCacheEntry *head;
+    MapCacheEntry *tail;
+    size_t         size;
+    size_t         data_sz;
+};
 
 
-#ifdef MAPDB_SQLITE
-    /* Attempt to retrieve map from database. */
-    if(SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 1, zoom)
-    && SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 2, tilex)
-    && SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 3, tiley)
-    && SQLITE_ROW == sqlite3_step(repo->stmt_map_exists)
-    && sqlite3_column_int(repo->stmt_map_exists, 0) > 0)
-    {
-        exists = TRUE;
-    }
-    else
-    {
-        exists = FALSE;
-    }
-    sqlite3_reset(repo->stmt_map_exists);
-#else
-    {
-        datum d;
-        gint32 key[] = {
-            GINT32_TO_BE(zoom),
-            GINT32_TO_BE(tilex),
-            GINT32_TO_BE(tiley)
-        };
-        d.dptr = (gchar*)&key;
-        d.dsize = sizeof(key);
-        exists = gdbm_exists(repo->db, d);
-    }
-#endif
+typedef struct _MapCache MapCache;
+struct _MapCache {
+    MapCacheList  lists[4];
+    size_t        cache_size;
+    size_t        p;
+    size_t        thits;
+    size_t        bhits;
+    size_t        misses;
+    GHashTable   *entries;
+};
 
 
-    g_mutex_unlock(_mapdb_mutex);
+static MapCache _map_cache;
 
 
-    vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, exists);
-    return exists;
-}
 
 
-GdkPixbuf*
-mapdb_get(RepoData *repo, gint zoom, gint tilex, gint tiley)
+static guint
+mapdb_get_data(RepoData *repo, gint zoom, gint tilex, gint tiley, gchar **data)
 {
 {
-    GdkPixbuf *pixbuf = NULL;
+    guint size;
     vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
             repo->name, zoom, tilex, tiley);
     vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
             repo->name, zoom, tilex, tiley);
-
-    g_mutex_lock(_mapdb_mutex);
+    *data = NULL;
+    size = 0;
 
     if(!repo->db)
     {
         /* There is no cache.  Return NULL. */
 
     if(!repo->db)
     {
         /* There is no cache.  Return NULL. */
-        g_mutex_unlock(_mapdb_mutex);
-        vprintf("%s(): return NULL\n", __PRETTY_FUNCTION__);
-        return NULL;
+        vprintf("%s(): return %u\n", __PRETTY_FUNCTION__,size);
+        return size;
     }
 
 #ifdef MAPDB_SQLITE
     }
 
 #ifdef MAPDB_SQLITE
@@ -187,7 +175,7 @@ mapdb_get(RepoData *repo, gint zoom, gint tilex, gint tiley)
     && SQLITE_ROW == sqlite3_step(repo->stmt_map_select))
     {
         const gchar *bytes = NULL;
     && SQLITE_ROW == sqlite3_step(repo->stmt_map_select))
     {
         const gchar *bytes = NULL;
-        gint size = sqlite3_column_bytes(repo->stmt_map_select, 0);
+        size = sqlite3_column_bytes(repo->stmt_map_select, 0);
 
         /* "Pixbufs" of size less than or equal to MAX_PIXBUF_DUP_SIZE are
          * actually keys into the dups table. */
 
         /* "Pixbufs" of size less than or equal to MAX_PIXBUF_DUP_SIZE are
          * actually keys into the dups table. */
@@ -218,6 +206,7 @@ mapdb_get(RepoData *repo, gint zoom, gint tilex, gint tiley)
 
                 /* We have no bytes to return to the caller. */
                 bytes = NULL;
 
                 /* We have no bytes to return to the caller. */
                 bytes = NULL;
+                size = 0;
             }
             /* Don't reset the statement yet - we need the blob. */
         }
             }
             /* Don't reset the statement yet - we need the blob. */
         }
@@ -227,13 +216,8 @@ mapdb_get(RepoData *repo, gint zoom, gint tilex, gint tiley)
         }
         if(bytes)
         {
         }
         if(bytes)
         {
-            GError *error = NULL;
-            GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
-            gdk_pixbuf_loader_write(loader, bytes, size, NULL);
-            gdk_pixbuf_loader_close(loader, &error);
-            if(!error)
-                pixbuf = g_object_ref(gdk_pixbuf_loader_get_pixbuf(loader));
-            g_object_unref(loader);
+            *data = g_slice_alloc(size);
+            memcpy(*data, bytes, size);
         }
         if(size <= MAX_PIXBUF_DUP_SIZE)
             sqlite3_reset(repo->stmt_dup_select);
         }
         if(size <= MAX_PIXBUF_DUP_SIZE)
             sqlite3_reset(repo->stmt_dup_select);
@@ -252,20 +236,398 @@ mapdb_get(RepoData *repo, gint zoom, gint tilex, gint tiley)
         d = gdbm_fetch(repo->db, d);
         if(d.dptr)
         {
         d = gdbm_fetch(repo->db, d);
         if(d.dptr)
         {
-            GError *error = NULL;
-            GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
-            gdk_pixbuf_loader_write(loader, d.dptr, d.dsize, NULL);
-            g_free(d.dptr);
-            gdk_pixbuf_loader_close(loader, &error);
-            if(!error)
-                pixbuf = g_object_ref(gdk_pixbuf_loader_get_pixbuf(loader));
+            size = d.dsize;
+            *data = g_slice_alloc(size);
+            memcpy(*data, d.dptr, size);
+            free(d.dptr);
+        }
+    }
+#endif
+
+    vprintf("%s(): return %u\n", __PRETTY_FUNCTION__, size);
+    return size;
+}
+
+static void map_cache_list_remove(MapCacheList *_list, MapCacheEntry *_entry)
+{
+    _list->size -= _entry->size;
+    _list->data_sz -= _entry->data_sz;
+    *(_entry->prev != NULL?&_entry->prev->next:&_list->head) = _entry->next;
+    *(_entry->next != NULL?&_entry->next->prev:&_list->tail) = _entry->prev;
+}
+
+static void map_cache_list_prepend(MapCacheList *_list, int _li,
+ MapCacheEntry *_entry)
+{
+    _entry->prev = NULL;
+    _entry->next = _list[_li].head;
+    *(_list[_li].head != NULL?&_list[_li].head->prev:&_list[_li].tail) = _entry;
+    _list[_li].head = _entry;
+    _list[_li].size += _entry->size;
+    _list[_li].data_sz += _entry->data_sz;
+    _entry->list = _li;
+}
+
+static guint map_cache_key_hash(gconstpointer _key){
+    const MapCacheKey *key;
+    key = (const MapCacheKey *)_key;
+    return g_direct_hash(key->repo)+g_int_hash(&key->zoom)+
+     g_int_hash(&key->tilex)+g_int_hash(&key->tiley);
+}
+
+static gboolean map_cache_key_equal(gconstpointer _v1, gconstpointer _v2){
+    const MapCacheKey *key1;
+    const MapCacheKey *key2;
+    key1 = (const MapCacheKey *)_v1;
+    key2 = (const MapCacheKey *)_v2;
+    return key1->tilex == key2->tilex && key1->tiley == key2->tiley &&
+     key1->zoom == key2->zoom && key1->repo == key2->repo;
+}
+
+static void map_cache_entry_make_pixbuf(MapCacheEntry *_entry){
+    if (_entry->data != NULL)
+    {
+        GError *error;
+        GdkPixbufLoader *loader;
+        error = NULL;
+        loader = gdk_pixbuf_loader_new();
+        gdk_pixbuf_loader_write(loader, _entry->data, _entry->data_sz, NULL);
+        gdk_pixbuf_loader_close(loader, &error);
+        if(!error)
+        {
+            _entry->pixbuf = g_object_ref(gdk_pixbuf_loader_get_pixbuf(loader));
+            _entry->size = _entry->data_sz+
+             gdk_pixbuf_get_rowstride(_entry->pixbuf)*
+             gdk_pixbuf_get_height(_entry->pixbuf);
             g_object_unref(loader);
             g_object_unref(loader);
+            return;
+        }
+        g_object_unref(loader);
+        g_slice_free1(_entry->data_sz, _entry->data);
+        _entry->data = NULL;
+        _entry->data_sz = 0;
+    }
+    _entry->pixbuf = NULL;
+    _entry->size = _entry->data_sz;
+}
+
+static void map_cache_entry_free_pixbuf(MapCacheEntry *_entry){
+    if(_entry->pixbuf!=NULL)
+    {
+        g_object_unref(_entry->pixbuf);
+        _entry->pixbuf = NULL;
+    }
+}
+
+static void map_cache_entry_free(MapCacheEntry *_entry){
+    if(_entry->list >= 0)
+        map_cache_list_remove(_map_cache.lists+_entry->list, _entry);
+    map_cache_entry_free_pixbuf(_entry);
+    g_slice_free1(_entry->data_sz, _entry->data);
+    g_slice_free(MapCacheEntry, _entry);
+}
+
+static gboolean
+map_cache_replace(size_t _size, gboolean _b2)
+{
+    gboolean ret;
+    size_t total_size;
+    total_size = _map_cache.lists[0].size+_map_cache.lists[1].data_sz
+     +_map_cache.lists[2].size+_map_cache.lists[3].data_sz;
+    ret = FALSE;
+    while(total_size+_size > _map_cache.cache_size)
+    {
+        MapCacheEntry *entry;
+        int list;
+        if(_map_cache.lists[0].tail != NULL &&
+         (_map_cache.lists[0].size > _map_cache.p ||
+         (_b2 && _map_cache.lists[0].size == _map_cache.p)))
+            list = 0;
+        else
+            list = 2;
+        entry = _map_cache.lists[list].tail;
+        if(entry == NULL)
+            break;
+        map_cache_list_remove(_map_cache.lists+list, entry);
+        map_cache_list_prepend(_map_cache.lists, list+1, entry);
+        total_size -= entry->size - entry->data_sz;
+        ret = TRUE;
+        _b2 = FALSE;
+    }
+    return ret;
+}
+
+static void
+map_cache_evict(size_t _size)
+{
+    size_t total_size;
+    size_t max_size;
+    total_size = _map_cache.lists[0].size+_map_cache.lists[1].size
+     +_map_cache.lists[2].size+_map_cache.lists[3].size;
+    max_size = _map_cache.cache_size<<1;
+    for(;;)
+    {
+        if(_map_cache.lists[0].size+_map_cache.lists[1].size+_size >
+         _map_cache.cache_size)
+        {
+            if(_map_cache.lists[1].tail != NULL)
+            {
+                g_hash_table_remove(_map_cache.entries,
+                 &_map_cache.lists[1].tail->key);
+                map_cache_replace(_size, FALSE);
+            }
+            else if(_map_cache.lists[0].tail != NULL)
+            {
+                g_hash_table_remove(_map_cache.entries,
+                 &_map_cache.lists[0].tail->key);
+            }
+            else break;
+        }
+        else if(total_size+_size > _map_cache.cache_size)
+        {
+            if(total_size+_size > max_size &&
+             _map_cache.lists[3].tail != NULL)
+            {
+                g_hash_table_remove(_map_cache.entries,
+                 &_map_cache.lists[3].tail->key);
+                map_cache_replace(_size, FALSE);
+            }
+            else if(!map_cache_replace(_size, FALSE))
+                break;
+        }
+        else break;
+        total_size = _map_cache.lists[0].size+_map_cache.lists[1].size
+         +_map_cache.lists[2].size+_map_cache.lists[3].size;
+    }
+}
+
+static GdkPixbuf *
+map_cache_get(RepoData *repo, gint zoom, gint tilex, gint tiley)
+{
+    MapCacheKey key;
+    MapCacheEntry *entry;
+    key.repo = repo;
+    key.zoom = zoom;
+    key.tilex = tilex;
+    key.tiley = tiley;
+    entry = (MapCacheEntry *)g_hash_table_lookup(_map_cache.entries, &key);
+    if(entry != NULL)
+    {
+        map_cache_list_remove(_map_cache.lists+entry->list, entry);
+        if(entry->pixbuf == NULL)
+        {
+            size_t bsize;
+            size_t dp;
+            map_cache_entry_make_pixbuf(entry);
+            bsize = _map_cache.lists[entry->list].size+entry->size;
+            if(bsize < 1)
+                bsize = 1;
+            dp = _map_cache.lists[entry->list^2].size/bsize;
+            if(dp < 1)
+                dp = 1;
+            if(entry->list == 1)
+            {
+                _map_cache.p += dp;
+                if(_map_cache.p > _map_cache.cache_size)
+                    _map_cache.p = _map_cache.cache_size;
+                map_cache_replace(entry->size, FALSE);
+            }
+            else
+            {
+                if(dp > _map_cache.p)
+                    _map_cache.p = 0;
+                else
+                    _map_cache.p -= dp;
+                map_cache_replace(entry->size, TRUE);
+            }
+            _map_cache.bhits++;
+        }
+        else
+            _map_cache.thits++;
+        map_cache_list_prepend(_map_cache.lists, 2, entry);
+    }
+    else
+    {
+        gchar *data;
+        guint  data_sz;
+        data_sz = mapdb_get_data(repo, zoom, tilex, tiley, &data);
+        entry = g_slice_new(MapCacheEntry);
+        *&entry->key = *&key;
+        entry->data = data;
+        entry->data_sz = data_sz;
+        map_cache_entry_make_pixbuf(entry);
+        map_cache_evict(entry->size);
+        map_cache_list_prepend(_map_cache.lists, 0, entry);
+        g_hash_table_insert(_map_cache.entries, &entry->key, entry);
+        _map_cache.misses++;
+    }
+    if(entry->pixbuf != NULL)
+        g_object_ref(entry->pixbuf);
+    return entry->pixbuf;
+}
+
+static void
+map_cache_update(RepoData *repo, gint zoom, gint tilex, gint tiley,
+ gchar *data,guint size)
+{
+    MapCacheKey key;
+    MapCacheEntry *entry;
+    key.repo = repo;
+    key.zoom = zoom;
+    key.tilex = tilex;
+    key.tiley = tiley;
+    entry = (MapCacheEntry *)g_hash_table_lookup(_map_cache.entries, &key);
+    if(entry != NULL)
+    {
+        g_slice_free1(entry->data_sz, entry->data);
+        entry->data = g_slice_alloc(size);
+        memcpy(entry->data, data, size);
+        entry->data_sz = size;
+        if(entry->pixbuf != NULL)
+        {
+            map_cache_entry_free_pixbuf(entry);
+            map_cache_list_remove(_map_cache.lists+entry->list, entry);
+            map_cache_list_prepend(_map_cache.lists, entry->list+1, entry);
+        }
+    }
+}
+
+static void
+map_cache_remove(RepoData *repo, gint zoom, gint tilex, gint tiley)
+{
+    MapCacheKey key;
+    key.repo = repo;
+    key.zoom = zoom;
+    key.tilex = tilex;
+    key.tiley = tiley;
+    g_hash_table_remove(_map_cache.entries, &key);
+}
+
+void
+map_cache_init(size_t cache_size)
+{
+    g_mutex_lock(_mapdb_mutex);
+    if(_map_cache.entries == NULL)
+        _map_cache.entries = g_hash_table_new_full(map_cache_key_hash,
+         map_cache_key_equal, NULL, (GDestroyNotify)map_cache_entry_free);
+    _map_cache.cache_size = cache_size;
+    if(_map_cache.p > cache_size)
+        _map_cache.p = cache_size;
+    map_cache_evict(0);
+    g_mutex_unlock(_mapdb_mutex);
+}
+
+size_t
+map_cache_resize(size_t cache_size)
+{
+    size_t total_size;
+    g_mutex_lock(_mapdb_mutex);
+    _map_cache.cache_size = cache_size;
+    total_size = _map_cache.lists[0].size+_map_cache.lists[1].data_sz
+     +_map_cache.lists[2].size+_map_cache.lists[3].data_sz;
+    g_mutex_unlock(_mapdb_mutex);
+    return total_size;
+}
+
+void
+map_cache_destroy(void)
+{
+    g_mutex_lock(_mapdb_mutex);
+    if(_map_cache.entries != NULL)
+    {
+        g_hash_table_destroy(_map_cache.entries);
+        _map_cache.entries = NULL;
+        printf("thits: %u (%0.2f%%)  bhits: %u (%0.2f%%)  "
+         "misses: %u (%0.2f%%)\n",
+         _map_cache.thits, 100*_map_cache.thits/(double)(
+         _map_cache.thits+_map_cache.bhits+_map_cache.misses),
+         _map_cache.bhits, 100*_map_cache.bhits/(double)(
+         _map_cache.thits+_map_cache.bhits+_map_cache.misses),
+         _map_cache.misses, 100*_map_cache.misses/(double)(
+         _map_cache.thits+_map_cache.bhits+_map_cache.misses));
+    }
+    g_mutex_unlock(_mapdb_mutex);
+}
+
+gboolean
+mapdb_exists(RepoData *repo, gint zoom, gint tilex, gint tiley)
+{
+    gboolean exists;
+    vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
+            repo->name, zoom, tilex, tiley);
+
+    g_mutex_lock(_mapdb_mutex);
+
+    if(!repo->db)
+    {
+        /* There is no cache.  Return FALSE. */
+        g_mutex_unlock(_mapdb_mutex);
+        vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+        return FALSE;
+    }
+
+    /* Search the cache first. */
+    {
+        MapCacheKey key;
+        MapCacheEntry *entry;
+        key.repo = repo;
+        key.zoom = zoom;
+        key.tilex = tilex;
+        key.tiley = tiley;
+        entry = (MapCacheEntry *)g_hash_table_lookup(_map_cache.entries, &key);
+        if(entry != NULL)
+        {
+            gboolean ret;
+            ret = entry->data != NULL;
+            g_mutex_unlock(_mapdb_mutex);
+            return ret;
         }
     }
         }
     }
+
+#ifdef MAPDB_SQLITE
+    /* Attempt to retrieve map from database. */
+    if(SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 1, zoom)
+    && SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 2, tilex)
+    && SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 3, tiley)
+    && SQLITE_ROW == sqlite3_step(repo->stmt_map_exists)
+    && sqlite3_column_int(repo->stmt_map_exists, 0) > 0)
+    {
+        exists = TRUE;
+    }
+    else
+    {
+        exists = FALSE;
+    }
+    sqlite3_reset(repo->stmt_map_exists);
+#else
+    {
+        datum d;
+        gint32 key[] = {
+            GINT32_TO_BE(zoom),
+            GINT32_TO_BE(tilex),
+            GINT32_TO_BE(tiley)
+        };
+        d.dptr = (gchar*)&key;
+        d.dsize = sizeof(key);
+        exists = gdbm_exists(repo->db, d);
+    }
 #endif
 
     g_mutex_unlock(_mapdb_mutex);
 
 #endif
 
     g_mutex_unlock(_mapdb_mutex);
 
+    vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, exists);
+    return exists;
+}
+
+GdkPixbuf*
+mapdb_get(RepoData *repo, gint zoom, gint tilex, gint tiley)
+{
+    GdkPixbuf *pixbuf;
+    vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
+            repo->name, zoom, tilex, tiley);
+    g_mutex_lock(_mapdb_mutex);
+    pixbuf = map_cache_get(repo, zoom, tilex, tiley);
+    g_mutex_unlock(_mapdb_mutex);
     vprintf("%s(): return %p\n", __PRETTY_FUNCTION__, pixbuf);
     return pixbuf;
 }
     vprintf("%s(): return %p\n", __PRETTY_FUNCTION__, pixbuf);
     return pixbuf;
 }
@@ -322,6 +684,7 @@ mapdb_update(gboolean exists, RepoData *repo,
             repo->name, zoom, tilex, tiley);
 
     g_mutex_lock(_mapdb_mutex);
             repo->name, zoom, tilex, tiley);
 
     g_mutex_lock(_mapdb_mutex);
+    map_cache_update(repo, zoom, tilex, tiley, bytes, size);
 
     if(!repo->db)
     {
 
     if(!repo->db)
     {
@@ -451,6 +814,7 @@ mapdb_delete(RepoData *repo, gint zoom, gint tilex, gint tiley)
             repo->name, zoom, tilex, tiley);
 
     g_mutex_lock(_mapdb_mutex);
             repo->name, zoom, tilex, tiley);
 
     g_mutex_lock(_mapdb_mutex);
+    map_cache_remove(repo, zoom, tilex, tiley);
 
     if(!repo->db)
     {
 
     if(!repo->db)
     {
index 09f4cbe293136131dc1c0291f9f10ef8573c550e..1452e365c50b1cd340bd4907d6f0829a03a6e1c7 100644 (file)
 #ifndef MAEMO_MAPPER_MAPS_H
 #define MAEMO_MAPPER_MAPS_H
 
 #ifndef MAEMO_MAPPER_MAPS_H
 #define MAEMO_MAPPER_MAPS_H
 
+void map_cache_init(size_t cache_size);
+size_t map_cache_resize(size_t cache_size);
+void map_cache_destroy(void);
+
 gboolean mapdb_exists(RepoData *repo, gint zoom, gint tilex, gint tiley);
 GdkPixbuf* mapdb_get(RepoData *repo, gint zoom, gint tilex, gint tiley);
 
 gboolean mapdb_exists(RepoData *repo, gint zoom, gint tilex, gint tiley);
 GdkPixbuf* mapdb_get(RepoData *repo, gint zoom, gint tilex, gint tiley);
 
index 67edeae287b49bbae0f8c5cf36263e3d176898d1..5c8aa0e55deb7d995df8f4e5bea1904d73b4b8d9 100644 (file)
@@ -709,8 +709,9 @@ auto_route_dl_idle()
     g_ascii_dtostr(lonstr, 32, _gps.lon);
     snprintf(latlonstr, sizeof(latlonstr), "%s, %s", latstr, lonstr);
 
     g_ascii_dtostr(lonstr, 32, _gps.lon);
     snprintf(latlonstr, sizeof(latlonstr), "%s, %s", latstr, lonstr);
 
-    route_download_and_setup(_window, _autoroute_data.source_url, latlonstr,
-            _autoroute_data.dest, _autoroute_data.avoid_highways,0);
+    if(!route_download_and_setup(_window, _autoroute_data.source_url, latlonstr,
+            _autoroute_data.dest, _autoroute_data.avoid_highways,0))
+        cancel_autoroute();
 
     _autoroute_data.in_progress = FALSE;
 
 
     _autoroute_data.in_progress = FALSE;
 
@@ -919,8 +920,9 @@ track_add(time_t time, gboolean newly_fixed)
         }
 
         /* Check if we should announce upcoming waypoints. */
         }
 
         /* Check if we should announce upcoming waypoints. */
-        if(_initial_distance_waypoint || _next_way_dist_squared
-                    < (announce_thres_unsquared * announce_thres_unsquared))
+        if(_enable_announce
+                && (_initial_distance_waypoint || _next_way_dist_squared
+                    < (announce_thres_unsquared * announce_thres_unsquared)))
         {
             if(show_directions)
             {
         {
             if(show_directions)
             {
index 5bac7204b9401c0976902a6a1b646307eac02e88..917dd71a93b0b78927db831809ca32859c5ae5fc 100644 (file)
 #include "settings.h"
 #include "util.h"
 
 #include "settings.h"
 #include "util.h"
 
+#define GCONF_KEY_PREFIX "/apps/maemo/maemo-mapper"
+#define GCONF_KEY_GPS_RCVR_TYPE GCONF_KEY_PREFIX"/gps_rcvr_type"
+#define GCONF_KEY_GPS_BT_MAC GCONF_KEY_PREFIX"/receiver_mac"
+#define GCONF_KEY_GPS_GPSD_HOST GCONF_KEY_PREFIX"/gps_gpsd_host"
+#define GCONF_KEY_GPS_GPSD_PORT GCONF_KEY_PREFIX"/gps_gpsd_port"
+#define GCONF_KEY_GPS_FILE_PATH GCONF_KEY_PREFIX"/gps_file_path"
+#define GCONF_KEY_AUTO_DOWNLOAD GCONF_KEY_PREFIX"/auto_download"
+#define GCONF_KEY_AUTO_DOWNLOAD_PRECACHE \
+                                      GCONF_KEY_PREFIX"/auto_download_precache"
+#define GCONF_KEY_CENTER_SENSITIVITY GCONF_KEY_PREFIX"/center_sensitivity"
+#define GCONF_KEY_ENABLE_ANNOUNCE GCONF_KEY_PREFIX"/enable_announce"
+#define GCONF_KEY_ANNOUNCE_NOTICE GCONF_KEY_PREFIX"/announce_notice"
+#define GCONF_KEY_ROTATE_SENSITIVITY GCONF_KEY_PREFIX"/rotate_sensitivity"
+#define GCONF_KEY_AC_MIN_SPEED GCONF_KEY_PREFIX"/autocenter_min_speed"
+#define GCONF_KEY_ROTATE_DIR GCONF_KEY_PREFIX"/rotate_direction"
+#define GCONF_KEY_DRAW_WIDTH GCONF_KEY_PREFIX"/draw_width"
+#define GCONF_KEY_ENABLE_VOICE GCONF_KEY_PREFIX"/enable_voice"
+#define GCONF_KEY_VOICE_SPEED GCONF_KEY_PREFIX"/voice_speed"
+#define GCONF_KEY_VOICE_PITCH GCONF_KEY_PREFIX"/voice_pitch"
+#define GCONF_KEY_FULLSCREEN GCONF_KEY_PREFIX"/fullscreen"
+#define GCONF_KEY_UNITS GCONF_KEY_PREFIX"/units"
+#define GCONF_KEY_SPEED_LIMIT_ON GCONF_KEY_PREFIX"/speed_limit_on"
+#define GCONF_KEY_SPEED_LIMIT GCONF_KEY_PREFIX"/speed_limit"
+#define GCONF_KEY_SPEED_LOCATION GCONF_KEY_PREFIX"/speed_location"
+#define GCONF_KEY_UNBLANK_SIZE GCONF_KEY_PREFIX"/unblank_option"
+#define GCONF_KEY_INFO_FONT_SIZE GCONF_KEY_PREFIX"/info_font_size"
+
+#define GCONF_KEY_POI_DB GCONF_KEY_PREFIX"/poi_db"
+#define GCONF_KEY_POI_ZOOM GCONF_KEY_PREFIX"/poi_zoom"
+
+#define GCONF_KEY_AUTOCENTER_MODE GCONF_KEY_PREFIX"/autocenter_mode"
+#define GCONF_KEY_AUTOCENTER_ROTATE GCONF_KEY_PREFIX"/autocenter_rotate"
+#define GCONF_KEY_LEAD_AMOUNT GCONF_KEY_PREFIX"/lead_amount"
+#define GCONF_KEY_LEAD_IS_FIXED GCONF_KEY_PREFIX"/lead_is_fixed"
+#define GCONF_KEY_LAST_LAT GCONF_KEY_PREFIX"/last_latitude"
+#define GCONF_KEY_LAST_LON GCONF_KEY_PREFIX"/last_longitude"
+#define GCONF_KEY_LAST_ALT GCONF_KEY_PREFIX"/last_altitude"
+#define GCONF_KEY_LAST_SPEED GCONF_KEY_PREFIX"/last_speed"
+#define GCONF_KEY_LAST_HEADING GCONF_KEY_PREFIX"/last_heading"
+#define GCONF_KEY_LAST_TIME GCONF_KEY_PREFIX"/last_timestamp"
+#define GCONF_KEY_CENTER_LAT GCONF_KEY_PREFIX"/center_latitude"
+#define GCONF_KEY_CENTER_LON GCONF_KEY_PREFIX"/center_longitude"
+#define GCONF_KEY_CENTER_ANGLE GCONF_KEY_PREFIX"/center_angle"
+#define GCONF_KEY_ZOOM GCONF_KEY_PREFIX"/zoom"
+#define GCONF_KEY_ROUTEDIR GCONF_KEY_PREFIX"/route_directory"
+#define GCONF_KEY_TRACKFILE GCONF_KEY_PREFIX"/track_file"
+#define GCONF_KEY_SHOWZOOMLEVEL GCONF_KEY_PREFIX"/show_zoomlevel"
+#define GCONF_KEY_SHOWSCALE GCONF_KEY_PREFIX"/show_scale"
+#define GCONF_KEY_SHOWCOMPROSE GCONF_KEY_PREFIX"/show_comprose"
+#define GCONF_KEY_SHOWTRACKS GCONF_KEY_PREFIX"/show_tracks"
+#define GCONF_KEY_SHOWROUTES GCONF_KEY_PREFIX"/show_routes"
+#define GCONF_KEY_SHOWVELVEC GCONF_KEY_PREFIX"/show_velocity_vector" 
+#define GCONF_KEY_SHOWPOIS GCONF_KEY_PREFIX"/show_poi" 
+#define GCONF_KEY_ENABLE_GPS GCONF_KEY_PREFIX"/enable_gps" 
+#define GCONF_KEY_ROUTE_LOCATIONS GCONF_KEY_PREFIX"/route_locations" 
+#define GCONF_KEY_REPOSITORIES GCONF_KEY_PREFIX"/repositories" 
+#define GCONF_KEY_CURRREPO GCONF_KEY_PREFIX"/curr_repo" 
+#define GCONF_KEY_GPS_INFO GCONF_KEY_PREFIX"/gps_info" 
+#define GCONF_KEY_ROUTE_DL_URL GCONF_KEY_PREFIX"/route_dl_url" 
+#define GCONF_KEY_ROUTE_DL_RADIUS GCONF_KEY_PREFIX"/route_dl_radius" 
+#define GCONF_KEY_POI_DL_URL GCONF_KEY_PREFIX"/poi_dl_url" 
+#define GCONF_KEY_DEG_FORMAT GCONF_KEY_PREFIX"/deg_format" 
+
+
 typedef struct _ScanInfo ScanInfo;
 struct _ScanInfo {
     GtkWidget *settings_dialog;
 typedef struct _ScanInfo ScanInfo;
 struct _ScanInfo {
     GtkWidget *settings_dialog;
@@ -182,6 +246,10 @@ settings_save()
     gconf_client_set_int(gconf_client,
             GCONF_KEY_DRAW_WIDTH, _draw_width, NULL);
 
     gconf_client_set_int(gconf_client,
             GCONF_KEY_DRAW_WIDTH, _draw_width, NULL);
 
+    /* Save Announce Flag. */
+    gconf_client_set_bool(gconf_client,
+            GCONF_KEY_ENABLE_ANNOUNCE, _enable_announce, NULL);
+
     /* Save Announce Advance Notice Ratio. */
     gconf_client_set_int(gconf_client,
             GCONF_KEY_ANNOUNCE_NOTICE, _announce_notice_ratio, NULL);
     /* Save Announce Advance Notice Ratio. */
     gconf_client_set_int(gconf_client,
             GCONF_KEY_ANNOUNCE_NOTICE, _announce_notice_ratio, NULL);
@@ -1044,6 +1112,7 @@ settings_dialog()
     static GtkWidget *num_ac_min_speed = NULL;
     static GtkWidget *num_announce_notice = NULL;
     static GtkWidget *chk_enable_voice = NULL;
     static GtkWidget *num_ac_min_speed = NULL;
     static GtkWidget *num_announce_notice = NULL;
     static GtkWidget *chk_enable_voice = NULL;
+    static GtkWidget *chk_enable_announce = NULL;
     static GtkWidget *num_draw_width = NULL;
     static GtkWidget *cmb_units = NULL;
     static GtkWidget *cmb_degformat = NULL;
     static GtkWidget *num_draw_width = NULL;
     static GtkWidget *cmb_units = NULL;
     static GtkWidget *cmb_degformat = NULL;
@@ -1247,14 +1316,22 @@ settings_dialog()
                 table = gtk_table_new(2, 3, FALSE),
                 label = gtk_label_new(_("Announce")));
 
                 table = gtk_table_new(2, 3, FALSE),
                 label = gtk_label_new(_("Announce")));
 
+        /* Enable Waypoint Announcements. */
+        gtk_table_attach(GTK_TABLE(table),
+                chk_enable_announce = gtk_check_button_new_with_label(
+                    _("Enable Waypoint Announcements")),
+                0, 2, 0, 1, GTK_FILL, 0, 2, 4);
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enable_announce),
+                _enable_announce);
+
         /* Announcement Advance Notice. */
         gtk_table_attach(GTK_TABLE(table),
                 label = gtk_label_new(_("Advance Notice")),
         /* Announcement Advance Notice. */
         gtk_table_attach(GTK_TABLE(table),
                 label = gtk_label_new(_("Advance Notice")),
-                0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+                0, 1, 1, 2, GTK_FILL, 0, 2, 4);
         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
         gtk_table_attach(GTK_TABLE(table),
                 num_announce_notice = hildon_controlbar_new(),
         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
         gtk_table_attach(GTK_TABLE(table),
                 num_announce_notice = hildon_controlbar_new(),
-                1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+                1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
         hildon_controlbar_set_range(
                 HILDON_CONTROLBAR(num_announce_notice), 1, 20);
         force_min_visible_bars(HILDON_CONTROLBAR(num_announce_notice), 1);
         hildon_controlbar_set_range(
                 HILDON_CONTROLBAR(num_announce_notice), 1, 20);
         force_min_visible_bars(HILDON_CONTROLBAR(num_announce_notice), 1);
@@ -1263,7 +1340,7 @@ settings_dialog()
         gtk_table_attach(GTK_TABLE(table),
                 chk_enable_voice = gtk_check_button_new_with_label(
                     _("Enable Voice Synthesis (requires flite)")),
         gtk_table_attach(GTK_TABLE(table),
                 chk_enable_voice = gtk_check_button_new_with_label(
                     _("Enable Voice Synthesis (requires flite)")),
-                0, 2, 1, 2, GTK_FILL, 0, 2, 4);
+                0, 2, 2, 3, GTK_FILL, 0, 2, 4);
         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enable_voice),
                 _enable_voice);
 
         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enable_voice),
                 _enable_voice);
 
@@ -1649,6 +1726,9 @@ settings_dialog()
         _announce_notice_ratio = hildon_controlbar_get_value(
                 HILDON_CONTROLBAR(num_announce_notice));
 
         _announce_notice_ratio = hildon_controlbar_get_value(
                 HILDON_CONTROLBAR(num_announce_notice));
 
+        _enable_announce = gtk_toggle_button_get_active(
+                GTK_TOGGLE_BUTTON(chk_enable_announce));
+
         _enable_voice = gtk_toggle_button_get_active(
                 GTK_TOGGLE_BUTTON(chk_enable_voice));
 
         _enable_voice = gtk_toggle_button_get_active(
                 GTK_TOGGLE_BUTTON(chk_enable_voice));
 
@@ -1776,6 +1856,31 @@ settings_init()
     gchar *str;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
     gchar *str;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
+    /* Initialize some constants. */
+    CUSTOM_KEY_GCONF[CUSTOM_KEY_UP] = GCONF_KEY_PREFIX"/key_up";
+    CUSTOM_KEY_GCONF[CUSTOM_KEY_DOWN] = GCONF_KEY_PREFIX"/key_down";
+    CUSTOM_KEY_GCONF[CUSTOM_KEY_LEFT] = GCONF_KEY_PREFIX"/key_left";
+    CUSTOM_KEY_GCONF[CUSTOM_KEY_RIGHT] = GCONF_KEY_PREFIX"/key_right";
+    CUSTOM_KEY_GCONF[CUSTOM_KEY_SELECT] = GCONF_KEY_PREFIX"/key_select";
+    CUSTOM_KEY_GCONF[CUSTOM_KEY_INCREASE] = GCONF_KEY_PREFIX"/key_increase";
+    CUSTOM_KEY_GCONF[CUSTOM_KEY_DECREASE] = GCONF_KEY_PREFIX"/key_decrease";
+    CUSTOM_KEY_GCONF[CUSTOM_KEY_FULLSCREEN]= GCONF_KEY_PREFIX"/key_fullscreen";
+    CUSTOM_KEY_GCONF[CUSTOM_KEY_ESC] = GCONF_KEY_PREFIX"/key_esc";
+
+    COLORABLE_GCONF[COLORABLE_MARK] = GCONF_KEY_PREFIX"/color_mark";
+    COLORABLE_GCONF[COLORABLE_MARK_VELOCITY]
+        = GCONF_KEY_PREFIX"/color_mark_velocity";
+    COLORABLE_GCONF[COLORABLE_MARK_OLD] = GCONF_KEY_PREFIX"/color_mark_old";
+    COLORABLE_GCONF[COLORABLE_TRACK] = GCONF_KEY_PREFIX"/color_track";
+    COLORABLE_GCONF[COLORABLE_TRACK_MARK] =GCONF_KEY_PREFIX"/color_track_mark";
+    COLORABLE_GCONF[COLORABLE_TRACK_BREAK]
+        = GCONF_KEY_PREFIX"/color_track_break";
+    COLORABLE_GCONF[COLORABLE_ROUTE] = GCONF_KEY_PREFIX"/color_route";
+    COLORABLE_GCONF[COLORABLE_ROUTE_WAY] = GCONF_KEY_PREFIX"/color_route_way";
+    COLORABLE_GCONF[COLORABLE_ROUTE_BREAK]
+        = GCONF_KEY_PREFIX"/color_route_break";
+    COLORABLE_GCONF[COLORABLE_POI] = GCONF_KEY_PREFIX"/color_poi";
+
     if(!gconf_client)
     {
         popup_error(_window, _("Failed to initialize GConf.  Quitting."));
     if(!gconf_client)
     {
         popup_error(_window, _("Failed to initialize GConf.  Quitting."));
@@ -1877,6 +1982,16 @@ settings_init()
     if(!_draw_width)
         _draw_width = 5;
 
     if(!_draw_width)
         _draw_width = 5;
 
+    /* Get Enable Announcements flag.  Default is TRUE. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_ENABLE_ANNOUNCE, NULL);
+    if(value)
+    {
+        _enable_announce = gconf_value_get_bool(value);
+        gconf_value_free(value);
+    }
+    else
+        _enable_announce = TRUE;
+
     /* Get Announce Advance Notice - Default is 30. */
     value = gconf_client_get(gconf_client, GCONF_KEY_ANNOUNCE_NOTICE, NULL);
     if(value)
     /* Get Announce Advance Notice - Default is 30. */
     value = gconf_client_get(gconf_client, GCONF_KEY_ANNOUNCE_NOTICE, NULL);
     if(value)