Commit f93621c6 authored by Thomas Guillem's avatar Thomas Guillem

preparser: add a timeout in playlist_preparser_Push

By default, the timeout is 5 seconds, see "preparse_timeout" option.
parent 31dbe910
......@@ -395,6 +395,7 @@ enum input_item_preparse_status
{
ITEM_PREPARSE_SKIPPED,
ITEM_PREPARSE_FAILED,
ITEM_PREPARSE_TIMEOUT,
ITEM_PREPARSE_DONE
};
......
......@@ -1103,6 +1103,10 @@ static const char *const ppsz_prefres[] = {
"Automatically preparse files added to the playlist " \
"(to retrieve some metadata)." )
#define PREPARSE_TIMEOUT_TEXT N_( "Preparsing timeout" )
#define PREPARSE_TIMEOUT_LONGTEXT N_( \
"Maximum time allowed to preparse a file" )
#define METADATA_NETWORK_TEXT N_( "Allow metadata network access" )
#define SD_TEXT N_( "Services discovery modules")
......@@ -2032,6 +2036,9 @@ vlc_module_begin ()
add_bool( "auto-preparse", true, PREPARSE_TEXT,
PREPARSE_LONGTEXT, false )
add_integer( "preparse-timeout", 5000, PREPARSE_TIMEOUT_TEXT,
PREPARSE_TIMEOUT_LONGTEXT, false )
add_obsolete_integer( "album-art" )
add_bool( "metadata-network-access", false, METADATA_NETWORK_TEXT,
METADATA_NETWORK_TEXT, false )
......
......@@ -627,7 +627,7 @@ int libvlc_MetaRequest(libvlc_int_t *libvlc, input_item_t *item,
if( i_options & META_REQUEST_OPTION_DO_INTERACT )
item->b_preparse_interact = true;
vlc_mutex_unlock( &item->lock );
playlist_preparser_Push(priv->parser, item, i_options, NULL);
playlist_preparser_Push(priv->parser, item, i_options, -1, NULL);
return VLC_SUCCESS;
}
......
......@@ -781,7 +781,7 @@ static void GoAndPreparse( playlist_t *p_playlist, int i_mode,
char *psz_album = input_item_GetAlbum( p_item->p_input );
if( sys->p_preparser != NULL && !input_item_IsPreparsed( p_item->p_input )
&& (EMPTY_STR(psz_artist) || EMPTY_STR(psz_album)) )
playlist_preparser_Push( sys->p_preparser, p_item->p_input, 0, NULL );
playlist_preparser_Push( sys->p_preparser, p_item->p_input, 0, -1, NULL );
free( psz_artist );
free( psz_album );
}
......
......@@ -43,12 +43,14 @@ struct preparser_entry_t
input_item_t *p_item;
input_item_meta_request_option_t i_options;
void *id;
mtime_t timeout;
};
struct playlist_preparser_t
{
vlc_object_t *object;
playlist_fetcher_t *p_fetcher;
mtime_t default_timeout;
input_thread_t *input;
void *input_id;
......@@ -77,6 +79,7 @@ playlist_preparser_t *playlist_preparser_New( vlc_object_t *parent )
p_preparser->input_id = NULL;
p_preparser->input_done = false;
p_preparser->object = parent;
p_preparser->default_timeout = var_InheritInteger( parent, "preparse-timeout" );
p_preparser->p_fetcher = playlist_fetcher_New( parent );
if( unlikely(p_preparser->p_fetcher == NULL) )
msg_Err( parent, "cannot create fetcher" );
......@@ -93,7 +96,7 @@ playlist_preparser_t *playlist_preparser_New( vlc_object_t *parent )
void playlist_preparser_Push( playlist_preparser_t *p_preparser, input_item_t *p_item,
input_item_meta_request_option_t i_options,
void *id )
int timeout, void *id )
{
preparser_entry_t *p_entry = malloc( sizeof(preparser_entry_t) );
......@@ -102,6 +105,7 @@ void playlist_preparser_Push( playlist_preparser_t *p_preparser, input_item_t *p
p_entry->p_item = p_item;
p_entry->i_options = i_options;
p_entry->id = id;
p_entry->timeout = (timeout < 0 ? p_preparser->default_timeout : timeout) * 1000;
vlc_gc_incref( p_entry->p_item );
vlc_mutex_lock( &p_preparser->lock );
......@@ -227,6 +231,7 @@ static void Preparse( playlist_preparser_t *preparser,
/* Do not preparse if it is already done (like by playing it) */
if( b_preparse && !input_item_IsPreparsed( p_item ) )
{
int status;
preparser->input = input_CreatePreparser( preparser->object, p_item );
if( preparser->input == NULL )
{
......@@ -240,9 +245,24 @@ static void Preparse( playlist_preparser_t *preparser,
preparser );
if( input_Start( preparser->input ) == VLC_SUCCESS )
{
while( !preparser->input_done )
vlc_cond_wait( &preparser->thread_wait, &preparser->lock );
if( p_entry->timeout > 0 )
{
mtime_t deadline = mdate() + p_entry->timeout;
int ret = 0;
while( !preparser->input_done && ret == 0 )
ret = vlc_cond_timedwait( &preparser->thread_wait,
&preparser->lock, deadline );
status = ret == 0 ? ITEM_PREPARSE_DONE : ITEM_PREPARSE_TIMEOUT;
}
else
{
while( !preparser->input_done )
vlc_cond_wait( &preparser->thread_wait, &preparser->lock );
status = ITEM_PREPARSE_DONE;
}
}
else
status = ITEM_PREPARSE_FAILED;
var_DelCallback( preparser->input, "intf-event", InputEvent,
preparser );
......@@ -252,7 +272,7 @@ static void Preparse( playlist_preparser_t *preparser,
var_SetAddress( preparser->object, "item-change", p_item );
input_item_SetPreparsed( p_item, true );
input_item_SignalPreparseEnded( p_item, ITEM_PREPARSE_DONE );
input_item_SignalPreparseEnded( p_item, status );
}
else if (!b_preparse)
input_item_SignalPreparseEnded( p_item, ITEM_PREPARSE_SKIPPED );
......
......@@ -48,11 +48,15 @@ playlist_preparser_t *playlist_preparser_New( vlc_object_t * );
* 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
* indefinitely. If > 0, the timeout will be used (in milliseconds).
* @param id unique id provided by the caller. This is can be used to cancel
* the request with playlist_preparser_Cancel()
*/
void playlist_preparser_Push( playlist_preparser_t *, input_item_t *,
input_item_meta_request_option_t, void *id );
input_item_meta_request_option_t,
int timeout, void *id );
void playlist_preparser_fetcher_Push( playlist_preparser_t *, input_item_t *,
input_item_meta_request_option_t );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment