diff options
author | Manuel Bachmann <manuel.bachmann@iot.bzh> | 2016-01-25 13:05:45 +0100 |
---|---|---|
committer | Manuel Bachmann <manuel.bachmann@iot.bzh> | 2016-01-25 13:05:45 +0100 |
commit | e3320f303c4eb8f7fe0fac69bfa9ce36d9916930 (patch) | |
tree | dec909da8024c41879385410a2ff745d51af78e8 /plugins/media | |
parent | ce4624801ed46ecf912205cd984f3488e3e07bac (diff) |
Fix Media Plugin refresh, add seek API
We no longer fail if init() is called multiple times
(typical refresh case).
We now support a "seek?value=<seconds>" API.
Signed-off-by: Manuel Bachmann <manuel.bachmann@iot.bzh>
Diffstat (limited to 'plugins/media')
-rw-r--r-- | plugins/media/media-api.c | 38 | ||||
-rw-r--r-- | plugins/media/media-rygel.c | 34 | ||||
-rw-r--r-- | plugins/media/media-rygel.h | 5 |
3 files changed, 62 insertions, 15 deletions
diff --git a/plugins/media/media-api.c b/plugins/media/media-api.c index 05237d39..257b1cf1 100644 --- a/plugins/media/media-api.c +++ b/plugins/media/media-api.c @@ -42,14 +42,18 @@ STATIC void freeMedia (void *context, void *handle) { STATIC json_object* init (AFB_request *request) { /* AFB_SESSION_CHECK */ + mediaCtxHandleT *ctx; json_object *jresp; /* create a private client context */ if (!request->context) request->context = initMediaCtx(); + ctx = (mediaCtxHandleT*)request->context; + /* initialize server connection */ - _rygel_init (request->context); + if (!ctx->media_server) + _rygel_init (request->context); jresp = json_object_new_object(); json_object_object_add(jresp, "info", json_object_new_string ("Media initialized")); @@ -72,7 +76,7 @@ STATIC json_object* list (AFB_request *request) { /* AFB_SESSION_CHECK */ return jresp; } -STATIC json_object* choose (AFB_request *request) { /* AFB_SESSION_CHECK */ +STATIC json_object* selecting (AFB_request *request) { /* AFB_SESSION_CHECK */ mediaCtxHandleT *ctx = (mediaCtxHandleT*)request->context; const char *value = getQueryValue (request, "value"); @@ -95,7 +99,7 @@ STATIC json_object* choose (AFB_request *request) { /* AFB_SESSION_CHECK */ else if (atoi(value) >= 0) { index = (unsigned int) atoi(value); - if (!_rygel_choose (ctx, index)) + if (!_rygel_select (ctx, index)) return jsonNewMessage(AFB_FAIL, "Chosen index superior to current media count"); ctx->index = index; @@ -110,7 +114,7 @@ STATIC json_object* play (AFB_request *request) { /* AFB_SESSION_CHECK */ mediaCtxHandleT *ctx = (mediaCtxHandleT*)request->context; - if (!_rygel_do (ctx, PLAY)) + if (!_rygel_do (ctx, PLAY, NULL)) return jsonNewMessage(AFB_FAIL, "Could not play chosen media"); return jsonNewMessage(AFB_SUCCESS, "PLaying media"); @@ -120,22 +124,37 @@ STATIC json_object* stop (AFB_request *request) { /* AFB_SESSION_CHECK */ mediaCtxHandleT *ctx = (mediaCtxHandleT*)request->context; - if (!_rygel_do (ctx, STOP)) + if (!_rygel_do (ctx, STOP, NULL)) return jsonNewMessage(AFB_FAIL, "Could not stop chosen media"); return jsonNewMessage(AFB_SUCCESS, "Stopped media"); } -STATIC json_object* paused (AFB_request *request) { /* AFB_SESSION_CHECK */ +STATIC json_object* pausing (AFB_request *request) { /* AFB_SESSION_CHECK */ mediaCtxHandleT *ctx = (mediaCtxHandleT*)request->context; - if (!_rygel_do (ctx, PAUSE)) + if (!_rygel_do (ctx, PAUSE, NULL)) return jsonNewMessage(AFB_FAIL, "Could not pause chosen media"); return jsonNewMessage(AFB_SUCCESS, "Paused media"); } +STATIC json_object* seek (AFB_request *request) { /* AFB_SESSION_CHECK */ + + mediaCtxHandleT *ctx = (mediaCtxHandleT*)request->context; + const char *value = getQueryValue (request, "value"); + + /* no "?value=" parameter : return error */ + if (!value) + return jsonNewMessage(AFB_FAIL, "You must provide a time"); + + if (!_rygel_do (ctx, SEEK, value)) + return jsonNewMessage(AFB_FAIL, "Could not seek chosen media"); + + return jsonNewMessage(AFB_SUCCESS, "Seeked media"); +} + STATIC json_object* upload (AFB_request *request) { /* AFB_SESSION_CHECK */ mediaCtxHandleT *ctx = (mediaCtxHandleT*)request->context; @@ -165,10 +184,11 @@ STATIC json_object* ping (AFB_request *request) { /* AFB_SESSION_NONE */ STATIC AFB_restapi pluginApis[]= { {"init" , AFB_SESSION_CHECK, (AFB_apiCB)init , "Media API - init" }, {"list" , AFB_SESSION_CHECK, (AFB_apiCB)list , "Media API - list" }, - {"choose" , AFB_SESSION_CHECK, (AFB_apiCB)choose , "Media API - choose" }, + {"select" , AFB_SESSION_CHECK, (AFB_apiCB)selecting , "Media API - select" }, {"play" , AFB_SESSION_CHECK, (AFB_apiCB)play , "Media API - play" }, {"stop" , AFB_SESSION_CHECK, (AFB_apiCB)stop , "Media API - stop" }, - {"pause" , AFB_SESSION_CHECK, (AFB_apiCB)paused , "Media API - pause" }, + {"pause" , AFB_SESSION_CHECK, (AFB_apiCB)pausing , "Media API - pause" }, + {"seek" , AFB_SESSION_CHECK, (AFB_apiCB)seek , "Media API - seek" }, {"upload" , AFB_SESSION_CHECK, (AFB_apiCB)upload , "Media API - upload" }, {"ping" , AFB_SESSION_NONE, (AFB_apiCB)ping , "Media API - ping" }, {NULL} diff --git a/plugins/media/media-rygel.c b/plugins/media/media-rygel.c index 539b6189..9e94a9e7 100644 --- a/plugins/media/media-rygel.c +++ b/plugins/media/media-rygel.c @@ -65,6 +65,7 @@ PUBLIC unsigned char _rygel_init (mediaCtxHandleT *ctx) { dev_ctx[client_count]->av_transport = NULL; dev_ctx[client_count]->state = STOP; dev_ctx[client_count]->target_state = STOP; + dev_ctx[client_count]->action_args = NULL; dev_ctx[client_count]->transfer_started = 0; client_count++; @@ -124,7 +125,7 @@ PUBLIC char* _rygel_list (mediaCtxHandleT *ctx) { return result; } -PUBLIC unsigned char _rygel_choose (mediaCtxHandleT *ctx, unsigned int index) { +PUBLIC unsigned char _rygel_select (mediaCtxHandleT *ctx, unsigned int index) { dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server; unsigned int count; @@ -160,7 +161,7 @@ PUBLIC unsigned char _rygel_upload (mediaCtxHandleT *ctx, char *path) { return _rygel_start_uploading (dev_ctx_c, path, upload_id); } -PUBLIC unsigned char _rygel_do (mediaCtxHandleT *ctx, State state) { +PUBLIC unsigned char _rygel_do (mediaCtxHandleT *ctx, State state, char *args) { dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server; unsigned int index = ctx->index; @@ -178,7 +179,7 @@ PUBLIC unsigned char _rygel_do (mediaCtxHandleT *ctx, State state) { metadata = _rygel_find_metadata_for_id (dev_ctx_c, id); uri = _rygel_find_uri_for_metadata (dev_ctx_c, metadata); - return _rygel_start_doing (dev_ctx_c, uri, metadata, state); + return _rygel_start_doing (dev_ctx_c, uri, metadata, state, args); } /* --- LOCAL HELPER FUNCTIONS --- */ @@ -311,6 +312,22 @@ STATIC char* _rygel_find_uri_for_metadata (dev_ctx_T* dev_ctx_c, char *metadata) return uri; } +STATIC char * _rygel_time_for_string (char *string) { + + int total_seconds; + unsigned int hours, minutes, seconds; + char *time; + + total_seconds = atoi (string); + hours = total_seconds / 3600; + minutes = (total_seconds / 60) - (hours * 60); + seconds = total_seconds - (hours * 3600) - (minutes * 60); + + asprintf (&time, "%u:%02u:%02u", hours, minutes, seconds); + + return time; +} + STATIC unsigned char _rygel_start_uploading (dev_ctx_T* dev_ctx_c, char *path, char *upload_id) { GUPnPServiceProxy *content_dir_proxy; @@ -366,7 +383,7 @@ STATIC unsigned char _rygel_start_uploading (dev_ctx_T* dev_ctx_c, char *path, c return 1; } -STATIC unsigned char _rygel_start_doing (dev_ctx_T* dev_ctx_c, char *uri, char *metadata, State state) { +STATIC unsigned char _rygel_start_doing (dev_ctx_T* dev_ctx_c, char *uri, char *metadata, State state, char *args) { GUPnPServiceProxy *av_transport_proxy; struct timeval tv_start, tv_now; @@ -376,6 +393,7 @@ STATIC unsigned char _rygel_start_doing (dev_ctx_T* dev_ctx_c, char *uri, char * return 0; } dev_ctx_c->target_state = state; + dev_ctx_c->action_args = args; av_transport_proxy = GUPNP_SERVICE_PROXY (dev_ctx_c->av_transport); gupnp_service_proxy_begin_action (av_transport_proxy, "SetAVTransportURI", _rygel_select_cb, dev_ctx_c, @@ -543,6 +561,7 @@ STATIC void _rygel_select_cb (GUPnPServiceProxy *av_transport, GUPnPServiceProxy dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data; GUPnPServiceProxy *av_transport_proxy; GError *error; + char *time; struct timeval tv_start, tv_now; av_transport_proxy = GUPNP_SERVICE_PROXY (av_transport); @@ -566,6 +585,13 @@ STATIC void _rygel_select_cb (GUPnPServiceProxy *av_transport, GUPnPServiceProxy "InstanceID", G_TYPE_UINT, 0, NULL); break; + case SEEK: + time = _rygel_time_for_string (dev_ctx_c->action_args); + gupnp_service_proxy_begin_action (av_transport_proxy, "Seek", _rygel_do_cb, dev_ctx_c, + "InstanceID", G_TYPE_UINT, 0, + "Unit", G_TYPE_STRING, "ABS_TIME", + "Target", G_TYPE_STRING, time, + NULL); default: break; } diff --git a/plugins/media/media-rygel.h b/plugins/media/media-rygel.h index c70ff5c3..278881c0 100644 --- a/plugins/media/media-rygel.h +++ b/plugins/media/media-rygel.h @@ -32,7 +32,7 @@ #define URN_CONTENT_DIR "urn:schemas-upnp-org:service:ContentDirectory" #define URN_AV_TRANSPORT "urn:schemas-upnp-org:service:AVTransport" -typedef enum { PLAY, PAUSE, STOP } State; +typedef enum { PLAY, PAUSE, STOP, SEEK } State; typedef struct dev_ctx dev_ctx_T; struct dev_ctx { @@ -45,6 +45,7 @@ struct dev_ctx { int content_num; State state; State target_state; + char *action_args; char *transfer_path; unsigned char transfer_started; }; @@ -55,7 +56,7 @@ STATIC char* _rygel_find_id_for_index (dev_ctx_T *, char *, unsigned int); STATIC char* _rygel_find_metadata_for_id (dev_ctx_T *, char *); STATIC char* _rygel_find_uri_for_metadata (dev_ctx_T *, char *); STATIC unsigned char _rygel_start_uploading (dev_ctx_T *, char *, char *); -STATIC unsigned char _rygel_start_doing (dev_ctx_T *, char *, char *, State); +STATIC unsigned char _rygel_start_doing (dev_ctx_T *, char *, char *, State, char *); STATIC unsigned char _rygel_find_av_transport (dev_ctx_T *); STATIC void _rygel_device_cb (GUPnPControlPoint *, GUPnPDeviceProxy *, gpointer); STATIC void _rygel_av_transport_cb (GUPnPControlPoint *, GUPnPDeviceProxy *, gpointer); |