X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fmap-download.c;h=2f07badd833e5fd337b7842cb895d1d7f78ffe22;hb=4c3fa14525e44c67b9b3fbf00f86fb24afd44c97;hp=0b272d694784c54bf1772458a80b77873180be8d;hpb=bfd9423677aab4372bc89edc0f18723c5190d04d;p=mapper diff --git a/src/map-download.c b/src/map-download.c index 0b272d6..2f07bad 100644 --- a/src/map-download.c +++ b/src/map-download.c @@ -43,7 +43,6 @@ #include "hildon-mapper.h" #include "utils.h" -#include "map.h" #include "osm.h" #include "db.h" #include "osm-db.h" @@ -57,10 +56,17 @@ #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 @@ -125,18 +131,15 @@ while (_curl_multi && (msg = curl_multi_info_read(_curl_multi, &num_msgs))) { 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 && 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); } - 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. */ @@ -147,27 +150,27 @@ while (_curl_multi && (msg = curl_multi_info_read(_curl_multi, &num_msgs))) { } /* 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. */ @@ -178,39 +181,31 @@ while (num_transfers < (BUF_WIDTH_TILES * BUF_HEIGHT_TILES) && g_tree_nnodes(_pu } /* 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; @@ -218,29 +213,24 @@ while (num_transfers < (BUF_WIDTH_TILES * BUF_HEIGHT_TILES) && g_tree_nnodes(_pu } 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; } @@ -250,11 +240,15 @@ if (!(num_transfers || g_tree_nnodes(_pui_tree))) { 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) { @@ -276,14 +270,14 @@ strncpy(srs + 4, srsstr + 8, 256); 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"); @@ -310,7 +304,7 @@ setlocale(LC_NUMERIC, ""); return ret; } - +#endif /** * Given the xyz coordinates of our map coordinate system, write the qrst @@ -347,60 +341,80 @@ map_construct_url(guint tilex, guint tiley, guint zoom) 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 { @@ -411,8 +425,8 @@ 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. */ @@ -424,18 +438,13 @@ 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; } @@ -456,13 +465,13 @@ pui = g_slice_new(ProgressUpdateInfo); 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; @@ -471,7 +480,7 @@ pui->src_str = NULL; 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); @@ -482,54 +491,82 @@ if (!_num_downloads++) 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; -} +} }