summaryrefslogtreecommitdiff
path: root/libgupnp
diff options
context:
space:
mode:
authorJens Georg <mail@jensge.org>2022-05-26 11:44:58 +0200
committerJens Georg <mail@jensge.org>2022-06-03 19:52:26 +0200
commitc04f65025634f15e1925d82b891ce4884dd511ae (patch)
tree8ea839e0c93bf6773a479c9502ed62e1b68efda8 /libgupnp
parentfa4ddc6fb9ce650b8a4dd908d22aec27d93fe727 (diff)
downloadgupnp-c04f65025634f15e1925d82b891ce4884dd511ae.tar.gz
device-info: Add method to download icon.
While porting to libsoup3 I have implemented this 3-4 times now. Just offer it in GUPnP itself.
Diffstat (limited to 'libgupnp')
-rw-r--r--libgupnp/gupnp-device-info.c187
-rw-r--r--libgupnp/gupnp-device-info.h19
2 files changed, 205 insertions, 1 deletions
diff --git a/libgupnp/gupnp-device-info.c b/libgupnp/gupnp-device-info.c
index 389281b..ef00920 100644
--- a/libgupnp/gupnp-device-info.c
+++ b/libgupnp/gupnp-device-info.c
@@ -12,8 +12,9 @@
#include <config.h>
#include <string.h>
-#include "gupnp-device-info.h"
+#include "gupnp-context-private.h"
#include "gupnp-device-info-private.h"
+#include "gupnp-device-info.h"
#include "gupnp-resource-factory-private.h"
#include "xml-util.h"
@@ -33,6 +34,21 @@ struct _GUPnPDeviceInfoPrivate {
};
typedef struct _GUPnPDeviceInfoPrivate GUPnPDeviceInfoPrivate;
+struct _GetIconData {
+ char *mime;
+ int depth;
+ int width;
+ int height;
+};
+typedef struct _GetIconData GetIconData;
+
+static void
+get_icon_data_free (GetIconData *data)
+{
+ g_clear_pointer (&data->mime, g_free);
+ g_free (data);
+}
+
/**
* GUPnPDeviceInfo:
*
@@ -1508,3 +1524,172 @@ _gupnp_device_info_get_document (GUPnPDeviceInfo *info)
return priv->doc;
}
+
+static void
+on_get_icon_async (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ GTask *task = G_TASK (user_data);
+ GError *error = NULL;
+
+ GBytes *data = soup_session_send_and_read_finish (SOUP_SESSION (source),
+ res,
+ &error);
+ SoupMessage *message =
+ soup_session_get_async_result_message (SOUP_SESSION (source),
+ res);
+
+ if (error != NULL) {
+ g_task_return_error (task, error);
+ } else {
+ if (SOUP_STATUS_IS_SUCCESSFUL (
+ soup_message_get_status (message))) {
+ g_task_return_pointer (task,
+ g_steal_pointer (&data),
+ (GDestroyNotify) g_bytes_unref);
+ } else {
+ g_bytes_unref (data);
+
+ g_task_return_new_error (
+ task,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Unable to download icon: %s",
+ soup_message_get_reason_phrase (message));
+ }
+ }
+
+ g_clear_pointer (&data, g_bytes_unref);
+ g_object_unref (task);
+}
+
+/**
+ * gupnp_device_info_get_icon_async:
+ * @info: A #GUPnPDeviceInfo
+ * @requested_mime_type: (nullable) (transfer none): The requested file
+ * format, or %NULL for any
+ * @requested_depth: The requested color depth, or -1 for any
+ * @requested_width: The requested width, or -1 for any
+ * @requested_height: The requested height, or -1 for any
+ * @prefer_bigger: %TRUE if a bigger, rather than a smaller icon should be
+ * returned if no exact match could be found
+ *
+ * Download the device icon matching the request parameters. For details on
+ * the lookup procedure, see [method@GUPnP.DeviceInfo.get_icon_url]
+ **/
+void
+gupnp_device_info_get_icon_async (GUPnPDeviceInfo *info,
+ const char *requested_mime_type,
+ int requested_depth,
+ int requested_width,
+ int requested_height,
+ gboolean prefer_bigger,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (GUPNP_IS_DEVICE_INFO (info));
+
+ GTask *task = g_task_new (info, cancellable, callback, user_data);
+ char *mime = NULL;
+ int depth = -1;
+ int width = -1;
+ int height = -1;
+
+ char *url = gupnp_device_info_get_icon_url (info,
+ requested_mime_type,
+ requested_depth,
+ requested_width,
+ requested_height,
+ prefer_bigger,
+ &mime,
+ &depth,
+ &width,
+ &height);
+
+ if (url == NULL) {
+ g_task_return_pointer (task, NULL, NULL);
+ g_object_unref (task);
+ g_clear_pointer (&mime, g_free);
+
+ return;
+ }
+
+ GUPnPContext *context = gupnp_device_info_get_context (info);
+ SoupSession *session = gupnp_context_get_session (context);
+ GUri *rewritten_url = gupnp_context_rewrite_uri_to_uri (context, url);
+ g_free (url);
+
+ GetIconData *data = g_new0 (GetIconData, 1);
+ data->mime = g_steal_pointer (&mime);
+ data->depth = depth;
+ data->width = width;
+ data->height = height;
+ g_task_set_task_data (task, data, (GDestroyNotify) get_icon_data_free);
+
+ SoupMessage *message =
+ soup_message_new_from_uri (SOUP_METHOD_GET, rewritten_url);
+ g_uri_unref (rewritten_url);
+
+ soup_session_send_and_read_async (session,
+ message,
+ G_PRIORITY_DEFAULT_IDLE,
+ g_task_get_cancellable (task),
+ on_get_icon_async,
+ task);
+ g_object_unref (message);
+ g_clear_pointer (&mime, g_free);
+}
+
+/**
+ * gupnp_device_info_get_icon_finish:
+ * @info: A #GUPnPDeviceInfo
+ * @res: A GAsyncResult
+ * @mime: (out) (optional): The location where to store the the format
+ * of the returned icon, or %NULL. The returned string should be freed after
+ * use
+ * @depth: (out) (optional): The location where to store the depth of the
+ * returned icon, or %NULL
+ * @width: (out) (optional): The location where to store the width of the
+ * returned icon, or %NULL
+ * @height: (out) (optional): The location where to store the height of the
+ * returned icon, or %NULL
+ * @error: A location for GError or NULL
+ *
+ * Returns: (transfer full): A GBytes contaning the icon or NULL on either
+ * error or no matching icon was found.
+ */
+GBytes *
+gupnp_device_info_get_icon_finish (GUPnPDeviceInfo *info,
+ GAsyncResult *res,
+ char **mime,
+ int *depth,
+ int *width,
+ int *height,
+ GError **error)
+{
+ g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, info), NULL);
+
+ GBytes *data = g_task_propagate_pointer (G_TASK (res), error);
+ GetIconData *icon_data = g_task_get_task_data (G_TASK (res));
+
+ if (mime != NULL) {
+ *mime = (icon_data == NULL)
+ ? NULL
+ : g_steal_pointer (&(icon_data->mime));
+ }
+
+ if (depth != NULL) {
+ *depth = (icon_data == NULL) ? -1 : icon_data->depth;
+ }
+
+ if (width != NULL) {
+ *width = (icon_data == NULL) ? -1 : icon_data->width;
+ }
+
+ if (height != NULL) {
+ *height = (icon_data == NULL) ? -1 : icon_data->height;
+ }
+
+ return data;
+}
diff --git a/libgupnp/gupnp-device-info.h b/libgupnp/gupnp-device-info.h
index affeeb4..4205ec4 100644
--- a/libgupnp/gupnp-device-info.h
+++ b/libgupnp/gupnp-device-info.h
@@ -100,6 +100,25 @@ gupnp_device_info_get_icon_url (GUPnPDeviceInfo *info,
int *width,
int *height);
+void
+gupnp_device_info_get_icon_async (GUPnPDeviceInfo *info,
+ const char *requested_mime_type,
+ int requested_depth,
+ int requested_width,
+ int requested_height,
+ gboolean prefer_bigger,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GBytes *
+gupnp_device_info_get_icon_finish (GUPnPDeviceInfo *info,
+ GAsyncResult *res,
+ char **mime,
+ int *depth,
+ int *width,
+ int *height,
+ GError **error);
char *
gupnp_device_info_get_presentation_url (GUPnPDeviceInfo *info);