-#include "config.h"
+/*
+ * This file is part of mapper
+ *
+ * Copyright (C) 2007 Kaj-Michael Lang
+ * 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 program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
-#define _GNU_SOURCE
+#include "config.h"
#include <unistd.h>
#include <stdlib.h>
#include "poi.h"
#include "route.h"
#include "gps.h"
-#include "bt.h"
#include "mapper-types.h"
#include "ui-common.h"
#include "settings.h"
#include "latlon.h"
#include "gpx.h"
#include "map-download.h"
+#include "iap.h"
-guint _num_downloads=0;
-guint _curr_download=0;
+static guint _num_downloads=0;
+static guint _curr_download=0;
+
+static GQueue *curl_easy_queue=NULL;
+static GTree *pui_tree=NULL;
+static GTree *downloading_tree=NULL;
+static GHashTable *pui_by_easy=NULL;
static gchar *map_construct_url(guint tilex, guint tiley, guint zoom);
return TRUE;
}
+static gint
+download_comparefunc(const ProgressUpdateInfo * a, const ProgressUpdateInfo * b, gpointer user_data)
+{
+gint diff = (a->priority - b->priority);
+if (diff)
+ return diff;
+diff = (a->tilex - b->tilex);
+if (diff)
+ return diff;
+diff = (a->tiley - b->tiley);
+if (diff)
+ return diff;
+diff = (a->zoom - b->zoom);
+if (diff)
+ return diff;
+diff = (a->repo - b->repo);
+if (diff)
+ return diff;
+/* Otherwise, deletes are "greatest" (least priority). */
+if (!a->retries)
+ return (b->retries ? -1 : 0);
+else if (!b->retries)
+ return (a->retries ? 1 : 0);
+/* Do updates after non-updates (because they'll both be done anyway). */
+return (a->retries - b->retries);
+}
+
/**
* Free a ProgressUpdateInfo data structure that was allocated during the
* auto-map-download process.
g_slice_free(ProgressUpdateInfo, pui);
}
-
gboolean
map_download_timeout()
{
gint num_transfers = 0, num_msgs = 0;
gint deletes_left = 50; /* only do 50 deletes at a time. */
CURLMsg *msg;
-vprintf("%s()\n", __PRETTY_FUNCTION__);
if (_curl_multi && CURLM_CALL_MULTI_PERFORM == curl_multi_perform(_curl_multi, &num_transfers))
return TRUE; /* Give UI a chance first. */
if (msg->easy_handle == _autoroute_data.curl_easy) {
/* This is the autoroute download. */
/* Now, parse the autoroute and update the display. */
- if (_autoroute_data.enabled
- && parse_gpx(&_route,
- _autoroute_data.rdl_data.bytes,
- _autoroute_data.rdl_data.bytes_read, 0)) {
+ if (_autoroute_data.enabled && parse_gpx(&_route, _autoroute_data.rdl_data.bytes, _autoroute_data.rdl_data.bytes_read, 0)) {
/* Find the nearest route point, if we're connected. */
route_find_nearest_point();
map_force_redraw();
}
cancel_autoroute(TRUE); /* We're done. Clean up. */
} else {
- ProgressUpdateInfo *pui = g_hash_table_lookup(_pui_by_easy, msg->easy_handle);
- g_queue_push_head(_curl_easy_queue, msg->easy_handle);
- g_hash_table_remove(_pui_by_easy, msg->easy_handle);
+ ProgressUpdateInfo *pui = g_hash_table_lookup(pui_by_easy, msg->easy_handle);
+ g_queue_push_head(curl_easy_queue, msg->easy_handle);
+ g_hash_table_remove(pui_by_easy, msg->easy_handle);
fclose(pui->file);
if (msg->data.result != CURLE_OK)
g_unlink(pui->dest_str); /* Delete so we try again. */
curl_multi_remove_handle(_curl_multi, msg->easy_handle);
- g_idle_add_full(G_PRIORITY_HIGH_IDLE,
- (GSourceFunc)map_download_idle_refresh, pui, NULL);
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)map_download_idle_refresh, pui, NULL);
}
}
}
/* Up to 1 transfer per tile. */
-while (num_transfers < (BUF_WIDTH_TILES * BUF_HEIGHT_TILES) && g_tree_nnodes(_pui_tree)) {
+while (num_transfers < (BUF_WIDTH_TILES * BUF_HEIGHT_TILES) && g_tree_nnodes(pui_tree)) {
ProgressUpdateInfo *pui;
- g_tree_foreach(_pui_tree, (GTraverseFunc) get_next_pui, &pui);
+ g_tree_foreach(pui_tree, (GTraverseFunc)get_next_pui, &pui);
if (pui->retries) {
/* This is a download. */
FILE *f;
- g_tree_steal(_pui_tree, pui);
- g_tree_insert(_downloading_tree, pui, pui);
+ g_tree_steal(pui_tree, pui);
+ g_tree_insert(downloading_tree, pui, pui);
- pui->src_str = map_construct_url(pui->tilex, pui->tiley, pui->zoom);
- pui->dest_str = g_strdup_printf("%s/%u/%u/%u.jpg",
- pui->repo->cache_dir, pui->zoom,
- pui->tilex, pui->tiley);
+ pui->src_str=map_construct_url(pui->tilex, pui->tiley, pui->zoom);
if (!pui->src_str) {
/* Failed to generate URL. */
+ g_debug("Failed to generate tile download URL");
g_idle_add_full(G_PRIORITY_HIGH_IDLE,(GSourceFunc)map_download_idle_refresh, pui, NULL);
continue;
}
+ pui->dest_str=g_strdup_printf("%s/%u/%u/%u.jpg", pui->repo->cache_dir, pui->zoom, pui->tilex, pui->tiley);
+
/* Check to see if we need to overwrite. */
if (pui->retries > 0) {
/* We're not updating - check if file already exists. */
if (g_file_test(pui->dest_str, G_FILE_TEST_EXISTS)) {
- g_idle_add_full(G_PRIORITY_HIGH_IDLE,
- (GSourceFunc)map_download_idle_refresh, pui, NULL);
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)map_download_idle_refresh, pui, NULL);
continue;
}
}
/* Attempt to open the file for writing. */
- if (!(f = g_fopen(pui->dest_str, "w"))
- && errno == ENOENT) {
+ if (!(f=g_fopen(pui->dest_str, "w")) && errno == ENOENT) {
/* Directory doesn't exist yet - create it, then we'll retry */
gchar buffer[BUFFER_SIZE];
- snprintf(buffer, sizeof(buffer), "%s/%u/%u",
- pui->repo->cache_dir, pui->zoom, pui->tilex);
+ g_snprintf(buffer, sizeof(buffer), "%s/%u/%u", pui->repo->cache_dir, pui->zoom, pui->tilex);
g_mkdir_with_parents(buffer, 0775);
- f = g_fopen(pui->dest_str, "w");
+ f=g_fopen(pui->dest_str, "w");
}
if (f) {
CURL *curl_easy;
pui->file = f;
- curl_easy = g_queue_pop_tail(_curl_easy_queue);
+ curl_easy = g_queue_pop_tail(curl_easy_queue);
if (!curl_easy) {
/* Need a new curl_easy. */
MACRO_CURL_EASY_INIT(curl_easy);
}
curl_easy_setopt(curl_easy, CURLOPT_URL, pui->src_str);
curl_easy_setopt(curl_easy, CURLOPT_WRITEDATA, f);
- g_hash_table_insert(_pui_by_easy, curl_easy, pui);
+ g_hash_table_insert(pui_by_easy, curl_easy, pui);
if (!_curl_multi) {
/* Initialize CURL. */
_curl_multi = curl_multi_init();
curl_multi_add_handle(_curl_multi, curl_easy);
num_transfers++;
} else {
- /* Unable to download file. */
+ /* Unable to open tile file for writing. */
gchar buffer[BUFFER_SIZE];
- snprintf(buffer, sizeof(buffer), "%s:\n%s",
- _("Failed to open file for writing"),
- pui->dest_str);
+ g_snprintf(buffer, sizeof(buffer), "%s:\n%s", _("Failed to open file for writing"), pui->dest_str);
MACRO_BANNER_SHOW_INFO(_window, buffer);
- g_idle_add_full(G_PRIORITY_HIGH_IDLE,
- (GSourceFunc)map_download_idle_refresh, pui,
- NULL);
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)map_download_idle_refresh, pui, NULL);
continue;
}
} else if (--deletes_left) {
/* This is a delete. */
gchar buffer[BUFFER_SIZE];
- g_tree_steal(_pui_tree, pui);
- g_tree_insert(_downloading_tree, pui, pui);
+ g_tree_steal(pui_tree, pui);
+ g_tree_insert(downloading_tree, pui, pui);
- snprintf(buffer, sizeof(buffer), "%s/%u/%u/%u.jpg",
- pui->repo->cache_dir, pui->zoom, pui->tilex,
- pui->tiley);
+ g_snprintf(buffer, sizeof(buffer), "%s/%u/%u/%u.jpg", pui->repo->cache_dir, pui->zoom, pui->tilex, pui->tiley);
g_unlink(buffer);
- g_idle_add_full(G_PRIORITY_HIGH_IDLE,
- (GSourceFunc)map_download_idle_refresh,
- pui, NULL);
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE,(GSourceFunc)map_download_idle_refresh, pui, NULL);
} else
break;
}
-if (!(num_transfers || g_tree_nnodes(_pui_tree))) {
+if (!(num_transfers || g_tree_nnodes(pui_tree))) {
/* Destroy curl after 50 counts (5 seconds). */
if (--destroy_counter) {
/* Clean up curl. */
CURL *curr;
- while ((curr = g_queue_pop_tail(_curl_easy_queue)))
+ while ((curr = g_queue_pop_tail(curl_easy_queue)))
curl_easy_cleanup(curr);
curl_multi_cleanup(_curl_multi);
_curl_multi = NULL;
_curl_sid = 0;
- vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
return FALSE;
}
} else
destroy_counter = 50;
-vprintf("%s(): return TRUE (%d, %d)\n", __PRETTY_FUNCTION__,
- num_transfers, g_tree_nnodes(_pui_tree));
return TRUE;
}
gint dwidth = widthstr ? atoi(widthstr + 6) - TILE_SIZE_PIXELS : 0;
gint dheight = heightstr ? atoi(heightstr + 7) - TILE_SIZE_PIXELS : 0;
-unit2latlon(tile2zunit(tilex, zoomlevel)
- - pixel2zunit(dwidth / 2, zoomlevel),
- tile2zunit(tiley + 1, zoomlevel)
- + pixel2zunit((dheight + 1) / 2, zoomlevel), lat1, lon1);
+unit2latlon(tile2zunit(tilex, zoomlevel) - pixel2zunit(dwidth / 2, zoomlevel),
+ tile2zunit(tiley + 1, zoomlevel) + pixel2zunit((dheight + 1) / 2, zoomlevel), lat1, lon1);
-unit2latlon(tile2zunit(tilex + 1, zoomlevel)
- + pixel2zunit((dwidth + 1) / 2, zoomlevel),
- tile2zunit(tiley, zoomlevel)
- - pixel2zunit(dheight / 2, zoomlevel), lat2, lon2);
+unit2latlon(tile2zunit(tilex + 1, zoomlevel) + pixel2zunit((dwidth + 1) / 2, zoomlevel),
+ tile2zunit(tiley, zoomlevel) - pixel2zunit(dheight / 2, zoomlevel), lat2, lon2);
setlocale(LC_NUMERIC, "C");
-snprintf(cmd, sizeof(cmd),
+g_snprintf(cmd, sizeof(cmd),
"(echo \"%.6f %.6f\"; echo \"%.6f %.6f\") | "
"/usr/bin/cs2cs +proj=longlat +datum=WGS84 +to +init=%s -f %%.6f "
" > /tmp/tmpcs2cs ", lon1, lat1, lon2, lat2, srs);
system_retcode = system(cmd);
if (system_retcode)
- g_printerr("cs2cs returned error code %d\n",
- WEXITSTATUS(system_retcode));
+ g_printerr("cs2cs returned error code %d\n", WEXITSTATUS(system_retcode));
else if (!(in = g_fopen("/tmp/tmpcs2cs", "r")))
g_printerr("Cannot open results of conversion\n");
-else if (5 !=
- fscanf(in, "%lf %lf %s %lf %lf", &lon1, &lat1, cmd, &lon2, &lat2)) {
+else if (5 != fscanf(in, "%lf %lf %s %lf %lf", &lon1, &lat1, cmd, &lon2, &lat2)) {
g_printerr("Wrong conversion\n");
fclose(in);
} else {
return "";
}
+void
+map_download_progress_clear(void)
+{
+g_assert(_progress_item);
+gtk_progress_bar_set_fraction(_progress_item, 0.0);
+gtk_progress_bar_set_text(_progress_item, "");
+}
+
+void
+map_download_progress_set(gint currd, gint numd)
+{
+gchar buffer[64];
+
+g_assert(_progress_item);
+g_snprintf(buffer, sizeof(buffer), _("Downloading maps (%d/%d)"), currd, numd);
+gtk_progress_bar_set_text(_progress_item, buffer);
+gtk_progress_bar_set_fraction(_progress_item, currd/(double)numd);
+}
gboolean
map_download_idle_refresh(ProgressUpdateInfo * pui)
/* If zoom has changed since we first put in the request for
* this tile, then we may have to update more than one tile. */
guint tilex, tiley, tilex_end, tiley_end;
- for (tilex = pui->tilex << zoom_diff,
- tilex_end = tilex + (1 << zoom_diff);
- tilex < tilex_end; tilex++) {
- for (tiley = pui->tiley << zoom_diff,
- tiley_end = tiley + (1 << zoom_diff);
- tiley < tiley_end; tiley++) {
+ for (tilex = pui->tilex << zoom_diff, tilex_end = tilex + (1 << zoom_diff); tilex < tilex_end; tilex++) {
+ for (tiley = pui->tiley << zoom_diff, tiley_end = tiley + (1 << zoom_diff); tiley < tiley_end; tiley++) {
if ((tilex - _base_tilex) < BUF_WIDTH_TILES && (tiley - _base_tiley) < BUF_HEIGHT_TILES) {
- map_render_tile(tilex, tiley,
- ((tilex - _base_tilex) << TILE_SIZE_P2),
- ((tiley - _base_tiley) << TILE_SIZE_P2),
- TRUE);
+ map_render_tile(tilex, tiley, ((tilex - _base_tilex) << TILE_SIZE_P2), ((tiley - _base_tiley) << TILE_SIZE_P2), TRUE);
map_render_data();
gtk_widget_queue_draw_area
(_map_widget,
if (pui->retries) {
/* removal automatically calls progress_update_info_free(). */
- g_tree_steal(_downloading_tree, pui);
- g_tree_insert(_pui_tree, pui, pui);
-#ifdef WITH_OSSO
+ g_tree_steal(downloading_tree, pui);
+ g_tree_insert(pui_tree, pui, pui);
if (iap_is_connected() && !_curl_sid)
-#else
- if (!_curl_sid)
-#endif
_curl_sid = g_timeout_add(100,(GSourceFunc)map_download_timeout, NULL);
/* Don't do anything else. */
return FALSE;
} else {
/* No more retries left - something must be wrong. */
- MACRO_BANNER_SHOW_INFO(_window, _("Error in download. Check internet connection"
- " and/or Map Repository URL Format."));
+ MACRO_BANNER_SHOW_INFO(_window, _("Error in download. Check internet connection and/or Map Repository URL Format."));
}
}
/* removal automatically calls progress_update_info_free(). */
-g_tree_remove(_downloading_tree, pui);
+g_tree_remove(downloading_tree, pui);
if (++_curr_download == _num_downloads) {
-#ifdef WITH_HILDON
- gtk_widget_destroy(_download_banner);
- _download_banner = NULL;
-#else
- gtk_widget_hide(GTK_WIDGET(_progress_item));
-#endif
_num_downloads = _curr_download = 0;
-} else
- hildon_banner_set_fraction(HILDON_BANNER(_download_banner), _curr_download / (double)_num_downloads);
-
+ map_download_progress_clear();
+} else {
+ map_download_progress_set(_curr_download, _num_downloads);
+}
return FALSE;
}
{
ProgressUpdateInfo *pui;
-#ifdef WITH_OSSO
iap_connect();
-#endif
pui = g_slice_new(ProgressUpdateInfo);
pui->tilex = tilex;
pui->retries = retries;
pui->repo = _curr_repo;
-if (g_tree_lookup(_pui_tree, pui) || g_tree_lookup(_downloading_tree, pui)) {
+if (g_tree_lookup(pui_tree, pui) || g_tree_lookup(downloading_tree, pui)) {
/* Already downloading. */
g_slice_free(ProgressUpdateInfo, pui);
return;
pui->dest_str = NULL;
pui->file = NULL;
-g_tree_insert(_pui_tree, pui, pui);
-#ifdef WITH_OSSO
+g_tree_insert(pui_tree, pui, pui);
if (iap_is_connected() && !_curl_sid)
-#else
-if (!_curl_sid)
-#endif
_curl_sid = g_timeout_add(100, (GSourceFunc) map_download_timeout, NULL);
-if (!_num_downloads++ && !_download_banner) {
- gchar buffer[100];
- g_snprintf(buffer, 100, _("Downloading maps (%d/%d)"), _curr_download, _num_downloads);
- _download_banner = hildon_banner_show_progress(_window, NULL, buffer);
-}
+if (!_num_downloads++)
+ gtk_progress_bar_set_text(_progress_item, _("Downloading maps..."));
}
void
map_download_init(void)
{
-_curl_easy_queue = g_queue_new();
-_pui_tree = g_tree_new_full((GCompareDataFunc) download_comparefunc, NULL, (GDestroyNotify) progress_update_info_free, NULL);
-_downloading_tree = g_tree_new_full((GCompareDataFunc) download_comparefunc, NULL, (GDestroyNotify) progress_update_info_free, NULL);
-_pui_by_easy = g_hash_table_new(g_direct_hash, g_direct_equal);
+curl_easy_queue = g_queue_new();
+pui_tree = g_tree_new_full((GCompareDataFunc)download_comparefunc, NULL, (GDestroyNotify) progress_update_info_free, NULL);
+downloading_tree = g_tree_new_full((GCompareDataFunc)download_comparefunc, NULL, (GDestroyNotify) progress_update_info_free, NULL);
+pui_by_easy = g_hash_table_new(g_direct_hash, g_direct_equal);
}
-void
-map_download_deinit(void)
+gboolean
+map_download_stop(void)
{
-/* Clean up CURL. */
if (_curl_multi) {
CURL *curr;
CURLMsg *msg;
- gint num_transfers, num_msgs;
-
- /* First, remove all downloads from _pui_tree. */
- g_tree_destroy(_pui_tree);
+ gint num_msgs;
- /* Finish up all downloads. */
- while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(_curl_multi, &num_transfers) || num_transfers) {
- /* XXX: should inform the user why it's taking so damn long... */
+ /* Clear the tree and create it again */
+ if (pui_tree) {
+ g_tree_destroy(pui_tree);
+ pui_tree = g_tree_new_full((GCompareDataFunc)download_comparefunc, NULL, (GDestroyNotify) progress_update_info_free, NULL);
}
/* Close all finished files. */
while ((msg = curl_multi_info_read(_curl_multi, &num_msgs))) {
if (msg->msg == CURLMSG_DONE) {
/* This is a map download. */
- ProgressUpdateInfo *pui = g_hash_table_lookup(_pui_by_easy, msg->easy_handle);
- g_queue_push_head(_curl_easy_queue, msg->easy_handle);
- g_hash_table_remove(_pui_by_easy, msg->easy_handle);
+ ProgressUpdateInfo *pui = g_hash_table_lookup(pui_by_easy, msg->easy_handle);
+ g_queue_push_head(curl_easy_queue, msg->easy_handle);
+ g_hash_table_remove(pui_by_easy, msg->easy_handle);
fclose(pui->file);
curl_multi_remove_handle(_curl_multi, msg->easy_handle);
}
}
- while ((curr = g_queue_pop_tail(_curl_easy_queue)))
+ g_debug("Stopping downloads");
+ while ((curr = g_queue_pop_tail(curl_easy_queue)))
curl_easy_cleanup(curr);
-
curl_multi_cleanup(_curl_multi);
_curl_multi = NULL;
+ return TRUE;
+}
+g_debug("No downloads to stop");
+return FALSE;
+}
- g_queue_free(_curl_easy_queue);
- g_tree_destroy(_downloading_tree);
- g_hash_table_destroy(_pui_by_easy);
+/*
+ * Clean up CURL and structures
+ */
+void
+map_download_deinit(void)
+{
+if (_curl_multi) {
+ CURL *curr;
+ gint num_transfers;
+
+ /* Finish up all downloads. */
+ while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(_curl_multi, &num_transfers) || num_transfers) {
+ g_debug("NT: %d", num_transfers);
+ }
+
+ /* Stop all transfers and cleanup */
+ map_download_stop();
+
+ if (pui_tree)
+ g_tree_destroy(pui_tree);
+ if (downloading_tree)
+ g_tree_destroy(downloading_tree);
+ if (pui_by_easy)
+ g_hash_table_destroy(pui_by_easy);
+ if (curl_easy_queue)
+ g_queue_free(curl_easy_queue);
}
+if (_curl_sid) {
+ g_source_remove(_curl_sid);
+ _curl_sid = 0;
+}
}