diff options
author | Ludovic Ferrandis <ludovic.ferrandis@intel.com> | 2013-09-13 17:56:08 +0200 |
---|---|---|
committer | Mark Ryan <mark.d.ryan@intel.com> | 2013-09-26 12:47:40 +0200 |
commit | d8ca8bb929fd05a479f4d3ac5d6cb3452697530f (patch) | |
tree | faf3c8302b4c8358f39fcb30cdc71b09717ac4c3 | |
parent | 4f8911743c2a14266c4c2098b4edce5abe8fcd30 (diff) | |
download | dleyna-server-d8ca8bb929fd05a479f4d3ac5d6cb3452697530f.tar.gz |
[BrowseObject]: Support Of ChildCount property
Fix issue #122: <https://github.com/01org/dleyna-server/issues/122>
Signed-off-by: Ludovic Ferrandis <ludovic.ferrandis@intel.com>
-rw-r--r-- | libdleyna/server/async.h | 1 | ||||
-rw-r--r-- | libdleyna/server/device.c | 215 |
2 files changed, 195 insertions, 21 deletions
diff --git a/libdleyna/server/async.h b/libdleyna/server/async.h index 468e461..c5e1579 100644 --- a/libdleyna/server/async.h +++ b/libdleyna/server/async.h @@ -84,6 +84,7 @@ struct dls_async_browse_objects_t_ { gchar *upnp_filter; const dleyna_task_queue_key_t *queue_id; const gchar **objects_id; + guint object_count; guint index; }; diff --git a/libdleyna/server/device.c b/libdleyna/server/device.c index 053b969..692895f 100644 --- a/libdleyna/server/device.c +++ b/libdleyna/server/device.c @@ -127,6 +127,13 @@ static void prv_upload_job_delete(gpointer up); static void prv_get_sr_token_for_props(GUPnPServiceProxy *proxy, const dls_device_t *device, dls_async_task_t *cb_data); +static void prv_browse_objects_end_action_cb(GUPnPServiceProxy *proxy, + GUPnPServiceProxyAction *action, + gpointer user_data); +static GUPnPServiceProxyAction *prv_browse_objects_begin_action_cb( + dleyna_service_task_t *task, + GUPnPServiceProxy *proxy, + gboolean *failed); static void prv_object_builder_delete(void *dob) { @@ -1552,7 +1559,7 @@ static void prv_get_container(GUPnPDIDLLiteParser *parser, if (GUPNP_IS_DIDL_LITE_CONTAINER(object)) { dls_props_add_container(cb_task_data->vb, (GUPnPDIDLLiteContainer *)object, - DLS_UPNP_MASK_ALL_PROPS, + cb_task_data->filter_mask, cb_task_data->protocol_info, &have_child_count); if (!have_child_count) @@ -2979,6 +2986,139 @@ static void prv_browse_objects_add_error_result(dls_async_browse_objects_t *bo, g_variant_builder_add(bo->avb, "@a{sv}", gv_result); } +static void prv_get_child_count_end_action_cb(GUPnPServiceProxy *proxy, + GUPnPServiceProxyAction *action, + gpointer user_data) +{ + GError *error = NULL; + const gchar *message; + guint count = G_MAXUINT32; + gboolean end; + dls_async_browse_objects_t *cb_task_data; + dls_async_task_t *cb_data = user_data; + + DLEYNA_LOG_DEBUG("Enter"); + + end = gupnp_service_proxy_end_action(proxy, action, &error, + "TotalMatches", G_TYPE_UINT, + &count, NULL); + + cb_task_data = &((dls_async_task_t *)user_data)->ut.browse_objects; + + if (!end || (count == G_MAXUINT32)) { + message = (error != NULL) ? error->message : "Invalid result"; + DLEYNA_LOG_WARNING("Browse operation failed: %s", message); + + cb_data->error = g_error_new(DLEYNA_SERVER_ERROR, + DLEYNA_ERROR_OPERATION_FAILED, + "Browse operation failed: %s", + message); + goto on_complete; + } + + g_variant_builder_add(cb_task_data->get_all.vb, "{sv}", + DLS_INTERFACE_PROP_CHILD_COUNT, + g_variant_new_uint32(count)); + + g_variant_builder_add(cb_task_data->avb, "@a{sv}", + g_variant_builder_end(cb_task_data->get_all.vb)); + + DLEYNA_LOG_DEBUG("Child Count: %u", count); + +on_complete: + + if (cb_data->error != NULL) { + message = cb_task_data->objects_id[cb_task_data->index - 1]; + prv_browse_objects_add_error_result(cb_task_data, message, + cb_data->error); + g_error_free(cb_data->error); + cb_data->error = NULL; + } + + if (cb_task_data->get_all.vb != NULL) { + g_variant_builder_unref(cb_task_data->get_all.vb); + cb_task_data->get_all.vb = NULL; + } + + if (cb_task_data->index < cb_task_data->object_count) + dleyna_service_task_add(cb_task_data->queue_id, + prv_browse_objects_begin_action_cb, + proxy, + prv_browse_objects_end_action_cb, + NULL, user_data); + + if (error) + g_error_free(error); + + DLEYNA_LOG_DEBUG("Exit"); +} + +static GUPnPServiceProxyAction *prv_get_child_count_begin_action_cb( + dleyna_service_task_t *task, + GUPnPServiceProxy *proxy, + gboolean *failed) +{ + GUPnPServiceProxyAction *action; + dls_task_t *user_data; + const gchar *path; + gchar *root_path = NULL; + gchar *id = NULL; + dls_async_browse_objects_t *cb_task_data; + GError *error = NULL; + + DLEYNA_LOG_DEBUG("Enter"); + + user_data = (dls_task_t *)dleyna_service_task_get_user_data(task); + cb_task_data = &((dls_async_task_t *)user_data)->ut.browse_objects; + path = cb_task_data->objects_id[cb_task_data->index - 1]; + + /* Should never fail. Error already managed in previous browse */ + (void) dls_path_get_path_and_id(path, &root_path, &id, &error); + + if (error != NULL) + goto exit; + + action = gupnp_service_proxy_begin_action( + proxy, "Browse", + dleyna_service_task_begin_action_cb, task, + "ObjectID", G_TYPE_STRING, id, + "BrowseFlag", G_TYPE_STRING, "BrowseDirectChildren", + "Filter", G_TYPE_STRING, "", + "StartingIndex", G_TYPE_INT, 0, + "RequestedCount", G_TYPE_INT, 1, + "SortCriteria", G_TYPE_STRING, "", + NULL); + + g_free(root_path); + g_free(id); + +exit: + *failed = FALSE; + + if (error != NULL) { + DLEYNA_LOG_WARNING("%s: %s", path, error->message); + action = NULL; + + prv_browse_objects_add_error_result(cb_task_data, path, error); + + if (cb_task_data->get_all.vb != NULL) { + g_variant_builder_unref(cb_task_data->get_all.vb); + cb_task_data->get_all.vb = NULL; + } + + if (cb_task_data->index < cb_task_data->object_count) + dleyna_service_task_add( + cb_task_data->queue_id, + prv_browse_objects_begin_action_cb, + proxy, + prv_browse_objects_end_action_cb, + NULL, user_data); + g_error_free(error); + } + + return action; +} + static void prv_browse_objects_end_action_cb(GUPnPServiceProxy *proxy, GUPnPServiceProxyAction *action, gpointer user_data) @@ -2986,6 +3126,7 @@ static void prv_browse_objects_end_action_cb(GUPnPServiceProxy *proxy, GError *error = NULL; dls_async_task_t *cb_data = user_data; dls_async_browse_objects_t *cb_task_data = &cb_data->ut.browse_objects; + dls_async_get_all_t *cb_all_data = &cb_data->ut.browse_objects.get_all; GUPnPDIDLLiteParser *parser = NULL; gchar *result = NULL; const gchar *message; @@ -3013,8 +3154,7 @@ static void prv_browse_objects_end_action_cb(GUPnPServiceProxy *proxy, DLEYNA_LOG_DEBUG("Result: %s", result); DLEYNA_LOG_DEBUG_NL(); - cb_task_data->get_all.vb = g_variant_builder_new( - G_VARIANT_TYPE("a{sv}")); + cb_all_data->vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); parser = gupnp_didl_lite_parser_new(); @@ -3045,8 +3185,19 @@ static void prv_browse_objects_end_action_cb(GUPnPServiceProxy *proxy, goto on_exit; } + if (cb_all_data->need_child_count && + (cb_all_data->filter_mask & DLS_UPNP_MASK_PROP_CHILD_COUNT)) { + DLEYNA_LOG_DEBUG("Need Child Count"); + dleyna_service_task_add(cb_task_data->queue_id, + prv_get_child_count_begin_action_cb, + cb_data->proxy, + prv_get_child_count_end_action_cb, + NULL, cb_data); + goto no_complete; + } + g_variant_builder_add(cb_task_data->avb, "@a{sv}", - g_variant_builder_end(cb_task_data->get_all.vb)); + g_variant_builder_end(cb_all_data->vb)); on_exit: @@ -3058,11 +3209,19 @@ on_exit: cb_data->error = NULL; } - if (cb_task_data->get_all.vb) { - g_variant_builder_unref(cb_data->ut.get_all.vb); - cb_data->ut.get_all.vb = NULL; + if (cb_all_data->vb != NULL) { + g_variant_builder_unref(cb_all_data->vb); + cb_all_data->vb = NULL; } + if (cb_task_data->index < cb_task_data->object_count) + dleyna_service_task_add(cb_task_data->queue_id, + prv_browse_objects_begin_action_cb, + cb_data->proxy, + prv_browse_objects_end_action_cb, + NULL, cb_data); +no_complete: + if (parser) g_object_unref(parser); @@ -3093,18 +3252,14 @@ static GUPnPServiceProxyAction *prv_browse_objects_begin_action_cb( cb_task_data = &((dls_async_task_t *)user_data)->ut.browse_objects; path = cb_task_data->objects_id[cb_task_data->index]; + /* Reset dynamic field. */ + cb_task_data->get_all.need_child_count = FALSE; + /* Process anyway. We will add an entry with error */ (void) dls_path_get_path_and_id(path, &root_path, &id, &error); - if (error != NULL) { - DLEYNA_LOG_WARNING("%s: %s", path, error->message); - - prv_browse_objects_add_error_result(cb_task_data, path, error); - action = NULL; - g_error_free(error); - + if (error != NULL) goto exit; - } DLEYNA_LOG_DEBUG("Browse Metadata for path [id]: %s [%s]", path, id); @@ -3123,8 +3278,26 @@ static GUPnPServiceProxyAction *prv_browse_objects_begin_action_cb( exit: *failed = FALSE; + + /* It's the ONLY place where index is incremented */ cb_task_data->index++; + if (error != NULL) { + DLEYNA_LOG_WARNING("%s: %s", path, error->message); + + prv_browse_objects_add_error_result(cb_task_data, path, error); + action = NULL; + g_error_free(error); + + if (cb_task_data->index < cb_task_data->object_count) + dleyna_service_task_add( + cb_task_data->queue_id, + prv_browse_objects_begin_action_cb, + proxy, + prv_browse_objects_end_action_cb, + NULL, user_data); + } + return action; } @@ -3211,6 +3384,7 @@ void dls_device_browse_objects(dls_client_t *client, dls_task_t *task) cb_task_data->queue_id = queue_id; cb_task_data->avb = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}")); cb_task_data->objects_id = objs; + cb_task_data->object_count = length; g_object_add_weak_pointer((G_OBJECT(context->service_proxy)), (gpointer *)&cb_data->proxy); @@ -3220,12 +3394,11 @@ void dls_device_browse_objects(dls_client_t *client, dls_task_t *task) G_CALLBACK(prv_browse_objects_chain_cancelled), cb_data, NULL); - for (i = 0; i < length; i++) - dleyna_service_task_add(queue_id, - prv_browse_objects_begin_action_cb, - cb_data->proxy, - prv_browse_objects_end_action_cb, - NULL, cb_data); + dleyna_service_task_add(queue_id, + prv_browse_objects_begin_action_cb, + cb_data->proxy, + prv_browse_objects_end_action_cb, + NULL, cb_data); dleyna_task_queue_start(queue_id); |