summaryrefslogtreecommitdiff
path: root/libdleyna/renderer/device.c
diff options
context:
space:
mode:
authorRegis Merlino <regis.merlino@intel.com>2013-05-28 10:40:56 +0200
committerRegis Merlino <regis.merlino@intel.com>2013-05-29 11:37:39 +0200
commit45baf6c8d77ae4c7ecf43d92bacaecd2499ba4c6 (patch)
treea5d621224495d762dba34aeccde87d4ec7728487 /libdleyna/renderer/device.c
parente95c135e09a86196d55a8e54a8c944cfab24e914 (diff)
downloaddleyna-renderer-45baf6c8d77ae4c7ecf43d92bacaecd2499ba4c6.tar.gz
[Device] Add a GetIcon() method
Signed-off-by: Regis Merlino <regis.merlino@intel.com>
Diffstat (limited to 'libdleyna/renderer/device.c')
-rw-r--r--libdleyna/renderer/device.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/libdleyna/renderer/device.c b/libdleyna/renderer/device.c
index 62b9f25..dff3d39 100644
--- a/libdleyna/renderer/device.c
+++ b/libdleyna/renderer/device.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <math.h>
+#include <libsoup/soup.h>
#include <libgupnp/gupnp-control-point.h>
#include <libgupnp-av/gupnp-av.h>
@@ -50,6 +51,13 @@ struct prv_new_device_ct_t_ {
const dleyna_connector_dispatch_cb_t *dispatch_table;
};
+typedef struct prv_download_info_t_ prv_download_info_t;
+struct prv_download_info_t_ {
+ SoupSession *session;
+ SoupMessage *msg;
+ dlr_async_task_t *task;
+};
+
static void prv_last_change_cb(GUPnPServiceProxy *proxy,
const char *variable,
GValue *value,
@@ -386,6 +394,10 @@ void dlr_device_delete(void *device)
if (dev->mpris_transport_play_speeds)
g_variant_unref(dev->mpris_transport_play_speeds);
g_free(dev->rate);
+
+ g_free(dev->icon.mime_type);
+ g_free(dev->icon.bytes);
+
g_free(dev);
}
}
@@ -2653,3 +2665,133 @@ void dlr_device_remove_uri(dlr_device_t *device, dlr_task_t *task,
(void) g_idle_add(dlr_async_task_complete, cb_data);
}
+
+static void prv_build_icon_result(dlr_device_t *device, dlr_task_t *task)
+{
+ GVariant *out_p[2];
+
+ out_p[0] = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+ device->icon.bytes,
+ device->icon.size,
+ 1);
+ out_p[1] = g_variant_new_string(device->icon.mime_type);
+ task->result = g_variant_ref_sink(g_variant_new_tuple(out_p, 2));
+}
+
+static void prv_get_icon_cancelled(GCancellable *cancellable,
+ gpointer user_data)
+{
+ prv_download_info_t *download = (prv_download_info_t *)user_data;
+
+ dlr_async_task_cancelled(cancellable, download->task);
+
+ if (download->msg) {
+ soup_session_cancel_message(download->session, download->msg,
+ SOUP_STATUS_CANCELLED);
+ DLEYNA_LOG_DEBUG("Cancelling device icon download");
+ }
+}
+
+static void prv_free_download_info(prv_download_info_t *download)
+{
+ if (download->msg)
+ g_object_unref(download->msg);
+ g_object_unref(download->session);
+ g_free(download);
+}
+
+static void prv_get_icon_session_cb(SoupSession *session,
+ SoupMessage *msg,
+ gpointer user_data)
+{
+ prv_download_info_t *download = (prv_download_info_t *)user_data;
+ dlr_async_task_t *cb_data = (dlr_async_task_t *)download->task;
+ dlr_device_t *device = (dlr_device_t *)cb_data->device;
+
+ if (msg->status_code == SOUP_STATUS_CANCELLED)
+ goto out;
+
+ if (SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) {
+ device->icon.size = msg->response_body->length;
+ device->icon.bytes = g_malloc(device->icon.size);
+ memcpy(device->icon.bytes, msg->response_body->data,
+ device->icon.size);
+
+ prv_build_icon_result(device, &cb_data->task);
+ } else {
+ DLEYNA_LOG_DEBUG("Failed to GET device icon: %s",
+ msg->reason_phrase);
+
+ cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+ DLEYNA_ERROR_OPERATION_FAILED,
+ "Failed to GET device icon");
+ }
+
+ (void) g_idle_add(dlr_async_task_complete, cb_data);
+ g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
+
+out:
+
+ prv_free_download_info(download);
+}
+
+void dlr_device_get_icon(dlr_device_t *device, dlr_task_t *task,
+ dlr_upnp_task_complete_t cb)
+{
+ GUPnPDeviceInfo *info;
+ dlr_device_context_t *context;
+ dlr_async_task_t *cb_data = (dlr_async_task_t *)task;
+ gchar *url;
+ prv_download_info_t *download;
+
+ cb_data->cb = cb;
+ cb_data->device = device;
+
+ if (device->icon.size != 0) {
+ prv_build_icon_result(device, task);
+ goto end;
+ }
+
+ context = dlr_device_get_context(device);
+ info = (GUPnPDeviceInfo *)context->device_proxy;
+
+ url = gupnp_device_info_get_icon_url(info, NULL, -1, -1, -1, FALSE,
+ &device->icon.mime_type, NULL,
+ NULL, NULL);
+ if (url == NULL || *url == 0) {
+ cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+ DLEYNA_ERROR_NOT_SUPPORTED,
+ "No icon available");
+ goto end;
+ }
+
+ download = g_new0(prv_download_info_t, 1);
+ download->session = soup_session_async_new();
+ download->msg = soup_message_new(SOUP_METHOD_GET, url);
+ download->task = cb_data;
+
+ if (!download->msg) {
+ DLEYNA_LOG_WARNING("Invalid URL %s", url);
+
+ cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+ DLEYNA_ERROR_BAD_RESULT,
+ "Invalid URL %s", url);
+ prv_free_download_info(download);
+
+ goto end;
+ }
+
+ cb_data->cancel_id =
+ g_cancellable_connect(cb_data->cancellable,
+ G_CALLBACK(prv_get_icon_cancelled),
+ download, NULL);
+
+ soup_session_queue_message(download->session, download->msg,
+ prv_get_icon_session_cb, download);
+
+ return;
+
+end:
+
+ (void) g_idle_add(dlr_async_task_complete, cb_data);
+}