summaryrefslogtreecommitdiff
path: root/libdleyna
diff options
context:
space:
mode:
authorRegis Merlino <regis.merlino@intel.com>2013-04-09 15:53:55 +0200
committerMark Ryan <mark.d.ryan@intel.com>2013-04-18 11:40:11 +0200
commit4f1fb6e61ae3c4586dc51f0572e206923be401c5 (patch)
tree71de5ff4b915766f95a36f0eda0e3504e4a83d02 /libdleyna
parentb3698c94b3a60d43ccbc8255839b7e2cdf050773 (diff)
downloaddleyna-renderer-4f1fb6e61ae3c4586dc51f0572e206923be401c5.tar.gz
[Device] Fix device construction
Signed-off-by: Regis Merlino <regis.merlino@intel.com>
Diffstat (limited to 'libdleyna')
-rw-r--r--libdleyna/renderer/device.c60
-rw-r--r--libdleyna/renderer/device.h8
-rw-r--r--libdleyna/renderer/upnp.c101
3 files changed, 133 insertions, 36 deletions
diff --git a/libdleyna/renderer/device.c b/libdleyna/renderer/device.c
index 9ef9f55..62b9f25 100644
--- a/libdleyna/renderer/device.c
+++ b/libdleyna/renderer/device.c
@@ -653,6 +653,8 @@ static void prv_get_protocol_info_cb(GUPnPServiceProxy *proxy,
DLEYNA_LOG_DEBUG("Enter");
+ priv_t->dev->construct_step++;
+
end = gupnp_service_proxy_end_action(proxy, action, &error, "Sink",
G_TYPE_STRING, &result, NULL);
if (!end || (result == NULL)) {
@@ -697,6 +699,7 @@ static GUPnPServiceProxyAction *prv_subscribe(dleyna_service_task_t *task,
device = (dlr_device_t *)dleyna_service_task_get_user_data(task);
+ device->construct_step++;
prv_device_subscribe_context(device);
*failed = FALSE;
@@ -721,6 +724,7 @@ static GUPnPServiceProxyAction *prv_declare(dleyna_service_task_t *task,
priv_t = (prv_new_device_ct_t *)dleyna_service_task_get_user_data(task);
device = priv_t->dev;
+ device->construct_step++;
table = priv_t->dispatch_table;
@@ -745,6 +749,43 @@ DLEYNA_LOG_DEBUG("Exit");
return NULL;
}
+void dlr_device_construct(
+ dlr_device_t *dev,
+ dlr_device_context_t *context,
+ dleyna_connector_id_t connection,
+ const dleyna_connector_dispatch_cb_t *dispatch_table,
+ const dleyna_task_queue_key_t *queue_id)
+{
+ prv_new_device_ct_t *priv_t;
+ GUPnPServiceProxy *s_proxy;
+
+ DLEYNA_LOG_DEBUG("Current step: %d", dev->construct_step);
+
+ priv_t = g_new0(prv_new_device_ct_t, 1);
+
+ priv_t->dev = dev;
+ priv_t->dispatch_table = dispatch_table;
+
+ s_proxy = context->service_proxies.cm_proxy;
+
+ if (dev->construct_step < 1)
+ dleyna_service_task_add(queue_id, prv_get_protocol_info,
+ s_proxy, prv_get_protocol_info_cb,
+ NULL, priv_t);
+
+ /* The following task should always be completed */
+ dleyna_service_task_add(queue_id, prv_subscribe, s_proxy,
+ NULL, NULL, dev);
+
+ if (dev->construct_step < 3)
+ dleyna_service_task_add(queue_id, prv_declare, s_proxy,
+ NULL, g_free, priv_t);
+
+ dleyna_task_queue_start(queue_id);
+
+ DLEYNA_LOG_DEBUG("Exit");
+}
+
dlr_device_t *dlr_device_new(
dleyna_connector_id_t connection,
GUPnPDeviceProxy *proxy,
@@ -754,10 +795,8 @@ dlr_device_t *dlr_device_new(
const dleyna_task_queue_key_t *queue_id)
{
dlr_device_t *dev;
- prv_new_device_ct_t *priv_t;
gchar *new_path;
dlr_device_context_t *context;
- GUPnPServiceProxy *s_proxy;
DLEYNA_LOG_DEBUG("New Device on %s", ip_address);
@@ -765,33 +804,20 @@ dlr_device_t *dlr_device_new(
DLEYNA_LOG_DEBUG("Server Path %s", new_path);
dev = g_new0(dlr_device_t, 1);
- priv_t = g_new0(prv_new_device_ct_t, 1);
dev->connection = connection;
dev->contexts = g_ptr_array_new_with_free_func(prv_dlr_context_delete);
dev->path = new_path;
dev->rate = g_strdup("1");
- priv_t->dev = dev;
- priv_t->dispatch_table = dispatch_table;
-
prv_props_init(&dev->props);
prv_device_append_new_context(dev, ip_address, proxy);
context = dlr_device_get_context(dev);
- s_proxy = context->service_proxies.cm_proxy;
- dleyna_service_task_add(queue_id, prv_get_protocol_info, s_proxy,
- prv_get_protocol_info_cb, NULL, priv_t);
-
- dleyna_service_task_add(queue_id, prv_subscribe, s_proxy,
- NULL, NULL, dev);
-
- dleyna_service_task_add(queue_id, prv_declare, s_proxy,
- NULL, g_free, priv_t);
-
- dleyna_task_queue_start(queue_id);
+ dlr_device_construct(dev, context, connection,
+ dispatch_table, queue_id);
DLEYNA_LOG_DEBUG("Exit");
diff --git a/libdleyna/renderer/device.h b/libdleyna/renderer/device.h
index 0e43884..dd9a1f3 100644
--- a/libdleyna/renderer/device.h
+++ b/libdleyna/renderer/device.h
@@ -78,8 +78,16 @@ struct dlr_device_t_ {
gchar *rate;
double min_rate;
double max_rate;
+ guint construct_step;
};
+void dlr_device_construct(
+ dlr_device_t *dev,
+ dlr_device_context_t *context,
+ dleyna_connector_id_t connection,
+ const dleyna_connector_dispatch_cb_t *dispatch_table,
+ const dleyna_task_queue_key_t *queue_id);
+
dlr_device_t *dlr_device_new(
dleyna_connector_id_t connection,
GUPnPDeviceProxy *proxy,
diff --git a/libdleyna/renderer/upnp.c b/libdleyna/renderer/upnp.c
index e6d905f..5d691b9 100644
--- a/libdleyna/renderer/upnp.c
+++ b/libdleyna/renderer/upnp.c
@@ -54,6 +54,7 @@ typedef struct prv_device_new_ct_t_ prv_device_new_ct_t;
struct prv_device_new_ct_t_ {
dlr_upnp_t *upnp;
char *udn;
+ gchar *ip_address;
dlr_device_t *device;
const dleyna_task_queue_key_t *queue_id;
};
@@ -62,6 +63,7 @@ static void prv_device_new_free(prv_device_new_ct_t *priv_t)
{
if (priv_t) {
g_free(priv_t->udn);
+ g_free(priv_t->ip_address);
g_free(priv_t);
}
}
@@ -95,6 +97,54 @@ on_clear:
DLEYNA_LOG_DEBUG_NL();
}
+static void prv_device_context_switch_end(gboolean cancelled, gpointer data)
+{
+ prv_device_new_ct_t *priv_t = (prv_device_new_ct_t *)data;
+
+ DLEYNA_LOG_DEBUG("Enter");
+
+ prv_device_new_free(priv_t);
+
+ DLEYNA_LOG_DEBUG("Exit");
+}
+
+static const dleyna_task_queue_key_t *prv_create_device_queue(
+ prv_device_new_ct_t **priv_t)
+{
+ const dleyna_task_queue_key_t *queue_id;
+
+ *priv_t = g_new0(prv_device_new_ct_t, 1);
+
+ queue_id = dleyna_task_processor_add_queue(
+ dlr_renderer_service_get_task_processor(),
+ dleyna_service_task_create_source(),
+ DLR_RENDERER_SINK,
+ DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE,
+ dleyna_service_task_process_cb,
+ dleyna_service_task_cancel_cb,
+ dleyna_service_task_delete_cb);
+ dleyna_task_queue_set_finally(queue_id, prv_device_chain_end);
+ dleyna_task_queue_set_user_data(queue_id, *priv_t);
+
+
+ return queue_id;
+}
+
+static void prv_update_device_context(prv_device_new_ct_t *priv_t,
+ dlr_upnp_t *upnp, const char *udn,
+ dlr_device_t *device,
+ const gchar *ip_address,
+ const dleyna_task_queue_key_t *queue_id)
+{
+ priv_t->upnp = upnp;
+ priv_t->udn = g_strdup(udn);
+ priv_t->ip_address = g_strdup(ip_address);
+ priv_t->queue_id = queue_id;
+ priv_t->device = device;
+
+ g_hash_table_insert(upnp->server_uc_map, g_strdup(udn), priv_t);
+}
+
static void prv_server_available_cb(GUPnPControlPoint *cp,
GUPnPDeviceProxy *proxy,
gpointer user_data)
@@ -133,32 +183,17 @@ static void prv_server_available_cb(GUPnPControlPoint *cp,
if (!device) {
DLEYNA_LOG_DEBUG("Device not found. Adding");
- priv_t = g_new0(prv_device_new_ct_t, 1);
-
- queue_id = dleyna_task_processor_add_queue(
- dlr_renderer_service_get_task_processor(),
- dleyna_service_task_create_source(),
- DLR_RENDERER_SINK,
- DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE,
- dleyna_service_task_process_cb,
- dleyna_service_task_cancel_cb,
- dleyna_service_task_delete_cb);
- dleyna_task_queue_set_finally(queue_id, prv_device_chain_end);
- dleyna_task_queue_set_user_data(queue_id, priv_t);
+ queue_id = prv_create_device_queue(&priv_t);
device = dlr_device_new(upnp->connection, proxy, ip_address,
upnp->counter,
upnp->interface_info,
queue_id);
- upnp->counter++;
-
- priv_t->upnp = upnp;
- priv_t->udn = g_strdup(udn);
- priv_t->queue_id = queue_id;
- priv_t->device = device;
+ prv_update_device_context(priv_t, upnp, udn, device, ip_address,
+ queue_id);
- g_hash_table_insert(upnp->server_uc_map, g_strdup(udn), priv_t);
+ upnp->counter++;
} else {
DLEYNA_LOG_DEBUG("Device Found");
@@ -206,6 +241,8 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
gboolean subscribed;
gboolean under_construction = FALSE;
prv_device_new_ct_t *priv_t;
+ gboolean construction_ctx = FALSE;
+ const dleyna_task_queue_key_t *queue_id;
DLEYNA_LOG_DEBUG("Enter");
@@ -245,6 +282,10 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
if (i < device->contexts->len) {
subscribed = (context->subscribed_av || context->subscribed_cm);
+ if (under_construction)
+ construction_ctx = !strcmp(context->ip_address,
+ priv_t->ip_address);
+
(void) g_ptr_array_remove_index(device->contexts, i);
if (device->contexts->len == 0) {
@@ -261,6 +302,28 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
dleyna_task_processor_cancel_queue(
priv_t->queue_id);
}
+ } else if (under_construction && construction_ctx) {
+ DLEYNA_LOG_WARNING(
+ "Device under construction. Switching context");
+
+ /* Cancel previous contruction task chain */
+ g_hash_table_remove(priv_t->upnp->server_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);
+
+ /* Create a new construction task chain */
+ context = dlr_device_get_context(device);
+ queue_id = prv_create_device_queue(&priv_t);
+ prv_update_device_context(priv_t, upnp, udn, device,
+ context->ip_address,
+ queue_id);
+
+ /* Start tasks from current construction step */
+ dlr_device_construct(device, context, upnp->connection,
+ upnp->interface_info, queue_id);
} else if (subscribed && !device->timeout_id) {
DLEYNA_LOG_DEBUG("Subscribe on new context");