[vlc-commits] preparser: provide events in callbacks
Romain Vimont
git at videolan.org
Mon Aug 20 13:59:11 CEST 2018
vlc | branch: master | Romain Vimont <rom1v at videolabs.io> | Fri Aug 10 15:39:16 2018 +0200| [812579453b64824f5d775b14f936ef23308e1523] | committer: Romain Vimont
preparser: provide events in callbacks
The input thread used by the preparser is not exposed to the caller.
Add a "callbacks" parameter to receive preparsing events.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=812579453b64824f5d775b14f936ef23308e1523
---
include/vlc_input_item.h | 10 +++-
lib/media.c | 2 +-
modules/gui/macosx/VLCPlaylistInfo.m | 3 +-
src/libvlc.c | 8 +++-
src/libvlc.h | 2 +
src/playlist/item.c | 3 +-
src/preparser/preparser.c | 90 ++++++++++++++++++++++++++++++++----
src/preparser/preparser.h | 4 +-
test/libvlc/media.c | 3 +-
9 files changed, 107 insertions(+), 18 deletions(-)
diff --git a/include/vlc_input_item.h b/include/vlc_input_item.h
index 38cc0e82c2..cd22b3277d 100644
--- a/include/vlc_input_item.h
+++ b/include/vlc_input_item.h
@@ -39,6 +39,7 @@
typedef struct input_item_opaque input_item_opaque_t;
typedef struct input_item_slave input_item_slave_t;
+typedef struct input_preparser_callbacks_t input_preparser_callbacks_t;
struct info_t
{
@@ -379,7 +380,7 @@ typedef enum input_item_meta_request_option_t
META_REQUEST_OPTION_DO_INTERACT = 0x04
} input_item_meta_request_option_t;
-/* status of the vlc_InputItemPreparseEnded event */
+/* status of the on_preparse_ended() callback */
enum input_item_preparse_status
{
ITEM_PREPARSE_SKIPPED,
@@ -388,8 +389,15 @@ enum input_item_preparse_status
ITEM_PREPARSE_DONE
};
+typedef struct input_preparser_callbacks_t {
+ void (*on_preparse_ended)(input_item_t *, enum input_item_preparse_status status, void *userdata);
+ void (*on_subtree_added)(input_item_t *, input_item_node_t *subtree, void *userdata);
+} input_preparser_callbacks_t;
+
VLC_API int libvlc_MetadataRequest( libvlc_int_t *, input_item_t *,
input_item_meta_request_option_t,
+ const input_preparser_callbacks_t *cbs,
+ void *cbs_userdata,
int, void * );
VLC_API int libvlc_ArtRequest(libvlc_int_t *, input_item_t *,
input_item_meta_request_option_t );
diff --git a/lib/media.c b/lib/media.c
index 5ffa91b47d..5ed5e2eaa1 100644
--- a/lib/media.c
+++ b/lib/media.c
@@ -811,7 +811,7 @@ static int media_parse(libvlc_media_t *media, bool b_async,
parse_scope |= META_REQUEST_OPTION_SCOPE_NETWORK;
if (parse_flag & libvlc_media_do_interact)
parse_scope |= META_REQUEST_OPTION_DO_INTERACT;
- ret = libvlc_MetadataRequest(libvlc, item, parse_scope, timeout, media);
+ ret = libvlc_MetadataRequest(libvlc, item, parse_scope, NULL, NULL, timeout, media);
if (ret != VLC_SUCCESS)
return ret;
}
diff --git a/modules/gui/macosx/VLCPlaylistInfo.m b/modules/gui/macosx/VLCPlaylistInfo.m
index 4fac0ae2d4..fdd4cfbe05 100644
--- a/modules/gui/macosx/VLCPlaylistInfo.m
+++ b/modules/gui/macosx/VLCPlaylistInfo.m
@@ -198,7 +198,8 @@
[_imageWell setImage: [NSImage imageNamed: @"noart.png"]];
} else {
if (!input_item_IsPreparsed(p_item))
- libvlc_MetadataRequest(getIntf()->obj.libvlc, p_item, META_REQUEST_OPTION_NONE, -1, NULL);
+ libvlc_MetadataRequest(getIntf()->obj.libvlc, p_item, META_REQUEST_OPTION_NONE,
+ NULL, NULL, -1, NULL);
/* fill uri info */
char *psz_url = vlc_uri_decode(input_item_GetURI(p_item));
diff --git a/src/libvlc.c b/src/libvlc.c
index 1f4fed6107..55604c1b79 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -472,6 +472,8 @@ static void GetFilenames( libvlc_int_t *p_vlc, unsigned n,
int vlc_MetadataRequest(libvlc_int_t *libvlc, input_item_t *item,
input_item_meta_request_option_t i_options,
+ const input_preparser_callbacks_t *cbs,
+ void *cbs_userdata,
int timeout, void *id)
{
libvlc_priv_t *priv = libvlc_priv(libvlc);
@@ -485,7 +487,7 @@ int vlc_MetadataRequest(libvlc_int_t *libvlc, input_item_t *item,
item->b_preparse_interact = true;
vlc_mutex_unlock( &item->lock );
}
- input_preparser_Push( priv->parser, item, i_options, timeout, id );
+ input_preparser_Push( priv->parser, item, i_options, cbs, cbs_userdata, timeout, id );
return VLC_SUCCESS;
}
@@ -497,6 +499,8 @@ int vlc_MetadataRequest(libvlc_int_t *libvlc, input_item_t *item,
*/
int libvlc_MetadataRequest(libvlc_int_t *libvlc, input_item_t *item,
input_item_meta_request_option_t i_options,
+ const input_preparser_callbacks_t *cbs,
+ void *cbs_userdata,
int timeout, void *id)
{
libvlc_priv_t *priv = libvlc_priv(libvlc);
@@ -509,7 +513,7 @@ int libvlc_MetadataRequest(libvlc_int_t *libvlc, input_item_t *item,
item->i_preparse_depth = 1;
vlc_mutex_unlock( &item->lock );
- return vlc_MetadataRequest(libvlc, item, i_options, timeout, id);
+ return vlc_MetadataRequest(libvlc, item, i_options, cbs, cbs_userdata, timeout, id);
}
/**
diff --git a/src/libvlc.h b/src/libvlc.h
index 5040968d57..6c0381122b 100644
--- a/src/libvlc.h
+++ b/src/libvlc.h
@@ -204,6 +204,8 @@ void intf_DestroyAll( libvlc_int_t * );
int vlc_MetadataRequest(libvlc_int_t *libvlc, input_item_t *item,
input_item_meta_request_option_t i_options,
+ const input_preparser_callbacks_t *cbs,
+ void *cbs_userdata,
int timeout, void *id);
/*
diff --git a/src/playlist/item.c b/src/playlist/item.c
index d365ca1e18..9e3d0fac43 100644
--- a/src/playlist/item.c
+++ b/src/playlist/item.c
@@ -744,7 +744,8 @@ static void playlist_Preparse( playlist_t *p_playlist,
if( sys->b_preparse && !input_item_IsPreparsed( input )
&& (EMPTY_STR(psz_artist) || EMPTY_STR(psz_album)) )
- vlc_MetadataRequest( p_playlist->obj.libvlc, input, 0, -1, p_item );
+ vlc_MetadataRequest( p_playlist->obj.libvlc, input, 0,
+ NULL, NULL, -1, p_item );
free( psz_artist );
free( psz_album );
}
diff --git a/src/preparser/preparser.c b/src/preparser/preparser.c
index 42ab9d7694..78e41f045a 100644
--- a/src/preparser/preparser.c
+++ b/src/preparser/preparser.c
@@ -24,6 +24,7 @@
#endif
#include <vlc_common.h>
+#include <vlc_atomic.h>
#include "misc/background_worker.h"
#include "input/input_interface.h"
@@ -39,15 +40,55 @@ struct input_preparser_t
atomic_bool deactivated;
};
+typedef struct input_preparser_req_t
+{
+ input_item_t *item;
+ const input_preparser_callbacks_t *cbs;
+ void *userdata;
+ vlc_atomic_rc_t rc;
+} input_preparser_req_t;
+
typedef struct input_preparser_task_t
{
+ input_preparser_req_t *req;
input_preparser_t* preparser;
input_thread_t* input;
atomic_int state;
atomic_bool done;
-
} input_preparser_task_t;
+static input_preparser_req_t *ReqCreate(input_item_t *item,
+ const input_preparser_callbacks_t *cbs,
+ void *userdata)
+{
+ input_preparser_req_t *req = malloc(sizeof(*req));
+ if (unlikely(!req))
+ return NULL;
+
+ req->item = item;
+ req->cbs = cbs;
+ req->userdata = userdata;
+ vlc_atomic_rc_init(&req->rc);
+
+ input_item_Hold(item);
+
+ return req;
+}
+
+static void ReqHold(input_preparser_req_t *req)
+{
+ vlc_atomic_rc_inc(&req->rc);
+}
+
+static void ReqRelease(input_preparser_req_t *req)
+{
+ if (vlc_atomic_rc_dec(&req->rc))
+ {
+ input_item_Release(req->item);
+ free(req);
+ }
+}
+
static void InputEvent( input_thread_t *input, void *task_,
const struct vlc_input_event *event )
{
@@ -64,13 +105,21 @@ static void InputEvent( input_thread_t *input, void *task_,
atomic_store( &task->done, true );
background_worker_RequestProbe( task->preparser->worker );
break;
+ case INPUT_EVENT_SUBITEMS:
+ {
+ input_preparser_req_t *req = task->req;
+ if (req->cbs && req->cbs->on_subtree_added)
+ req->cbs->on_subtree_added(req->item, event->subitems, req->userdata);
+ break;
+ }
default: ;
}
}
-static int PreparserOpenInput( void* preparser_, void* item_, void** out )
+static int PreparserOpenInput( void* preparser_, void* req_, void** out )
{
input_preparser_t* preparser = preparser_;
+ input_preparser_req_t *req = req_;
input_preparser_task_t* task = malloc( sizeof *task );
if( unlikely( !task ) )
@@ -81,10 +130,12 @@ static int PreparserOpenInput( void* preparser_, void* item_, void** out )
task->preparser = preparser_;
task->input = input_CreatePreparser( preparser->owner, InputEvent,
- task, item_ );
+ task, req->item );
if( !task->input )
goto error;
+ task->req = req;
+
if( input_Start( task->input ) )
{
input_Close( task->input );
@@ -97,7 +148,10 @@ static int PreparserOpenInput( void* preparser_, void* item_, void** out )
error:
free( task );
- input_item_SignalPreparseEnded( item_, ITEM_PREPARSE_FAILED );
+ /* TODO remove legacy input_item_SignalPreparseEnded() */
+ input_item_SignalPreparseEnded(req->item, ITEM_PREPARSE_FAILED);
+ if (req->cbs && req->cbs->on_preparse_ended)
+ req->cbs->on_preparse_ended(req->item, ITEM_PREPARSE_FAILED, req->userdata);
return VLC_EGENERIC;
}
@@ -111,6 +165,7 @@ static int PreparserProbeInput( void* preparser_, void* task_ )
static void PreparserCloseInput( void* preparser_, void* task_ )
{
input_preparser_task_t* task = task_;
+ input_preparser_req_t *req = task->req;
input_preparser_t* preparser = preparser_;
input_thread_t* input = task->input;
@@ -141,11 +196,14 @@ static void PreparserCloseInput( void* preparser_, void* task_ )
}
input_item_SetPreparsed( item, true );
+ /* TODO remove legacy input_item_SignalPreparseEnded() */
input_item_SignalPreparseEnded( item, status );
+ if (req->cbs && req->cbs->on_preparse_ended)
+ req->cbs->on_preparse_ended(req->item, status, req->userdata);
}
-static void InputItemRelease( void* item ) { input_item_Release( item ); }
-static void InputItemHold( void* item ) { input_item_Hold( item ); }
+static void ReqHoldVoid(void *item) { ReqHold(item); }
+static void ReqReleaseVoid(void *item) { ReqRelease(item); }
input_preparser_t* input_preparser_New( vlc_object_t *parent )
{
@@ -157,8 +215,9 @@ input_preparser_t* input_preparser_New( vlc_object_t *parent )
.pf_start = PreparserOpenInput,
.pf_probe = PreparserProbeInput,
.pf_stop = PreparserCloseInput,
- .pf_release = InputItemRelease,
- .pf_hold = InputItemHold };
+ .pf_release = ReqReleaseVoid,
+ .pf_hold = ReqHoldVoid
+ };
if( likely( preparser ) )
@@ -182,6 +241,7 @@ input_preparser_t* input_preparser_New( vlc_object_t *parent )
void input_preparser_Push( input_preparser_t *preparser,
input_item_t *item, input_item_meta_request_option_t i_options,
+ const input_preparser_callbacks_t *cbs, void *cbs_userdata,
int timeout, void *id )
{
if( atomic_load( &preparser->deactivated ) )
@@ -202,12 +262,24 @@ void input_preparser_Push( input_preparser_t *preparser,
break;
/* fallthrough */
default:
+ /* TODO remove legacy input_item_SignalPreparseEnded() */
input_item_SignalPreparseEnded( item, ITEM_PREPARSE_SKIPPED );
+ if (cbs && cbs->on_preparse_ended)
+ cbs->on_preparse_ended(item, ITEM_PREPARSE_SKIPPED, cbs_userdata);
return;
}
- if( background_worker_Push( preparser->worker, item, id, timeout ) )
+ struct input_preparser_req_t *req = ReqCreate(item, cbs, cbs_userdata);
+
+ if (background_worker_Push(preparser->worker, req, id, timeout))
+ {
+ /* TODO remove legacy input_item_SignalPreparseEnded() */
input_item_SignalPreparseEnded( item, ITEM_PREPARSE_FAILED );
+ if (req->cbs && cbs->on_preparse_ended)
+ cbs->on_preparse_ended(item, ITEM_PREPARSE_FAILED, cbs_userdata);
+ }
+
+ ReqRelease(req);
}
void input_preparser_fetcher_Push( input_preparser_t *preparser,
diff --git a/src/preparser/preparser.h b/src/preparser/preparser.h
index 7cc9930eba..9fe4ae8e87 100644
--- a/src/preparser/preparser.h
+++ b/src/preparser/preparser.h
@@ -45,8 +45,6 @@ input_preparser_t *input_preparser_New( vlc_object_t * );
*
* The input item is retained until the preparsing is done or until the
* preparser object is deleted.
- * Listen to vlc_InputItemPreparseEnded event to get notified when item is
- * preparsed.
*
* @param timeout maximum time allowed to preparse the item. If -1, the default
* "preparse-timeout" option will be used as a timeout. If 0, it will wait
@@ -56,6 +54,8 @@ input_preparser_t *input_preparser_New( vlc_object_t * );
*/
void input_preparser_Push( input_preparser_t *, input_item_t *,
input_item_meta_request_option_t,
+ const input_preparser_callbacks_t *cbs,
+ void *cbs_userdata,
int timeout, void *id );
void input_preparser_fetcher_Push( input_preparser_t *, input_item_t *,
diff --git a/test/libvlc/media.c b/test/libvlc/media.c
index 4de30c7187..933ca41f70 100644
--- a/test/libvlc/media.c
+++ b/test/libvlc/media.c
@@ -158,7 +158,8 @@ static void test_input_metadata_timeout(libvlc_instance_t *vlc, int timeout,
input_item_preparse_timeout, &sem);
assert(i_ret == 0);
i_ret = libvlc_MetadataRequest(vlc->p_libvlc_int, p_item,
- META_REQUEST_OPTION_SCOPE_LOCAL, timeout, vlc);
+ META_REQUEST_OPTION_SCOPE_LOCAL,
+ NULL, NULL, timeout, vlc);
assert(i_ret == 0);
if (wait_and_cancel > 0)
More information about the vlc-commits
mailing list