summaryrefslogtreecommitdiff
path: root/src/common/icons.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/icons.c')
-rw-r--r--src/common/icons.c199
1 files changed, 85 insertions, 114 deletions
diff --git a/src/common/icons.c b/src/common/icons.c
index 3419f8d..e8fa308 100644
--- a/src/common/icons.c
+++ b/src/common/icons.c
@@ -39,11 +39,6 @@ static SoupSession *download_session;
static GList *pending_gets;
typedef struct {
- GUPnPDeviceInfo *info;
-
- DeviceIconAvailableCallback callback;
-
- SoupMessage *message;
gchar *mime_type;
gint width;
gint height;
@@ -52,28 +47,23 @@ typedef struct {
static void
get_icon_url_data_free (GetIconURLData *data)
{
- g_object_unref (data->info);
-
g_free (data->mime_type);
g_slice_free (GetIconURLData, data);
}
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GetIconURLData, get_icon_url_data_free)
+
static GdkPixbuf *
-get_icon_from_message (SoupMessage *msg,
- GetIconURLData *data,
- GError **error)
+get_icon_from_bytes (GBytes *icon_data, GetIconURLData *data, GError **error)
{
- GdkPixbufLoader *loader;
+ g_autoptr (GdkPixbufLoader) loader;
GdkPixbuf *pixbuf;
loader = gdk_pixbuf_loader_new_with_mime_type (data->mime_type, error);
if (loader == NULL)
return NULL;
- gdk_pixbuf_loader_write (loader,
- (guchar *) msg->response_body->data,
- msg->response_body->length,
- error);
+ gdk_pixbuf_loader_write_bytes (loader, icon_data, error);
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
if (pixbuf) {
gfloat aspect_ratio;
@@ -89,7 +79,6 @@ get_icon_from_message (SoupMessage *msg,
}
gdk_pixbuf_loader_close (loader, NULL);
- g_object_unref (loader);
return pixbuf;
}
@@ -97,123 +86,115 @@ get_icon_from_message (SoupMessage *msg,
/**
* Icon downloaded.
**/
+
static void
-got_icon_url (SoupSession *session,
- SoupMessage *msg,
- GetIconURLData *data)
+on_got_icon (GObject *source, GAsyncResult *res, gpointer user_data)
{
- GdkPixbuf *pixbuf = NULL;
-
- if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- GError *error = NULL;
+ GError *error = NULL;
+ g_autoptr (GTask) task = G_TASK (user_data);
+ SoupMessage *message =
+ soup_session_get_async_result_message (SOUP_SESSION (source),
+ res);
+
+ g_autoptr (GBytes) body =
+ soup_session_send_and_read_finish (SOUP_SESSION (source),
+ res,
+ &error);
- pixbuf = get_icon_from_message (msg, data, &error);
+ if (error != NULL) {
+ g_task_return_error (task, error);
- if (error) {
- g_warning ("Failed to create icon for '%s': %s",
- gupnp_device_info_get_udn (data->info),
- error->message);
- g_error_free (error);
- } else if (!pixbuf) {
- g_warning ("Failed to create icon for '%s'",
- gupnp_device_info_get_udn (data->info));
- }
+ return;
}
- data->callback (data->info, pixbuf);
-
- pending_gets = g_list_remove (pending_gets, data);
- get_icon_url_data_free (data);
-}
+ if (!SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (message))) {
+ g_task_return_error (
+ task,
+ g_error_new (G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Unable to download icon: %s",
+ error->message));
+ return;
+ }
-static gboolean
-on_icon_schedule_error (gpointer user_data)
-{
- GetIconURLData *data = (GetIconURLData *) user_data;
+ GdkPixbuf *device_icon =
+ get_icon_from_bytes (body, g_task_get_task_data (task), &error);
+ if (error != NULL) {
+ g_task_return_error (task, error);
- data->callback (data->info, NULL);
- g_object_unref (data->info);
- g_slice_free (GetIconURLData, data);
+ return;
+ }
- return FALSE;
+ g_task_return_pointer (task, device_icon, g_object_unref);
}
void
-schedule_icon_update (GUPnPDeviceInfo *info,
- DeviceIconAvailableCallback callback)
+update_icon_async (GUPnPDeviceInfo *info,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- GetIconURLData *data;
- char *icon_url;
+ g_autoptr (GTask) task =
+ g_task_new (info, cancellable, callback, user_data);
+
+ g_autoptr (GetIconURLData) data;
+ g_autofree char *icon_url;
data = g_slice_new0 (GetIconURLData);
- data->info = g_object_ref (info);
- data->callback = callback;
-
- icon_url = gupnp_device_info_get_icon_url
- (info,
- NULL,
- PREFERED_DEPTH,
- PREFERED_WIDTH,
- PREFERED_HEIGHT,
- TRUE,
- &data->mime_type,
- NULL,
- &data->width,
- &data->height);
+
+ icon_url = gupnp_device_info_get_icon_url (info,
+ NULL,
+ PREFERED_DEPTH,
+ PREFERED_WIDTH,
+ PREFERED_HEIGHT,
+ TRUE,
+ &data->mime_type,
+ NULL,
+ &data->width,
+ &data->height);
+
if (icon_url == NULL) {
- g_free (data->mime_type);
+ g_task_return_pointer (task, NULL, NULL);
- g_idle_add (on_icon_schedule_error, data);
return;
}
- char *new_uri = gupnp_context_rewrite_uri (gupnp_device_info_get_context (info), icon_url);
- g_free (icon_url);
+ g_autofree char *new_url =
+ gupnp_context_rewrite_uri (gupnp_device_info_get_context (info),
+ icon_url);
+ g_autoptr (SoupMessage) message =
+ soup_message_new (SOUP_METHOD_GET, new_url);
- data->message = soup_message_new (SOUP_METHOD_GET, new_uri);
-
- if (data->message == NULL) {
- g_warning ("Invalid URL icon for device '%s': %s",
- gupnp_device_info_get_udn (info),
- new_uri);
-
- g_free (new_uri);
- g_free (data->mime_type);
- g_idle_add (on_icon_schedule_error, data);
+ if (message == NULL) {
+ g_task_return_error (task,
+ g_error_new (G_URI_ERROR,
+ G_URI_ERROR_FAILED,
+ "Could not parse icon url %s",
+ new_url));
return;
}
- pending_gets = g_list_prepend (pending_gets, data);
- soup_session_queue_message (download_session,
- data->message,
- (SoupSessionCallback) got_icon_url,
- data);
+ g_task_set_task_data (task,
+ g_steal_pointer (&data),
+ (GDestroyNotify) get_icon_url_data_free);
- g_free (new_uri);
+ soup_session_send_and_read_async (download_session,
+ message,
+ G_PRIORITY_LOW,
+ cancellable,
+ on_got_icon,
+ task);
+
+ g_steal_pointer (&task);
}
-void
-unschedule_icon_update (GUPnPDeviceInfo *info)
+GdkPixbuf *
+update_icon_finish (GUPnPDeviceInfo *info, GAsyncResult *res, GError **error)
{
- GList *gets;
-
- for (gets = pending_gets; gets; gets = gets->next) {
- GetIconURLData *data;
- const char *udn1;
- const char *udn2;
-
- data = gets->data;
- udn1 = gupnp_device_info_get_udn (info);
- udn2 = gupnp_device_info_get_udn (data->info);
-
- if (udn1 && udn2 && strcmp (udn1, udn2) == 0) {
- soup_session_cancel_message (download_session,
- data->message,
- SOUP_STATUS_CANCELLED);
- break;
- }
- }
+ g_return_val_if_fail (g_task_is_valid (res, info), NULL);
+
+ return g_task_propagate_pointer (G_TASK (res), error);
}
GdkPixbuf *
@@ -329,16 +310,6 @@ deinit_icons (void)
{
int i;
- while (pending_gets) {
- GetIconURLData *data;
-
- data = pending_gets->data;
-
- soup_session_cancel_message (download_session,
- data->message,
- SOUP_STATUS_CANCELLED);
- }
-
g_object_unref (download_session);
for (i = 0; i < ICON_LAST; i++) {