From 7df1714b593e73533cfb50a4ece623267d94df79 Mon Sep 17 00:00:00 2001 From: Christophe Guiraud Date: Wed, 11 Sep 2013 15:26:27 +0200 Subject: [Device] Fix DLR_INTERFACE_PROP_BYTE_POSITION retrieval DLR_INTERFACE_PROP_BYTE_POSITION is now assigned with the result of a call to upnp action X_DLNA_GetBytePositionInfo[RelByte] instead of upnp action GetPositionInfo[RelCount]. Partial fix for issue: https://github.com/01org/dleyna-renderer/issues/115 Signed-off-by: Christophe Guiraud --- libdleyna/renderer/device.c | 328 +++++++++++++++++++++++++++++++------------- 1 file changed, 236 insertions(+), 92 deletions(-) (limited to 'libdleyna') diff --git a/libdleyna/renderer/device.c b/libdleyna/renderer/device.c index 7dc6eb2..0c24963 100644 --- a/libdleyna/renderer/device.c +++ b/libdleyna/renderer/device.c @@ -37,11 +37,18 @@ #include "prop-defs.h" #include "server.h" -typedef void (*dlr_device_local_cb_t)(dlr_async_task_t *cb_data); +typedef struct dlr_device_get_all_position_t_ dlr_device_get_all_position_t; +struct dlr_device_get_all_position_t_ { + gint expected_props; + gchar *rel_time; + gchar *rel_cnt; +}; typedef struct dlr_device_data_t_ dlr_device_data_t; struct dlr_device_data_t_ { - dlr_device_local_cb_t local_cb; + union { + dlr_device_get_all_position_t get_all_position; + } ut; }; typedef struct dlr_rc_event_t_ dlr_rc_event_t; @@ -95,6 +102,10 @@ static void prv_add_player_speed_props(GHashTable *player_props, static gint prv_compare_rationals(const gchar *a, const gchar *b); +static void prv_get_position_info(dlr_async_task_t *cb_data, + const gchar *action_name, + GUPnPServiceProxyActionCallback callback); + static void prv_unref_variant(gpointer variant) { GVariant *var = variant; @@ -1733,62 +1744,161 @@ static void prv_get_position_info_cb(GUPnPServiceProxy *proxy, GUPnPServiceProxyAction *action, gpointer user_data) { - gchar *rel_pos = NULL; - gchar *rel_cnt = NULL; + gchar *result = NULL; const gchar *message; gboolean end; dlr_async_task_t *cb_data = user_data; GError *error = NULL; - dlr_device_data_t *device_data = cb_data->private; GVariantBuilder *changed_props_vb; GVariant *changed_props; - gint expected_props = 2; - end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action, - &error, - "RelTime", G_TYPE_STRING, &rel_pos, - "RelCount", G_TYPE_STRING, - &rel_cnt, NULL); + end = gupnp_service_proxy_end_action( + cb_data->proxy, cb_data->action, &error, + "RelTime", G_TYPE_STRING, &result, + NULL); + + if (!end || (result == NULL)) { + message = (error != NULL) ? error->message : "Invalid result"; + cb_data->error = g_error_new(DLEYNA_SERVER_ERROR, + DLEYNA_ERROR_OPERATION_FAILED, + "GetPositionInfo operation failed: %s", + message); + + if (error != NULL) + g_error_free(error); - if (!end && !cb_data->task.type == DLR_TASK_GET_ALL_PROPS) goto on_error; + } - if (rel_pos == NULL) { - expected_props--; - if (cb_data->task.type == DLR_TASK_GET_ALL_PROPS) { - /* Do not fail, just remove the property */ - g_hash_table_remove(cb_data->device->props.player_props, - DLR_INTERFACE_PROP_POSITION); - } else if (!strcmp(cb_data->task.ut.get_prop.prop_name, - DLR_INTERFACE_PROP_POSITION)) { - goto on_error; - } + changed_props_vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + g_strstrip(result); + + prv_add_reltime(cb_data->device, result, changed_props_vb); + + changed_props = g_variant_ref_sink( + g_variant_builder_end(changed_props_vb)); + prv_emit_signal_properties_changed(cb_data->device, + DLR_INTERFACE_PLAYER, + changed_props); + g_variant_unref(changed_props); + g_variant_builder_unref(changed_props_vb); + + g_free(result); + + prv_get_prop(cb_data); + +on_error: + + (void) g_idle_add(dlr_async_task_complete, cb_data); + g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id); +} + +static void prv_get_byte_position_info_cb(GUPnPServiceProxy *proxy, + GUPnPServiceProxyAction *action, + gpointer user_data) +{ + gchar *result = NULL; + const gchar *message; + gboolean end; + dlr_async_task_t *cb_data = user_data; + GError *error = NULL; + GVariantBuilder *changed_props_vb; + GVariant *changed_props; + + end = gupnp_service_proxy_end_action( + cb_data->proxy, cb_data->action, &error, + "RelByte", G_TYPE_STRING, &result, + NULL); + + if (!end || (result == NULL)) { + message = (error != NULL) ? error->message : "Invalid result"; + cb_data->error = g_error_new(DLEYNA_SERVER_ERROR, + DLEYNA_ERROR_OPERATION_FAILED, + "X_DLNA_GetBytePositionInfo operation failed: %s", + message); + + if (error != NULL) + g_error_free(error); + + goto on_error; } - if (rel_cnt == NULL) { - expected_props--; - if (cb_data->task.type == DLR_TASK_GET_ALL_PROPS) { - /* Do not fail, just remove the property */ - g_hash_table_remove(cb_data->device->props.player_props, - DLR_INTERFACE_PROP_BYTE_POSITION); - } else if (!strcmp(cb_data->task.ut.get_prop.prop_name, - DLR_INTERFACE_PROP_BYTE_POSITION)) { - goto on_error; + changed_props_vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + g_strstrip(result); + + prv_add_relcount(cb_data->device, result, changed_props_vb); + + changed_props = g_variant_ref_sink( + g_variant_builder_end(changed_props_vb)); + prv_emit_signal_properties_changed(cb_data->device, + DLR_INTERFACE_PLAYER, + changed_props); + g_variant_unref(changed_props); + g_variant_builder_unref(changed_props_vb); + + g_free(result); + + prv_get_prop(cb_data); + +on_error: + + (void) g_idle_add(dlr_async_task_complete, cb_data); + g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id); +} + +static void prv_get_all_position_info_cb(GUPnPServiceProxy *proxy, + GUPnPServiceProxyAction *action, + gpointer user_data) +{ + gchar *result = NULL; + dlr_async_task_t *cb_data = user_data; + GError *error = NULL; + dlr_device_data_t *device_data = cb_data->private; + GVariantBuilder *changed_props_vb; + GVariant *changed_props; + + if (!gupnp_service_proxy_end_action(cb_data->proxy, + cb_data->action, &error, + "RelTime", G_TYPE_STRING, &result, + NULL)) { + if (error != NULL) { + DLEYNA_LOG_WARNING( + "GetPositionInfo operation failed: %s", + error->message); + + g_error_free(error); } } - if (!expected_props) - goto out; + if (result == NULL) { + device_data->ut.get_all_position.expected_props--; + + /* Do not fail, just remove the property */ + g_hash_table_remove(cb_data->device->props.player_props, + DLR_INTERFACE_PROP_POSITION); + } + + device_data->ut.get_all_position.rel_time = result; + + if (!device_data->ut.get_all_position.expected_props) + goto on_complete; changed_props_vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); - if (rel_pos != NULL) { - g_strstrip(rel_pos); - prv_add_reltime(cb_data->device, rel_pos, changed_props_vb); + if (device_data->ut.get_all_position.rel_time != NULL) { + g_strstrip(device_data->ut.get_all_position.rel_time); + prv_add_reltime(cb_data->device, + device_data->ut.get_all_position.rel_time, + changed_props_vb); } - if (rel_cnt != NULL) { - g_strstrip(rel_cnt); - prv_add_relcount(cb_data->device, rel_cnt, changed_props_vb); + + if (device_data->ut.get_all_position.rel_cnt != NULL) { + g_strstrip(device_data->ut.get_all_position.rel_cnt); + prv_add_relcount(cb_data->device, + device_data->ut.get_all_position.rel_cnt, + changed_props_vb); } changed_props = g_variant_ref_sink( @@ -1799,30 +1909,61 @@ static void prv_get_position_info_cb(GUPnPServiceProxy *proxy, g_variant_unref(changed_props); g_variant_builder_unref(changed_props_vb); - goto out; +on_complete: -on_error: + prv_get_props(cb_data); + (void) g_idle_add(dlr_async_task_complete, cb_data); + g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id); - message = (error != NULL) ? error->message : - "Invalid result"; - cb_data->error = g_error_new( - DLEYNA_SERVER_ERROR, - DLEYNA_ERROR_OPERATION_FAILED, - "GetPositionInfo operation failed: %s", - message); + return; +} -out: +static void prv_get_all_byte_position_info_cb(GUPnPServiceProxy *proxy, + GUPnPServiceProxyAction *action, + gpointer user_data) +{ + gchar *result = NULL; + dlr_async_task_t *cb_data = user_data; + GError *error = NULL; + dlr_device_data_t *device_data = cb_data->private; - g_free(rel_pos); - g_free(rel_cnt); + if (!gupnp_service_proxy_end_action(cb_data->proxy, + cb_data->action, &error, + "RelByte", G_TYPE_STRING, &result, + NULL)) { + if (error != NULL) { + DLEYNA_LOG_WARNING( + "X_DLNA_GetBytePositionInfo operation failed: %s", + error->message); - if (error != NULL) - g_error_free(error); + g_error_free(error); + } + } + + if (result == NULL) { + device_data->ut.get_all_position.expected_props--; + + /* Do not fail, just remove the property */ + g_hash_table_remove(cb_data->device->props.player_props, + DLR_INTERFACE_PROP_BYTE_POSITION); + } + + device_data->ut.get_all_position.rel_cnt = result; + + cb_data->action = gupnp_service_proxy_begin_action( + cb_data->proxy, + "GetPositionInfo", + prv_get_all_position_info_cb, + cb_data, + "InstanceID", G_TYPE_INT, 0, + NULL); - device_data->local_cb(cb_data); + return; } -static void prv_get_position_info(dlr_async_task_t *cb_data) +static void prv_get_position_info(dlr_async_task_t *cb_data, + const gchar *action_name, + GUPnPServiceProxyActionCallback callback) { dlr_device_context_t *context; @@ -1837,13 +1978,13 @@ static void prv_get_position_info(dlr_async_task_t *cb_data) g_object_add_weak_pointer((G_OBJECT(context->service_proxies.av_proxy)), (gpointer *)&cb_data->proxy); - cb_data->action = - gupnp_service_proxy_begin_action(cb_data->proxy, - "GetPositionInfo", - prv_get_position_info_cb, - cb_data, - "InstanceID", G_TYPE_INT, 0, - NULL); + cb_data->action = gupnp_service_proxy_begin_action( + cb_data->proxy, + action_name, + callback, + cb_data, + "InstanceID", G_TYPE_INT, 0, + NULL); } /***********************************************************************/ @@ -2260,20 +2401,6 @@ on_lost_device: return device_alive; } -static void prv_complete_get_prop(dlr_async_task_t *cb_data) -{ - prv_get_prop(cb_data); - (void) g_idle_add(dlr_async_task_complete, cb_data); - g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id); -} - -static void prv_complete_get_props(dlr_async_task_t *cb_data) -{ - prv_get_props(cb_data); - (void) g_idle_add(dlr_async_task_complete, cb_data); - g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id); -} - static void prv_simple_call_cb(GUPnPServiceProxy *proxy, GUPnPServiceProxyAction *action, gpointer user_data) @@ -2498,12 +2625,29 @@ exit: g_idle_add(dlr_async_task_complete, cb_data); } +static void prv_free_get_all_position_data(gpointer data) +{ + dlr_device_data_t *device_cb_data = data; + + if (device_cb_data) { + g_free(device_cb_data->ut.get_all_position.rel_cnt); + + g_free(device_cb_data->ut.get_all_position.rel_time); + + g_free(device_cb_data); + } +} + void dlr_device_get_prop(dlr_device_t *device, dlr_task_t *task, dlr_upnp_task_complete_t cb) { dlr_async_task_t *cb_data = (dlr_async_task_t *)task; dlr_task_get_prop_t *get_prop = &task->ut.get_prop; - dlr_device_data_t *device_cb_data; + const gchar *get_position_action; + GUPnPServiceProxyActionCallback get_position_cb; + + cb_data->cb = cb; + cb_data->device = device; /* Need to check to see if the property is DLR_INTERFACE_PROP_POSITION. If it is we need to call GetPositionInfo. This value is not evented. @@ -2518,19 +2662,18 @@ void dlr_device_get_prop(dlr_device_t *device, dlr_task_t *task, /* Need to read the current position. This property is not evented */ - device_cb_data = g_new(dlr_device_data_t, 1); - device_cb_data->local_cb = prv_complete_get_prop; - - cb_data->cb = cb; - cb_data->private = device_cb_data; - cb_data->free_private = g_free; - cb_data->device = device; + if (!strcmp(task->ut.get_prop.prop_name, + DLR_INTERFACE_PROP_POSITION)) { + get_position_action = "GetPositionInfo"; + get_position_cb = prv_get_position_info_cb; + } else { + get_position_action = "X_DLNA_GetBytePositionInfo"; + get_position_cb = prv_get_byte_position_info_cb; + } - prv_get_position_info(cb_data); + prv_get_position_info(cb_data, get_position_action, + get_position_cb); } else { - cb_data->cb = cb; - cb_data->device = device; - if (!device->props.synced && !prv_props_update(device, task)) { cb_data->error = g_error_new( DLEYNA_SERVER_ERROR, @@ -2565,13 +2708,14 @@ void dlr_device_get_all_props(dlr_device_t *device, dlr_task_t *task, /* Need to read the current position. This property is not evented */ - device_cb_data = g_new(dlr_device_data_t, 1); - device_cb_data->local_cb = prv_complete_get_props; + device_cb_data = g_new0(dlr_device_data_t, 1); + device_cb_data->ut.get_all_position.expected_props = 2; cb_data->private = device_cb_data; - cb_data->free_private = g_free; + cb_data->free_private = prv_free_get_all_position_data; - prv_get_position_info(cb_data); + prv_get_position_info(cb_data, "X_DLNA_GetBytePositionInfo", + prv_get_all_byte_position_info_cb); } else { prv_get_props(cb_data); (void) g_idle_add(dlr_async_task_complete, cb_data); -- cgit v1.2.1