[libchamplain] Fix various problems with asynchronous tile loading
- From: Jiří Techet <jiritechet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libchamplain] Fix various problems with asynchronous tile loading
- Date: Sun, 15 Aug 2010 21:18:10 +0000 (UTC)
commit ec6fa72c18daed6b68052d024800db8339f5dc2c
Author: JiÅ?Ã Techet <techet gmail com>
Date: Sun Aug 15 19:19:12 2010 +0200
Fix various problems with asynchronous tile loading
Signed-off-by: JiÅ?Ã Techet <techet gmail com>
champlain/champlain-file-cache.c | 54 +++++----
champlain/champlain-file-tile-source.c | 66 ++++++++--
champlain/champlain-image-renderer.c | 2 +-
champlain/champlain-memory-cache.c | 46 ++++++--
champlain/champlain-memphis-renderer.c | 3 +-
champlain/champlain-network-bbox-tile-source.c | 66 ++++++++--
champlain/champlain-network-tile-source.c | 154 ++++++++++++++---------
champlain/champlain-null-tile-source.c | 67 +++++++++--
8 files changed, 327 insertions(+), 131 deletions(-)
---
diff --git a/champlain/champlain-file-cache.c b/champlain/champlain-file-cache.c
index 4f340a7..9722a96 100644
--- a/champlain/champlain-file-cache.c
+++ b/champlain/champlain-file-cache.c
@@ -519,9 +519,9 @@ tile_rendered_cb (ChamplainTile *tile,
{
ChamplainMapSource *map_source = user_data->map_source;
GFile *file;
- ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE (map_source);
- ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
- ChamplainFileCachePrivate *priv = file_cache->priv;
+ ChamplainFileCache *file_cache;
+ ChamplainMapSource *next_source;
+ ChamplainFileCachePrivate *priv;
GFileInfo *info = NULL;
GTimeVal modified_time = { 0, };
gchar *filename = NULL;
@@ -529,15 +529,19 @@ tile_rendered_cb (ChamplainTile *tile,
// this frees user_data
g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, user_data);
- if (!tile)
+ if (!map_source)
{
- DEBUG ("Tile destroyed while loading");
- goto cleanup;
+ DEBUG ("Map source destroyed while loading");
+ return;
}
+ next_source = champlain_map_source_get_next_source (map_source);
+ file_cache = CHAMPLAIN_FILE_CACHE (map_source);
+ priv = file_cache->priv;
+
if (data->error)
{
- DEBUG ("Tile rendering failed: %s", filename);
+ DEBUG ("Tile rendering failed");
goto load_next;
}
@@ -662,18 +666,15 @@ file_loaded_cb (GFile *file,
g_object_unref (file);
- if (!tile)
+ if (!tile || !map_source)
{
- DEBUG ("Tile destroyed while loading");
- // data already destroyed by destroy_cb_data
- return;
- }
+ if (map_source)
+ g_object_remove_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
- if (!map_source)
- {
- DEBUG ("Map source destroyed while loading");
- // this destros the data by destroy_cb_data
- g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, user_data);
+ if (tile)
+ g_object_remove_weak_pointer (G_OBJECT (tile), (gpointer *) &user_data->tile);
+
+ g_slice_free (FileLoadedData, user_data);
return;
}
@@ -681,6 +682,9 @@ file_loaded_cb (GFile *file,
g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
+ g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
+ user_data, (GClosureNotify) destroy_cb_data, 0);
+
champlain_renderer_set_data (renderer, contents, length);
champlain_renderer_render (renderer, tile);
}
@@ -693,6 +697,8 @@ fill_tile (ChamplainMapSource *map_source,
g_return_if_fail (CHAMPLAIN_IS_FILE_CACHE (map_source));
g_return_if_fail (CHAMPLAIN_IS_TILE (tile));
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
+
if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_LOADED)
{
FileLoadedData *user_data;
@@ -711,17 +717,15 @@ fill_tile (ChamplainMapSource *map_source,
DEBUG ("fill of %s", filename);
- g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
- user_data, (GClosureNotify) destroy_cb_data, 0);
g_file_load_contents_async (file, NULL, (GAsyncReadyCallback) file_loaded_cb, user_data);
}
- else
+ else if (CHAMPLAIN_IS_MAP_SOURCE (next_source))
+ champlain_map_source_fill_tile (next_source, tile);
+ else if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_LOADED)
{
- ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
-
- /* Previous cache in the chain is validating its contents */
- if (CHAMPLAIN_IS_MAP_SOURCE (next_source))
- champlain_map_source_fill_tile (next_source, tile);
+ /* if we have some content, use the tile even if it wasn't validated */
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+ champlain_tile_display_content (tile);
}
}
diff --git a/champlain/champlain-file-tile-source.c b/champlain/champlain-file-tile-source.c
index 81c428b..23a6aec 100644
--- a/champlain/champlain-file-tile-source.c
+++ b/champlain/champlain-file-tile-source.c
@@ -141,17 +141,33 @@ champlain_file_tile_source_load_map_data (ChamplainFileTileSource *self,
}
+typedef struct
+{
+ ChamplainMapSource *map_source;
+} TileRenderedData;
+
+
static void
tile_rendered_cb (ChamplainTile *tile,
ChamplainRenderCallbackData *data,
- ChamplainMapSource *map_source)
+ TileRenderedData *user_data)
{
- ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (map_source);
- ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source);
- ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
+ ChamplainMapSource *map_source = user_data->map_source;
+ ChamplainMapSource *next_source;
+
+ // frees user_data - must not be used later in the function
+ g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
+
+ if (!map_source)
+ return;
+ next_source = champlain_map_source_get_next_source (map_source);
+
if (!data->error)
{
+ ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (map_source);
+ ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source);
+
if (tile_cache && data->data)
champlain_tile_cache_store_tile (tile_cache, tile, data->data, data->size);
@@ -161,9 +177,17 @@ tile_rendered_cb (ChamplainTile *tile,
}
else if (next_source)
champlain_map_source_fill_tile (next_source, tile);
+}
- g_object_unref (map_source);
- g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
+
+static void
+destroy_cb_data (TileRenderedData *data,
+ G_GNUC_UNUSED GClosure *closure)
+{
+ if (data->map_source)
+ g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
+
+ g_slice_free (TileRenderedData, data);
}
@@ -174,15 +198,33 @@ fill_tile (ChamplainMapSource *map_source,
g_return_if_fail (CHAMPLAIN_IS_FILE_TILE_SOURCE (map_source));
g_return_if_fail (CHAMPLAIN_IS_TILE (tile));
- ChamplainRenderer *renderer;
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
+
+ if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_LOADED)
+ {
+ ChamplainRenderer *renderer;
+ TileRenderedData *user_data;
+
+ renderer = champlain_map_source_get_renderer (map_source);
- renderer = champlain_map_source_get_renderer (map_source);
+ g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
- g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
+ user_data = g_slice_new (TileRenderedData);
+ user_data->map_source = map_source;
- g_object_ref (map_source);
+ g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
- g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), map_source);
+ g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
+ user_data, (GClosureNotify) destroy_cb_data, 0);
- champlain_renderer_render (renderer, tile);
+ champlain_renderer_render (renderer, tile);
+ }
+ else if (CHAMPLAIN_IS_MAP_SOURCE (next_source))
+ champlain_map_source_fill_tile (next_source, tile);
+ else if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_LOADED)
+ {
+ /* if we have some content, use the tile even if it wasn't validated */
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+ champlain_tile_display_content (tile);
+ }
}
diff --git a/champlain/champlain-image-renderer.c b/champlain/champlain-image-renderer.c
index e301f99..9dc8130 100644
--- a/champlain/champlain-image-renderer.c
+++ b/champlain/champlain-image-renderer.c
@@ -128,7 +128,7 @@ render (ChamplainRenderer *renderer, ChamplainTile *tile)
g_warning ("Unable to load the pixbuf: %s", error->message);
g_error_free (error);
}
-
+ goto error;
}
gdk_pixbuf_loader_close (loader, &error);
diff --git a/champlain/champlain-memory-cache.c b/champlain/champlain-memory-cache.c
index 187ef8d..7d03609 100644
--- a/champlain/champlain-memory-cache.c
+++ b/champlain/champlain-memory-cache.c
@@ -254,27 +254,50 @@ delete_queue_member (QueueMember *member, gpointer user_data)
}
+typedef struct
+{
+ ChamplainMapSource *map_source;
+} TileRenderedData;
+
+
static void
tile_rendered_cb (ChamplainTile *tile,
ChamplainRenderCallbackData *data,
- ChamplainMapSource *map_source)
+ TileRenderedData *user_data)
{
- ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
+ ChamplainMapSource *map_source = user_data->map_source;
+ ChamplainMapSource *next_source;
+
+ // frees user_data - must not be used later in the function
+ g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
+
+ if (!map_source)
+ return;
+ next_source = champlain_map_source_get_next_source (map_source);
+
if (!data->error)
{
if (CHAMPLAIN_IS_TILE_CACHE (next_source))
on_tile_filled (CHAMPLAIN_TILE_CACHE (next_source), tile);
- champlain_tile_set_fade_in (tile, TRUE);
+ champlain_tile_set_fade_in (tile, FALSE);
champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
champlain_tile_display_content (tile);
}
- else if (CHAMPLAIN_IS_MAP_SOURCE (next_source))
+ else if (next_source)
champlain_map_source_fill_tile (next_source, tile);
+}
- g_object_unref (map_source);
- g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
+
+static void
+destroy_cb_data (TileRenderedData *data,
+ G_GNUC_UNUSED GClosure *closure)
+{
+ if (data->map_source)
+ g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
+
+ g_slice_free (TileRenderedData, data);
}
@@ -300,6 +323,7 @@ fill_tile (ChamplainMapSource *map_source,
if (link)
{
QueueMember *member = link->data;
+ TileRenderedData *user_data;
move_queue_member_to_head (priv->queue, link);
@@ -307,8 +331,14 @@ fill_tile (ChamplainMapSource *map_source,
g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
- g_object_ref (map_source);
- g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), map_source);
+ user_data = g_slice_new (TileRenderedData);
+ user_data->map_source = map_source;
+
+ g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
+
+ g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
+ user_data, (GClosureNotify) destroy_cb_data, 0);
+
champlain_renderer_set_data (renderer, member->data, member->size);
champlain_renderer_render (renderer, tile);
diff --git a/champlain/champlain-memphis-renderer.c b/champlain/champlain-memphis-renderer.c
index d5d1eee..9fecca6 100644
--- a/champlain/champlain-memphis-renderer.c
+++ b/champlain/champlain-memphis-renderer.c
@@ -352,7 +352,8 @@ error:
callback_data.size = 0;
finish:
- g_signal_emit_by_name (tile, "render-complete", &callback_data);
+ if (tile)
+ g_signal_emit_by_name (tile, "render-complete", &callback_data);
if (pixbuf)
g_object_unref (pixbuf);
diff --git a/champlain/champlain-network-bbox-tile-source.c b/champlain/champlain-network-bbox-tile-source.c
index 4b0746c..392fe4d 100644
--- a/champlain/champlain-network-bbox-tile-source.c
+++ b/champlain/champlain-network-bbox-tile-source.c
@@ -366,17 +366,33 @@ champlain_network_bbox_tile_source_load_map_data (
}
+typedef struct
+{
+ ChamplainMapSource *map_source;
+} TileRenderedData;
+
+
static void
tile_rendered_cb (ChamplainTile *tile,
ChamplainRenderCallbackData *data,
- ChamplainMapSource *map_source)
+ TileRenderedData *user_data)
{
- ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (map_source);
- ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source);
- ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
+ ChamplainMapSource *map_source = user_data->map_source;
+ ChamplainMapSource *next_source;
+
+ // frees user_data - must not be used later in the function
+ g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
+
+ if (!map_source)
+ return;
+ next_source = champlain_map_source_get_next_source (map_source);
+
if (!data->error)
{
+ ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (map_source);
+ ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source);
+
if (tile_cache && data->data)
champlain_tile_cache_store_tile (tile_cache, tile, data->data, data->size);
@@ -386,9 +402,17 @@ tile_rendered_cb (ChamplainTile *tile,
}
else if (next_source)
champlain_map_source_fill_tile (next_source, tile);
+}
- g_object_unref (map_source);
- g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
+
+static void
+destroy_cb_data (TileRenderedData *data,
+ G_GNUC_UNUSED GClosure *closure)
+{
+ if (data->map_source)
+ g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
+
+ g_slice_free (TileRenderedData, data);
}
@@ -399,17 +423,35 @@ fill_tile (ChamplainMapSource *map_source,
g_return_if_fail (CHAMPLAIN_IS_NETWORK_BBOX_TILE_SOURCE (map_source));
g_return_if_fail (CHAMPLAIN_IS_TILE (tile));
- ChamplainRenderer *renderer;
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
+
+ if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_LOADED)
+ {
+ ChamplainRenderer *renderer;
+ TileRenderedData *user_data;
+
+ renderer = champlain_map_source_get_renderer (map_source);
- renderer = champlain_map_source_get_renderer (map_source);
+ g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
- g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
+ user_data = g_slice_new (TileRenderedData);
+ user_data->map_source = map_source;
- g_object_ref (map_source);
+ g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
- g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), map_source);
+ g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
+ user_data, (GClosureNotify) destroy_cb_data, 0);
- champlain_renderer_render (renderer, tile);
+ champlain_renderer_render (renderer, tile);
+ }
+ else if (CHAMPLAIN_IS_MAP_SOURCE (next_source))
+ champlain_map_source_fill_tile (next_source, tile);
+ else if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_LOADED)
+ {
+ /* if we have some content, use the tile even if it wasn't validated */
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+ champlain_tile_display_content (tile);
+ }
}
diff --git a/champlain/champlain-network-tile-source.c b/champlain/champlain-network-tile-source.c
index 2c5a78f..9eeff25 100644
--- a/champlain/champlain-network-tile-source.c
+++ b/champlain/champlain-network-tile-source.c
@@ -85,13 +85,13 @@ typedef struct
{
ChamplainMapSource *map_source;
ChamplainTile *tile;
-} TileLoadedCallbackData;
+} TileLoadedData;
typedef struct
{
ChamplainMapSource *map_source;
gchar *etag;
-} TileRenderedCallbackData;
+} TileRenderedData;
typedef struct
{
@@ -524,41 +524,29 @@ get_tile_uri (ChamplainNetworkTileSource *tile_source,
static void
-tile_destroyed_cb (G_GNUC_UNUSED ChamplainTile *tile,
- TileDestroyedCbData *data)
-{
- if (data->map_source && data->msg)
- {
- DEBUG ("Canceling tile download");
- ChamplainNetworkTileSourcePrivate *priv = CHAMPLAIN_NETWORK_TILE_SOURCE (data->map_source)->priv;
-
- soup_session_cancel_message (priv->soup_session, data->msg, SOUP_STATUS_CANCELLED);
- }
-}
-
-
-static void
-destroy_cb_data (TileDestroyedCbData *data,
- G_GNUC_UNUSED GClosure *closure)
-{
- if (data->map_source)
- g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
-
- g_slice_free (TileDestroyedCbData, data);
-}
-
-
-static void
-tile_rendered_cb (ChamplainTile *tile, ChamplainRenderCallbackData *data, TileRenderedCallbackData *user_data)
+tile_rendered_cb (ChamplainTile *tile,
+ ChamplainRenderCallbackData *data,
+ TileRenderedData *user_data)
{
ChamplainMapSource *map_source = user_data->map_source;
- ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (map_source);
- ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source);
- ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
- gchar *etag = user_data->etag;
+ ChamplainMapSource *next_source;
+ gchar *etag;
+
+ etag = g_strdup (user_data->etag);
+
+ // frees user_data - must not be used later in the function
+ g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
+
+ if (!map_source)
+ return;
+ next_source = champlain_map_source_get_next_source (map_source);
+
if (!data->error)
{
+ ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (map_source);
+ ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source);
+
if (etag != NULL)
champlain_tile_set_etag (tile, etag);
@@ -569,15 +557,24 @@ tile_rendered_cb (ChamplainTile *tile, ChamplainRenderCallbackData *data, TileRe
champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
champlain_tile_display_content (tile);
}
- else
- {
- if (next_source)
- champlain_map_source_fill_tile (next_source, tile);
- }
+ else if (next_source)
+ champlain_map_source_fill_tile (next_source, tile);
+
+ g_free (etag);
+}
- g_object_unref (map_source);
- g_slice_free (TileRenderedCallbackData, user_data);
- g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, user_data);
+
+static void
+destroy_render_complete_data (TileRenderedData *data,
+ G_GNUC_UNUSED GClosure *closure)
+{
+ if (data->map_source)
+ g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
+
+ if (data->etag)
+ g_free (data->etag);
+
+ g_slice_free (TileRenderedData, data);
}
@@ -586,33 +583,40 @@ tile_loaded_cb (G_GNUC_UNUSED SoupSession *session,
SoupMessage *msg,
gpointer user_data)
{
- TileLoadedCallbackData *callback_data = (TileLoadedCallbackData *) user_data;
+ TileLoadedData *callback_data = (TileLoadedData *) user_data;
ChamplainMapSource *map_source = callback_data->map_source;
ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (map_source);
ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source);
ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
ChamplainTile *tile = callback_data->tile;
const gchar *etag;
- TileRenderedCallbackData *data;
+ TileRenderedData *data;
ChamplainRenderer *renderer;
-
if (tile)
g_object_remove_weak_pointer (G_OBJECT (tile), (gpointer *) &callback_data->tile);
- g_slice_free (TileLoadedCallbackData, callback_data);
+ if (map_source)
+ g_object_remove_weak_pointer (G_OBJECT (map_source), (gpointer *) &callback_data->map_source);
+
+ g_slice_free (TileLoadedData, callback_data);
DEBUG ("Got reply %d", msg->status_code);
- if (!tile || msg->status_code == SOUP_STATUS_CANCELLED)
+ if (!tile)
{
- if (!tile)
- DEBUG ("Tile destroyed while loading");
- else
- DEBUG ("Download of tile %d, %d got cancelled",
- champlain_tile_get_x (tile), champlain_tile_get_y (tile));
-
- g_object_unref (map_source);
+ DEBUG ("Tile destroyed while loading");
+ return;
+ }
+ else if (msg->status_code == SOUP_STATUS_CANCELLED)
+ {
+ DEBUG ("Download of tile %d, %d got cancelled",
+ champlain_tile_get_x (tile), champlain_tile_get_y (tile));
+ return;
+ }
+ else if (!map_source)
+ {
+ DEBUG ("Map source destroyed");
return;
}
@@ -637,13 +641,17 @@ tile_loaded_cb (G_GNUC_UNUSED SoupSession *session,
etag = soup_message_headers_get (msg->response_headers, "ETag");
DEBUG ("Received ETag %s", etag);
- data = g_slice_new (TileRenderedCallbackData);
+ renderer = champlain_map_source_get_renderer (map_source);
+ g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
+
+ data = g_slice_new (TileRenderedData);
data->map_source = map_source;
data->etag = g_strdup (etag);
- renderer = champlain_map_source_get_renderer (map_source);
+ g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &data->map_source);
- g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), data);
+ g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
+ data, (GClosureNotify) destroy_render_complete_data, 0);
champlain_renderer_set_data (renderer, msg->response_body->data, msg->response_body->length);
champlain_renderer_render (renderer, tile);
@@ -653,14 +661,40 @@ tile_loaded_cb (G_GNUC_UNUSED SoupSession *session,
load_next:
if (next_source)
champlain_map_source_fill_tile (next_source, tile);
- g_object_unref (map_source);
return;
finish:
champlain_tile_set_fade_in (tile, TRUE);
champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
champlain_tile_display_content (tile);
- g_object_unref (map_source);
+}
+
+
+static void
+destroy_cb_data (TileDestroyedCbData *data,
+ G_GNUC_UNUSED GClosure *closure)
+{
+ if (data->map_source)
+ g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
+
+ if (data->msg)
+ g_object_remove_weak_pointer (G_OBJECT (data->msg), (gpointer *) &data->msg);
+
+ g_slice_free (TileDestroyedCbData, data);
+}
+
+
+static void
+tile_destroyed_cb (G_GNUC_UNUSED ChamplainTile *tile,
+ TileDestroyedCbData *data)
+{
+ if (data->map_source && data->msg)
+ {
+ DEBUG ("Canceling tile download");
+ ChamplainNetworkTileSourcePrivate *priv = CHAMPLAIN_NETWORK_TILE_SOURCE (data->map_source)->priv;
+
+ soup_session_cancel_message (priv->soup_session, data->msg, SOUP_STATUS_CANCELLED);
+ }
}
@@ -701,7 +735,7 @@ fill_tile (ChamplainMapSource *map_source,
if (!priv->offline)
{
- TileLoadedCallbackData *callback_data;
+ TileLoadedData *callback_data;
SoupMessage *msg;
gchar *uri;
@@ -749,12 +783,12 @@ fill_tile (ChamplainMapSource *map_source,
g_signal_connect_data (tile, "destroy", G_CALLBACK (tile_destroyed_cb),
tile_destroyed_cb_data, (GClosureNotify) destroy_cb_data, 0);
- callback_data = g_slice_new (TileLoadedCallbackData);
+ callback_data = g_slice_new (TileLoadedData);
callback_data->tile = tile;
callback_data->map_source = map_source;
g_object_add_weak_pointer (G_OBJECT (tile), (gpointer *) &callback_data->tile);
- g_object_ref (map_source);
+ g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &callback_data->map_source);
soup_session_queue_message (priv->soup_session, msg,
tile_loaded_cb,
diff --git a/champlain/champlain-null-tile-source.c b/champlain/champlain-null-tile-source.c
index a5e3db9..eec204e 100644
--- a/champlain/champlain-null-tile-source.c
+++ b/champlain/champlain-null-tile-source.c
@@ -75,17 +75,33 @@ champlain_null_tile_source_new_full (ChamplainRenderer *renderer)
}
+typedef struct
+{
+ ChamplainMapSource *map_source;
+} TileRenderedData;
+
+
static void
tile_rendered_cb (ChamplainTile *tile,
ChamplainRenderCallbackData *data,
- ChamplainMapSource *map_source)
+ TileRenderedData *user_data)
{
- ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (map_source);
- ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source);
- ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
+ ChamplainMapSource *map_source = user_data->map_source;
+ ChamplainMapSource *next_source;
+
+ // frees user_data - must not be used later in the function
+ g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
+
+ if (!map_source)
+ return;
+ next_source = champlain_map_source_get_next_source (map_source);
+
if (!data->error)
{
+ ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (map_source);
+ ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source);
+
if (tile_cache && data->data)
champlain_tile_cache_store_tile (tile_cache, tile, data->data, data->size);
@@ -95,9 +111,17 @@ tile_rendered_cb (ChamplainTile *tile,
}
else if (next_source)
champlain_map_source_fill_tile (next_source, tile);
+}
- g_object_unref (map_source);
- g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
+
+static void
+destroy_cb_data (TileRenderedData *data,
+ G_GNUC_UNUSED GClosure *closure)
+{
+ if (data->map_source)
+ g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
+
+ g_slice_free (TileRenderedData, data);
}
@@ -108,15 +132,34 @@ fill_tile (ChamplainMapSource *map_source,
g_return_if_fail (CHAMPLAIN_IS_NULL_TILE_SOURCE (map_source));
g_return_if_fail (CHAMPLAIN_IS_TILE (tile));
- ChamplainRenderer *renderer;
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);
+
+ if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_LOADED)
+ {
+ ChamplainRenderer *renderer;
+ TileRenderedData *user_data;
- renderer = champlain_map_source_get_renderer (map_source);
+ renderer = champlain_map_source_get_renderer (map_source);
- g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
+ g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
- g_object_ref (map_source);
+ user_data = g_slice_new (TileRenderedData);
+ user_data->map_source = map_source;
- g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), map_source);
+ g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
- champlain_renderer_render (renderer, tile);
+ g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
+ user_data, (GClosureNotify) destroy_cb_data, 0);
+
+ champlain_renderer_render (renderer, tile);
+ }
+ else if (CHAMPLAIN_IS_MAP_SOURCE (next_source))
+ champlain_map_source_fill_tile (next_source, tile);
+ else if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_LOADED)
+ {
+ /* if we have some content, use the tile even if it wasn't validated */
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+ champlain_tile_display_content (tile);
+ }
}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]