#include "config.h"
-#define _GNU_SOURCE
-
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "hildon-mapper.h"
#include "utils.h"
-#include "map.h"
#include "osm.h"
#include "db.h"
#include "osm-db.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"
+#include "map-repo.h"
+#include "gtkmap.h"
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);
static gboolean
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 && path_gpx_parse(_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();
+ path_find_nearest_point(_route, _gps->data.lat, _gps->data.lon);
}
- cancel_autoroute(TRUE); /* We're done. Clean up. */
+ route_cancel_autoroute(_route, 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. */
}
/* Up to 1 transfer per tile. */
-while (num_transfers < (BUF_WIDTH_TILES * BUF_HEIGHT_TILES) && g_tree_nnodes(_pui_tree)) {
+while (num_transfers < (4*4) && 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. */
}
/* 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];
- g_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);
- if (!_curl_multi) {
- /* Initialize CURL. */
- _curl_multi = curl_multi_init();
- /*curl_multi_setopt(_curl_multi, CURLMOPT_PIPELINING, 1); */
- }
+ g_hash_table_insert(pui_by_easy, curl_easy, pui);
curl_multi_add_handle(_curl_multi, curl_easy);
num_transfers++;
} else {
/* Unable to open tile file for writing. */
gchar buffer[BUFFER_SIZE];
- g_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);
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);
- g_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);
} 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;
return FALSE;
}
return TRUE;
}
+#ifdef MAP_DOWNLOAD_WMS
/**
* Given a wms uri pattern, compute the coordinate transformation and
* trimming.
* 'proj' is used for the conversion
*/
+
+#define WMS_TILE_SIZE_PIXELS (256)
+
static gchar *
map_convert_wms_to_wms(gint tilex, gint tiley, gint zoomlevel, gchar * uri)
{
srs[srsstre - srsstr - 4] = 0;
/* convert to lower, as WMC is EPSG and cs2cs is epsg */
-gint dwidth = widthstr ? atoi(widthstr + 6) - TILE_SIZE_PIXELS : 0;
-gint dheight = heightstr ? atoi(heightstr + 7) - TILE_SIZE_PIXELS : 0;
+gint dwidth = widthstr ? atoi(widthstr + 6) - WMS_TILE_SIZE_PIXELS : 0;
+gint dheight = heightstr ? atoi(heightstr + 7) - WMS_TILE_SIZE_PIXELS : 0;
unit2latlon(tile2zunit(tilex, zoomlevel) - pixel2zunit(dwidth / 2, zoomlevel),
- tile2zunit(tiley + 1, zoomlevel) + pixel2zunit((dheight + 1) / 2, zoomlevel), lat1, lon1);
+ 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);
+ tile2zunit(tiley, zoomlevel) - pixel2zunit(dheight / 2, zoomlevel), &lat2, &lon2);
setlocale(LC_NUMERIC, "C");
return ret;
}
-
+#endif
/**
* Given the xyz coordinates of our map coordinate system, write the qrst
switch (_curr_repo->type) {
case REPOTYPE_XYZ:
return g_strdup_printf(_curr_repo->url, tilex, tiley, zoom);
-
case REPOTYPE_XYZ_INV:
return g_strdup_printf(_curr_repo->url, 17 - zoom, tilex, tiley);
-
-case REPOTYPE_QUAD_QRST:
- {
- gchar location[MAX_ZOOM + 2];
+case REPOTYPE_QUAD_QRST: {
+ gchar location[32];
map_convert_coords_to_quadtree_string(tilex, tiley, zoom, location, 't', "qrts");
return g_strdup_printf(_curr_repo->url, location);
}
-
-case REPOTYPE_QUAD_ZERO:
- {
+case REPOTYPE_QUAD_ZERO: {
/* This is a zero-based quadtree URI. */
- gchar location[MAX_ZOOM + 2];
+ gchar location[32];
map_convert_coords_to_quadtree_string(tilex, tiley, zoom, location, '\0', "0123");
return g_strdup_printf(_curr_repo->url, location);
}
-
+#ifdef MAP_DOWNLOAD_WMD
case REPOTYPE_WMS:
return map_convert_wms_to_wms(tilex, tiley, zoom, _curr_repo->url);
-
+#endif
default:
return NULL;
}
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)
{
+guint tmp=0;
/* Test if download succeeded (only if retries != 0). */
if (!pui->retries || g_file_test(pui->dest_str, G_FILE_TEST_EXISTS)) {
- gint zoom_diff = pui->zoom - _zoom;
+ gint zoom_diff = pui->zoom - gtk_map_get_zoom(_map);
+
+#if 0
/* Only refresh at same or "lower" (more detailed) zoom level. */
if (zoom_diff >= 0) {
+ guint tilex, tiley, tilex_end, tiley_end;
+
/* 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++) {
- 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);
+ tmp++;
+ if (map_render_tile(tilex, tiley, ((tilex - _base_tilex) << TILE_SIZE_P2), ((tiley - _base_tiley) << TILE_SIZE_P2), TRUE)==TRUE) {
map_render_data();
- gtk_widget_queue_draw_area
- (_map_widget,
+ gtk_widget_queue_draw_area(_map_widget,
((tilex - _base_tilex) << TILE_SIZE_P2) - _offsetx,
((tiley - _base_tiley) << TILE_SIZE_P2) - _offsety,
TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
}
}
}
+ g_debug("*** MDIR LOOP: %u", tmp);
}
+#else
+ g_debug("XXX: Add cb or signal or something to inform map widget about fresh tile");
+#endif
}
/* Else the download failed. Update retries and maybe try again. */
else {
if (pui->retries) {
/* removal automatically calls progress_update_info_free(). */
- g_tree_steal(_downloading_tree, pui);
- g_tree_insert(_pui_tree, pui, pui);
+ g_tree_steal(downloading_tree, pui);
+ g_tree_insert(pui_tree, pui, pui);
if (iap_is_connected() && !_curl_sid)
_curl_sid = g_timeout_add(100,(GSourceFunc)map_download_timeout, NULL);
/* Don't do anything else. */
}
/* removal automatically calls progress_update_info_free(). */
-g_tree_remove(_downloading_tree, pui);
+g_tree_remove(downloading_tree, pui);
if (++_curr_download == _num_downloads) {
_num_downloads = _curr_download = 0;
- gtk_progress_bar_set_fraction(_progress_item, 0.0);
- gtk_progress_bar_set_text(_progress_item, "");
+ map_download_progress_clear();
} else {
- gchar buffer[64];
-
- g_snprintf(buffer, sizeof(buffer), _("Downloading maps (%d/%d)"), _curr_download, _num_downloads);
- gtk_progress_bar_set_text(_progress_item, buffer);
- gtk_progress_bar_set_fraction(_progress_item, _curr_download / (double)_num_downloads);
+ map_download_progress_set(_curr_download, _num_downloads);
}
return FALSE;
}
pui->tilex = tilex;
pui->tiley = tiley;
pui->zoom = zoom;
-pui->priority = (abs((gint) tilex - unit2tile(_center.unitx)) + abs((gint) tiley - unit2tile(_center.unity)));
+pui->priority = 1;
if (!retries)
pui->priority = -pui->priority; /* "Negative" makes them lowest pri. */
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);
+g_tree_insert(pui_tree, pui, pui);
if (iap_is_connected() && !_curl_sid)
_curl_sid = g_timeout_add(100, (GSourceFunc) map_download_timeout, NULL);
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);
+_curl_multi = curl_multi_init();
+/* curl_multi_setopt(_curl_multi, CURLMOPT_PIPELINING, 1); */
}
-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;
+ gint num_msgs;
- /* First, remove all downloads from _pui_tree. */
- g_tree_destroy(_pui_tree);
-
- /* 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);
- fclose(pui->file);
+ 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);
+ if (pui->file)
+ 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);
+ return TRUE;
+}
+g_debug("No downloads to stop");
+return FALSE;
+}
+
+/*
+ * 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);
curl_multi_cleanup(_curl_multi);
_curl_multi = NULL;
-
- g_queue_free(_curl_easy_queue);
- g_tree_destroy(_downloading_tree);
- g_hash_table_destroy(_pui_by_easy);
}
+if (_curl_sid) {
+ g_source_remove(_curl_sid);
+ _curl_sid = 0;
+}
}