AC_DEFINE_UNQUOTED(VIK_CONFIG_MAPCACHE_SIZE, ${VIK_CONFIG_MAPCACHE_SIZE},
[Size of the map cache])
+
+AC_ARG_WITH(tileage,
+ [AC_HELP_STRING([--with-tileage],
+ [specify the age of a tile before checking it (default is 30 s)])],
+ [if test "x$withval" = "xno"; then
+ VIK_CONFIG_DEFAULT_TILE_AGE=0;
+ elif test "x$withval" = "xyes"; then
+ AC_MSG_ERROR([Please, set a value for age of tiles])
+ else
+ VIK_CONFIG_DEFAULT_TILE_AGE=${withval}
+ fi],
+ [VIK_CONFIG_DEFAULT_TILE_AGE=30])
+AC_DEFINE_UNQUOTED(VIK_CONFIG_DEFAULT_TILE_AGE, ${VIK_CONFIG_DEFAULT_TILE_AGE},
+ [Age of tiles before cheking it (in seconds)])
+
dnl man pages processing
DB2MAN_XSL=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl
AC_SUBST(DB2MAN_XSL)
echo "USGS 24k DEM : $ac_cv_enable_dem24k"
echo "Realtime GPS Tracking : $ac_cv_enable_realtimegpstracking"
echo "Size of map cache (in memory) : ${VIK_CONFIG_MAPCACHE_SIZE}"
+echo "Age of tiles (in seconds) : ${VIK_CONFIG_DEFAULT_TILE_AGE}"
echo "-------------------------------------------"
echo ""
echo "Configure finished, type 'make' to build."
gboolean a_babel_convert_from_url ( VikTrwLayer *vt, const char *url, const char *input_type, BabelStatusFunc cb, gpointer user_data )
{
- static DownloadOptions options = {NULL, 0, a_check_kml_file};
+ static DownloadOptions options = { FALSE, NULL, 0, a_check_kml_file};
gint fd_src;
int fetch_ret;
gboolean ret = FALSE;
#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#include <glib.h>
#include <glib/gstdio.h>
#include <glib/gi18n.h>
curl_download_user_agent = g_strdup_printf ("%s/%s %s", PACKAGE, VERSION, curl_version());
}
-int curl_download_uri ( const char *uri, FILE *f, DownloadOptions *options )
+int curl_download_uri ( const char *uri, FILE *f, DownloadOptions *options, time_t time_condition )
{
CURL *curl;
CURLcode res = CURLE_FAILED_INIT;
g_debug("%s: uri=%s", __PRETTY_FUNCTION__, uri);
curl = curl_easy_init ();
- if ( curl )
- {
- if (vik_verbose)
- curl_easy_setopt ( curl, CURLOPT_VERBOSE, 1 );
- curl_easy_setopt ( curl, CURLOPT_URL, uri );
- curl_easy_setopt ( curl, CURLOPT_WRITEDATA, f );
- curl_easy_setopt ( curl, CURLOPT_WRITEFUNCTION, curl_write_func);
- curl_easy_setopt ( curl, CURLOPT_NOPROGRESS, 0 );
- curl_easy_setopt ( curl, CURLOPT_PROGRESSDATA, NULL );
- curl_easy_setopt ( curl, CURLOPT_PROGRESSFUNCTION, curl_progress_func);
- if (options != NULL) {
- if(options->referer != NULL)
- curl_easy_setopt ( curl, CURLOPT_REFERER, options->referer);
- if(options->follow_location != 0) {
- curl_easy_setopt ( curl, CURLOPT_FOLLOWLOCATION, 1);
- curl_easy_setopt ( curl, CURLOPT_MAXREDIRS, options->follow_location);
- }
- }
- curl_easy_setopt ( curl, CURLOPT_USERAGENT, curl_download_user_agent );
- if ((cookie_file = get_cookie_file(FALSE)) != NULL)
- curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_file);
- res = curl_easy_perform ( curl );
- curl_easy_cleanup ( curl );
+ if ( !curl ) {
+ return DOWNLOAD_ERROR;
+ }
+ if (vik_verbose)
+ curl_easy_setopt ( curl, CURLOPT_VERBOSE, 1 );
+ curl_easy_setopt ( curl, CURLOPT_URL, uri );
+ curl_easy_setopt ( curl, CURLOPT_WRITEDATA, f );
+ curl_easy_setopt ( curl, CURLOPT_WRITEFUNCTION, curl_write_func);
+ curl_easy_setopt ( curl, CURLOPT_NOPROGRESS, 0 );
+ curl_easy_setopt ( curl, CURLOPT_PROGRESSDATA, NULL );
+ curl_easy_setopt ( curl, CURLOPT_PROGRESSFUNCTION, curl_progress_func);
+ if (options != NULL) {
+ if(options->referer != NULL)
+ curl_easy_setopt ( curl, CURLOPT_REFERER, options->referer);
+ if(options->follow_location != 0) {
+ curl_easy_setopt ( curl, CURLOPT_FOLLOWLOCATION, 1);
+ curl_easy_setopt ( curl, CURLOPT_MAXREDIRS, options->follow_location);
+ }
+ if(options->check_file_server_time && time_condition != 0) {
+ /* if file exists, check against server if file is recent enough */
+ curl_easy_setopt ( curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
+ curl_easy_setopt ( curl, CURLOPT_TIMEVALUE, time_condition);
}
- return(res);
+ }
+ curl_easy_setopt ( curl, CURLOPT_USERAGENT, curl_download_user_agent );
+ if ((cookie_file = get_cookie_file(FALSE)) != NULL)
+ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_file);
+ res = curl_easy_perform ( curl );
+ if (res == 0) {
+ glong response;
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+ if (response == 304) { // 304 = Not Modified
+ res = DOWNLOAD_NO_NEWER_FILE;
+ } else if (response == 200 || // http: 200 = Ok
+ response == 226) { // ftp: 226 = sucess
+ gdouble size;
+ /* verify if curl sends us any data - this is a workaround on using CURLOPT_TIMECONDITION
+ when the server has a (incorrect) time earlier than the time on the file we already have */
+ curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &size);
+ if (size == 0)
+ res = DOWNLOAD_ERROR;
+ else
+ res = DOWNLOAD_NO_ERROR;
+ } else {
+ g_warning("%s: http response: %ld for uri %s (time_condition = %ld)\n", __FUNCTION__, response, uri, time_condition);
+ res = DOWNLOAD_ERROR;
+ }
+ } else {
+ res = DOWNLOAD_ERROR;
+ }
+ curl_easy_cleanup ( curl );
+ return res;
}
-int curl_download_get_url ( const char *hostname, const char *uri, FILE *f, DownloadOptions *options, gboolean ftp )
+int curl_download_get_url ( const char *hostname, const char *uri, FILE *f, DownloadOptions *options, gboolean ftp, time_t time_condition )
{
int ret;
gchar *full = NULL;
/* Compose the full url */
full = g_strdup_printf ( "%s://%s%s", (ftp?"ftp":"http"), hostname, uri );
- ret = curl_download_uri ( full, f, options );
+ ret = curl_download_uri ( full, f, options, time_condition );
g_free ( full );
full = NULL;
- return (ret ? -2 : 0); /* -2 HTTP error */
+ return ret;
}
#include "download.h"
void curl_download_init ();
-int curl_download_get_url ( const char *hostname, const char *uri, FILE *f, DownloadOptions *options, gboolean ftp );
-int curl_download_uri ( const char *uri, FILE *f, DownloadOptions *options );
+int curl_download_get_url ( const char *hostname, const char *uri, FILE *f, DownloadOptions *options, gboolean ftp, time_t time_condition );
+int curl_download_uri ( const char *uri, FILE *f, DownloadOptions *options, time_t time_condition );
#endif
#include <stdio.h>
#include <ctype.h>
+#include <errno.h>
#include <string.h>
+#include <sys/types.h>
+#include <utime.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <glib/gi18n.h>
+
#include "download.h"
#include "curl_download.h"
return check_file_first_line(f, kml_str);
}
+static GList *file_list = NULL;
+static GMutex *file_list_mutex = NULL;
+
+void a_download_init (void)
+{
+ file_list_mutex = g_mutex_new();
+}
+
+static gboolean lock_file(const char *fn)
+{
+ gboolean locked = FALSE;
+ g_mutex_lock(file_list_mutex);
+ if (g_list_find(file_list, fn) == NULL)
+ {
+ // The filename is not yet locked
+ file_list = g_list_append(file_list, (gpointer)fn),
+ locked = TRUE;
+ }
+ g_mutex_unlock(file_list_mutex);
+ return locked;
+}
+
+static void unlock_file(const char *fn)
+{
+ g_mutex_lock(file_list_mutex);
+ file_list = g_list_remove(file_list, (gconstpointer)fn);
+ g_mutex_unlock(file_list_mutex);
+}
+
static int download( const char *hostname, const char *uri, const char *fn, DownloadOptions *options, gboolean ftp)
{
FILE *f;
int ret;
gchar *tmpfilename;
gboolean failure = FALSE;
+ time_t time_condition = 0;
/* Check file */
if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == TRUE )
{
- /* File exists: return */
- return -3;
+ if (options != NULL && options->check_file_server_time) {
+ /* Get the modified time of this file */
+ struct stat buf;
+ g_stat ( fn, &buf );
+ time_condition = buf.st_mtime;
+ if ( (time(NULL) - time_condition) < options->check_file_server_time )
+ /* File cache is too recent, so return */
+ return -3;
+ } else {
+ /* Nothing to do as file already exists, so return */
+ return -3;
+ }
} else {
gchar *dir = g_path_get_dirname ( fn );
g_mkdir_with_parents ( dir , 0777 );
g_free ( dir );
-
- /* create placeholder file */
- if ( ! (f = g_fopen ( fn, "w+b" )) ) /* immediately open file so other threads won't -- prevents race condition */
- return -4;
- fclose ( f );
- f = NULL;
}
tmpfilename = g_strdup_printf("%s.tmp", fn);
- f = g_fopen ( tmpfilename, "w+b" );
+ if (!lock_file ( tmpfilename ) )
+ {
+ g_debug("%s: Couldn't take lock on temporary file \"%s\"\n", __FUNCTION__, tmpfilename);
+ g_free ( tmpfilename );
+ return -4;
+ }
+ f = g_fopen ( tmpfilename, "w+b" ); /* truncate file and open it */
if ( ! f ) {
+ g_warning("Couldn't open temporary file \"%s\": %s", tmpfilename, g_strerror(errno));
g_free ( tmpfilename );
- g_remove ( fn ); /* couldn't create temporary. delete 0-byte file. */
return -4;
}
/* Call the backend function */
- ret = curl_download_get_url ( hostname, uri, f, options, ftp );
- if (ret == -1 || ret == 1 || ret == -2) {
+ ret = curl_download_get_url ( hostname, uri, f, options, ftp, time_condition );
+
+ if (ret != DOWNLOAD_NO_ERROR && ret != DOWNLOAD_NO_NEWER_FILE) {
g_debug("%s: download failed: curl_download_get_url=%d", __FUNCTION__, ret);
failure = TRUE;
}
if (failure)
{
g_warning(_("Download error: %s"), fn);
- fclose ( f );
- f = NULL;
g_remove ( tmpfilename );
+ unlock_file ( tmpfilename );
g_free ( tmpfilename );
+ fclose ( f );
+ f = NULL;
g_remove ( fn ); /* couldn't create temporary. delete 0-byte file. */
return -1;
}
+ if (ret == DOWNLOAD_NO_NEWER_FILE)
+ g_remove ( tmpfilename );
+ else
+ g_rename ( tmpfilename, fn ); /* move completely-downloaded file to permanent location */
+ unlock_file ( tmpfilename );
+ g_free ( tmpfilename );
fclose ( f );
f = NULL;
- g_rename ( tmpfilename, fn ); /* move completely-downloaded file to permanent location */
- g_free ( tmpfilename );
- return ret;
+ return 0;
}
/* success = 0, -1 = couldn't connect, -2 HTTP error, -3 file exists, -4 couldn't write to file... */
gboolean a_check_kml_file(FILE*);
typedef struct {
+ /**
+ * Check if the server has a more recent file than the one we have before downloading it
+ * This uses http header If-Modified-Since
+ * Nevertheless, the current file cache must be older than the specified
+ * value.
+ */
+ time_t check_file_server_time;
+
/**
* The REFERER string to use.
* Could be NULL.
* File content checker.
*/
VikFileContentCheckerFunc check_file;
+
} DownloadOptions;
+void a_download_init(void);
+
/* TODO: convert to Glib */
int a_http_download_get_url ( const char *hostname, const char *uri, const char *fn, DownloadOptions *opt );
int a_ftp_download_get_url ( const char *hostname, const char *uri, const char *fn, DownloadOptions *opt );
+/* Error messages returned by download functions */
+enum { DOWNLOAD_NO_ERROR = 0,
+ DOWNLOAD_NO_NEWER_FILE,
+ DOWNLOAD_ERROR };
+
#endif
static void expedia_mapcoord_to_center_coord ( MapCoord *src, VikCoord *dest );
static int expedia_download ( MapCoord *src, const gchar *dest_fn );
-static DownloadOptions expedia_options = { NULL, 2, a_check_map_file };
+static DownloadOptions expedia_options = { 0, NULL, 2, a_check_map_file };
void expedia_init() {
- VikMapsLayer_MapType map_type = { 5, 0, 0, VIK_VIEWPORT_DRAWMODE_EXPEDIA, expedia_coord_to_mapcoord, expedia_mapcoord_to_center_coord, expedia_download };
+ VikMapsLayer_MapType map_type = { 5, 0, 0, VIK_VIEWPORT_DRAWMODE_EXPEDIA, expedia_coord_to_mapcoord, expedia_mapcoord_to_center_coord, expedia_download, &expedia_options };
maps_layer_register_type(_("Expedia Street Maps"), 5, &map_type);
}
tmp_file = fdopen(tmp_fd, "r+");
// TODO: curl may not be available
- if (curl_download_uri(uri, tmp_file, NULL)) { // error
+ if (curl_download_uri(uri, tmp_file, NULL, 0)) { // error
fclose(tmp_file);
tmp_file = NULL;
g_remove(tmpname);
#define GOOGLE_GOTO_PATTERN_2 ",lng:"
#define GOOGLE_GOTO_NOT_FOUND "not understand the location"
-static DownloadOptions googlesearch_options = { "http://maps.google.com/", 0, a_check_map_file };
+static DownloadOptions googlesearch_options = { 0, "http://maps.google.com/", 0, a_check_map_file };
static void google_goto_tool_class_init ( GoogleGotoToolClass *klass );
static void google_goto_tool_init ( GoogleGotoTool *vwd );
if (!vik_debug)
g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, mute_log, NULL);
+ a_download_init();
curl_download_init();
a_preferences_init ();
/* initialisation */
void osm_init () {
- VikMapSource *osmarender_type = VIK_MAP_SOURCE(vik_slippy_map_source_new_with_id(12, "OpenStreetMap (Osmarender)", "tah.openstreetmap.org", "/Tiles/tile/%d/%d/%d.png"));
- VikMapSource *mapnik_type = VIK_MAP_SOURCE(vik_slippy_map_source_new_with_id( 13, "OpenStreetMap (Mapnik)", "tile.openstreetmap.org", "/%d/%d/%d.png"));
- VikMapSource *maplint_type = VIK_MAP_SOURCE(vik_slippy_map_source_new_with_id( 14, "OpenStreetMap (Maplint)", "tah.openstreetmap.org", "/Tiles/maplint.php/%d/%d/%d.png"));
- VikMapSource *cycle_type = VIK_MAP_SOURCE(vik_slippy_map_source_new_with_id( 17, "OpenStreetMap (Cycle)", "thunderflames.org/tiles/cycle/", "%d/%d/%d.png" ));
+ VikMapSource *osmarender_type =
+ VIK_MAP_SOURCE(g_object_new(VIK_TYPE_SLIPPY_MAP_SOURCE,
+ "id", 12,
+ "label", "OpenStreetMap (Osmarender)",
+ "hostname", "tah.openstreetmap.org",
+ "url", "/Tiles/tile/%d/%d/%d.png",
+ "check-file-server-time", VIK_CONFIG_DEFAULT_TILE_AGE,
+ NULL));
+ VikMapSource *mapnik_type =
+ VIK_MAP_SOURCE(g_object_new(VIK_TYPE_SLIPPY_MAP_SOURCE,
+ "id", 13,
+ "label", "OpenStreetMap (Mapnik)",
+ "hostname", "tile.openstreetmap.org",
+ "url", "/%d/%d/%d.png",
+ "check-file-server-time", VIK_CONFIG_DEFAULT_TILE_AGE,
+ NULL));
+ VikMapSource *maplint_type =
+ VIK_MAP_SOURCE(g_object_new(VIK_TYPE_SLIPPY_MAP_SOURCE,
+ "id", 14,
+ "label", "OpenStreetMap (Maplint)",
+ "hostname", "tah.openstreetmap.org",
+ "url", "/Tiles/maplint.php/%d/%d/%d.png",
+ "check-file-server-time", VIK_CONFIG_DEFAULT_TILE_AGE,
+ NULL));
+ VikMapSource *cycle_type =
+ VIK_MAP_SOURCE(g_object_new(VIK_TYPE_SLIPPY_MAP_SOURCE,
+ "id", 17,
+ "label", "OpenStreetMap (Cycle)",
+ "hostname", "thunderflames.org/tiles/cycle/",
+ "url", "%d/%d/%d.png",
+ "check-file-server-time", VIK_CONFIG_DEFAULT_TILE_AGE,
+ NULL));
maps_layer_register_map_source (osmarender_type);
maps_layer_register_map_source (mapnik_type);
(intlon >= 0) ? 'E' : 'W',
ABS(intlon) );
- static DownloadOptions options = { NULL, 0, a_check_map_file };
+ static DownloadOptions options = { 0, NULL, 0, a_check_map_file };
a_http_download_get_url ( SRTM_HTTP_SITE, src_fn, p->dest, &options );
g_free ( src_fn );
}
uri = g_strdup_printf(vik_goto_tool_get_url_format(self), escaped_srch_str);
/* TODO: curl may not be available */
- if (curl_download_uri(uri, tmp_file, vik_goto_tool_get_download_options(self))) { /* error */
+ if (curl_download_uri(uri, tmp_file, vik_goto_tool_get_download_options(self), 0)) { /* error */
fclose(tmp_file);
tmp_file = NULL;
ret = -1;
VikViewport *redownload_vvp;
};
-enum { REDOWNLOAD_NONE = 0, REDOWNLOAD_BAD, REDOWNLOAD_ALL, DOWNLOAD_OR_REFRESH };
+enum { REDOWNLOAD_NONE = 0, /* download only missing maps */
+ REDOWNLOAD_BAD, /* download missing and bad maps */
+ REDOWNLOAD_NEW, /* download missing maps that are newer on server only */
+ REDOWNLOAD_ALL, /* download all maps */
+ DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */
/****************************************/
#ifdef DEBUG
fputs(stderr, "DEBUG: Starting autodownload\n");
#endif
- start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
+ if ( vik_map_source_supports_if_modified_since (map) )
+ // Try to download newer tiles
+ start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
+ else
+ // Download only missing tiles
+ start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
}
if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
remove_mem_cache = TRUE;
} else if ( mdi->redownload == DOWNLOAD_OR_REFRESH ) {
remove_mem_cache = TRUE;
+ } else if ( mdi->redownload == REDOWNLOAD_NEW) {
+ need_download = TRUE;
+ remove_mem_cache = TRUE;
} else
continue;
{
start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
}
+
static void maps_layer_redownload_all ( VikMapsLayer *vml )
{
start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
}
+static void maps_layer_redownload_new ( VikMapsLayer *vml )
+{
+ start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
+}
+
static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
{
if (!vml || vml->vl.type != VIK_LAYER_MAPS)
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
+ item = gtk_menu_item_new_with_label ( _("Redownload new map(s)") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
+
item = gtk_menu_item_new_with_label ( _("Redownload all map(s)") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
}
-static void maps_layer_download_onscreen_maps ( gpointer vml_vvp[2] )
+static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
{
download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
}
+static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
+{
+ download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
+}
+
static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
{
download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( _("Download Onscreen Maps") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_onscreen_maps), pass_along );
+ item = gtk_menu_item_new_with_label ( _("Download missing Onscreen Maps") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
+ if ( vik_map_source_supports_if_modified_since (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
+ item = gtk_menu_item_new_with_label ( _("Download new Onscreen Maps from server") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ }
+
/* TODO Add GTK_STOCK_REFRESH icon */
item = gtk_menu_item_new_with_label ( _("Refresh Onscreen Tiles") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
static void vik_map_source_finalize (GObject *object);
static void vik_map_source_class_init (VikMapSourceClass *klass);
+static void _supports_if_modified_since (VikMapSource *object);
+
G_DEFINE_TYPE_EXTENDED (VikMapSource, vik_map_source, G_TYPE_OBJECT, (GTypeFlags)G_TYPE_FLAG_ABSTRACT,);
static void
klass->get_tilesize_x = NULL;
klass->get_tilesize_y = NULL;
klass->get_drawmode = NULL;
+ klass->supports_if_modified_since = _supports_if_modified_since;
klass->coord_to_mapcoord = NULL;
klass->mapcoord_to_center_coord = NULL;
klass->download = NULL;
object_class->finalize = vik_map_source_finalize;
}
+void
+_supports_if_modified_since (VikMapSource *self)
+{
+ // Default feature: does not support
+ return FALSE;
+}
guint8
vik_map_source_get_uniq_id (VikMapSource *self)
return (*klass->get_drawmode)(self);
}
+gboolean
+vik_map_source_supports_if_modified_since (VikMapSource * self)
+{
+ VikMapSourceClass *klass;
+ g_return_val_if_fail (self != NULL, 0);
+ g_return_val_if_fail (VIK_IS_MAP_SOURCE (self), 0);
+ klass = VIK_MAP_SOURCE_GET_CLASS(self);
+
+ g_return_val_if_fail (klass->supports_if_modified_since != NULL, 0);
+
+ return (*klass->supports_if_modified_since)(self);
+}
+
gboolean
vik_map_source_coord_to_mapcoord (VikMapSource *self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest )
{
guint16 (* get_tilesize_x) (VikMapSource * self);
guint16 (* get_tilesize_y) (VikMapSource * self);
VikViewportDrawMode (* get_drawmode) (VikMapSource * self);
+ gboolean (* supports_if_modified_since) (VikMapSource * self);
gboolean (* coord_to_mapcoord) (VikMapSource * self, const VikCoord * src, gdouble xzoom, gdouble yzoom, MapCoord * dest);
void (* mapcoord_to_center_coord) (VikMapSource * self, MapCoord * src, VikCoord * dest);
int (* download) (VikMapSource * self, MapCoord * src, const gchar * dest_fn);
guint16 vik_map_source_get_tilesize_x (VikMapSource * self);
guint16 vik_map_source_get_tilesize_y (VikMapSource * self);
VikViewportDrawMode vik_map_source_get_drawmode (VikMapSource * self);
+gboolean vik_map_source_supports_if_modified_since (VikMapSource * self);
gboolean vik_map_source_coord_to_mapcoord (VikMapSource * self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest );
void vik_map_source_mapcoord_to_center_coord (VikMapSource * self, MapCoord *src, VikCoord *dest);
int vik_map_source_download (VikMapSource * self, MapCoord * src, const gchar * dest_fn);
static gboolean _coord_to_mapcoord ( VikMapSource *self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest );
static void _mapcoord_to_center_coord ( VikMapSource *self, MapCoord *src, VikCoord *dest );
static int _download ( VikMapSource *self, MapCoord *src, const gchar *dest_fn );
+static gboolean _supports_if_modified_since (VikMapSource *self );
static gchar *_get_uri( VikSlippyMapSource *self, MapCoord *src );
static gchar *_get_hostname( VikSlippyMapSource *self );
PROP_URL,
PROP_REFERER,
PROP_FOLLOW_LOCATION,
+ PROP_CHECK_FILE_SERVER_TIME,
};
G_DEFINE_TYPE_EXTENDED (VikSlippyMapSource, vik_slippy_map_source, VIK_TYPE_MAP_SOURCE_DEFAULT, (GTypeFlags)0,);
priv->options.referer = NULL;
priv->options.follow_location = 0;
priv->options.check_file = a_check_map_file;
+ priv->options.check_file_server_time = 0;
g_object_set (G_OBJECT (self),
"tilesize-x", 256,
priv->options.follow_location = g_value_get_long (value);
break;
+ case PROP_CHECK_FILE_SERVER_TIME:
+ priv->options.check_file_server_time = g_value_get_uint (value);
+ break;
+
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
g_value_set_long (value, priv->options.follow_location);
break;
+ case PROP_CHECK_FILE_SERVER_TIME:
+ g_value_set_uint (value, priv->options.check_file_server_time);
+ break;
+
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
parent_class->coord_to_mapcoord = _coord_to_mapcoord;
parent_class->mapcoord_to_center_coord = _mapcoord_to_center_coord;
parent_class->download = _download;
+ parent_class->supports_if_modified_since = _supports_if_modified_since;
/* Default implementation of methods */
klass->get_uri = _get_uri;
0 /* default value */,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_FOLLOW_LOCATION, pspec);
+
+ pspec = g_param_spec_uint ("check-file-server-time",
+ "Check file server time",
+ "Age of current cache before redownloading tile",
+ 0 /* minimum value */,
+ G_MAXUINT16 /* maximum value */,
+ 0 /* default value */,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_CHECK_FILE_SERVER_TIME, pspec);
g_type_class_add_private (klass, sizeof (VikSlippyMapSourcePrivate));
return (*klass->get_download_options)(self);
}
+gboolean
+_supports_if_modified_since (VikMapSource *self)
+{
+ g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), FALSE);
+
+ VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
+
+ g_debug ("%s: priv->options.check_file_server_time = %d", __FUNCTION__, priv->options.check_file_server_time);
+
+ return priv->options.check_file_server_time != 0;
+}
static gboolean
_coord_to_mapcoord ( VikMapSource *self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest )
{