Update dLeyna to v0.2.1
[profile/ivi/dLeyna.git] / dleyna-renderer / libdleyna / renderer / upnp.c
index e6d905f..fefc340 100644 (file)
@@ -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)
@@ -112,12 +162,12 @@ static void prv_server_available_cb(GUPnPControlPoint *cp,
 
        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);
 
@@ -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,17 +241,19 @@ 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");
 
        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);
 
@@ -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");
 
@@ -348,12 +411,12 @@ GVariant *dlr_upnp_get_server_ids(dlr_upnp_t *upnp)
 
        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");
@@ -732,6 +795,32 @@ void dlr_upnp_remove_uri(dlr_upnp_t *upnp, dlr_task_t *task,
        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);
@@ -750,3 +839,15 @@ void dlr_upnp_unsubscribe(dlr_upnp_t *upnp)
 
        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;
+}