diff options
author | Regis Merlino <regis.merlino@intel.com> | 2013-05-28 10:40:56 +0200 |
---|---|---|
committer | Regis Merlino <regis.merlino@intel.com> | 2013-05-29 11:37:39 +0200 |
commit | 45baf6c8d77ae4c7ecf43d92bacaecd2499ba4c6 (patch) | |
tree | a5d621224495d762dba34aeccde87d4ec7728487 /libdleyna/renderer/device.c | |
parent | e95c135e09a86196d55a8e54a8c944cfab24e914 (diff) | |
download | dleyna-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.c | 142 |
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); +} |