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;
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;
#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"
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)
{
g_mutex_unlock(_mapdb_mutex);
#endif
}
+ map_cache_destroy();
gps_destroy(TRUE);
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_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\"";
_conic_connection_cond = g_cond_new();
settings_init();
+ map_cache_init(_map_cache_size);
/* Initialize _program. */
_program = HILDON_PROGRAM(hildon_program_get_instance());
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;
}
- 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);
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);
-
- g_mutex_lock(_mapdb_mutex);
+ *data = NULL;
+ size = 0;
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
&& 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. */
/* We have no bytes to return to the caller. */
bytes = NULL;
+ size = 0;
}
/* Don't reset the statement yet - we need the blob. */
}
}
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);
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);
+ 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);
+ 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;
}
repo->name, zoom, tilex, tiley);
g_mutex_lock(_mapdb_mutex);
+ map_cache_update(repo, zoom, tilex, tiley, bytes, size);
if(!repo->db)
{
repo->name, zoom, tilex, tiley);
g_mutex_lock(_mapdb_mutex);
+ map_cache_remove(repo, zoom, tilex, tiley);
if(!repo->db)
{
#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);
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;
}
/* 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)
{
#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;
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);
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;
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")),
- 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(),
- 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);
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);
_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));
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(!_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)