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;
};
{
if (priv_t) {
g_free(priv_t->udn);
+ g_free(priv_t->ip_address);
g_free(priv_t);
}
}
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)
udn = gupnp_device_info_get_udn((GUPnPDeviceInfo *)proxy);
- if (!udn)
- goto on_error;
-
ip_address = gupnp_context_get_host_ip(
gupnp_control_point_get_context(cp));
+ if (!udn || !ip_address)
+ goto on_error;
+
DLEYNA_LOG_DEBUG("UDN %s", udn);
DLEYNA_LOG_DEBUG("IP Address %s", ip_address);
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");
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");
udn = gupnp_device_info_get_udn((GUPnPDeviceInfo *)proxy);
- if (!udn)
- goto on_error;
-
ip_address = gupnp_context_get_host_ip(
gupnp_control_point_get_context(cp));
+ if (!udn || !ip_address)
+ goto on_error;
+
DLEYNA_LOG_DEBUG("UDN %s", udn);
DLEYNA_LOG_DEBUG("IP Address %s", ip_address);
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) {
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");
DLEYNA_LOG_DEBUG("Enter");
- g_variant_builder_init(&vb, G_VARIANT_TYPE("as"));
+ g_variant_builder_init(&vb, G_VARIANT_TYPE("ao"));
g_hash_table_iter_init(&iter, upnp->server_udn_map);
while (g_hash_table_iter_next(&iter, NULL, &value)) {
device = value;
- g_variant_builder_add(&vb, "s", device->path);
+ g_variant_builder_add(&vb, "o", device->path);
}
DLEYNA_LOG_DEBUG("Exit");
DLEYNA_LOG_DEBUG("Exit");
}
+void dlr_upnp_get_icon(dlr_upnp_t *upnp, dlr_task_t *task,
+ dlr_upnp_task_complete_t cb)
+{
+ dlr_device_t *device;
+ dlr_async_task_t *cb_data = (dlr_async_task_t *)task;
+
+ DLEYNA_LOG_DEBUG("Enter");
+
+ device = dlr_device_from_path(task->path, upnp->server_udn_map);
+
+ if (!device) {
+ DLEYNA_LOG_WARNING("Cannot locate device");
+
+ cb_data->cb = cb;
+ cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+ DLEYNA_ERROR_OBJECT_NOT_FOUND,
+ "Cannot locate a device for the specified object");
+
+ (void) g_idle_add(dlr_async_task_complete, cb_data);
+ } else {
+ dlr_device_get_icon(device, task, cb);
+ }
+
+ DLEYNA_LOG_DEBUG("Exit");
+}
+
void dlr_upnp_lost_client(dlr_upnp_t *upnp, const gchar *client_name)
{
dlr_host_service_lost_client(upnp->host_service, client_name);
DLEYNA_LOG_DEBUG("Exit");
}
+
+void dlr_upnp_rescan(dlr_upnp_t *upnp)
+{
+ DLEYNA_LOG_DEBUG("re-scanning control points");
+
+ gupnp_context_manager_rescan_control_points(upnp->context_manager);
+}
+
+GUPnPContextManager *dlr_upnp_get_context_manager(dlr_upnp_t *upnp)
+{
+ return upnp->context_manager;
+}