summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Guiraud <christophe.guiraud@intel.com>2013-09-11 15:26:27 +0200
committerChristophe Guiraud <christophe.guiraud@intel.com>2013-09-17 15:20:34 +0200
commit7df1714b593e73533cfb50a4ece623267d94df79 (patch)
treed853801d7239b2df109ff206ac37191a8dc74fba
parent59837824fefdf9d1677f4c632c1cf35ddba2db23 (diff)
downloaddleyna-renderer-7df1714b593e73533cfb50a4ece623267d94df79.tar.gz
[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 <christophe.guiraud@intel.com>
-rw-r--r--libdleyna/renderer/device.c328
1 files changed, 236 insertions, 92 deletions
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);