summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--doc/server/dbus/API.txt12
-rw-r--r--libdleyna/server/Makefile.am10
-rw-r--r--libdleyna/server/device.c769
-rw-r--r--libdleyna/server/device.h37
-rw-r--r--libdleyna/server/interface.h3
-rw-r--r--libdleyna/server/props.c29
-rw-r--r--libdleyna/server/props.h8
-rw-r--r--libdleyna/server/server.c14
-rw-r--r--libdleyna/server/task.c13
-rw-r--r--libdleyna/server/task.h7
-rw-r--r--libdleyna/server/upnp.c147
-rw-r--r--libdleyna/server/upnp.h8
-rw-r--r--libdleyna/server/xml-util.c133
-rw-r--r--libdleyna/server/xml-util.h35
-rw-r--r--test/dbus/mediaconsole.py3
16 files changed, 1006 insertions, 223 deletions
diff --git a/configure.ac b/configure.ac
index 355f516..539aa43 100644
--- a/configure.ac
+++ b/configure.ac
@@ -43,6 +43,7 @@ PKG_CHECK_MODULES([GUPNP], [gupnp-1.0 >= 0.20.3])
PKG_CHECK_MODULES([GUPNPAV], [gupnp-av-1.0 >= 0.11.5])
PKG_CHECK_MODULES([GUPNPDLNA], [gupnp-dlna-2.0 >= 0.9.4])
PKG_CHECK_MODULES([SOUP], [libsoup-2.4 >= 2.28.2])
+PKG_CHECK_MODULES([LIBXML], [libxml-2.0])
# Checks for header files.
AC_CHECK_HEADERS([stdlib.h string.h syslog.h])
diff --git a/doc/server/dbus/API.txt b/doc/server/dbus/API.txt
index 0804691..2943378 100644
--- a/doc/server/dbus/API.txt
+++ b/doc/server/dbus/API.txt
@@ -204,6 +204,9 @@ below:
|------------------------------------------------------------------------------|
| UDN | s | m | The Unique Device Name of the server. |
|------------------------------------------------------------------------------|
+| RootUDN | s | o | The Unique Device Name of the root |
+| | | | device, if the server is a sub-device. |
+|------------------------------------------------------------------------------|
| FriendlyName | s | m | The friendly name of the media server. |
-------------------------------------------------------------------------------|
| IconURL | s | o | A URL pointing to an icon that |
@@ -265,7 +268,9 @@ below:
| SystemUpdateID | u | m | An integer value that is incremenented |
| | | | every time changes are made to the DMS. |
|------------------------------------------------------------------------------|
-
+| Sleeping | b | o | An boolean value which represents the |
+| | | | server sleeping state. |
+|------------------------------------------------------------------------------|
(* where m/o indicates whether the property is optional or mandatory )
(1) A value of -1 for the srs-rt-retention-period capability denotes an
infinite retention period.
@@ -350,6 +355,7 @@ Both RequestedMimeType and Resolution parameters are currently
reserved for future use and should be set as an empty string.
BrowseObjects(as ObjectPath, as Filter) -> aa{sv}
+
This method returns properties of all media objects specified by the first
parameter. The list of properties to return is specified by the second
parameter.
@@ -375,6 +381,10 @@ The purposes of this method are:
retrieve a subset of an object's properties. Browse is likely to be more
efficient than GetAll in such cases.
+Wake() -> void
+
+Sends a magic packet to the server to wake it up if it is in sleeping state.
+
Signals:
---------
diff --git a/libdleyna/server/Makefile.am b/libdleyna/server/Makefile.am
index 0c8a6d8..020b41c 100644
--- a/libdleyna/server/Makefile.am
+++ b/libdleyna/server/Makefile.am
@@ -8,6 +8,7 @@ AM_CFLAGS = $(GLIB_CFLAGS) \
$(GUPNPAV_CFLAGS) \
$(GUPNPDLNA_CFLAGS) \
$(SOUP_CFLAGS) \
+ $(LIBXML_CFLAGS) \
-include config.h
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
@@ -31,7 +32,8 @@ libdleyna_server_1_0_la_SOURCES = $(libdleyna_serverinc_HEADERS) \
search.c \
sort.c \
task.c \
- upnp.c
+ upnp.c \
+ xml-util.c
libdleyna_server_1_0_la_LIBADD = $(GLIB_LIBS) \
$(GIO_LIBS) \
@@ -40,7 +42,8 @@ libdleyna_server_1_0_la_LIBADD = $(GLIB_LIBS) \
$(GUPNP_LIBS) \
$(GUPNPAV_LIBS) \
$(GUPNPDLNA_LIBS) \
- $(SOUP_LIBS)
+ $(SOUP_LIBS) \
+ $(LIBXML_LIBS)
MAINTAINERCLEANFILES = Makefile.in \
aclocal.m4 \
@@ -66,7 +69,8 @@ EXTRA_DIST = $(sysconf_DATA) \
server.h \
sort.h \
task.h \
- upnp.h
+ upnp.h \
+ xml-util.h
CLEANFILES = dleyna-server-service.conf
DISTCLEANFILES = dleyna-server-service.conf
diff --git a/libdleyna/server/device.c b/libdleyna/server/device.c
index 86045f2..d5d5bf8 100644
--- a/libdleyna/server/device.c
+++ b/libdleyna/server/device.c
@@ -36,12 +36,17 @@
#include "interface.h"
#include "path.h"
#include "server.h"
+#include "xml-util.h"
#define DLS_SYSTEM_UPDATE_VAR "SystemUpdateID"
#define DLS_CONTAINER_UPDATE_VAR "ContainerUpdateIDs"
#define DLS_LAST_CHANGE_VAR "LastChange"
+#define DLS_NETWORK_INTERFACE_INFO_VAR "NetworkInterfaceInfo"
#define DLS_DMS_DEVICE_TYPE "urn:schemas-upnp-org:device:MediaServer:"
-
+#define DLS_CONTENT_DIRECTORY_SERVICE_TYPE \
+ "urn:schemas-upnp-org:service:ContentDirectory"
+#define DLS_ENERGY_MANAGEMENT_SERVICE_TYPE \
+ "urn:schemas-upnp-org:service:EnergyManagement:1"
#define DLS_UPLOAD_STATUS_IN_PROGRESS "IN_PROGRESS"
#define DLS_UPLOAD_STATUS_CANCELLED "CANCELLED"
#define DLS_UPLOAD_STATUS_ERROR "ERROR"
@@ -122,6 +127,10 @@ static void prv_last_change_cb(GUPnPServiceProxy *proxy,
const char *variable,
GValue *value,
gpointer user_data);
+static void prv_network_interface_info_cb(GUPnPServiceProxy *proxy,
+ const char *variable,
+ GValue *value,
+ gpointer user_data);
static void prv_upload_delete(gpointer up);
static void prv_upload_job_delete(gpointer up);
static void prv_get_sr_token_for_props(GUPnPServiceProxy *proxy,
@@ -135,6 +144,8 @@ static GUPnPServiceProxyAction *prv_browse_objects_begin_action_cb(
GUPnPServiceProxy *proxy,
gboolean *failed);
+static void prv_free_network_if_info(dls_network_if_info_t *info);
+
static void prv_object_builder_delete(void *dob)
{
dls_device_object_builder_t *builder = dob;
@@ -163,32 +174,45 @@ static void prv_count_data_new(dls_async_task_t *cb_data,
static void prv_context_unsubscribe(dls_device_context_t *ctx)
{
- if (ctx->timeout_id) {
- (void) g_source_remove(ctx->timeout_id);
- ctx->timeout_id = 0;
+ if (ctx->cds.timeout_id) {
+ (void) g_source_remove(ctx->cds.timeout_id);
+ ctx->cds.timeout_id = 0;
}
- if (ctx->subscribed) {
- gupnp_service_proxy_remove_notify(
- ctx->service_proxy,
- DLS_SYSTEM_UPDATE_VAR,
- prv_system_update_cb,
- ctx->device);
- gupnp_service_proxy_remove_notify(
- ctx->service_proxy,
- DLS_CONTAINER_UPDATE_VAR,
- prv_container_update_cb,
- ctx->device);
+ if (ctx->ems.timeout_id) {
+ (void) g_source_remove(ctx->ems.timeout_id);
+ ctx->ems.timeout_id = 0;
+ }
+
+ if (ctx->cds.subscribed) {
+ gupnp_service_proxy_remove_notify(ctx->cds.proxy,
+ DLS_SYSTEM_UPDATE_VAR,
+ prv_system_update_cb,
+ ctx->device);
+ gupnp_service_proxy_remove_notify(ctx->cds.proxy,
+ DLS_CONTAINER_UPDATE_VAR,
+ prv_container_update_cb,
+ ctx->device);
+ gupnp_service_proxy_remove_notify(ctx->cds.proxy,
+ DLS_LAST_CHANGE_VAR,
+ prv_last_change_cb,
+ ctx->device);
+
+ gupnp_service_proxy_set_subscribed(ctx->cds.proxy, FALSE);
+
+ ctx->cds.subscribed = FALSE;
+ }
+
+ if (ctx->ems.subscribed) {
gupnp_service_proxy_remove_notify(
- ctx->service_proxy,
- DLS_LAST_CHANGE_VAR,
- prv_last_change_cb,
- ctx->device);
+ ctx->ems.proxy,
+ DLS_NETWORK_INTERFACE_INFO_VAR,
+ prv_network_interface_info_cb,
+ ctx->device);
- gupnp_service_proxy_set_subscribed(ctx->service_proxy,
- FALSE);
+ gupnp_service_proxy_set_subscribed(ctx->ems.proxy, FALSE);
- ctx->subscribed = FALSE;
+ ctx->ems.subscribed = FALSE;
}
}
@@ -199,35 +223,94 @@ static void prv_context_delete(gpointer context)
if (ctx) {
prv_context_unsubscribe(ctx);
+ if (ctx->device_info)
+ g_object_unref(ctx->device_info);
+
if (ctx->device_proxy)
g_object_unref(ctx->device_proxy);
- if (ctx->service_proxy)
- g_object_unref(ctx->service_proxy);
+ prv_free_network_if_info(ctx->network_if_info);
+
+ if (ctx->cds.proxy)
+ g_object_unref(ctx->cds.proxy);
+
+ if (ctx->ems.proxy)
+ g_object_unref(ctx->ems.proxy);
g_free(ctx->ip_address);
g_free(ctx);
}
}
+static GUPnPServiceInfo *prv_lookup_em_service(GUPnPDeviceInfo *device_info)
+{
+ GList *child_devices;
+ GList *next;
+ GUPnPDeviceInfo *child_info = NULL;
+ GUPnPServiceInfo *service_info = NULL;
+
+ child_devices = gupnp_device_info_list_devices(device_info);
+
+ next = child_devices;
+ while (next != NULL) {
+ child_info = (GUPnPDeviceInfo *)next->data;
+
+ service_info = gupnp_device_info_get_service(child_info,
+ DLS_ENERGY_MANAGEMENT_SERVICE_TYPE);
+
+ if (service_info != NULL)
+ break;
+
+ service_info = prv_lookup_em_service(child_info);
+
+ if (service_info != NULL)
+ break;
+
+ next = g_list_next(next);
+ }
+
+ g_list_free_full(child_devices, g_object_unref);
+
+ return service_info;
+}
+
static void prv_context_new(const gchar *ip_address,
GUPnPDeviceProxy *proxy,
+ GUPnPDeviceInfo *device_info,
dls_device_t *device,
dls_device_context_t **context)
{
- const gchar *service_type =
- "urn:schemas-upnp-org:service:ContentDirectory";
dls_device_context_t *ctx = g_new(dls_device_context_t, 1);
ctx->ip_address = g_strdup(ip_address);
ctx->device_proxy = proxy;
+ ctx->device_info = device_info;
+
ctx->device = device;
+ ctx->cds.subscribed = FALSE;
+ ctx->cds.timeout_id = 0;
+ ctx->ems.subscribed = FALSE;
+ ctx->ems.timeout_id = 0;
+
+ ctx->network_if_info = NULL;
+
g_object_ref(proxy);
- ctx->service_proxy = (GUPnPServiceProxy *)
- gupnp_device_info_get_service((GUPnPDeviceInfo *)proxy,
- service_type);
- ctx->subscribed = FALSE;
- ctx->timeout_id = 0;
+ g_object_ref(device_info);
+
+ ctx->cds.proxy = (GUPnPServiceProxy *)
+ gupnp_device_info_get_service(
+ device_info,
+ DLS_CONTENT_DIRECTORY_SERVICE_TYPE);
+
+ ctx->ems.proxy = (GUPnPServiceProxy *)
+ gupnp_device_info_get_service(
+ (GUPnPDeviceInfo *)proxy,
+ DLS_ENERGY_MANAGEMENT_SERVICE_TYPE);
+
+ if (ctx->ems.proxy == NULL)
+ ctx->ems.proxy = (GUPnPServiceProxy *)
+ prv_lookup_em_service(
+ (GUPnPDeviceInfo *)proxy);
*context = ctx;
}
@@ -459,6 +542,254 @@ on_error:
g_error_free(error);
}
+static void prv_free_network_if_info(dls_network_if_info_t *info)
+{
+ if (info != NULL) {
+ g_free(info->mac_address);
+ g_free(info->device_uuid);
+ g_free(info->network_if_mode);
+ g_free(info->wake_on_pattern);
+ g_free(info->wake_transport);
+ g_list_free_full(info->ip_addresses, g_free);
+
+ g_free(info);
+ }
+}
+
+static dls_network_if_info_t *prv_get_network_if_info(xmlNode *device_if_node)
+{
+ dls_network_if_info_t *info = NULL;
+ GList *ipv4_addresses;
+ GList *ipv6_addresses;
+
+ info = g_new0(dls_network_if_info_t, 1);
+
+ ipv4_addresses = xml_util_get_child_string_list_content_by_name(
+ device_if_node,
+ "NetworkInterface",
+ "AssociatedIpAddresses",
+ "Ipv4", NULL);
+
+ ipv6_addresses = xml_util_get_child_string_list_content_by_name(
+ device_if_node,
+ "NetworkInterface",
+ "AssociatedIpAddresses",
+ "Ipv6", NULL);
+
+ info->ip_addresses = g_list_concat(ipv4_addresses, ipv6_addresses);
+
+ info->device_uuid = xml_util_get_child_string_content_by_name(
+ device_if_node,
+ "DeviceUUID", NULL);
+
+ info->mac_address = xml_util_get_child_string_content_by_name(
+ device_if_node,
+ "NetworkInterface",
+ "MacAddress", NULL);
+
+ info->network_if_mode = xml_util_get_child_string_content_by_name(
+ device_if_node,
+ "NetworkInterface",
+ "NetworkInterfaceMode"
+ , NULL);
+
+ info->wake_on_pattern = xml_util_get_child_string_content_by_name(
+ device_if_node,
+ "NetworkInterface",
+ "WakeOnPattern", NULL);
+
+ info->wake_transport = xml_util_get_child_string_content_by_name(
+ device_if_node,
+ "NetworkInterface",
+ "WakeSupportedTransport", NULL);
+
+ if ((info->device_uuid == NULL || strlen(info->device_uuid) > 70) ||
+ (info->mac_address == NULL || strlen(info->mac_address) != 17) ||
+ (info->network_if_mode == NULL) || (info->ip_addresses == NULL) ||
+ (info->wake_on_pattern == NULL) || (info->wake_transport == NULL))
+ goto on_error;
+
+ return info;
+
+on_error:
+ prv_free_network_if_info(info);
+
+ return NULL;
+}
+
+static GList *prv_network_if_info_decode(const gchar *info)
+{
+ xmlDoc *doc;
+ xmlNode *node;
+ GList *info_list = NULL;
+ dls_network_if_info_t *if_info;
+
+ DLEYNA_LOG_DEBUG("Enter");
+
+ DLEYNA_LOG_DEBUG_NL();
+ DLEYNA_LOG_DEBUG("NetworkInterfaceInfo XML: %s", info);
+ DLEYNA_LOG_DEBUG_NL();
+
+ doc = xmlParseMemory(info, strlen(info) + 1);
+ if (doc == NULL) {
+ DLEYNA_LOG_WARNING("XML: invalid document");
+
+ goto on_exit;
+ }
+
+ node = xmlDocGetRootElement(doc);
+ if (node == NULL) {
+ DLEYNA_LOG_WARNING("XML: empty document");
+
+ goto on_exit;
+ }
+
+ if (node->name == NULL) {
+ DLEYNA_LOG_WARNING("XML: empty document name");
+
+ goto on_exit;
+ }
+
+ if (strcmp((char *)node->name, "NetworkInterfaceInfo")) {
+ DLEYNA_LOG_WARNING("XML: invalid document name");
+
+ goto on_exit;
+ }
+
+ for (node = node->children; node; node = node->next) {
+ if (node->name != NULL &&
+ !strcmp((char *)node->name, "DeviceInterface")) {
+ if_info = prv_get_network_if_info(node);
+
+ if (if_info != NULL)
+ info_list = g_list_prepend(info_list, if_info);
+ }
+ }
+
+on_exit:
+ DLEYNA_LOG_DEBUG("Exit");
+
+ if (doc != NULL)
+ xmlFreeDoc(doc);
+
+ return info_list;
+}
+
+static gboolean prv_lookup_device_ctx_network_if_info(dls_device_context_t *ctx,
+ dls_network_if_info_t *info,
+ gboolean *sleeping)
+{
+ gboolean found = FALSE;
+ const gchar *udn;
+ gchar *ip_address;
+ GList *next;
+
+ next = info->ip_addresses;
+ while (next != NULL) {
+ ip_address = (gchar *)next->data;
+ if (!strcmp(ctx->ip_address, ip_address)) {
+ udn = gupnp_device_info_get_udn((GUPnPDeviceInfo *)
+ ctx->device_proxy);
+ if (!strcmp(info->device_uuid, udn)) {
+ found = TRUE;
+ if (!strcmp(info->network_if_mode, "IP-up"))
+ *sleeping = FALSE;
+ else
+ *sleeping = TRUE;
+ }
+ }
+
+ if (found)
+ break;
+
+ next = g_list_next(next);
+ }
+
+ return found;
+}
+
+static gboolean prv_get_device_sleeping_state(dls_device_t *device,
+ const gchar *network_if_info_xml,
+ gboolean *sleeping)
+{
+ dls_network_if_info_t *info;
+ GList *info_list;
+ GList *next;
+ unsigned int i;
+ dls_device_context_t *ctx;
+ gboolean found = FALSE;
+
+ info_list = prv_network_if_info_decode(network_if_info_xml);
+ if (info_list == NULL)
+ goto on_exit;
+
+ next = info_list;
+ while (next != NULL) {
+ info = (dls_network_if_info_t *)next->data;
+ for (i = 0; i < device->contexts->len; ++i) {
+ ctx = g_ptr_array_index(device->contexts, i);
+ found = prv_lookup_device_ctx_network_if_info(ctx,
+ info,
+ sleeping);
+ if (found)
+ break;
+ }
+
+ next = g_list_next(next);
+
+ if (found) {
+ prv_free_network_if_info(ctx->network_if_info);
+
+ ctx->network_if_info = info;
+
+ info_list = g_list_remove(info_list, info);
+
+ break;
+ }
+ }
+
+ g_list_free_full(info_list, (GDestroyNotify)prv_free_network_if_info);
+
+on_exit:
+
+ return found;
+}
+
+static void prv_network_interface_info_cb(GUPnPServiceProxy *proxy,
+ const char *variable,
+ GValue *value,
+ gpointer user_data)
+{
+ dls_device_t *device = user_data;
+ GVariantBuilder *array;
+ GVariant *val;
+ gboolean sleeping;
+
+ if (prv_get_device_sleeping_state(device,
+ g_value_get_string(value),
+ &sleeping)) {
+ device->sleeping = sleeping;
+
+ array = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+ g_variant_builder_add(array, "{sv}",
+ DLS_INTERFACE_PROP_SLEEPING,
+ g_variant_new_boolean(sleeping));
+ val = g_variant_new("(s@a{sv}as)",
+ DLEYNA_SERVER_INTERFACE_MEDIA_DEVICE,
+ g_variant_builder_end(array),
+ NULL);
+
+ (void) dls_server_get_connector()->notify(device->connection,
+ device->path,
+ DLS_INTERFACE_PROPERTIES,
+ DLS_INTERFACE_PROPERTIES_CHANGED,
+ val,
+ NULL);
+
+ g_variant_builder_unref(array);
+ }
+}
+
static void prv_build_container_update_array(const gchar *root_path,
const gchar *value,
GVariantBuilder *builder)
@@ -599,49 +930,82 @@ static void prv_system_update_cb(GUPnPServiceProxy *proxy,
g_variant_builder_unref(array);
}
-static gboolean prv_re_enable_subscription(gpointer user_data)
+static gboolean prv_re_enable_cd_subscription(gpointer user_data)
{
dls_device_context_t *context = user_data;
- context->timeout_id = 0;
+ context->cds.timeout_id = 0;
return FALSE;
}
-static void prv_subscription_lost_cb(GUPnPServiceProxy *proxy,
+static void prv_cd_subscription_lost_cb(GUPnPServiceProxy *proxy,
const GError *reason,
gpointer user_data)
{
dls_device_context_t *context = user_data;
- if (!context->timeout_id) {
- gupnp_service_proxy_set_subscribed(context->service_proxy,
- TRUE);
- context->timeout_id = g_timeout_add_seconds(
+ if (!context->cds.timeout_id) {
+ gupnp_service_proxy_set_subscribed(context->cds.proxy, TRUE);
+ context->cds.timeout_id = g_timeout_add_seconds(
10,
- prv_re_enable_subscription,
+ prv_re_enable_cd_subscription,
context);
} else {
- g_source_remove(context->timeout_id);
- gupnp_service_proxy_remove_notify(context->service_proxy,
+ g_source_remove(context->cds.timeout_id);
+ gupnp_service_proxy_remove_notify(context->cds.proxy,
DLS_SYSTEM_UPDATE_VAR,
prv_system_update_cb,
context->device);
- gupnp_service_proxy_remove_notify(context->service_proxy,
+ gupnp_service_proxy_remove_notify(context->cds.proxy,
DLS_CONTAINER_UPDATE_VAR,
prv_container_update_cb,
context->device);
- gupnp_service_proxy_remove_notify(context->service_proxy,
+ gupnp_service_proxy_remove_notify(context->cds.proxy,
DLS_LAST_CHANGE_VAR,
prv_last_change_cb,
context->device);
- context->timeout_id = 0;
- context->subscribed = FALSE;
+ context->cds.timeout_id = 0;
+ context->cds.subscribed = FALSE;
+ }
+}
+
+static gboolean prv_re_enable_em_subscription(gpointer user_data)
+{
+ dls_device_context_t *context = user_data;
+
+ context->cds.timeout_id = 0;
+
+ return FALSE;
+}
+
+static void prv_em_subscription_lost_cb(GUPnPServiceProxy *proxy,
+ const GError *reason,
+ gpointer user_data)
+{
+ dls_device_context_t *context = user_data;
+
+ if (!context->ems.timeout_id) {
+ gupnp_service_proxy_set_subscribed(context->ems.proxy, TRUE);
+ context->ems.timeout_id = g_timeout_add_seconds(
+ 10,
+ prv_re_enable_em_subscription,
+ context);
+ } else {
+ g_source_remove(context->ems.timeout_id);
+ gupnp_service_proxy_remove_notify(
+ context->ems.proxy,
+ DLS_NETWORK_INTERFACE_INFO_VAR,
+ prv_network_interface_info_cb,
+ context->device);
+
+ context->ems.timeout_id = 0;
+ context->ems.subscribed = FALSE;
}
}
-void dls_device_subscribe_to_contents_change(dls_device_t *device)
+void dls_device_subscribe_to_service_changes(dls_device_t *device)
{
dls_device_context_t *context;
@@ -650,31 +1014,47 @@ void dls_device_subscribe_to_contents_change(dls_device_t *device)
DLEYNA_LOG_DEBUG("Subscribe for events on context: %s",
context->ip_address);
- gupnp_service_proxy_add_notify(context->service_proxy,
- DLS_SYSTEM_UPDATE_VAR,
- G_TYPE_UINT,
- prv_system_update_cb,
- device);
-
- gupnp_service_proxy_add_notify(context->service_proxy,
- DLS_CONTAINER_UPDATE_VAR,
- G_TYPE_STRING,
- prv_container_update_cb,
- device);
+ if (context->cds.proxy) {
+ gupnp_service_proxy_add_notify(context->cds.proxy,
+ DLS_SYSTEM_UPDATE_VAR,
+ G_TYPE_UINT,
+ prv_system_update_cb,
+ device);
+
+ gupnp_service_proxy_add_notify(context->cds.proxy,
+ DLS_CONTAINER_UPDATE_VAR,
+ G_TYPE_STRING,
+ prv_container_update_cb,
+ device);
+
+ gupnp_service_proxy_add_notify(context->cds.proxy,
+ DLS_LAST_CHANGE_VAR,
+ G_TYPE_STRING,
+ prv_last_change_cb,
+ device);
+
+ context->cds.subscribed = TRUE;
+ gupnp_service_proxy_set_subscribed(context->cds.proxy, TRUE);
+
+ g_signal_connect(context->cds.proxy, "subscription-lost",
+ G_CALLBACK(prv_cd_subscription_lost_cb),
+ context);
+ }
- gupnp_service_proxy_add_notify(context->service_proxy,
- DLS_LAST_CHANGE_VAR,
- G_TYPE_STRING,
- prv_last_change_cb,
- device);
+ if (context->ems.proxy) {
+ gupnp_service_proxy_add_notify(context->ems.proxy,
+ DLS_NETWORK_INTERFACE_INFO_VAR,
+ G_TYPE_STRING,
+ prv_network_interface_info_cb,
+ device);
- context->subscribed = TRUE;
- gupnp_service_proxy_set_subscribed(context->service_proxy, TRUE);
+ context->ems.subscribed = TRUE;
+ gupnp_service_proxy_set_subscribed(context->ems.proxy, TRUE);
- g_signal_connect(context->service_proxy,
- "subscription-lost",
- G_CALLBACK(prv_subscription_lost_cb),
- context);
+ g_signal_connect(context->ems.proxy, "subscription-lost",
+ G_CALLBACK(prv_em_subscription_lost_cb),
+ context);
+ }
}
static void prv_feature_list_add_feature(gchar *root_path,
@@ -1039,7 +1419,7 @@ static GUPnPServiceProxyAction *prv_subscribe(dleyna_service_task_t *task,
device = (dls_device_t *)dleyna_service_task_get_user_data(task);
device->construct_step++;
- dls_device_subscribe_to_contents_change(device);
+ dls_device_subscribe_to_service_changes(device);
*failed = FALSE;
@@ -1141,7 +1521,7 @@ void dls_device_construct(
priv_t->vtable = dispatch_table;
priv_t->property_map = property_map;
- s_proxy = context->service_proxy;
+ s_proxy = context->cds.proxy;
if (dev->construct_step < 1)
dleyna_service_task_add(queue_id, prv_get_search_capabilities,
@@ -1179,6 +1559,7 @@ void dls_device_construct(
dls_device_t *dls_device_new(
dleyna_connector_id_t connection,
GUPnPDeviceProxy *proxy,
+ GUPnPDeviceInfo *device_info,
const gchar *ip_address,
const dleyna_connector_dispatch_cb_t *dispatch_table,
GHashTable *property_map,
@@ -1200,7 +1581,8 @@ dls_device_t *dls_device_new(
dev->contexts = g_ptr_array_new_with_free_func(prv_context_delete);
dev->path = new_path;
- context = dls_device_append_new_context(dev, ip_address, proxy);
+ context = dls_device_append_new_context(dev, ip_address,
+ proxy, device_info);
dls_device_construct(dev, context, connection, dispatch_table,
property_map, queue_id);
@@ -1209,12 +1591,13 @@ dls_device_t *dls_device_new(
}
dls_device_context_t *dls_device_append_new_context(dls_device_t *device,
- const gchar *ip_address,
- GUPnPDeviceProxy *proxy)
+ const gchar *ip_address,
+ GUPnPDeviceProxy *proxy,
+ GUPnPDeviceInfo *device_info)
{
dls_device_context_t *context;
- prv_context_new(ip_address, proxy, device, &context);
+ prv_context_new(ip_address, proxy, device_info, device, &context);
g_ptr_array_add(device->contexts, context);
return context;
@@ -1495,8 +1878,13 @@ void dls_device_get_children(dls_client_t *client,
context = dls_device_get_context(task->target.device, client);
+ cb_data->proxy = context->cds.proxy;
+
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
+ (gpointer *)&cb_data->proxy);
+
cb_data->action =
- gupnp_service_proxy_begin_action(context->service_proxy,
+ gupnp_service_proxy_begin_action(cb_data->proxy,
"Browse",
prv_get_children_cb,
cb_data,
@@ -1517,11 +1905,6 @@ void dls_device_get_children(dls_client_t *client,
sort_by,
NULL);
- cb_data->proxy = context->service_proxy;
-
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
- (gpointer *)&cb_data->proxy);
-
cb_data->cancel_id = g_cancellable_connect(
cb_data->cancellable,
G_CALLBACK(dls_async_task_cancelled_cb),
@@ -1645,7 +2028,7 @@ static void prv_get_all(GUPnPDIDLLiteParser *parser,
}
}
-static gboolean prv_subscribed(const dls_device_t *device)
+static gboolean prv_cds_subscribed(const dls_device_t *device)
{
dls_device_context_t *context;
unsigned int i;
@@ -1653,7 +2036,7 @@ static gboolean prv_subscribed(const dls_device_t *device)
for (i = 0; i < device->contexts->len; ++i) {
context = g_ptr_array_index(device->contexts, i);
- if (context->subscribed) {
+ if (context->cds.subscribed) {
subscribed = TRUE;
break;
}
@@ -1712,7 +2095,7 @@ static void prv_get_system_update_id_for_prop(GUPnPServiceProxy *proxy,
DLEYNA_LOG_DEBUG("Enter");
- if (prv_subscribed(device)) {
+ if (prv_cds_subscribed(device)) {
suid = device->system_update_id;
cb_data->task.result = g_variant_ref_sink(
@@ -1805,7 +2188,7 @@ static void prv_get_system_update_id_for_props(GUPnPServiceProxy *proxy,
DLEYNA_LOG_DEBUG("Enter");
- if (prv_subscribed(device)) {
+ if (prv_cds_subscribed(device)) {
suid = device->system_update_id;
cb_task_data = &cb_data->ut.get_all;
@@ -2135,6 +2518,7 @@ static void prv_get_all_ms2spec_props_cb(GUPnPServiceProxy *proxy,
goto no_complete;
} else if (cb_data->task.type == DLS_TASK_GET_ALL_PROPS &&
cb_task_data->device_object) {
+
prv_get_system_update_id_for_props(proxy,
cb_data->task.target.device,
cb_data);
@@ -2193,7 +2577,7 @@ static void prv_get_all_ms2spec_props(dls_device_context_t *context,
}
cb_data->action = gupnp_service_proxy_begin_action(
- context->service_proxy, "Browse",
+ context->cds.proxy, "Browse",
prv_get_all_ms2spec_props_cb, cb_data,
"ObjectID", G_TYPE_STRING, task->target.id,
"BrowseFlag", G_TYPE_STRING, "BrowseMetadata",
@@ -2203,9 +2587,9 @@ static void prv_get_all_ms2spec_props(dls_device_context_t *context,
"SortCriteria", G_TYPE_STRING,
"", NULL);
- cb_data->proxy = context->service_proxy;
+ cb_data->proxy = context->cds.proxy;
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
(gpointer *)&cb_data->proxy);
cb_data->cancel_id = g_cancellable_connect(
@@ -2246,15 +2630,16 @@ void dls_device_get_all_props(dls_client_t *client,
if (!strcmp(task_data->interface_name,
DLEYNA_SERVER_INTERFACE_MEDIA_DEVICE)) {
if (root_object) {
- dls_props_add_device(
- (GUPnPDeviceInfo *)context->device_proxy,
- task->target.device,
- cb_task_data->vb);
-
+ dls_props_add_device((GUPnPDeviceInfo *)
+ context->device_proxy,
+ context->device_info,
+ context->ems.proxy,
+ task->target.device,
+ cb_task_data->vb);
prv_get_system_update_id_for_props(
- context->service_proxy,
- task->target.device,
- cb_data);
+ context->cds.proxy,
+ task->target.device,
+ cb_data);
} else {
cb_data->error =
g_error_new(DLEYNA_SERVER_ERROR,
@@ -2269,11 +2654,12 @@ void dls_device_get_all_props(dls_client_t *client,
prv_get_all_ms2spec_props(context, cb_data);
} else {
if (root_object)
- dls_props_add_device(
- (GUPnPDeviceInfo *)context->device_proxy,
- task->target.device,
- cb_task_data->vb);
-
+ dls_props_add_device((GUPnPDeviceInfo *)
+ context->device_proxy,
+ context->device_info,
+ context->ems.proxy,
+ task->target.device,
+ cb_task_data->vb);
prv_get_all_ms2spec_props(context, cb_data);
}
@@ -2599,8 +2985,13 @@ static void prv_get_ms2spec_prop(dls_device_context_t *context,
goto on_error;
}
+ cb_data->proxy = context->cds.proxy;
+
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
+ (gpointer *)&cb_data->proxy);
+
cb_data->action = gupnp_service_proxy_begin_action(
- context->service_proxy, "Browse",
+ cb_data->proxy, "Browse",
prv_get_ms2spec_prop_cb,
cb_data,
"ObjectID", G_TYPE_STRING, cb_data->task.target.id,
@@ -2613,11 +3004,6 @@ static void prv_get_ms2spec_prop(dls_device_context_t *context,
"",
NULL);
- cb_data->proxy = context->service_proxy;
-
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
- (gpointer *)&cb_data->proxy);
-
cb_data->cancel_id = g_cancellable_connect(
cb_data->cancellable,
G_CALLBACK(dls_async_task_cancelled_cb),
@@ -2656,23 +3042,25 @@ void dls_device_get_prop(dls_client_t *client,
task_data->prop_name,
DLS_INTERFACE_PROP_ESV_SYSTEM_UPDATE_ID)) {
prv_get_system_update_id_for_prop(
- context->service_proxy,
+ context->cds.proxy,
task->target.device,
cb_data);
} else if (!strcmp(
task_data->prop_name,
DLS_INTERFACE_PROP_SV_SERVICE_RESET_TOKEN)) {
prv_get_sr_token_for_prop(
- context->service_proxy,
+ context->cds.proxy,
task->target.device,
cb_data);
} else {
cb_data->task.result =
dls_props_get_device_prop(
- (GUPnPDeviceInfo *)
- context->device_proxy,
- task->target.device,
- task_data->prop_name);
+ (GUPnPDeviceInfo *)
+ context->device_proxy,
+ context->device_info,
+ context->ems.proxy,
+ task->target.device,
+ task_data->prop_name);
if (!cb_data->task.result)
cb_data->error = g_error_new(
@@ -2702,7 +3090,7 @@ void dls_device_get_prop(dls_client_t *client,
task_data->prop_name,
DLS_INTERFACE_PROP_ESV_SYSTEM_UPDATE_ID)) {
prv_get_system_update_id_for_prop(
- context->service_proxy,
+ context->cds.proxy,
task->target.device,
cb_data);
complete = TRUE;
@@ -2710,17 +3098,20 @@ void dls_device_get_prop(dls_client_t *client,
task_data->prop_name,
DLS_INTERFACE_PROP_SV_SERVICE_RESET_TOKEN)) {
prv_get_sr_token_for_prop(
- context->service_proxy,
+ context->cds.proxy,
task->target.device,
cb_data);
complete = TRUE;
} else {
cb_data->task.result =
- dls_props_get_device_prop(
+ dls_props_get_device_prop(
(GUPnPDeviceInfo *)
context->device_proxy,
+ context->device_info,
+ context->ems.proxy,
task->target.device,
task_data->prop_name);
+
if (cb_data->task.result) {
(void) g_idle_add(
dls_async_task_complete,
@@ -2919,8 +3310,13 @@ void dls_device_search(dls_client_t *client,
context = dls_device_get_context(task->target.device, client);
+ cb_data->proxy = context->cds.proxy;
+
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
+ (gpointer *)&cb_data->proxy);
+
cb_data->action = gupnp_service_proxy_begin_action(
- context->service_proxy, "Search",
+ cb_data->proxy, "Search",
prv_search_cb,
cb_data,
"ContainerID", G_TYPE_STRING, task->target.id,
@@ -2931,11 +3327,6 @@ void dls_device_search(dls_client_t *client,
"SortCriteria", G_TYPE_STRING, sort_by,
NULL);
- cb_data->proxy = context->service_proxy;
-
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
- (gpointer *)&cb_data->proxy);
-
cb_data->cancel_id = g_cancellable_connect(
cb_data->cancellable,
G_CALLBACK(dls_async_task_cancelled_cb),
@@ -3383,7 +3774,7 @@ void dls_device_browse_objects(dls_client_t *client, dls_task_t *task)
dleyna_task_queue_set_user_data(queue_id, task);
context = dls_device_get_context(task->target.device, client);
- cb_data->proxy = context->service_proxy;
+ cb_data->proxy = context->cds.proxy;
cb_task_data = &cb_data->ut.browse_objects;
cb_task_data->queue_id = queue_id;
@@ -3391,7 +3782,7 @@ void dls_device_browse_objects(dls_client_t *client, dls_task_t *task)
cb_task_data->objects_id = objs;
cb_task_data->object_count = length;
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
(gpointer *)&cb_data->proxy);
cb_data->cancel_id = g_cancellable_connect(
@@ -3428,8 +3819,13 @@ void dls_device_get_resource(dls_client_t *client,
cb_task_data->prop_func = G_CALLBACK(prv_get_resource);
cb_task_data->device_object = FALSE;
+ cb_data->proxy = context->cds.proxy;
+
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
+ (gpointer *)&cb_data->proxy);
+
cb_data->action = gupnp_service_proxy_begin_action(
- context->service_proxy, "Browse",
+ cb_data->proxy, "Browse",
prv_get_all_ms2spec_props_cb, cb_data,
"ObjectID", G_TYPE_STRING, task->target.id,
"BrowseFlag", G_TYPE_STRING, "BrowseMetadata",
@@ -3439,11 +3835,6 @@ void dls_device_get_resource(dls_client_t *client,
"SortCriteria", G_TYPE_STRING,
"", NULL);
- cb_data->proxy = context->service_proxy;
-
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
- (gpointer *)&cb_data->proxy);
-
cb_data->cancel_id = g_cancellable_connect(
cb_data->cancellable,
G_CALLBACK(dls_async_task_cancelled_cb),
@@ -4127,18 +4518,18 @@ void dls_device_upload(dls_client_t *client,
DLEYNA_LOG_DEBUG("DIDL: %s", didl);
DLEYNA_LOG_DEBUG_NL();
+ cb_data->proxy = context->cds.proxy;
+
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
+ (gpointer *)&cb_data->proxy);
+
cb_data->action = gupnp_service_proxy_begin_action(
- context->service_proxy, "CreateObject",
+ cb_data->proxy, "CreateObject",
prv_create_object_upload_cb, cb_data,
"ContainerID", G_TYPE_STRING, parent_id,
"Elements", G_TYPE_STRING, didl,
NULL);
- cb_data->proxy = context->service_proxy;
-
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
- (gpointer *)&cb_data->proxy);
-
cb_data->cancel_id = g_cancellable_connect(
cb_data->cancellable,
G_CALLBACK(dls_async_task_cancelled_cb),
@@ -4280,17 +4671,17 @@ void dls_device_delete_object(dls_client_t *client,
context = dls_device_get_context(task->target.device, client);
+ cb_data->proxy = context->cds.proxy;
+
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
+ (gpointer *)&cb_data->proxy);
+
cb_data->action = gupnp_service_proxy_begin_action(
- context->service_proxy, "DestroyObject",
+ cb_data->proxy, "DestroyObject",
prv_destroy_object_cb, cb_data,
"ObjectID", G_TYPE_STRING, task->target.id,
NULL);
- cb_data->proxy = context->service_proxy;
-
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
- (gpointer *)&cb_data->proxy);
-
cb_data->cancel_id = g_cancellable_connect(cb_data->cancellable,
G_CALLBACK(dls_async_task_cancelled_cb),
cb_data, NULL);
@@ -4322,18 +4713,18 @@ void dls_device_create_container(dls_client_t *client,
DLEYNA_LOG_DEBUG("DIDL: %s", didl);
+ cb_data->proxy = context->cds.proxy;
+
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
+ (gpointer *)&cb_data->proxy);
+
cb_data->action = gupnp_service_proxy_begin_action(
- context->service_proxy, "CreateObject",
+ cb_data->proxy, "CreateObject",
prv_create_container_cb, cb_data,
"ContainerID", G_TYPE_STRING, parent_id,
"Elements", G_TYPE_STRING, didl,
NULL);
- cb_data->proxy = context->service_proxy;
-
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
- (gpointer *)&cb_data->proxy);
-
cb_data->cancel_id = g_cancellable_connect(
cb_data->cancellable,
G_CALLBACK(dls_async_task_cancelled_cb),
@@ -4670,8 +5061,13 @@ void dls_device_update_object(dls_client_t *client,
context = dls_device_get_context(task->target.device, client);
+ cb_data->proxy = context->cds.proxy;
+
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
+ (gpointer *)&cb_data->proxy);
+
cb_data->action = gupnp_service_proxy_begin_action(
- context->service_proxy, "Browse",
+ cb_data->proxy, "Browse",
prv_update_object_browse_cb, cb_data,
"ObjectID", G_TYPE_STRING, task->target.id,
"BrowseFlag", G_TYPE_STRING, "BrowseMetadata",
@@ -4681,11 +5077,6 @@ void dls_device_update_object(dls_client_t *client,
"SortCriteria", G_TYPE_STRING,
"", NULL);
- cb_data->proxy = context->service_proxy;
-
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
- (gpointer *)&cb_data->proxy);
-
cb_data->cancel_id = g_cancellable_connect(cb_data->cancellable,
G_CALLBACK(dls_async_task_cancelled_cb),
cb_data, NULL);
@@ -4750,8 +5141,13 @@ void dls_device_get_object_metadata(dls_client_t *client,
context = dls_device_get_context(task->target.device, client);
+ cb_data->proxy = context->cds.proxy;
+
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
+ (gpointer *)&cb_data->proxy);
+
cb_data->action = gupnp_service_proxy_begin_action(
- context->service_proxy, "Browse",
+ cb_data->proxy, "Browse",
prv_get_object_metadata_cb, cb_data,
"ObjectID", G_TYPE_STRING, task->target.id,
"BrowseFlag", G_TYPE_STRING, "BrowseMetadata",
@@ -4761,11 +5157,6 @@ void dls_device_get_object_metadata(dls_client_t *client,
"SortCriteria", G_TYPE_STRING, "",
NULL);
- cb_data->proxy = context->service_proxy;
-
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
- (gpointer *)&cb_data->proxy);
-
cb_data->cancel_id = g_cancellable_connect(cb_data->cancellable,
G_CALLBACK(dls_async_task_cancelled_cb),
cb_data, NULL);
@@ -4852,18 +5243,18 @@ void dls_device_create_reference(dls_client_t *client,
context = dls_device_get_context(task->target.device, client);
+ cb_data->proxy = context->cds.proxy;
+
+ g_object_add_weak_pointer((G_OBJECT(context->cds.proxy)),
+ (gpointer *)&cb_data->proxy);
+
cb_data->action = gupnp_service_proxy_begin_action(
- context->service_proxy, "CreateReference",
+ cb_data->proxy, "CreateReference",
prv_create_reference_cb, cb_data,
"ContainerID", G_TYPE_STRING, task->target.id,
"ObjectID", G_TYPE_STRING, i_id,
NULL);
- cb_data->proxy = context->service_proxy;
-
- g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
- (gpointer *)&cb_data->proxy);
-
cb_data->cancel_id = g_cancellable_connect(
cb_data->cancellable,
G_CALLBACK(dls_async_task_cancelled_cb),
@@ -4949,7 +5340,6 @@ out:
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;
@@ -4962,9 +5352,9 @@ void dls_device_get_icon(dls_client_t *client,
}
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,
+ url = gupnp_device_info_get_icon_url(context->device_info,
+ NULL, -1, -1, -1, FALSE,
&device->icon.mime_type, NULL,
NULL, NULL);
if (url == NULL) {
@@ -5008,3 +5398,46 @@ end:
(void) g_idle_add(dls_async_task_complete, cb_data);
}
+
+void dls_device_wake(dls_client_t *client, dls_task_t *task)
+{
+ dls_device_context_t *context;
+ dls_async_task_t *cb_data = (dls_async_task_t *)task;
+ dls_device_t *device = task->target.device;
+ dls_network_if_info_t *info;
+ GList *next;
+
+ DLEYNA_LOG_DEBUG("Enter");
+
+ context = dls_device_get_context(device, client);
+
+ if ((context->ems.proxy == NULL) ||
+ (context->network_if_info == NULL)) {
+ cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+ DLEYNA_ERROR_NOT_SUPPORTED,
+ "WOL is not supported");
+ goto end;
+ }
+
+ info = context->network_if_info;
+
+ DLEYNA_LOG_DEBUG("MacAddress = %s", info->mac_address);
+ DLEYNA_LOG_DEBUG("DeviceUUID = %s", info->device_uuid);
+ DLEYNA_LOG_DEBUG("NetworkInterfaceMode = %s", info->network_if_mode);
+ DLEYNA_LOG_DEBUG("WakeOnPattern = %s", info->wake_on_pattern);
+ DLEYNA_LOG_DEBUG("WakeSupportedTransport = %s", info->wake_transport);
+
+ next = info->ip_addresses;
+ while (next != NULL) {
+ DLEYNA_LOG_DEBUG("IpAddress = %s", (gchar *)next->data);
+
+ next = g_list_next(next);
+ }
+
+ DLEYNA_LOG_DEBUG("context IpAddress = %s", context->ip_address);
+
+end:
+ (void) g_idle_add(dls_async_task_complete, cb_data);
+
+ DLEYNA_LOG_DEBUG("Exit");
+}
diff --git a/libdleyna/server/device.h b/libdleyna/server/device.h
index 6771464..891351c 100644
--- a/libdleyna/server/device.h
+++ b/libdleyna/server/device.h
@@ -32,13 +32,32 @@
#include "client.h"
#include "props.h"
+typedef struct dls_network_if_info_t_ dls_network_if_info_t;
+struct dls_network_if_info_t_ {
+ gchar *system_name;
+ gchar *mac_address;
+ gchar *device_uuid;
+ gchar *network_if_mode;
+ gchar *wake_on_pattern;
+ gchar *wake_transport;
+ GList *ip_addresses;
+};
+
+typedef struct dls_service_t_ dls_service_t;
+struct dls_service_t_ {
+ GUPnPServiceProxy *proxy;
+ gboolean subscribed;
+ guint timeout_id;
+};
+
struct dls_device_context_t_ {
gchar *ip_address;
GUPnPDeviceProxy *device_proxy;
- GUPnPServiceProxy *service_proxy;
+ GUPnPDeviceInfo *device_info;
dls_device_t *device;
- gboolean subscribed;
- guint timeout_id;
+ dls_service_t cds;
+ dls_service_t ems;
+ dls_network_if_info_t *network_if_info;
};
typedef struct dls_device_icon_t_ dls_device_icon_t;
@@ -66,11 +85,13 @@ struct dls_device_t_ {
gboolean has_last_change;
guint construct_step;
dls_device_icon_t icon;
+ gboolean sleeping;
};
dls_device_context_t *dls_device_append_new_context(dls_device_t *device,
- const gchar *ip_address,
- GUPnPDeviceProxy *proxy);
+ const gchar *ip_address,
+ GUPnPDeviceProxy *proxy,
+ GUPnPDeviceInfo *device_info);
void dls_device_delete(void *device);
void dls_device_unsubscribe(void *device);
@@ -86,6 +107,7 @@ void dls_device_construct(
dls_device_t *dls_device_new(
dleyna_connector_id_t connection,
GUPnPDeviceProxy *proxy,
+ GUPnPDeviceInfo *device_info,
const gchar *ip_address,
const dleyna_connector_dispatch_cb_t *dispatch_table,
GHashTable *filter_map,
@@ -120,7 +142,7 @@ void dls_device_get_resource(dls_client_t *client,
dls_task_t *task,
const gchar *upnp_filter);
-void dls_device_subscribe_to_contents_change(dls_device_t *device);
+void dls_device_subscribe_to_service_changes(dls_device_t *device);
void dls_device_upload(dls_client_t *client,
dls_task_t *task, const gchar *parent_id);
@@ -152,4 +174,7 @@ void dls_device_create_reference(dls_client_t *client,
void dls_device_get_icon(dls_client_t *client,
dls_task_t *task);
+void dls_device_wake(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 3a2a6a4..f955db2 100644
--- a/libdleyna/server/interface.h
+++ b/libdleyna/server/interface.h
@@ -85,6 +85,7 @@ enum dls_interface_type_ {
/* Device Properties */
#define DLS_INTERFACE_PROP_LOCATION "Location"
#define DLS_INTERFACE_PROP_UDN "UDN"
+#define DLS_INTERFACE_PROP_ROOT_UDN "RootUDN"
#define DLS_INTERFACE_PROP_DEVICE_TYPE "DeviceType"
#define DLS_INTERFACE_PROP_FRIENDLY_NAME "FriendlyName"
#define DLS_INTERFACE_PROP_MANUFACTURER "Manufacturer"
@@ -96,6 +97,7 @@ enum dls_interface_type_ {
#define DLS_INTERFACE_PROP_SERIAL_NUMBER "SerialNumber"
#define DLS_INTERFACE_PROP_PRESENTATION_URL "PresentationURL"
#define DLS_INTERFACE_PROP_ICON_URL "IconURL"
+#define DLS_INTERFACE_PROP_SLEEPING "Sleeping"
#define DLS_INTERFACE_PROP_SV_DLNA_CAPABILITIES "DLNACaps"
#define DLS_INTERFACE_PROP_SV_SEARCH_CAPABILITIES "SearchCaps"
#define DLS_INTERFACE_PROP_SV_SORT_CAPABILITIES "SortCaps"
@@ -215,6 +217,7 @@ enum dls_interface_type_ {
#define DLS_INTERFACE_ICON_BYTES "Bytes"
#define DLS_INTERFACE_MIME_TYPE "MimeType"
#define DLS_INTERFACE_REQ_MIME_TYPE "RequestedMimeType"
+#define DLS_INTERFACE_WAKE "Wake"
#define DLS_INTERFACE_GET_METADATA "GetMetaData"
#define DLS_INTERFACE_METADATA "MetaData"
diff --git a/libdleyna/server/props.c b/libdleyna/server/props.c
index c63ce30..4196e68 100644
--- a/libdleyna/server/props.c
+++ b/libdleyna/server/props.c
@@ -715,7 +715,9 @@ static GVariant *prv_get_artists_prop(GList *list)
return g_variant_builder_end(&vb);
}
-void dls_props_add_device(GUPnPDeviceInfo *proxy,
+void dls_props_add_device(GUPnPDeviceInfo *root_proxy,
+ GUPnPDeviceInfo *proxy,
+ GUPnPServiceProxy *ems_proxy,
const dls_device_t *device,
GVariantBuilder *vb)
{
@@ -729,6 +731,10 @@ void dls_props_add_device(GUPnPDeviceInfo *proxy,
prv_add_string_prop(vb, DLS_INTERFACE_PROP_UDN,
gupnp_device_info_get_udn(proxy));
+ if (proxy != root_proxy)
+ prv_add_string_prop(vb, DLS_INTERFACE_PROP_ROOT_UDN,
+ gupnp_device_info_get_udn(root_proxy));
+
prv_add_string_prop(vb, DLS_INTERFACE_PROP_DEVICE_TYPE,
gupnp_device_info_get_device_type(proxy));
@@ -802,9 +808,15 @@ void dls_props_add_device(GUPnPDeviceInfo *proxy,
g_variant_builder_add(vb, "{sv}",
DLS_INTERFACE_PROP_SV_FEATURE_LIST,
device->feature_list);
+
+ if (ems_proxy != NULL)
+ prv_add_bool_prop(vb, DLS_INTERFACE_PROP_SLEEPING,
+ device->sleeping);
}
-GVariant *dls_props_get_device_prop(GUPnPDeviceInfo *proxy,
+GVariant *dls_props_get_device_prop(GUPnPDeviceInfo *root_proxy,
+ GUPnPDeviceInfo *proxy,
+ GUPnPServiceProxy *ems_proxy,
const dls_device_t *device,
const gchar *prop)
{
@@ -818,6 +830,9 @@ GVariant *dls_props_get_device_prop(GUPnPDeviceInfo *proxy,
str = gupnp_device_info_get_location(proxy);
} else if (!strcmp(DLS_INTERFACE_PROP_UDN, prop)) {
str = gupnp_device_info_get_udn(proxy);
+ } else if (!strcmp(DLS_INTERFACE_PROP_ROOT_UDN, prop)) {
+ if (proxy != root_proxy)
+ str = gupnp_device_info_get_udn(root_proxy);
} else if (!strcmp(DLS_INTERFACE_PROP_DEVICE_TYPE, prop)) {
str = gupnp_device_info_get_device_type(proxy);
} else if (!strcmp(DLS_INTERFACE_PROP_FRIENDLY_NAME, prop)) {
@@ -900,6 +915,16 @@ GVariant *dls_props_get_device_prop(GUPnPDeviceInfo *proxy,
DLEYNA_LOG_DEBUG("Prop %s = %s", prop, copy);
#endif
}
+ } else if (!strcmp(DLS_INTERFACE_PROP_SLEEPING, prop)) {
+ if (ems_proxy != NULL) {
+ retval = g_variant_ref_sink(
+ g_variant_new_boolean(device->sleeping));
+ }
+
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+ DLEYNA_LOG_DEBUG("Prop %s = %s", prop,
+ device->sleeping ? "TRUE":"FALSE");
+#endif
}
if (!retval) {
diff --git a/libdleyna/server/props.h b/libdleyna/server/props.h
index 72cff1b..41f66b0 100644
--- a/libdleyna/server/props.h
+++ b/libdleyna/server/props.h
@@ -93,11 +93,15 @@ gboolean dls_props_parse_update_filter(GHashTable *filter_map,
dls_upnp_prop_mask *mask,
gchar **upnp_filter);
-void dls_props_add_device(GUPnPDeviceInfo *proxy,
+void dls_props_add_device(GUPnPDeviceInfo *root_proxy,
+ GUPnPDeviceInfo *proxy,
+ GUPnPServiceProxy *ems_proxy,
const dls_device_t *device,
GVariantBuilder *vb);
-GVariant *dls_props_get_device_prop(GUPnPDeviceInfo *proxy,
+GVariant *dls_props_get_device_prop(GUPnPDeviceInfo *root_proxy,
+ GUPnPDeviceInfo *proxy,
+ GUPnPServiceProxy *ems_proxy,
const dls_device_t *device,
const gchar *prop);
diff --git a/libdleyna/server/server.c b/libdleyna/server/server.c
index 5a30500..5367252 100644
--- a/libdleyna/server/server.c
+++ b/libdleyna/server/server.c
@@ -439,6 +439,8 @@ static const gchar g_server_introspection[] =
" </method>"
" <method name='"DLS_INTERFACE_CANCEL"'>"
" </method>"
+ " <method name='"DLS_INTERFACE_WAKE"'>"
+ " </method>"
" <method name='"DLS_INTERFACE_GET_ICON"'>"
" <arg type='s' name='"DLS_INTERFACE_REQ_MIME_TYPE"'"
" direction='in'/>"
@@ -483,6 +485,8 @@ static const gchar g_server_introspection[] =
" access='read'/>"
" <property type='s' name='"DLS_INTERFACE_PROP_ICON_URL"'"
" access='read'/>"
+ " <property type='b' name='"DLS_INTERFACE_PROP_SLEEPING"'"
+ " access='read'/>"
" <property type='a{sv}'name='"
DLS_INTERFACE_PROP_SV_DLNA_CAPABILITIES"'"
" access='read'/>"
@@ -547,7 +551,7 @@ static void prv_process_sync_task(dls_task_t *task)
dls_task_complete(task);
break;
case DLS_TASK_GET_SERVERS:
- task->result = dls_upnp_get_server_ids(g_context.upnp);
+ task->result = dls_upnp_get_device_ids(g_context.upnp);
dls_task_complete(task);
break;
case DLS_TASK_RESCAN:
@@ -699,6 +703,10 @@ static void prv_process_async_task(dls_task_t *task)
dls_upnp_get_icon(g_context.upnp, client, task,
prv_async_task_complete);
break;
+ case DLS_TASK_WAKE:
+ dls_upnp_wake(g_context.upnp, client, task,
+ prv_async_task_complete);
+ break;
default:
break;
}
@@ -934,7 +942,7 @@ gboolean dls_server_get_object_info(const gchar *object_path,
}
*device = dls_device_from_path(*root_path,
- dls_upnp_get_server_udn_map(g_context.upnp));
+ dls_upnp_get_device_udn_map(g_context.upnp));
if (*device == NULL) {
DLEYNA_LOG_WARNING("Cannot locate device for %s", *root_path);
@@ -1185,6 +1193,8 @@ static void prv_device_method_call(dleyna_connector_id_t conn,
} else if (!strcmp(method, DLS_INTERFACE_BROWSE_OBJECTS)) {
task = dls_task_browse_objects_new(invocation, object,
parameters, &error);
+ } else if (!strcmp(method, DLS_INTERFACE_WAKE)) {
+ task = dls_task_wake_new(invocation, object, &error);
} else if (!strcmp(method, DLS_INTERFACE_CANCEL)) {
task = NULL;
diff --git a/libdleyna/server/task.c b/libdleyna/server/task.c
index 1ad4108..312efc0 100644
--- a/libdleyna/server/task.c
+++ b/libdleyna/server/task.c
@@ -97,6 +97,8 @@ static void prv_delete(dls_task_t *task)
g_free(task->ut.get_icon.resolution);
g_free(task->ut.get_icon.mime_type);
break;
+ case DLS_TASK_WAKE:
+ break;
default:
break;
}
@@ -658,6 +660,17 @@ finished:
return task;
}
+dls_task_t *dls_task_wake_new(dleyna_connector_msg_id_t invocation,
+ const gchar *path, GError **error)
+{
+ dls_task_t *task;
+
+ task = prv_m2spec_task_new(DLS_TASK_WAKE, invocation, path,
+ NULL, error, FALSE);
+
+ 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 a06b3e2..6642e8d 100644
--- a/libdleyna/server/task.h
+++ b/libdleyna/server/task.h
@@ -57,7 +57,8 @@ enum dls_task_type_t_ {
DLS_TASK_GET_ICON,
DLS_TASK_MANAGER_GET_ALL_PROPS,
DLS_TASK_MANAGER_GET_PROP,
- DLS_TASK_MANAGER_SET_PROP
+ DLS_TASK_MANAGER_SET_PROP,
+ DLS_TASK_WAKE
};
typedef enum dls_task_type_t_ dls_task_type_t;
@@ -309,6 +310,10 @@ dls_task_t *dls_task_manager_set_prop_new(dleyna_connector_msg_id_t invocation,
GVariant *parameters,
GError **error);
+dls_task_t *dls_task_wake_new(dleyna_connector_msg_id_t invocation,
+ const gchar *path,
+ 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 68338e6..7301e61 100644
--- a/libdleyna/server/upnp.c
+++ b/libdleyna/server/upnp.c
@@ -38,6 +38,8 @@
#include "sort.h"
#include "upnp.h"
+#define DLS_DMS_DEVICE_TYPE "urn:schemas-upnp-org:device:MediaServer:"
+
struct dls_upnp_t_ {
dleyna_connector_id_t connection;
const dleyna_connector_dispatch_cb_t *interface_info;
@@ -47,8 +49,8 @@ struct dls_upnp_t_ {
dls_upnp_callback_t lost_server;
GUPnPContextManager *context_manager;
void *user_data;
- GHashTable *server_udn_map;
- GHashTable *server_uc_map;
+ GHashTable *device_udn_map;
+ GHashTable *device_uc_map;
guint counter;
};
@@ -84,13 +86,13 @@ static void prv_device_chain_end(gboolean cancelled, gpointer data)
goto on_clear;
DLEYNA_LOG_DEBUG("Notify new server available: %s", device->path);
- g_hash_table_insert(priv_t->upnp->server_udn_map, g_strdup(priv_t->udn),
+ g_hash_table_insert(priv_t->upnp->device_udn_map, g_strdup(priv_t->udn),
device);
priv_t->upnp->found_server(device->path, priv_t->upnp->user_data);
on_clear:
- g_hash_table_remove(priv_t->upnp->server_uc_map, priv_t->udn);
+ g_hash_table_remove(priv_t->upnp->device_uc_map, priv_t->udn);
if (cancelled)
dls_device_delete(device);
@@ -106,7 +108,7 @@ static void prv_device_context_switch_end(gboolean cancelled, gpointer data)
DLEYNA_LOG_DEBUG("Enter");
- g_hash_table_remove(priv_t->upnp->server_uc_map, priv_t->udn);
+ g_hash_table_remove(priv_t->upnp->device_uc_map, priv_t->udn);
prv_device_new_free(priv_t);
DLEYNA_LOG_DEBUG("Exit");
@@ -146,10 +148,49 @@ static void prv_update_device_context(prv_device_new_ct_t *priv_t,
priv_t->queue_id = queue_id;
priv_t->device = device;
- g_hash_table_insert(upnp->server_uc_map, g_strdup(udn), priv_t);
+ g_hash_table_insert(upnp->device_uc_map, g_strdup(udn), priv_t);
+}
+
+static GUPnPDeviceInfo *prv_lookup_dms_child_device(GUPnPDeviceInfo *proxy)
+{
+ GList *child_devices;
+ GList *next;
+ const gchar *device_type;
+ GUPnPDeviceInfo *info = NULL;
+ GUPnPDeviceInfo *child_info = NULL;
+
+ child_devices = gupnp_device_info_list_device_types(proxy);
+
+ next = child_devices;
+ while (next != NULL) {
+ device_type = (gchar *)next->data;
+
+ child_info = gupnp_device_info_get_device(proxy, device_type);
+
+ if (g_str_has_prefix(device_type, DLS_DMS_DEVICE_TYPE)) {
+ break;
+ } else {
+ info = prv_lookup_dms_child_device(child_info);
+
+ g_object_unref(child_info);
+ child_info = NULL;
+
+ if (info != NULL) {
+ child_info = info;
+
+ break;
+ }
+ }
+
+ next = g_list_next(next);
+ }
+
+ g_list_free_full(child_devices, (GDestroyNotify)g_free);
+
+ return child_info;
}
-static void prv_server_available_cb(GUPnPControlPoint *cp,
+static void prv_device_available_cb(GUPnPControlPoint *cp,
GUPnPDeviceProxy *proxy,
gpointer user_data)
{
@@ -161,8 +202,11 @@ static void prv_server_available_cb(GUPnPControlPoint *cp,
const dleyna_task_queue_key_t *queue_id;
unsigned int i;
prv_device_new_ct_t *priv_t;
+ GUPnPDeviceInfo *device_proxy = (GUPnPDeviceInfo *)proxy;
+ GUPnPDeviceInfo *device_info = NULL;
+ const gchar *device_type;
- udn = gupnp_device_info_get_udn((GUPnPDeviceInfo *)proxy);
+ udn = gupnp_device_info_get_udn(device_proxy);
ip_address = gupnp_context_get_host_ip(
gupnp_control_point_get_context(cp));
@@ -173,10 +217,21 @@ static void prv_server_available_cb(GUPnPControlPoint *cp,
DLEYNA_LOG_DEBUG("UDN %s", udn);
DLEYNA_LOG_DEBUG("IP Address %s", ip_address);
- device = g_hash_table_lookup(upnp->server_udn_map, udn);
+ device_type = gupnp_device_info_get_device_type(device_proxy);
+
+ if (!g_str_has_prefix(device_type, DLS_DMS_DEVICE_TYPE)) {
+ device_info = prv_lookup_dms_child_device(device_proxy);
+
+ if (device_info == NULL)
+ goto on_error;
+ } else {
+ device_info = device_proxy;
+ }
+
+ device = g_hash_table_lookup(upnp->device_udn_map, udn);
if (!device) {
- priv_t = g_hash_table_lookup(upnp->server_uc_map, udn);
+ priv_t = g_hash_table_lookup(upnp->device_uc_map, udn);
if (priv_t)
device = priv_t->device;
@@ -188,7 +243,10 @@ static void prv_server_available_cb(GUPnPControlPoint *cp,
queue_id = prv_create_device_queue(&priv_t);
- device = dls_device_new(upnp->connection, proxy, ip_address,
+ device = dls_device_new(upnp->connection,
+ proxy,
+ device_info,
+ ip_address,
upnp->interface_info,
upnp->property_map, upnp->counter,
queue_id);
@@ -208,8 +266,10 @@ static void prv_server_available_cb(GUPnPControlPoint *cp,
if (i == device->contexts->len) {
DLEYNA_LOG_DEBUG("Adding Context");
- (void) dls_device_append_new_context(device, ip_address,
- proxy);
+ (void) dls_device_append_new_context(device,
+ ip_address,
+ proxy,
+ device_info);
}
DLEYNA_LOG_DEBUG_NL();
@@ -220,17 +280,17 @@ on_error:
return;
}
-static gboolean prv_subscribe_to_contents_change(gpointer user_data)
+static gboolean prv_subscribe_to_service_changes(gpointer user_data)
{
dls_device_t *device = user_data;
device->timeout_id = 0;
- dls_device_subscribe_to_contents_change(device);
+ dls_device_subscribe_to_service_changes(device);
return FALSE;
}
-static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
+static void prv_device_unavailable_cb(GUPnPControlPoint *cp,
GUPnPDeviceProxy *proxy,
gpointer user_data)
{
@@ -259,10 +319,10 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
DLEYNA_LOG_DEBUG("UDN %s", udn);
DLEYNA_LOG_DEBUG("IP Address %s", ip_address);
- device = g_hash_table_lookup(upnp->server_udn_map, udn);
+ device = g_hash_table_lookup(upnp->device_udn_map, udn);
if (!device) {
- priv_t = g_hash_table_lookup(upnp->server_uc_map, udn);
+ priv_t = g_hash_table_lookup(upnp->device_uc_map, udn);
if (priv_t) {
device = priv_t->device;
@@ -284,7 +344,7 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
if (i >= device->contexts->len)
goto on_error;
- subscribed = context->subscribed;
+ subscribed = (context->cds.subscribed || context->ems.subscribed);
if (under_construction)
construction_ctx = !strcmp(context->ip_address,
priv_t->ip_address);
@@ -295,7 +355,7 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
if (!under_construction) {
DLEYNA_LOG_DEBUG("Last Context lost. Delete device");
upnp->lost_server(device->path, upnp->user_data);
- g_hash_table_remove(upnp->server_udn_map, udn);
+ g_hash_table_remove(upnp->device_udn_map, udn);
} else {
DLEYNA_LOG_WARNING(
"Device under construction. Cancelling");
@@ -307,7 +367,7 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
"Device under construction. Switching context");
/* Cancel previous contruction task chain */
- g_hash_table_remove(priv_t->upnp->server_uc_map, priv_t->udn);
+ g_hash_table_remove(priv_t->upnp->device_uc_map, priv_t->udn);
dleyna_task_queue_set_finally(priv_t->queue_id,
prv_device_context_switch_end);
dleyna_task_processor_cancel_queue(priv_t->queue_id);
@@ -330,7 +390,7 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
DLEYNA_LOG_DEBUG("Subscribe on new context");
device->timeout_id = g_timeout_add_seconds(1,
- prv_subscribe_to_contents_change,
+ prv_subscribe_to_service_changes,
device);
}
@@ -351,13 +411,13 @@ static void prv_on_context_available(GUPnPContextManager *context_manager,
cp = gupnp_control_point_new(
context,
- "urn:schemas-upnp-org:device:MediaServer:1");
+ "upnp:rootdevice");
g_signal_connect(cp, "device-proxy-available",
- G_CALLBACK(prv_server_available_cb), upnp);
+ G_CALLBACK(prv_device_available_cb), upnp);
g_signal_connect(cp, "device-proxy-unavailable",
- G_CALLBACK(prv_server_unavailable_cb), upnp);
+ G_CALLBACK(prv_device_unavailable_cb), upnp);
gssdp_resource_browser_set_active(GSSDP_RESOURCE_BROWSER(cp), TRUE);
gupnp_context_manager_manage_control_point(upnp->context_manager, cp);
@@ -378,11 +438,11 @@ dls_upnp_t *dls_upnp_new(dleyna_connector_id_t connection,
upnp->found_server = found_server;
upnp->lost_server = lost_server;
- upnp->server_udn_map = g_hash_table_new_full(g_str_hash, g_str_equal,
+ upnp->device_udn_map = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free,
dls_device_delete);
- upnp->server_uc_map = g_hash_table_new_full(g_str_hash, g_str_equal,
+ upnp->device_uc_map = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, NULL);
dls_prop_maps_new(&upnp->property_map, &upnp->filter_map);
@@ -402,13 +462,13 @@ void dls_upnp_delete(dls_upnp_t *upnp)
g_object_unref(upnp->context_manager);
g_hash_table_unref(upnp->property_map);
g_hash_table_unref(upnp->filter_map);
- g_hash_table_unref(upnp->server_udn_map);
- g_hash_table_unref(upnp->server_uc_map);
+ g_hash_table_unref(upnp->device_udn_map);
+ g_hash_table_unref(upnp->device_uc_map);
g_free(upnp);
}
}
-GVariant *dls_upnp_get_server_ids(dls_upnp_t *upnp)
+GVariant *dls_upnp_get_device_ids(dls_upnp_t *upnp)
{
GVariantBuilder vb;
GHashTableIter iter;
@@ -420,7 +480,7 @@ GVariant *dls_upnp_get_server_ids(dls_upnp_t *upnp)
g_variant_builder_init(&vb, G_VARIANT_TYPE("ao"));
- g_hash_table_iter_init(&iter, upnp->server_udn_map);
+ g_hash_table_iter_init(&iter, upnp->device_udn_map);
while (g_hash_table_iter_next(&iter, NULL, &value)) {
device = value;
DLEYNA_LOG_DEBUG("Have device %s", device->path);
@@ -434,9 +494,9 @@ GVariant *dls_upnp_get_server_ids(dls_upnp_t *upnp)
return retval;
}
-GHashTable *dls_upnp_get_server_udn_map(dls_upnp_t *upnp)
+GHashTable *dls_upnp_get_device_udn_map(dls_upnp_t *upnp)
{
- return upnp->server_udn_map;
+ return upnp->device_udn_map;
}
void dls_upnp_get_children(dls_upnp_t *upnp, dls_client_t *client,
@@ -1088,6 +1148,21 @@ void dls_upnp_get_icon(dls_upnp_t *upnp, dls_client_t *client,
DLEYNA_LOG_DEBUG("Exit");
}
+void dls_upnp_wake(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_wake(client, task);
+
+ DLEYNA_LOG_DEBUG("Exit");
+}
+
void dls_upnp_unsubscribe(dls_upnp_t *upnp)
{
GHashTableIter iter;
@@ -1096,7 +1171,7 @@ void dls_upnp_unsubscribe(dls_upnp_t *upnp)
DLEYNA_LOG_DEBUG("Enter");
- g_hash_table_iter_init(&iter, upnp->server_udn_map);
+ g_hash_table_iter_init(&iter, upnp->device_udn_map);
while (g_hash_table_iter_next(&iter, NULL, &value)) {
device = value;
dls_device_unsubscribe(device);
@@ -1131,11 +1206,11 @@ gboolean dls_upnp_device_context_exist(dls_device_t *device,
goto on_exit;
/* Check if the device still exist */
- result = g_hash_table_find(upnp->server_udn_map, prv_device_find,
+ result = g_hash_table_find(upnp->device_udn_map, prv_device_find,
device);
if (result == NULL)
- if (g_hash_table_find(upnp->server_uc_map, prv_device_uc_find,
+ if (g_hash_table_find(upnp->device_uc_map, prv_device_uc_find,
device) == NULL)
goto on_exit;
diff --git a/libdleyna/server/upnp.h b/libdleyna/server/upnp.h
index 08441c6..b2d9ba1 100644
--- a/libdleyna/server/upnp.h
+++ b/libdleyna/server/upnp.h
@@ -39,9 +39,9 @@ dls_upnp_t *dls_upnp_new(dleyna_connector_id_t connection,
void dls_upnp_delete(dls_upnp_t *upnp);
-GVariant *dls_upnp_get_server_ids(dls_upnp_t *upnp);
+GVariant *dls_upnp_get_device_ids(dls_upnp_t *upnp);
-GHashTable *dls_upnp_get_server_udn_map(dls_upnp_t *upnp);
+GHashTable *dls_upnp_get_device_udn_map(dls_upnp_t *upnp);
void dls_upnp_get_children(dls_upnp_t *upnp, dls_client_t *client,
dls_task_t *task,
@@ -109,6 +109,10 @@ 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_wake(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,
diff --git a/libdleyna/server/xml-util.c b/libdleyna/server/xml-util.c
new file mode 100644
index 0000000..f6ddf6a
--- /dev/null
+++ b/libdleyna/server/xml-util.c
@@ -0,0 +1,133 @@
+/*
+ * dLeyna
+ *
+ * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Christophe Guiraud <christophe.guiraud@intel.com>
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "xml-util.h"
+
+static xmlNode *prv_get_child_node(xmlNode *node, va_list args)
+{
+ const gchar *name;
+
+ name = va_arg(args, const gchar *);
+ while (name != NULL) {
+ node = node->children;
+ while (node != NULL) {
+ if (node->name != NULL &&
+ !strcmp(name, (char *)node->name))
+ break;
+
+ node = node->next;
+ }
+
+ if (node == NULL)
+ break;
+
+ name = va_arg(args, const gchar *);
+ }
+
+ return node;
+}
+
+static GList *prv_get_children_list(xmlNode *node, const gchar *name)
+{
+ GList *child_list = NULL;
+
+ node = node->children;
+ while (node != NULL) {
+ if (node->name != NULL &&
+ !strcmp(name, (char *)node->name))
+ child_list = g_list_prepend(child_list, node);
+
+ node = node->next;
+ }
+
+ return child_list;
+}
+
+GList *xml_util_get_child_string_list_content_by_name(xmlNode *node, ...)
+{
+ xmlChar *content;
+ va_list args;
+ GList *child_list = NULL;
+ GList *next;
+ GList *str_list = NULL;
+ xmlNode *child_list_node;
+ xmlNode *child_node;
+
+ va_start(args, node);
+
+ child_node = prv_get_child_node(node, args);
+
+ va_end(args);
+
+ if (child_node != NULL) {
+ child_list = prv_get_children_list(child_node->parent,
+ (const gchar *)child_node->name);
+ next = child_list;
+ while (next) {
+ child_list_node = (xmlNode *)next->data;
+
+ content = xmlNodeGetContent(child_list_node);
+
+ if (content != NULL) {
+ str_list = g_list_prepend(str_list,
+ g_strdup((gchar *)content));
+
+ xmlFree(content);
+ }
+
+ next = g_list_next(next);
+ }
+
+ g_list_free(child_list);
+ }
+
+ return str_list;
+}
+
+gchar *xml_util_get_child_string_content_by_name(xmlNode *node, ...)
+{
+ xmlChar *content;
+ va_list args;
+ gchar *str = NULL;
+ xmlNode *child_node;
+
+ va_start(args, node);
+
+ child_node = prv_get_child_node(node, args);
+
+ va_end(args);
+
+ if (child_node != NULL) {
+ content = xmlNodeGetContent(child_node);
+
+ if (content != NULL) {
+ str = g_strdup((gchar *)content);
+
+ xmlFree(content);
+ }
+ }
+
+ return str;
+}
diff --git a/libdleyna/server/xml-util.h b/libdleyna/server/xml-util.h
new file mode 100644
index 0000000..d5c72f4
--- /dev/null
+++ b/libdleyna/server/xml-util.h
@@ -0,0 +1,35 @@
+/*
+ * dLeyna
+ *
+ * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Christophe Guiraud <christophe.guiraud@intel.com>
+ *
+ */
+
+
+#ifndef DLS_XML_UTIL_H__
+#define DLS_XML_UTIL_H__
+
+#include <glib.h>
+#include <stdarg.h>
+#include <libxml/tree.h>
+
+GList *xml_util_get_child_string_list_content_by_name(xmlNode *node, ...);
+
+gchar *xml_util_get_child_string_content_by_name(xmlNode *node, ...);
+
+#endif /* DLS_XML_UTIL_H__ */
diff --git a/test/dbus/mediaconsole.py b/test/dbus/mediaconsole.py
index d54bb84..887c1f1 100644
--- a/test/dbus/mediaconsole.py
+++ b/test/dbus/mediaconsole.py
@@ -191,6 +191,9 @@ class Device(Container):
bytes, mime = self._deviceIF.GetIcon(mime_type, resolution)
print "Icon mime type: " + mime
+ def wake(self):
+ return self._deviceIF.Wake()
+
class UPNP(object):
def __init__(self):