mirror of https://code.videolan.org/videolan/vlc
stream_extractor: store and forward volume information
Also propagates missing volume information to directories listing. Until now it was assumed archives only had direcoty info in the first volume.
This commit is contained in:
parent
b84d09bd98
commit
9856c789ec
|
@ -64,6 +64,8 @@ typedef struct stream_extractor_t {
|
|||
int (*pf_control)(struct stream_extractor_t*, int request, va_list args);
|
||||
/** @} */
|
||||
|
||||
char ** volumes;
|
||||
size_t volumes_count;
|
||||
char const* identifier; /**< the name of the entity to be extracted */
|
||||
stream_t* source; /**< the source stream to be consumed */
|
||||
void* p_sys; /**< private opaque handle to be used by the module */
|
||||
|
@ -84,6 +86,8 @@ typedef struct stream_directory_t {
|
|||
int (*pf_readdir)(struct stream_directory_t*, input_item_node_t* );
|
||||
/** @} */
|
||||
|
||||
char ** volumes;
|
||||
size_t volumes_count;
|
||||
stream_t* source; /**< the source stream to be consumed */
|
||||
void* p_sys; /**< private opaque handle to be used by the module */
|
||||
|
||||
|
@ -146,6 +150,8 @@ VLC_API char* vlc_stream_extractor_CreateMRL( stream_directory_t *extractor,
|
|||
* \param identifier (if present) NULL or a c-style string referring to the
|
||||
* desired entity
|
||||
* \param module_name NULL or an explicit stream-extractor module name
|
||||
* \param volumes media additional volumes MRLs
|
||||
* \param volumes_count number of additional volumes
|
||||
*
|
||||
* \return VLC_SUCCESS if a stream-extractor was successfully
|
||||
* attached, an error-code on failure.
|
||||
|
@ -154,11 +160,13 @@ VLC_API char* vlc_stream_extractor_CreateMRL( stream_directory_t *extractor,
|
|||
**/
|
||||
|
||||
VLC_API int vlc_stream_extractor_Attach( stream_t** source,
|
||||
char const* identifier,
|
||||
char const* module_name );
|
||||
char const* identifier,
|
||||
char const* module_name,
|
||||
const char **volumes, size_t volumes_count );
|
||||
|
||||
VLC_API int vlc_stream_directory_Attach( stream_t** source,
|
||||
char const* module_name );
|
||||
char const* module_name,
|
||||
const char **volumes, size_t volumes_count );
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -227,7 +227,7 @@ bool ThemeLoader::unarchive( const std::string& fileName, const std::string &tem
|
|||
}
|
||||
|
||||
stream_t* stream = input.get();
|
||||
if( vlc_stream_directory_Attach( &stream, NULL ) )
|
||||
if( vlc_stream_directory_Attach( &stream, NULL, NULL, 0 ) )
|
||||
{
|
||||
msg_Err( getIntf(), "unable to attach stream_directory, treat as XML!" );
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ static int vlclua_directory_stream_new( lua_State *L )
|
|||
stream_t *p_stream = vlc_stream_NewURL( p_this, psz_url );
|
||||
if( !p_stream )
|
||||
return vlclua_error( L );
|
||||
if( vlc_stream_directory_Attach( &p_stream, NULL ) != VLC_SUCCESS )
|
||||
if( vlc_stream_directory_Attach( &p_stream, NULL, NULL, 0 ) != VLC_SUCCESS )
|
||||
{
|
||||
vlc_stream_Delete( p_stream );
|
||||
return vlclua_error( L );
|
||||
|
|
|
@ -2552,7 +2552,9 @@ InputStreamHandleAnchor( input_thread_t *p_input, input_source_t *source,
|
|||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
if( vlc_stream_directory_Attach( stream, NULL ) )
|
||||
if( vlc_stream_directory_Attach( stream, NULL,
|
||||
(const char **) mrli.volumes.pp_elems,
|
||||
mrli.volumes.i_count ) )
|
||||
msg_Dbg( p_input, "attachment of directory-extractor failed for %s",
|
||||
(*stream)->psz_url );
|
||||
|
||||
|
@ -2701,6 +2703,7 @@ static int InputSourceInit( input_source_t *in, input_thread_t *p_input,
|
|||
}
|
||||
}
|
||||
|
||||
char *psz_newanchor = NULL;
|
||||
if( strcasecmp( psz_access, "concat" ) )
|
||||
{ /* Autodetect extra files if none specified */
|
||||
int count;
|
||||
|
@ -2708,28 +2711,16 @@ static int InputSourceInit( input_source_t *in, input_thread_t *p_input,
|
|||
|
||||
TAB_INIT( count, tab );
|
||||
InputGetExtraFiles( p_input, &count, &tab, &psz_access, psz_mrl );
|
||||
if( count > 0 )
|
||||
|
||||
for( int i = 0; i < count; i++ )
|
||||
{
|
||||
char *list = NULL;
|
||||
|
||||
for( int i = 0; i < count; i++ )
|
||||
char *psz = mrl_AppendAnchorFragment( psz_newanchor ? psz_newanchor : psz_anchor, tab[i] );
|
||||
if( psz )
|
||||
{
|
||||
char *str;
|
||||
if( asprintf( &str, "%s,%s", list ? list : psz_mrl,
|
||||
tab[i] ) < 0 )
|
||||
break;
|
||||
|
||||
free( tab[i] );
|
||||
free( list );
|
||||
list = str;
|
||||
}
|
||||
|
||||
var_Create( p_input, "concat-list", VLC_VAR_STRING );
|
||||
if( likely(list != NULL) )
|
||||
{
|
||||
var_SetString( p_input, "concat-list", list );
|
||||
free( list );
|
||||
free( psz_newanchor );
|
||||
psz_newanchor = psz;
|
||||
}
|
||||
free( tab[i] );
|
||||
}
|
||||
TAB_CLEAN( count, tab );
|
||||
}
|
||||
|
@ -2746,12 +2737,13 @@ static int InputSourceInit( input_source_t *in, input_thread_t *p_input,
|
|||
|
||||
if( es_out )
|
||||
in->p_demux = InputDemuxNew( p_input, es_out, in, url,
|
||||
psz_demux, psz_anchor );
|
||||
psz_demux, psz_newanchor ? psz_newanchor : psz_anchor );
|
||||
free( url );
|
||||
}
|
||||
else
|
||||
in->p_demux = NULL;
|
||||
|
||||
free( psz_newanchor );
|
||||
free( psz_demux_var );
|
||||
free( psz_dup );
|
||||
|
||||
|
|
|
@ -89,6 +89,36 @@ mrl_EscapeFragmentIdentifier( char const* payload )
|
|||
return mstream.ptr;
|
||||
}
|
||||
|
||||
static inline char *
|
||||
mrl_AppendAnchorFragment( const char *anchor, char const *payload )
|
||||
{
|
||||
struct vlc_memstream mstream;
|
||||
if( vlc_memstream_open( &mstream ) )
|
||||
return NULL;
|
||||
|
||||
if( anchor )
|
||||
vlc_memstream_puts( &mstream, anchor );
|
||||
else
|
||||
vlc_memstream_putc( &mstream, '#' );
|
||||
|
||||
char *escaped = mrl_EscapeFragmentIdentifier( payload );
|
||||
if( escaped == NULL )
|
||||
{
|
||||
if( !vlc_memstream_close( &mstream ) )
|
||||
free( mstream.ptr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vlc_memstream_puts( &mstream, "!+" );
|
||||
vlc_memstream_puts( &mstream, escaped );
|
||||
free( escaped );
|
||||
|
||||
if( vlc_memstream_close( &mstream ) )
|
||||
return NULL;
|
||||
|
||||
return mstream.ptr;
|
||||
}
|
||||
|
||||
struct mrl_info
|
||||
{
|
||||
vlc_array_t identifiers;
|
||||
|
|
|
@ -218,7 +218,8 @@ se_InitStream( struct stream_extractor_private* priv, stream_t* s )
|
|||
s->pf_control = se_StreamControl;
|
||||
s->psz_url = StreamExtractorCreateMRL( priv->extractor.source->psz_url,
|
||||
priv->extractor.identifier,
|
||||
NULL, 0 );
|
||||
(char const **) priv->extractor.volumes,
|
||||
priv->extractor.volumes_count );
|
||||
if( unlikely( !s->psz_url ) )
|
||||
return VLC_ENOMEM;
|
||||
|
||||
|
@ -226,9 +227,20 @@ se_InitStream( struct stream_extractor_private* priv, stream_t* s )
|
|||
}
|
||||
|
||||
static void
|
||||
se_CleanStream( struct stream_extractor_private* priv )
|
||||
se_CleanStreamExtractor( struct stream_extractor_private* priv )
|
||||
{
|
||||
free( (char*)priv->extractor.identifier );
|
||||
for( size_t i=0; i<priv->extractor.volumes_count; i++ )
|
||||
free( priv->extractor.volumes[i] );
|
||||
free( priv->extractor.volumes );
|
||||
}
|
||||
|
||||
static void
|
||||
se_CleanStreamDirectory( struct stream_extractor_private* priv )
|
||||
{
|
||||
for( size_t i=0; i<priv->directory.volumes_count; i++ )
|
||||
free( priv->directory.volumes[i] );
|
||||
free( priv->directory.volumes );
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -288,7 +300,7 @@ se_AttachWrapper( struct stream_extractor_private* priv, stream_t* source )
|
|||
|
||||
static int
|
||||
StreamExtractorAttach( stream_t** source, char const* identifier,
|
||||
char const* module_name )
|
||||
char const* module_name, const char **volumes, size_t volumes_count )
|
||||
{
|
||||
const bool extractor = identifier != NULL;
|
||||
char const* capability = extractor ? "stream_extractor"
|
||||
|
@ -300,27 +312,49 @@ StreamExtractorAttach( stream_t** source, char const* identifier,
|
|||
if( unlikely( !priv ) )
|
||||
return VLC_ENOMEM;
|
||||
|
||||
char ***dst_volumes;
|
||||
size_t * dst_volumes_count;
|
||||
|
||||
if( extractor )
|
||||
{
|
||||
priv->object = VLC_OBJECT( &priv->extractor );
|
||||
|
||||
priv->pf_init = se_InitStream;
|
||||
priv->pf_clean = se_CleanStream;
|
||||
priv->pf_clean = se_CleanStreamExtractor;
|
||||
|
||||
priv->extractor.source = *source;
|
||||
priv->extractor.identifier = strdup( identifier );
|
||||
|
||||
if( unlikely( !priv->extractor.identifier ) )
|
||||
goto error;
|
||||
|
||||
dst_volumes = &priv->extractor.volumes;
|
||||
dst_volumes_count = &priv->extractor.volumes_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->object = VLC_OBJECT( &priv->directory );
|
||||
|
||||
priv->pf_init = se_InitDirectory;
|
||||
priv->pf_clean = NULL;
|
||||
priv->pf_clean = se_CleanStreamDirectory;
|
||||
|
||||
priv->directory.source = *source;
|
||||
|
||||
dst_volumes = &priv->directory.volumes;
|
||||
dst_volumes_count = &priv->directory.volumes_count;
|
||||
}
|
||||
|
||||
if( volumes_count )
|
||||
{
|
||||
*dst_volumes = malloc(volumes_count * sizeof(char *));
|
||||
if( unlikely(!*dst_volumes) )
|
||||
goto error;
|
||||
for( *dst_volumes_count=0; *dst_volumes_count<volumes_count; (*dst_volumes_count)++ )
|
||||
{
|
||||
(*dst_volumes)[*dst_volumes_count] = strdup(volumes[*dst_volumes_count]);
|
||||
if( unlikely(!(*dst_volumes)[*dst_volumes_count]) )
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
priv->module = module_need( priv->object, capability, module_name, true );
|
||||
|
@ -337,16 +371,17 @@ error:
|
|||
}
|
||||
|
||||
int
|
||||
vlc_stream_directory_Attach( stream_t** source, char const* module_name )
|
||||
vlc_stream_directory_Attach( stream_t** source, char const* module_name,
|
||||
const char **volumes, size_t volumes_count )
|
||||
{
|
||||
return StreamExtractorAttach( source, NULL, module_name );
|
||||
return StreamExtractorAttach( source, NULL, module_name, volumes, volumes_count );
|
||||
}
|
||||
|
||||
int
|
||||
vlc_stream_extractor_Attach( stream_t** source, char const* identifier,
|
||||
char const* module_name )
|
||||
char const* module_name, const char **volumes, size_t volumes_count )
|
||||
{
|
||||
return StreamExtractorAttach( source, identifier, module_name );
|
||||
return StreamExtractorAttach( source, identifier, module_name, volumes, volumes_count );
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -359,7 +394,9 @@ stream_extractor_AttachParsed( stream_t** source, const struct mrl_info *mrli )
|
|||
{
|
||||
char* id = vlc_array_item_at_index( &mrli->identifiers, idx );
|
||||
|
||||
if( vlc_stream_extractor_Attach( source, id, NULL ) )
|
||||
if( vlc_stream_extractor_Attach( source, id, NULL,
|
||||
(char const **) mrli->volumes.pp_elems,
|
||||
mrli->volumes.i_count ) )
|
||||
break;
|
||||
|
||||
++idx;
|
||||
|
|
Loading…
Reference in New Issue