summaryrefslogtreecommitdiff
path: root/libdleyna
diff options
context:
space:
mode:
authorRegis Merlino <regis.merlino@intel.com>2013-05-29 14:43:00 +0200
committerRegis Merlino <regis.merlino@intel.com>2013-05-31 11:53:32 +0200
commitdb12b51022f7cbafc6817a84b46da14455af6ce6 (patch)
tree56f64f49e6ec009585eb23786ca39678421c084f /libdleyna
parent24027a95f8c356888c933af9b0fecc0419043a0b (diff)
downloaddleyna-server-db12b51022f7cbafc6817a84b46da14455af6ce6.tar.gz
[Device] Add a GetIcon() method
Signed-off-by: Regis Merlino <regis.merlino@intel.com>
Diffstat (limited to 'libdleyna')
-rw-r--r--libdleyna/server/device.c140
-rw-r--r--libdleyna/server/device.h11
-rw-r--r--libdleyna/server/interface.h5
-rw-r--r--libdleyna/server/server.c17
-rw-r--r--libdleyna/server/task.c25
-rw-r--r--libdleyna/server/task.h14
-rw-r--r--libdleyna/server/upnp.c15
-rw-r--r--libdleyna/server/upnp.h4
8 files changed, 230 insertions, 1 deletions
diff --git a/libdleyna/server/device.c b/libdleyna/server/device.c
index a6268d0..1c3b6a4 100644
--- a/libdleyna/server/device.c
+++ b/libdleyna/server/device.c
@@ -82,6 +82,13 @@ struct dls_device_upload_job_t_ {
guint remove_idle;
};
+typedef struct dls_device_download_t_ dls_device_download_t;
+struct dls_device_download_t_ {
+ SoupSession *session;
+ SoupMessage *msg;
+ dls_async_task_t *task;
+};
+
/* Private structure used in chain task */
typedef struct prv_new_device_ct_t_ prv_new_device_ct_t;
struct prv_new_device_ct_t_ {
@@ -233,6 +240,8 @@ void dls_device_delete(void *device)
g_variant_unref(dev->sort_caps);
g_variant_unref(dev->sort_ext_caps);
g_variant_unref(dev->feature_list);
+ g_free(dev->icon.mime_type);
+ g_free(dev->icon.bytes);
g_free(dev);
}
}
@@ -4262,3 +4271,134 @@ on_error:
DLEYNA_LOG_DEBUG("Exit");
}
+static void prv_build_icon_result(dls_device_t *device, dls_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)
+{
+ dls_device_download_t *download = (dls_device_download_t *)user_data;
+
+ dls_async_task_cancelled_cb(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(dls_device_download_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)
+{
+ dls_device_download_t *download = (dls_device_download_t *)user_data;
+ dls_async_task_t *cb_data = (dls_async_task_t *)download->task;
+ dls_device_t *device = (dls_device_t *)cb_data->task.target.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(dls_async_task_complete, cb_data);
+ g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
+
+out:
+
+ prv_free_download_info(download);
+}
+
+void dls_device_get_icon(dls_client_t *client,
+ dls_task_t *task)
+{
+ GUPnPDeviceInfo *info;
+ dls_device_context_t *context;
+ dls_async_task_t *cb_data = (dls_async_task_t *)task;
+ dls_device_t *device = task->target.device;
+ gchar *url;
+ dls_device_download_t *download;
+
+ if (device->icon.size != 0) {
+ prv_build_icon_result(device, task);
+ goto end;
+ }
+
+ context = dls_device_get_context(device, client);
+ 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) {
+ cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+ DLEYNA_ERROR_NOT_SUPPORTED,
+ "No icon available");
+ goto end;
+ }
+
+ download = g_new0(dls_device_download_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);
+ g_free(url);
+
+ goto end;
+ }
+
+ cb_data->cancel_id =
+ g_cancellable_connect(cb_data->cancellable,
+ G_CALLBACK(prv_get_icon_cancelled),
+ download, NULL);
+
+ g_object_ref(download->msg);
+ soup_session_queue_message(download->session, download->msg,
+ prv_get_icon_session_cb, download);
+
+ g_free(url);
+
+ return;
+
+end:
+
+ (void) g_idle_add(dls_async_task_complete, cb_data);
+}
diff --git a/libdleyna/server/device.h b/libdleyna/server/device.h
index 36687a2..30788db 100644
--- a/libdleyna/server/device.h
+++ b/libdleyna/server/device.h
@@ -41,6 +41,13 @@ struct dls_device_context_t_ {
guint timeout_id;
};
+typedef struct dls_device_icon_t_ dls_device_icon_t;
+struct dls_device_icon_t_ {
+ gchar *mime_type;
+ guchar *bytes;
+ gsize size;
+};
+
struct dls_device_t_ {
dleyna_connector_id_t connection;
guint id;
@@ -57,6 +64,7 @@ struct dls_device_t_ {
GVariant *feature_list;
gboolean shutting_down;
guint construct_step;
+ dls_device_icon_t icon;
};
dls_device_context_t *dls_device_append_new_context(dls_device_t *device,
@@ -138,4 +146,7 @@ void dls_device_get_object_metadata(dls_client_t *client,
void dls_device_create_reference(dls_client_t *client,
dls_task_t *task);
+void dls_device_get_icon(dls_client_t *client,
+ dls_task_t *task);
+
#endif /* DLS_DEVICE_H__ */
diff --git a/libdleyna/server/interface.h b/libdleyna/server/interface.h
index 7d69b6b..14a214b 100644
--- a/libdleyna/server/interface.h
+++ b/libdleyna/server/interface.h
@@ -182,6 +182,11 @@ enum dls_interface_type_ {
#define DLS_INTERFACE_TO_ADD_UPDATE "ToAddUpdate"
#define DLS_INTERFACE_TO_DELETE "ToDelete"
#define DLS_INTERFACE_CANCEL "Cancel"
+#define DLS_INTERFACE_GET_ICON "GetIcon"
+#define DLS_INTERFACE_RESOLUTION "Resolution"
+#define DLS_INTERFACE_ICON_BYTES "Bytes"
+#define DLS_INTERFACE_MIME_TYPE "MimeType"
+#define DLS_INTERFACE_REQ_MIME_TYPE "RequestedMimeType"
#define DLS_INTERFACE_GET_METADATA "GetMetaData"
#define DLS_INTERFACE_METADATA "MetaData"
diff --git a/libdleyna/server/server.c b/libdleyna/server/server.c
index 6141398..a3a901b 100644
--- a/libdleyna/server/server.c
+++ b/libdleyna/server/server.c
@@ -399,6 +399,16 @@ static const gchar g_server_introspection[] =
" </method>"
" <method name='"DLS_INTERFACE_CANCEL"'>"
" </method>"
+ " <method name='"DLS_INTERFACE_GET_ICON"'>"
+ " <arg type='s' name='"DLS_INTERFACE_REQ_MIME_TYPE"'"
+ " direction='in'/>"
+ " <arg type='s' name='"DLS_INTERFACE_RESOLUTION"'"
+ " direction='in'/>"
+ " <arg type='ay' name='"DLS_INTERFACE_ICON_BYTES"'"
+ " direction='out'/>"
+ " <arg type='s' name='"DLS_INTERFACE_MIME_TYPE"'"
+ " direction='out'/>"
+ " </method>"
" <property type='s' name='"DLS_INTERFACE_PROP_LOCATION"'"
" access='read'/>"
" <property type='s' name='"DLS_INTERFACE_PROP_UDN"'"
@@ -619,6 +629,10 @@ static void prv_process_async_task(dls_task_t *task)
dls_upnp_create_reference(g_context.upnp, client, task,
prv_async_task_complete);
break;
+ case DLS_TASK_GET_ICON:
+ dls_upnp_get_icon(g_context.upnp, client, task,
+ prv_async_task_complete);
+ break;
default:
break;
}
@@ -1041,6 +1055,9 @@ static void prv_device_method_call(dleyna_connector_id_t conn,
} else if (!strcmp(method, DLS_INTERFACE_CANCEL_UPLOAD)) {
task = dls_task_cancel_upload_new(invocation, object,
parameters, &error);
+ } else if (!strcmp(method, DLS_INTERFACE_GET_ICON)) {
+ task = dls_task_get_icon_new(invocation, object, parameters,
+ &error);
} else if (!strcmp(method, DLS_INTERFACE_CANCEL)) {
task = NULL;
diff --git a/libdleyna/server/task.c b/libdleyna/server/task.c
index c171206..94f4cf2 100644
--- a/libdleyna/server/task.c
+++ b/libdleyna/server/task.c
@@ -114,6 +114,10 @@ static void prv_delete(dls_task_t *task)
case DLS_TASK_CREATE_REFERENCE:
g_free(task->ut.create_reference.item_path);
break;
+ case DLS_TASK_GET_ICON:
+ g_free(task->ut.get_icon.resolution);
+ g_free(task->ut.get_icon.mime_type);
+ break;
default:
break;
}
@@ -536,6 +540,27 @@ dls_task_t *dls_task_get_metadata_new(dleyna_connector_msg_id_t invocation,
return task;
}
+dls_task_t *dls_task_get_icon_new(dleyna_connector_msg_id_t invocation,
+ const gchar *path, GVariant *parameters,
+ GError **error)
+{
+ dls_task_t *task;
+
+ task = prv_m2spec_task_new(DLS_TASK_GET_ICON, invocation, path,
+ "(@ays)", error, FALSE);
+ if (!task)
+ goto finished;
+
+ task->multiple_retvals = TRUE;
+
+ g_variant_get(parameters, "(ss)", &task->ut.get_icon.mime_type,
+ &task->ut.get_icon.resolution);
+
+finished:
+
+ return task;
+}
+
void dls_task_complete(dls_task_t *task)
{
GVariant *variant = NULL;
diff --git a/libdleyna/server/task.h b/libdleyna/server/task.h
index 3e7b708..bf9f3ba 100644
--- a/libdleyna/server/task.h
+++ b/libdleyna/server/task.h
@@ -52,7 +52,8 @@ enum dls_task_type_t_ {
DLS_TASK_CREATE_CONTAINER_IN_ANY,
DLS_TASK_UPDATE_OBJECT,
DLS_TASK_GET_OBJECT_METADATA,
- DLS_TASK_CREATE_REFERENCE
+ DLS_TASK_CREATE_REFERENCE,
+ DLS_TASK_GET_ICON
};
typedef enum dls_task_type_t_ dls_task_type_t;
@@ -142,6 +143,12 @@ struct dls_task_target_info_t_ {
dls_device_t *device;
};
+typedef struct dls_task_get_icon_t_ dls_task_get_icon_t;
+struct dls_task_get_icon_t_ {
+ gchar *mime_type;
+ gchar *resolution;
+};
+
typedef struct dls_task_t_ dls_task_t;
struct dls_task_t_ {
dleyna_task_atom_t atom; /* pseudo inheritance - MUST be first field */
@@ -165,6 +172,7 @@ struct dls_task_t_ {
dls_task_create_container_t create_container;
dls_task_update_t update;
dls_task_create_reference_t create_reference;
+ dls_task_get_icon_t get_icon;
} ut;
};
@@ -259,6 +267,10 @@ dls_task_t *dls_task_get_metadata_new(dleyna_connector_msg_id_t invocation,
const gchar *path,
GError **error);
+dls_task_t *dls_task_get_icon_new(dleyna_connector_msg_id_t invocation,
+ const gchar *path, GVariant *parameters,
+ GError **error);
+
void dls_task_cancel(dls_task_t *task);
void dls_task_complete(dls_task_t *task);
diff --git a/libdleyna/server/upnp.c b/libdleyna/server/upnp.c
index f603647..92b3943 100644
--- a/libdleyna/server/upnp.c
+++ b/libdleyna/server/upnp.c
@@ -1045,6 +1045,21 @@ void dls_upnp_create_reference(dls_upnp_t *upnp, dls_client_t *client,
return;
}
+void dls_upnp_get_icon(dls_upnp_t *upnp, dls_client_t *client,
+ dls_task_t *task,
+ dls_upnp_task_complete_t cb)
+{
+ dls_async_task_t *cb_data = (dls_async_task_t *)task;
+
+ DLEYNA_LOG_DEBUG("Enter");
+
+ cb_data->cb = cb;
+
+ dls_device_get_icon(client, task);
+
+ DLEYNA_LOG_DEBUG("Exit");
+}
+
void dls_upnp_unsubscribe(dls_upnp_t *upnp)
{
GHashTableIter iter;
diff --git a/libdleyna/server/upnp.h b/libdleyna/server/upnp.h
index 206dba2..833723f 100644
--- a/libdleyna/server/upnp.h
+++ b/libdleyna/server/upnp.h
@@ -101,6 +101,10 @@ void dls_upnp_create_reference(dls_upnp_t *upnp, dls_client_t *client,
dls_task_t *task,
dls_upnp_task_complete_t cb);
+void dls_upnp_get_icon(dls_upnp_t *upnp, dls_client_t *client,
+ dls_task_t *task,
+ dls_upnp_task_complete_t cb);
+
void dls_upnp_unsubscribe(dls_upnp_t *upnp);
gboolean dls_upnp_device_context_exist(dls_device_t *device,