access: rist: fix misspellings on help text
[vlc.git] / src / input / stream_extractor.c
blobc8e9298ab08b6c9cf01f8341096c3a94f753010c
1 /*****************************************************************************
2 * stream_extractor.c
3 *****************************************************************************
4 * Copyright (C) 2016 VLC authors and VideoLAN
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifndef STREAM_EXTRACTOR_H
22 #define STREAM_EXTRACTOR_H
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include <vlc_common.h>
29 #include <vlc_stream.h>
30 #include <vlc_stream_extractor.h>
31 #include <vlc_modules.h>
32 #include <vlc_url.h>
33 #include <vlc_memstream.h>
34 #include <libvlc.h>
35 #include <assert.h>
37 #include "stream.h"
38 #include "mrl_helpers.h"
40 /**
41 * \defgroup stream_extractor_Internals Stream Extractor Internals
42 * \ingroup stream_extractor
43 * \internal
44 * @{
45 * \file
46 **/
48 struct stream_extractor_private {
49 union {
50 stream_extractor_t extractor;
51 stream_directory_t directory;
54 /**
55 * Callback to handle initialization
57 * \ref pf_init will be called after successful module probing to initialize
58 * the relevant members of the underlying stream-extractor object, as well
59 * as the wrapping stream.
60 **/
61 int (*pf_init)( struct stream_extractor_private*, stream_t* );
63 /**
64 * Callback to handle clean-up
66 * \ref pf_clean, unless NULL, will be called when the stream-extractor is to
67 * be destroyed, and shall be used to clean-up resources (acquired during
68 * initialization, see \ref pf_init).
70 void (*pf_clean)( struct stream_extractor_private* );
72 stream_t* wrapper; /**< the wrapping \ref stream_t used to access the
73 underlying stream-extractor */
75 stream_t* source; /**< the source stream consumed by the stream-extractor */
76 module_t* module; /**< the stream-extractor module */
78 vlc_object_t* object; /**< the underlying stream-extractor object */
81 /**
82 * Create an MRL for a specific sub-entry
84 * This internal function is used to create an MRL that refers to \subentry
85 * within \ref base, see \ref mrl_helpers for further information.
86 **/
88 static char*
89 StreamExtractorCreateMRL( char const* base, char const* subentry )
91 struct vlc_memstream buffer;
92 char* escaped;
94 if( mrl_EscapeFragmentIdentifier( &escaped, subentry ) )
95 return NULL;
97 if( vlc_memstream_open( &buffer ) )
99 free( escaped );
100 return NULL;
103 vlc_memstream_puts( &buffer, base );
105 if( !strstr( base, "#" ) )
106 vlc_memstream_putc( &buffer, '#' );
108 vlc_memstream_printf( &buffer, "!/%s", escaped );
110 free( escaped );
111 return vlc_memstream_close( &buffer ) ? NULL : buffer.ptr;
115 * Release the private data associated with a stream-extractor
116 * \param priv pointer to the private section
118 static void se_Release( struct stream_extractor_private* priv )
120 if( priv->pf_clean )
121 priv->pf_clean( priv );
123 if( priv->module )
125 module_unneed( priv->object, priv->module );
127 if( priv->source )
128 vlc_stream_Delete( priv->source );
131 vlc_object_release( priv->object );
135 * \name Callbacks to forward work to the underlying stream-extractor
137 * @{
140 static void
141 se_StreamDelete( stream_t* stream )
143 se_Release( stream->p_sys );
146 static ssize_t
147 se_StreamRead( stream_t* stream, void* buf, size_t len )
149 struct stream_extractor_private* priv = stream->p_sys;
150 return priv->extractor.pf_read( &priv->extractor, buf, len );
153 static block_t*
154 se_StreamBlock( stream_t* stream, bool* eof )
156 struct stream_extractor_private* priv = stream->p_sys;
157 return priv->extractor.pf_block( &priv->extractor, eof );
160 static int
161 se_StreamSeek( stream_t* stream, uint64_t offset )
163 struct stream_extractor_private* priv = stream->p_sys;
164 return priv->extractor.pf_seek( &priv->extractor, offset );
167 static int
168 se_ReadDir( stream_t* stream, input_item_node_t* node )
170 struct stream_extractor_private* priv = stream->p_sys;
171 return priv->directory.pf_readdir( &priv->directory, node );
174 static int
175 se_StreamControl( stream_t* stream, int req, va_list args )
177 struct stream_extractor_private* priv = stream->p_sys;
178 return priv->extractor.pf_control( &priv->extractor, req, args );
181 static int
182 se_DirControl( stream_t* stream, int req, va_list args )
184 (void)stream;
185 (void)req;
186 (void)args;
188 return VLC_EGENERIC;
192 * @}
196 * \name stream-extractor resource handlers
197 * \ingroup stream_extractor
198 * @{
201 static int
202 se_InitStream( struct stream_extractor_private* priv, stream_t* s )
204 if( priv->extractor.pf_read ) s->pf_read = se_StreamRead;
205 else s->pf_block = se_StreamBlock;
207 s->pf_seek = se_StreamSeek;
208 s->pf_control = se_StreamControl;
209 s->psz_url = StreamExtractorCreateMRL( priv->extractor.source->psz_url,
210 priv->extractor.identifier );
211 if( unlikely( !s->psz_url ) )
212 return VLC_ENOMEM;
214 return VLC_SUCCESS;
217 static void
218 se_CleanStream( struct stream_extractor_private* priv )
220 free( (char*)priv->extractor.identifier );
223 static int
224 se_InitDirectory( struct stream_extractor_private* priv, stream_t* s )
226 stream_directory_t* directory = &priv->directory;
228 s->pf_readdir = se_ReadDir;
229 s->pf_control = se_DirControl;
230 s->psz_url = strdup( directory->source->psz_url );
232 if( unlikely( !s->psz_url ) )
233 return VLC_EGENERIC;
235 return VLC_SUCCESS;
239 * @}
243 * Create the public stream_t that wraps a stream-extractor
245 * This initializes the relevant data-members of the public stream_t which is
246 * used to read from the underlying stream-extractor.
248 * \param priv the private section of the stream_extractor_t
249 * \param source the source stream which the stream_extractor_t should
250 * will read from
251 * \return VLC_SUCCESS on success, an error-code on failure.
253 static int
254 se_AttachWrapper( struct stream_extractor_private* priv, stream_t* source )
256 stream_t* s = vlc_stream_CommonNew( source->obj.parent, se_StreamDelete );
258 if( unlikely( !s ) )
259 return VLC_ENOMEM;
261 if( priv->pf_init( priv, s ) )
263 stream_CommonDelete( s );
264 return VLC_EGENERIC;
267 priv->wrapper = s;
268 priv->wrapper->p_input_item = source->p_input_item;
269 priv->wrapper->p_sys = priv;
271 priv->source = source;
273 priv->wrapper = stream_FilterChainNew( priv->wrapper, "cache" );
274 return VLC_SUCCESS;
277 static int
278 StreamExtractorAttach( stream_t** source, char const* identifier,
279 char const* module_name )
281 const bool extractor = identifier != NULL;
282 char const* capability = extractor ? "stream_extractor"
283 : "stream_directory";
285 struct stream_extractor_private* priv = vlc_custom_create(
286 (*source)->obj.parent, sizeof( *priv ), capability );
288 if( unlikely( !priv ) )
289 return VLC_ENOMEM;
291 if( extractor )
293 priv->object = VLC_OBJECT( &priv->extractor );
295 priv->pf_init = se_InitStream;
296 priv->pf_clean = se_CleanStream;
298 priv->extractor.source = *source;
299 priv->extractor.identifier = strdup( identifier );
301 if( unlikely( !priv->extractor.identifier ) )
302 goto error;
304 else
306 priv->object = VLC_OBJECT( &priv->directory );
308 priv->pf_init = se_InitDirectory;
309 priv->pf_clean = NULL;
311 priv->directory.source = *source;
314 priv->module = module_need( priv->object, capability, module_name, true );
316 if( !priv->module || se_AttachWrapper( priv, *source ) )
317 goto error;
319 *source = priv->wrapper;
320 return VLC_SUCCESS;
322 error:
323 se_Release( priv );
324 return VLC_EGENERIC;
328 vlc_stream_directory_Attach( stream_t** source, char const* module_name )
330 return StreamExtractorAttach( source, NULL, module_name );
334 vlc_stream_extractor_Attach( stream_t** source, char const* identifier,
335 char const* module_name )
337 return StreamExtractorAttach( source, identifier, module_name );
341 stream_extractor_AttachParsed( stream_t** source, char const* data,
342 char const** out_extra )
344 vlc_array_t identifiers;
346 if( mrl_FragmentSplit( &identifiers, out_extra, data ) )
347 return VLC_EGENERIC;
349 size_t count = vlc_array_count( &identifiers );
350 size_t idx = 0;
352 while( idx < count )
354 char* id = vlc_array_item_at_index( &identifiers, idx );
356 if( vlc_stream_extractor_Attach( source, id, NULL ) )
357 break;
359 ++idx;
362 for( size_t i = 0; i < count; ++i )
363 free( vlc_array_item_at_index( &identifiers, i ) );
364 vlc_array_clear( &identifiers );
366 return idx == count ? VLC_SUCCESS : VLC_EGENERIC;
369 char*
370 vlc_stream_extractor_CreateMRL( stream_directory_t* directory,
371 char const* subentry )
373 return StreamExtractorCreateMRL( directory->source->psz_url, subentry );
377 * @}
380 #endif /* include-guard */