diff options
author | Corentin Noël <corentin.noel@collabora.com> | 2022-10-12 10:42:51 +0200 |
---|---|---|
committer | Corentin Noël <tintou@noel.tf> | 2023-01-11 11:18:15 +0100 |
commit | 31373b9987b9b5526f9e7a9457d163c67f4acd21 (patch) | |
tree | 42c240d09d2026507e1219c28d82ba0a25cbccf0 | |
parent | aabaf74a66fc822913985cb30c955b9884d14594 (diff) | |
download | libchamplain-31373b9987b9b5526f9e7a9457d163c67f4acd21.tar.gz |
Port to libsoup3
Allows to use libchamplain with libsoup3 libraries and applications.
-rw-r--r-- | .gitlab-ci.yml | 4 | ||||
-rw-r--r-- | champlain/champlain-network-bbox-tile-source.c | 76 | ||||
-rw-r--r-- | champlain/champlain-network-tile-source.c | 305 | ||||
-rw-r--r-- | champlain/meson.build | 9 | ||||
-rw-r--r-- | demos/meson.build | 8 | ||||
-rw-r--r-- | demos/url-marker.c | 102 | ||||
-rw-r--r-- | meson.build | 13 | ||||
-rw-r--r-- | meson_options.txt | 4 |
8 files changed, 424 insertions, 97 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9f68909..a808d62 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: fedora:29 +image: fedora:37 stages: - build @@ -19,7 +19,7 @@ build-champlain: - mkdir -p _ccache - ccache --zero-stats - ccache --show-stats - - meson -Dwidgetry=true -Ddemos=true -Dgtk_doc=true -Dintrospection=true -Dvapi=true _build . + - meson -Dwidgetry=true -Ddemos=true -Dgtk_doc=true -Dintrospection=true -Dvapi=true -Dlibsoup3=false _build . - ninja -C _build - ninja -C _build test - ninja -C _build champlain-0.12-doc diff --git a/champlain/champlain-network-bbox-tile-source.c b/champlain/champlain-network-bbox-tile-source.c index f6f10ba..56efc4e 100644 --- a/champlain/champlain-network-bbox-tile-source.c +++ b/champlain/champlain-network-bbox-tile-source.c @@ -116,8 +116,16 @@ champlain_network_bbox_tile_source_set_property (GObject *object, priv->proxy_uri = g_value_dup_string (value); if (priv->soup_session) - g_object_set (G_OBJECT (priv->soup_session), "proxy-uri", - soup_uri_new (priv->proxy_uri), NULL); + { +#ifdef CHAMPLAIN_LIBSOUP_3 + GProxyResolver *resolver = soup_session_get_proxy_resolver (priv->soup_session); + if (!resolver && G_IS_SIMPLE_PROXY_RESOLVER (resolver)) + g_simple_proxy_resolver_set_default_proxy (G_SIMPLE_PROXY_RESOLVER (resolver), priv->proxy_uri); +#else + g_object_set (G_OBJECT (priv->soup_session), "proxy-uri", + soup_uri_new (priv->proxy_uri), NULL); +#endif + } break; case PROP_STATE: @@ -253,6 +261,13 @@ champlain_network_bbox_tile_source_init (ChamplainNetworkBboxTileSource *self) priv->api_uri = g_strdup ("https://www.informationfreeway.org/api/0.6"); /* informationfreeway.org is a load-balancer for different api servers */ +#ifdef CHAMPLAIN_LIBSOUP_3 + priv->soup_session = soup_session_new_with_options ( + "user-agent", "libchamplain/" CHAMPLAIN_VERSION_S, + "max-conns-per-host", 2, + NULL + ); +#else priv->proxy_uri = g_strdup (""); priv->soup_session = soup_session_new_with_options ( "proxy-uri", soup_uri_new (priv->proxy_uri), @@ -265,11 +280,11 @@ champlain_network_bbox_tile_source_init (ChamplainNetworkBboxTileSource *self) "libchamplain/" CHAMPLAIN_VERSION_S, "max-conns-per-host", 2, NULL); +#endif priv->state = CHAMPLAIN_STATE_NONE; } - /** * champlain_network_bbox_tile_source_new_full: * @id: the map source's id @@ -314,14 +329,52 @@ champlain_network_bbox_tile_source_new_full (const gchar *id, return source; } +static void +map_data_loaded (ChamplainNetworkBboxTileSource *self, + const guint8 *data, + gsize size) +{ + ChamplainRenderer *renderer; + g_object_set (G_OBJECT (self), "state", CHAMPLAIN_STATE_DONE, NULL); + + renderer = champlain_map_source_get_renderer (CHAMPLAIN_MAP_SOURCE (self)); + champlain_renderer_set_data (renderer, data, size); +} + +#ifdef CHAMPLAIN_LIBSOUP_3 +static void +load_map_data_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + ChamplainNetworkBboxTileSource *self = + CHAMPLAIN_NETWORK_BBOX_TILE_SOURCE (user_data); + GBytes *bytes; + GError *error = NULL; + gsize size; + gconstpointer data; + + bytes = soup_session_send_and_read_finish (SOUP_SESSION (source_object), res, &error); + if (error != NULL) + { + DEBUG ("Unable to download file: %s", error->message); + + g_clear_error (&error); + return; + } + + data = g_bytes_get_data (bytes, &size); + map_data_loaded (self, data, size); + g_bytes_unref (bytes); +} +#else static void load_map_data_cb (G_GNUC_UNUSED SoupSession *session, SoupMessage *msg, gpointer user_data) { ChamplainNetworkBboxTileSource *self = CHAMPLAIN_NETWORK_BBOX_TILE_SOURCE (user_data); - ChamplainRenderer *renderer; if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { @@ -331,11 +384,11 @@ load_map_data_cb (G_GNUC_UNUSED SoupSession *session, SoupMessage *msg, return; } - g_object_set (G_OBJECT (self), "state", CHAMPLAIN_STATE_DONE, NULL); - - renderer = champlain_map_source_get_renderer (CHAMPLAIN_MAP_SOURCE (self)); - champlain_renderer_set_data (renderer, (guint8*) msg->response_body->data, msg->response_body->length); + map_data_loaded (self, + (const guint8*) msg->response_body->data, + msg->response_body->length); } +#endif /** @@ -370,7 +423,7 @@ champlain_network_bbox_tile_source_load_map_data ( url = g_strdup_printf ( "https://api.openstreetmap.org/api/0.6/map?bbox=%f,%f,%f,%f", bbox->left, bbox->bottom, bbox->right, bbox->top); - msg = soup_message_new ("GET", url); + msg = soup_message_new (SOUP_METHOD_GET, url); DEBUG ("Request BBox data: '%s'", url); @@ -378,7 +431,12 @@ champlain_network_bbox_tile_source_load_map_data ( g_object_set (G_OBJECT (self), "state", CHAMPLAIN_STATE_LOADING, NULL); +#ifdef CHAMPLAIN_LIBSOUP_3 + soup_session_send_and_read_async (priv->soup_session, msg, G_PRIORITY_DEFAULT_IDLE, NULL, load_map_data_cb, self); + g_object_unref (msg); +#else soup_session_queue_message (priv->soup_session, msg, load_map_data_cb, self); +#endif } diff --git a/champlain/champlain-network-tile-source.c b/champlain/champlain-network-tile-source.c index 281f000..324e2e5 100644 --- a/champlain/champlain-network-tile-source.c +++ b/champlain/champlain-network-tile-source.c @@ -80,17 +80,24 @@ G_DEFINE_TYPE_WITH_PRIVATE (ChamplainNetworkTileSource, champlain_network_tile_s */ #define MAX_CONNS_DEFAULT 2 +#ifndef CHAMPLAIN_LIBSOUP_3 typedef struct { ChamplainMapSource *map_source; SoupMessage *msg; } TileCancelledData; +#endif typedef struct { ChamplainMapSource *map_source; ChamplainTile *tile; +#ifdef CHAMPLAIN_LIBSOUP_3 + SoupMessage *msg; + GCancellable *cancellable; +#else TileCancelledData *cancelled_data; +#endif } TileLoadedData; typedef struct @@ -104,7 +111,7 @@ static void fill_tile (ChamplainMapSource *map_source, ChamplainTile *tile); static void tile_state_notify (ChamplainTile *tile, G_GNUC_UNUSED GParamSpec *pspec, - TileCancelledData *data); + gpointer user_data); static gchar *get_tile_uri (ChamplainNetworkTileSource *source, gint x, @@ -185,11 +192,9 @@ champlain_network_tile_source_dispose (GObject *object) ChamplainNetworkTileSourcePrivate *priv = CHAMPLAIN_NETWORK_TILE_SOURCE (object)->priv; if (priv->soup_session) - { soup_session_abort (priv->soup_session); - g_object_unref (priv->soup_session); - priv->soup_session = NULL; - } + + g_clear_object (&priv->soup_session); G_OBJECT_CLASS (champlain_network_tile_source_parent_class)->dispose (object); } @@ -322,6 +327,13 @@ champlain_network_tile_source_init (ChamplainNetworkTileSource *tile_source) priv->offline = FALSE; priv->max_conns = MAX_CONNS_DEFAULT; +#ifdef CHAMPLAIN_LIBSOUP_3 + priv->soup_session = soup_session_new_with_options ( + "user-agent", "libchamplain/" CHAMPLAIN_VERSION_S, + "max-conns-per-host", MAX_CONNS_DEFAULT, + "max-conns", MAX_CONNS_DEFAULT, + NULL); +#else priv->soup_session = soup_session_new_with_options ( "proxy-uri", NULL, "ssl-strict", FALSE, @@ -336,6 +348,7 @@ champlain_network_tile_source_init (ChamplainNetworkTileSource *tile_source) "max-conns-per-host", MAX_CONNS_DEFAULT, "max-conns", MAX_CONNS_DEFAULT, NULL); +#endif } @@ -474,11 +487,21 @@ champlain_network_tile_source_set_proxy_uri (ChamplainNetworkTileSource *tile_so g_return_if_fail (CHAMPLAIN_IS_NETWORK_TILE_SOURCE (tile_source)); ChamplainNetworkTileSourcePrivate *priv = tile_source->priv; +#ifndef CHAMPLAIN_LIBSOUP_3 SoupURI *uri = NULL; +#endif g_free (priv->proxy_uri); priv->proxy_uri = g_strdup (proxy_uri); +#ifdef CHAMPLAIN_LIBSOUP_3 + if (priv->soup_session) + { + GProxyResolver *resolver = soup_session_get_proxy_resolver (priv->soup_session); + if (!resolver && G_IS_SIMPLE_PROXY_RESOLVER (resolver)) + g_simple_proxy_resolver_set_default_proxy (G_SIMPLE_PROXY_RESOLVER (resolver), priv->proxy_uri); + } +#else if (priv->proxy_uri) uri = soup_uri_new (priv->proxy_uri); @@ -489,6 +512,7 @@ champlain_network_tile_source_set_proxy_uri (ChamplainNetworkTileSource *tile_so if (uri) soup_uri_free (uri); +#endif g_object_notify (G_OBJECT (tile_source), "proxy-uri"); } @@ -660,6 +684,25 @@ get_tile_uri (ChamplainNetworkTileSource *tile_source, return token; } +static void +tile_rendered_data_free (TileRenderedData *data) +{ + g_clear_pointer (&data->etag, g_free); + g_clear_object (&data->map_source); + g_slice_free (TileRenderedData, data); +} + +static void +tile_loaded_data_free (TileLoadedData *data) +{ + g_clear_object (&data->tile); + g_clear_object (&data->map_source); +#ifdef CHAMPLAIN_LIBSOUP_3 + g_clear_object (&data->cancellable); + g_clear_object (&data->msg); +#endif + g_slice_free (TileLoadedData, data); +} static void tile_rendered_cb (ChamplainTile *tile, @@ -668,12 +711,11 @@ tile_rendered_cb (ChamplainTile *tile, gboolean error, TileRenderedData *user_data) { - ChamplainMapSource *map_source = user_data->map_source; + ChamplainMapSource *map_source = g_steal_pointer (&user_data->map_source); ChamplainMapSource *next_source; - gchar *etag = user_data->etag; + gchar *etag = g_steal_pointer (&user_data->etag); g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, user_data); - g_slice_free (TileRenderedData, user_data); next_source = champlain_map_source_get_next_source (map_source); @@ -697,27 +739,170 @@ tile_rendered_cb (ChamplainTile *tile, g_free (etag); g_object_unref (map_source); - g_object_unref (tile); } +static void +tile_source_loaded (ChamplainMapSource *self, + const guint8 *data, + gsize size, + ChamplainTile *tile) +{ + ChamplainRenderer *renderer = champlain_map_source_get_renderer (self); + champlain_renderer_set_data (renderer, data, size); + champlain_renderer_render (renderer, tile); +} + +static void +on_tile_load_already_cached (ChamplainMapSource *self, + ChamplainTile *tile) +{ + ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (self); + ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source); + + if (tile_cache) + champlain_tile_cache_refresh_tile_time (tile_cache, tile); + + champlain_tile_set_fade_in (tile, TRUE); + champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE); + champlain_tile_display_content (tile); +} + +static void +on_tile_load_failure (ChamplainMapSource *self, + ChamplainTile *tile) +{ + ChamplainMapSource *next_source = champlain_map_source_get_next_source (self); + + if (next_source) + champlain_map_source_fill_tile (next_source, tile); +} + +static void +connect_to_render_complete (ChamplainMapSource *self, + ChamplainTile *tile, + const char *etag) +{ + TileRenderedData *data; + data = g_slice_new (TileRenderedData); + data->map_source = g_object_ref (self); + data->etag = g_strdup (etag); + + g_signal_connect_data (tile, + "render-complete", + G_CALLBACK (tile_rendered_cb), + data, + (GClosureNotify)tile_rendered_data_free, + 0); +} + +#ifdef CHAMPLAIN_LIBSOUP_3 +static void +tile_bytes_loaded_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GMemoryOutputStream *output_stream = G_MEMORY_OUTPUT_STREAM (source_object); + TileLoadedData *callback_data = user_data; + ChamplainTile *tile = callback_data->tile; + ChamplainMapSource *map_source = callback_data->map_source; + GError *error = NULL; + + if (g_output_stream_splice_finish (G_OUTPUT_STREAM (output_stream), res, &error) != -1) { + gsize size = g_memory_output_stream_get_data_size (output_stream); + gconstpointer data = g_memory_output_stream_get_data (output_stream); + tile_source_loaded (map_source, data, size, tile); + } + + g_clear_error (&error); + tile_loaded_data_free (callback_data); +} static void +tile_loaded_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + TileLoadedData *callback_data = (TileLoadedData *) user_data; + GCancellable *cancellable = callback_data->cancellable; + SoupMessage *msg = callback_data->msg; + ChamplainTile *tile = callback_data->tile; + ChamplainMapSource *map_source = callback_data->map_source; + const gchar *etag; + GInputStream *stream; + GOutputStream *ostream; + GError *error = NULL; + SoupStatus status; + SoupMessageHeaders *response_headers; + + stream = soup_session_send_finish (SOUP_SESSION (source_object), res, &error); + status = soup_message_get_status (msg); + + g_signal_handlers_disconnect_by_func (tile, tile_state_notify, cancellable); + + DEBUG ("Got reply %d", status); + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + DEBUG ("Download of tile %d, %d got cancelled", + champlain_tile_get_x (tile), champlain_tile_get_y (tile)); + goto cleanup; + } + + if (status == SOUP_STATUS_NOT_MODIFIED) + { + on_tile_load_already_cached (map_source, tile); + goto cleanup; + } + + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) + { + DEBUG ("Unable to download tile %d, %d: %s : %s", + champlain_tile_get_x (tile), + champlain_tile_get_y (tile), + soup_status_get_phrase (status), + soup_message_get_reason_phrase (msg)); + + on_tile_load_failure (map_source, tile); + goto cleanup; + } + + /* Verify if the server sent an etag and save it */ + response_headers = soup_message_get_response_headers (msg); + etag = soup_message_headers_get_one (response_headers, "ETag"); + DEBUG ("Received ETag %s", etag); + + connect_to_render_complete (map_source, tile, etag); + + ostream = g_memory_output_stream_new_resizable (); + g_output_stream_splice_async (ostream, + stream, + G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | + G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, + G_PRIORITY_DEFAULT_IDLE, + cancellable, + tile_bytes_loaded_cb, + callback_data); + g_clear_object (&ostream); + g_clear_object (&stream); + + return; +cleanup: + tile_loaded_data_free (callback_data); + g_clear_error (&error); + g_clear_object (&stream); +} +#else +static void tile_loaded_cb (G_GNUC_UNUSED SoupSession *session, SoupMessage *msg, gpointer 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; - TileRenderedData *data; - ChamplainRenderer *renderer; g_signal_handlers_disconnect_by_func (tile, tile_state_notify, callback_data->cancelled_data); - g_slice_free (TileLoadedData, callback_data); DEBUG ("Got reply %d", msg->status_code); @@ -730,9 +915,8 @@ tile_loaded_cb (G_GNUC_UNUSED SoupSession *session, if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { - if (tile_cache) - champlain_tile_cache_refresh_tile_time (tile_cache, tile); - goto finish; + on_tile_load_already_cached (map_source, tile); + goto cleanup; } if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) @@ -742,44 +926,22 @@ tile_loaded_cb (G_GNUC_UNUSED SoupSession *session, champlain_tile_get_y (tile), soup_status_get_phrase (msg->status_code)); - goto load_next; + on_tile_load_failure (map_source, tile); + goto cleanup; } /* Verify if the server sent an etag and save it */ etag = soup_message_headers_get_one (msg->response_headers, "ETag"); DEBUG ("Received ETag %s", etag); - 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); - - g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), data); - - champlain_renderer_set_data (renderer, (guint8*) msg->response_body->data, msg->response_body->length); - champlain_renderer_render (renderer, tile); - - return; - -load_next: - if (next_source) - champlain_map_source_fill_tile (next_source, tile); + connect_to_render_complete (map_source, tile, etag); - goto cleanup; - -finish: - champlain_tile_set_fade_in (tile, TRUE); - champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE); - champlain_tile_display_content (tile); + tile_source_loaded (map_source, (guint8*) msg->response_body->data, msg->response_body->length, tile); cleanup: - g_object_unref (tile); - g_object_unref (map_source); + tile_loaded_data_free (callback_data); } - static void destroy_cancelled_data (TileCancelledData *data, G_GNUC_UNUSED GClosure *closure) @@ -792,18 +954,31 @@ destroy_cancelled_data (TileCancelledData *data, g_slice_free (TileCancelledData, data); } +#endif static void tile_state_notify (ChamplainTile *tile, G_GNUC_UNUSED GParamSpec *pspec, - TileCancelledData *data) + gpointer user_data) { - if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_DONE && data->map_source && data->msg) +#ifdef CHAMPLAIN_LIBSOUP_3 + GCancellable *cancellable = user_data; +#else + TileCancelledData *data = user_data; + if (!data->map_source || !data->msg) + return; +#endif + + if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_DONE) { DEBUG ("Canceling tile download"); +#ifdef CHAMPLAIN_LIBSOUP_3 + g_cancellable_cancel (cancellable); +#else ChamplainNetworkTileSourcePrivate *priv = CHAMPLAIN_NETWORK_TILE_SOURCE (data->map_source)->priv; soup_session_cancel_message (priv->soup_session, data->msg, SOUP_STATUS_CANCELLED); +#endif } } @@ -842,6 +1017,9 @@ fill_tile (ChamplainMapSource *map_source, ChamplainNetworkTileSource *tile_source = CHAMPLAIN_NETWORK_TILE_SOURCE (map_source); ChamplainNetworkTileSourcePrivate *priv = tile_source->priv; +#ifdef CHAMPLAIN_LIBSOUP_3 + GCancellable *cancellable = NULL; +#endif if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_DONE) return; @@ -865,6 +1043,11 @@ fill_tile (ChamplainMapSource *map_source, const gchar *etag = champlain_tile_get_etag (tile); gchar *date = get_modified_time_string (tile); +#ifdef CHAMPLAIN_LIBSOUP_3 + SoupMessageHeaders *headers = soup_message_get_request_headers (msg); +#else + SoupMessageHeaders *headers = msg->request_headers; +#endif /* If an etag is available, only use it. * OSM servers seems to send now as the modified time for all tiles @@ -873,19 +1056,23 @@ fill_tile (ChamplainMapSource *map_source, if (etag) { DEBUG ("If-None-Match: %s", etag); - soup_message_headers_append (msg->request_headers, + soup_message_headers_append (headers, "If-None-Match", etag); } else if (date) { DEBUG ("If-Modified-Since %s", date); - soup_message_headers_append (msg->request_headers, + soup_message_headers_append (headers, "If-Modified-Since", date); } g_free (date); } +#ifdef CHAMPLAIN_LIBSOUP_3 + cancellable = g_cancellable_new (); + g_signal_connect_data (tile, "notify::state", G_CALLBACK (tile_state_notify), g_object_ref (cancellable), (GClosureNotify) g_object_unref, 0); +#else TileCancelledData *tile_cancelled_data = g_slice_new (TileCancelledData); tile_cancelled_data->map_source = map_source; tile_cancelled_data->msg = msg; @@ -895,18 +1082,26 @@ fill_tile (ChamplainMapSource *map_source, g_signal_connect_data (tile, "notify::state", G_CALLBACK (tile_state_notify), tile_cancelled_data, (GClosureNotify) destroy_cancelled_data, 0); +#endif callback_data = g_slice_new (TileLoadedData); - callback_data->tile = tile; - callback_data->map_source = map_source; + callback_data->tile = g_object_ref (tile); + callback_data->map_source = g_object_ref (map_source); +#ifdef CHAMPLAIN_LIBSOUP_3 + callback_data->cancellable = g_steal_pointer (&cancellable); + callback_data->msg = g_steal_pointer (&msg); + soup_session_send_async (priv->soup_session, + callback_data->msg, + G_PRIORITY_DEFAULT_IDLE, + callback_data->cancellable, + tile_loaded_cb, + callback_data); +#else callback_data->cancelled_data = tile_cancelled_data; - - g_object_ref (map_source); - g_object_ref (tile); - soup_session_queue_message (priv->soup_session, msg, tile_loaded_cb, callback_data); +#endif } else { diff --git a/champlain/meson.build b/champlain/meson.build index 0bf8ba5..9a7b8c7 100644 --- a/champlain/meson.build +++ b/champlain/meson.build @@ -112,6 +112,12 @@ libchamplain_c_args = [ '-DG_LOG_DOMAIN="@0@"'.format(meson.project_name()), ] +if get_option('libsoup3') + libchamplain_c_args += [ + '-DCHAMPLAIN_LIBSOUP_3', + ] +endif + libchamplain_link_args = [ ] @@ -244,4 +250,7 @@ libchamplain_pc = pkg.generate( description: 'Map View for Clutter', subdirs: package_string, requires: libchamplain_requires, + variables: [ + 'soupapiversion=@0@'.format(libsoup_api_version), + ], ) diff --git a/demos/meson.build b/demos/meson.build index bf9b3bb..9b5ee05 100644 --- a/demos/meson.build +++ b/demos/meson.build @@ -7,6 +7,13 @@ libchamplain_demos = [ ['create_destroy_test', 'create-destroy-test.c', []], ] +libchamplain_demos_c_args = [] +if get_option('libsoup3') + libchamplain_demos_c_args += [ + '-DCHAMPLAIN_LIBSOUP_3', + ] +endif + foreach demo: libchamplain_demos demo_name = demo.get(0) demo_sources = demo.get(1) @@ -17,6 +24,7 @@ foreach demo: libchamplain_demos demo_sources, install: false, dependencies: demo_deps + [libchamplain_dep], + c_args: libchamplain_demos_c_args, ) endforeach diff --git a/demos/url-marker.c b/demos/url-marker.c index 8134d66..7d026ce 100644 --- a/demos/url-marker.c +++ b/demos/url-marker.c @@ -28,6 +28,7 @@ typedef struct gdouble longitude; } MarkerData; +#ifndef CHAMPLAIN_LIBSOUP_3 /** * Returns a GdkPixbuf from a given SoupMessage. This function assumes that the * message has completed successfully. @@ -86,7 +87,7 @@ cleanup: return pixbuf; } - +#endif static ClutterActor * texture_new_from_pixbuf (GdkPixbuf *pixbuf, GError **error) @@ -116,6 +117,31 @@ texture_new_from_pixbuf (GdkPixbuf *pixbuf, GError **error) return texture; } +static void +add_marker_with_pixbuf (MarkerData *marker_data, + GdkPixbuf *pixbuf) +{ + ClutterActor *texture = NULL; + ClutterActor *marker = NULL; + GError *error = NULL; + + /* Transform the pixbuf into a texture */ + texture = texture_new_from_pixbuf (pixbuf, &error); + if (error != NULL) + { + g_print ("Failed to convert the image into a texture: %s\n", + error->message); + return; + } + + /* Create a marker with the texture */ + marker = champlain_label_new_with_image (texture); + champlain_location_set_location (CHAMPLAIN_LOCATION (marker), + marker_data->latitude, marker_data->longitude); + champlain_marker_layer_add_marker (marker_data->layer, CHAMPLAIN_MARKER (marker)); + + g_clear_object (&texture); +} /** * Called when an image has been downloaded. This callback will transform the @@ -125,6 +151,41 @@ texture_new_from_pixbuf (GdkPixbuf *pixbuf, GError **error) * * This callback expects the parameter data to be a valid ChamplainMarkerLayer. */ +#ifdef CHAMPLAIN_LIBSOUP_3 +static void +image_downloaded_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + MarkerData *marker_data = (MarkerData *) user_data; + GError *error = NULL; + GdkPixbuf *pixbuf = NULL; + GInputStream *stream; + + stream = soup_session_send_finish (SOUP_SESSION (source_object), res, &error); + if (error != NULL) { + g_print ("Failed to download image: %s\n", error->message); + goto cleanup; + } + + pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error); + if (error != NULL) + { + g_print ("Failed to parse the image: %s\n", error->message); + goto cleanup; + } + + add_marker_with_pixbuf (marker_data, pixbuf); + +cleanup: + if (marker_data) + g_clear_object (&marker_data->layer); + g_slice_free (MarkerData, marker_data); + + g_clear_error (&error); + g_clear_object (&pixbuf); +} +#else static void image_downloaded_cb (SoupSession *session, SoupMessage *message, @@ -135,8 +196,6 @@ image_downloaded_cb (SoupSession *session, char *url = NULL; GError *error = NULL; GdkPixbuf *pixbuf = NULL; - ClutterActor *texture = NULL; - ClutterActor *marker = NULL; if (data == NULL) goto cleanup; @@ -159,37 +218,18 @@ image_downloaded_cb (SoupSession *session, goto cleanup; } - /* Then transform the pixbuf into a texture */ - texture = texture_new_from_pixbuf (pixbuf, &error); - if (error != NULL) - { - g_print ("Failed to convert %s into a texture: %s\n", url, - error->message); - goto cleanup; - } - - /* Finally create a marker with the texture */ - marker = champlain_label_new_with_image (texture); - texture = NULL; - champlain_location_set_location (CHAMPLAIN_LOCATION (marker), - marker_data->latitude, marker_data->longitude); - champlain_marker_layer_add_marker (marker_data->layer, CHAMPLAIN_MARKER (marker)); + add_marker_with_pixbuf (marker_data, pixbuf); cleanup: if (marker_data) - g_object_unref (marker_data->layer); + g_clear_object (&marker_data->layer); g_slice_free (MarkerData, marker_data); g_free (url); - if (error != NULL) - g_error_free (error); - - if (pixbuf != NULL) - g_object_unref (G_OBJECT (pixbuf)); - - if (texture != NULL) - clutter_actor_destroy (CLUTTER_ACTOR (texture)); + g_clear_error (&error); + g_clear_object (&pixbuf); } +#endif /** @@ -212,8 +252,14 @@ create_marker_from_url (ChamplainMarkerLayer *layer, data->latitude = latitude; data->longitude = longitude; - message = soup_message_new ("GET", url); + message = soup_message_new (SOUP_METHOD_GET, url); +#ifdef CHAMPLAIN_LIBSOUP_3 + soup_session_send_async (session, message, G_PRIORITY_DEFAULT_IDLE, NULL, + image_downloaded_cb, data); + g_object_unref (message); +#else soup_session_queue_message (session, message, image_downloaded_cb, data); +#endif } diff --git a/meson.build b/meson.build index 8c40f52..1fee9e9 100644 --- a/meson.build +++ b/meson.build @@ -51,13 +51,14 @@ cc = meson.get_compiler('c') libm_dep = cc.find_library('m', required: true) -glib_req = '>= 2.38' +glib_req = '>= 2.68' gtk_req = '>= 3.0' clutter_req = '>= 1.24' clutter_gtk_req = '>= 1.0' cairo_req = '>= 1.4' sqlite_req = '>= 3.0' -libsoup_req = '>= 2.42' +libsoup2_req = '>= 2.42' +libsoup3_req = '>= 3.0' memphis_req = '>= 0.2.1' introspection_req = '>= 0.6.3' vala_req = '>= 0.11.0' @@ -70,7 +71,13 @@ gdk_dep = dependency('gdk-3.0', version: gtk_req) clutter_dep = dependency('clutter-1.0', version: clutter_req) cairo_dep = dependency('cairo', version: cairo_req) sqlite_dep = dependency('sqlite3', version: sqlite_req) -libsoup_dep = dependency('libsoup-2.4', version: libsoup_req) +if get_option('libsoup3') + libsoup_dep = dependency('libsoup-3.0', version: libsoup3_req) + libsoup_api_version = '3.0' +else + libsoup_dep = dependency('libsoup-2.4', version: libsoup2_req) + libsoup_api_version = '2.4' +endif gtk_dep = dependency('gtk+-3.0', version: gtk_req, required: false) clutter_gtk_dep = dependency('clutter-gtk-1.0', version: clutter_gtk_req, required: false) diff --git a/meson_options.txt b/meson_options.txt index 8713d62..98852be 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -20,3 +20,7 @@ option('gtk_doc', option('demos', type: 'boolean', value: false, description: 'Build demonstration programs') + +option('libsoup3', + type: 'boolean', value: true, + description: 'Use libsoup 3.0')
\ No newline at end of file |