diff options
author | Christophe Guiraud <christophe.guiraud@intel.com> | 2013-09-11 17:45:24 +0200 |
---|---|---|
committer | Christophe Guiraud <christophe.guiraud@intel.com> | 2013-09-17 15:42:56 +0200 |
commit | dfda858b5ae63914b45fc35fcbbc47b63d215b04 (patch) | |
tree | 187a400ff686cb496474218fcaae91fa599bd243 | |
parent | 7df1714b593e73533cfb50a4ece623267d94df79 (diff) | |
download | dleyna-renderer-dfda858b5ae63914b45fc35fcbbc47b63d215b04.tar.gz |
[Device] Fix dlr_device_seek implementation
dlr_device_seek was incorrectly implemented.
Modify the current implemention to retrieve the current position with
the right method depending on the unit (time or byte) and add it to
the delta specified in Seek request, and then call
dlr_device_set_position().
so now we have:
- TIME SEEK OPERATIONS
Seek(offset)
-> current_position = UPNP GetPositionInfo["RelTime"]
-> UPNP Seek["REL_TIME", current_position + offset]
SetPosition(position)
-> UPNP Seek["REL_TIME", position]
- BYTE SEEK OPERATIONS
ByteSeek(offset)
-> current_position = UPNP X_DLNA_GetBytePositionInfo["RelByte"]
-> UPNP Seek["X_DLNA_REL_BYTE", current_position + offset]
SetBytePosition(position)
-> UPNP Seek["X_DLNA_REL_BYTE", position]
Partial fix for issue:
https://github.com/01org/dleyna-renderer/issues/115
Signed-off-by: Christophe Guiraud <christophe.guiraud@intel.com>
-rw-r--r-- | doc/server/dbus/API.txt | 4 | ||||
-rw-r--r-- | libdleyna/renderer/device.c | 116 |
2 files changed, 111 insertions, 9 deletions
diff --git a/doc/server/dbus/API.txt b/doc/server/dbus/API.txt index bfd2721..7556b6a 100644 --- a/doc/server/dbus/API.txt +++ b/doc/server/dbus/API.txt @@ -344,8 +344,8 @@ ByteSeek(x Offset) -> void SetBytePosition(o TrackID, x Position) -> void Same as Seek and SetPosition but last parameter (Offset and Position) is not -expressed in second but in byte, and allows to set the seekmode to respectively -“REL_COUNT” and “ABS_COUNT” . New in version 0.2.1 +expressed in second but in byte, and allows to set the seekmode by using +“X_DLNA_REL_BYTE” unit. New in version 0.2.1 org.mpris.MediaPlayer2.TrackList and org.mpris.MediaPlayer2.Playlists diff --git a/libdleyna/renderer/device.c b/libdleyna/renderer/device.c index 0c24963..4f22eef 100644 --- a/libdleyna/renderer/device.c +++ b/libdleyna/renderer/device.c @@ -3029,28 +3029,130 @@ static void prv_device_set_position(dlr_device_t *device, dlr_task_t *task, g_free(position); } +static void prv_device_seek_set_position(dlr_device_t *device, dlr_task_t *task, + const gchar *pos_type, + dlr_upnp_task_complete_t cb) +{ + dlr_async_task_t *cb_data = (dlr_async_task_t *)task; + dlr_task_seek_t *seek_data = &task->ut.seek; + gchar *position; + + cb_data->cb = cb; + cb_data->device = device; + + if (g_strrstr(pos_type, "_TIME") != NULL) + position = prv_int64_to_duration(seek_data->position); + else + position = g_strdup_printf("%llu", + (long long unsigned int)seek_data->counter_position); + + DLEYNA_LOG_INFO("set %s position : %s", pos_type, position); + + cb_data->action = + gupnp_service_proxy_begin_action(cb_data->proxy, + "Seek", + prv_simple_call_cb, + cb_data, + "InstanceID", G_TYPE_INT, 0, + "Unit", G_TYPE_STRING, + pos_type, + "Target", + G_TYPE_STRING, position, + NULL); + + g_free(position); +} + +static void prv_complete_seek_get_position(GUPnPServiceProxy *proxy, + GUPnPServiceProxyAction *action, + gpointer user_data) +{ + gchar *result = NULL; + const gchar *message; + gboolean end; + GError *error = NULL; + dlr_async_task_t *cb_data = user_data; + dlr_task_t *task = &cb_data->task; + dlr_task_seek_t *seek_data = &task->ut.seek; + guint64 count; + + end = gupnp_service_proxy_end_action( + proxy, action, &error, + (task->type == DLR_TASK_SEEK) ? + "RelTime" : "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, + "%s operation failed: %s", + (task->type == DLR_TASK_SEEK) ? + "GetPositionInfo" : "X_DLNA_GetBytePositionInfo", + message); + + if (error != NULL) + g_error_free(error); + + goto on_error; + } + + g_strstrip(result); + + if (task->type == DLR_TASK_SEEK) { + seek_data->position += prv_duration_to_int64(result); + + prv_device_seek_set_position(cb_data->device, task, + "REL_TIME", cb_data->cb); + } else { + count = strtoull(result, NULL, 10); + + seek_data->counter_position += count; + + prv_device_seek_set_position(cb_data->device, task, + "X_DLNA_REL_BYTE", cb_data->cb); + } + + g_free(result); + + return; + +on_error: + + (void) g_idle_add(dlr_async_task_complete, task); + g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id); +} + void dlr_device_seek(dlr_device_t *device, dlr_task_t *task, dlr_upnp_task_complete_t cb) { - if (task->type == DLR_TASK_SEEK) - prv_device_set_position(device, task, "REL_TIME", cb); - else - prv_device_set_position(device, task, "REL_COUNT", cb); + dlr_async_task_t *cb_data = (dlr_async_task_t *)task; + + cb_data->cb = cb; + cb_data->device = device; + + prv_get_position_info(cb_data, + (task->type == DLR_TASK_SEEK) ? + "GetPositionInfo" : "X_DLNA_GetBytePositionInfo", + prv_complete_seek_get_position); } void dlr_device_set_position(dlr_device_t *device, dlr_task_t *task, dlr_upnp_task_complete_t cb) { if (task->type == DLR_TASK_SET_POSITION) - prv_device_set_position(device, task, "REL_TIME", cb); + prv_device_set_position(device, task, "REL_TIME", cb); else - prv_device_set_position(device, task, "X_DLNA_REL_BYTE", cb); + prv_device_set_position(device, task, "X_DLNA_REL_BYTE", cb); } void dlr_device_goto_track(dlr_device_t *device, dlr_task_t *task, dlr_upnp_task_complete_t cb) { - prv_device_set_position(device, task, "TRACK_NR", cb); + prv_device_set_position(device, task, "TRACK_NR", cb); } void dlr_device_host_uri(dlr_device_t *device, dlr_task_t *task, |