diff --git a/include/vlc_stream_extractor.h b/include/vlc_stream_extractor.h index bb4a736380..da659e12f7 100644 --- a/include/vlc_stream_extractor.h +++ b/include/vlc_stream_extractor.h @@ -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 ); /** * @} */ diff --git a/modules/gui/skins2/src/theme_loader.cpp b/modules/gui/skins2/src/theme_loader.cpp index ea0c35a3e0..c496c84f5f 100644 --- a/modules/gui/skins2/src/theme_loader.cpp +++ b/modules/gui/skins2/src/theme_loader.cpp @@ -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!" ); } diff --git a/modules/lua/libs/stream.c b/modules/lua/libs/stream.c index 29ac68a177..b098649ba0 100644 --- a/modules/lua/libs/stream.c +++ b/modules/lua/libs/stream.c @@ -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 ); diff --git a/src/input/input.c b/src/input/input.c index b1d59b239c..38fa19e345 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -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 ) - { - char *list = NULL; - - for( int i = 0; i < count; i++ ) - { - 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) ) + for( int i = 0; i < count; i++ ) + { + char *psz = mrl_AppendAnchorFragment( psz_newanchor ? psz_newanchor : psz_anchor, tab[i] ); + if( psz ) { - 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 ); diff --git a/src/input/mrl_helpers.h b/src/input/mrl_helpers.h index a7fe2da1e5..9fc778a5be 100644 --- a/src/input/mrl_helpers.h +++ b/src/input/mrl_helpers.h @@ -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; diff --git a/src/input/stream_extractor.c b/src/input/stream_extractor.c index 5c5c42df32..f3d4583c5d 100644 --- a/src/input/stream_extractor.c +++ b/src/input/stream_extractor.c @@ -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; iextractor.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; idirectory.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_countmodule = 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;