~ubuntu-branches/debian/wheezy/vlc/wheezy

« back to all changes in this revision

Viewing changes to modules/demux/m3u.c

Tags: upstream-0.7.2.final
ImportĀ upstreamĀ versionĀ 0.7.2.final

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * m3u.c: a meta demux to parse pls, m3u, asx et b4s playlists
 
3
 *****************************************************************************
 
4
 * Copyright (C) 2001-2004 VideoLAN
 
5
 * $Id: m3u.c 7442 2004-04-23 12:46:34Z gbazin $
 
6
 *
 
7
 * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
 
8
 *          Gildas Bazin <gbazin@netcourrier.com>
 
9
 *          Clļæ½ment Stenac <zorglub@via.ecp.fr>
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2 of the License, or
 
14
 * (at your option) any later version.
 
15
 *
 
16
 * This program is distributed in the hope that it will be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this program; if not, write to the Free Software
 
23
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 
24
 *****************************************************************************/
 
25
 
 
26
/*****************************************************************************
 
27
 * Preamble
 
28
 *****************************************************************************/
 
29
#include <stdlib.h>                                      /* malloc(), free() */
 
30
 
 
31
#include <vlc/vlc.h>
 
32
#include <vlc/input.h>
 
33
#include <vlc_playlist.h>
 
34
 
 
35
/*****************************************************************************
 
36
 * Constants and structures
 
37
 *****************************************************************************/
 
38
#define MAX_LINE 8192
 
39
 
 
40
#define TYPE_UNKNOWN 0
 
41
#define TYPE_M3U 1
 
42
#define TYPE_ASX 2
 
43
#define TYPE_HTML 3
 
44
#define TYPE_PLS 4
 
45
#define TYPE_B4S 5
 
46
 
 
47
struct demux_sys_t
 
48
{
 
49
    int i_type;                                   /* playlist type (m3u/asx) */
 
50
};
 
51
 
 
52
/*****************************************************************************
 
53
 * Local prototypes
 
54
 *****************************************************************************/
 
55
static int  Activate  ( vlc_object_t * );
 
56
static void Deactivate( vlc_object_t * );
 
57
static int  Demux ( input_thread_t * );
 
58
 
 
59
/*****************************************************************************
 
60
 * Module descriptor
 
61
 *****************************************************************************/
 
62
vlc_module_begin();
 
63
    set_description( _("Playlist metademux") );
 
64
    set_capability( "demux", 180 );
 
65
    set_callbacks( Activate, Deactivate );
 
66
    add_shortcut( "m3u" );
 
67
    add_shortcut( "asx" );
 
68
    add_shortcut( "html" );
 
69
    add_shortcut( "pls" );
 
70
    add_shortcut( "b4s" );
 
71
vlc_module_end();
 
72
 
 
73
/*****************************************************************************
 
74
 * Activate: initializes m3u demux structures
 
75
 *****************************************************************************/
 
76
static int Activate( vlc_object_t * p_this )
 
77
{
 
78
    input_thread_t *p_input = (input_thread_t *)p_this;
 
79
    char           *psz_ext;
 
80
    int             i_type  = TYPE_UNKNOWN;
 
81
    int             i_type2 = TYPE_UNKNOWN;
 
82
 
 
83
    /* Initialize access plug-in structures. */
 
84
    if( p_input->i_mtu == 0 )
 
85
    {
 
86
        /* Improve speed. */
 
87
        p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
 
88
    }
 
89
 
 
90
    p_input->pf_demux = Demux;
 
91
    p_input->pf_rewind = NULL;
 
92
 
 
93
    /* Check for m3u/asx file extension or if the demux has been forced */
 
94
    psz_ext = strrchr ( p_input->psz_name, '.' );
 
95
 
 
96
    if( ( psz_ext && !strcasecmp( psz_ext, ".m3u") ) ||
 
97
        ( p_input->psz_demux && !strcmp(p_input->psz_demux, "m3u") ) )
 
98
    {
 
99
        i_type = TYPE_M3U;
 
100
    }
 
101
    else if( ( psz_ext && !strcasecmp( psz_ext, ".asx") ) ||
 
102
             ( p_input->psz_demux && !strcmp(p_input->psz_demux, "asx") ) )
 
103
    {
 
104
        i_type = TYPE_ASX;
 
105
    }
 
106
    else if( ( psz_ext && !strcasecmp( psz_ext, ".html") ) ||
 
107
             ( p_input->psz_demux && !strcmp(p_input->psz_demux, "html") ) )
 
108
    {
 
109
        i_type = TYPE_HTML;
 
110
    }
 
111
    else if( ( psz_ext && !strcasecmp( psz_ext, ".pls") ) ||
 
112
             ( p_input->psz_demux && !strcmp(p_input->psz_demux, "pls") ) )
 
113
    {
 
114
        i_type = TYPE_PLS;
 
115
    }
 
116
    else if( ( psz_ext && !strcasecmp( psz_ext, ".b4s") ) ||
 
117
             ( p_input->psz_demux && !strcmp(p_input->psz_demux, "b4s") ) )
 
118
    {
 
119
        i_type = TYPE_B4S;
 
120
    }
 
121
 
 
122
    /* we had no luck looking at the file extention, so we have a look
 
123
     * at the content. This is useful for .asp, .php and similar files
 
124
     * that are actually html. Also useful for some asx files that have
 
125
     * another extension */
 
126
    /* XXX we double check for file != m3u as some asx ... are just m3u file */
 
127
    if( i_type != TYPE_M3U )
 
128
    {
 
129
        byte_t *p_peek;
 
130
        int i_size = input_Peek( p_input, &p_peek, MAX_LINE );
 
131
        i_size -= sizeof("[playlist]") - 1;
 
132
        if ( i_size > 0 ) {
 
133
            while ( i_size
 
134
                    && strncasecmp( p_peek, "[playlist]", sizeof("[playlist]") - 1 )
 
135
                    && strncasecmp( p_peek, "<html>", sizeof("<html>") - 1 )
 
136
                    && strncasecmp( p_peek, "<asx", sizeof("<asx") - 1 )
 
137
                    && strncasecmp( p_peek, "<?xml", sizeof("<?xml") -1 ) )
 
138
            {
 
139
                p_peek++;
 
140
                i_size--;
 
141
            }
 
142
            if ( !i_size )
 
143
            {
 
144
                ;
 
145
            }
 
146
            else if ( !strncasecmp( p_peek, "[playlist]", sizeof("[playlist]") -1 ) )
 
147
            {
 
148
                i_type2 = TYPE_PLS;
 
149
            }
 
150
            else if ( !strncasecmp( p_peek, "<html>", sizeof("<html>") -1 ) )
 
151
            {
 
152
                i_type2 = TYPE_HTML;
 
153
            }
 
154
            else if ( !strncasecmp( p_peek, "<asx", sizeof("<asx") -1 ) )
 
155
            {
 
156
                i_type2 = TYPE_ASX;
 
157
            }
 
158
#if 0
 
159
            else if ( !strncasecmp( p_peek, "<?xml", sizeof("<?xml") -1 ) )
 
160
            {
 
161
                i_type2 = TYPE_B4S;
 
162
            }
 
163
#endif
 
164
        }
 
165
    }
 
166
    if ( i_type == TYPE_UNKNOWN && i_type2 == TYPE_UNKNOWN)
 
167
    {
 
168
        return VLC_EGENERIC;
 
169
    }
 
170
    if ( i_type  != TYPE_UNKNOWN && i_type2 == TYPE_UNKNOWN )
 
171
    {
 
172
        i_type = TYPE_M3U;
 
173
    }
 
174
    else
 
175
    {
 
176
        i_type = i_type2;
 
177
    }
 
178
 
 
179
    /* Allocate p_m3u */
 
180
    p_input->p_demux_data = malloc( sizeof( demux_sys_t ) );
 
181
    p_input->p_demux_data->i_type = i_type;
 
182
 
 
183
    return VLC_SUCCESS;
 
184
}
 
185
 
 
186
/*****************************************************************************
 
187
 * Deactivate: frees unused data
 
188
 *****************************************************************************/
 
189
static void Deactivate( vlc_object_t *p_this )
 
190
{
 
191
    input_thread_t *p_input = (input_thread_t *)p_this;
 
192
 
 
193
    free( p_input->p_demux_data );
 
194
}
 
195
 
 
196
/*****************************************************************************
 
197
 * XMLSpecialChars: Handle the special chars in a XML file.
 
198
 * ***************************************************************************/
 
199
static void XMLSpecialChars ( char *str )
 
200
{
 
201
    char *src = str;
 
202
    char *dst = str;
 
203
 
 
204
    while( *src )
 
205
    {
 
206
        if( *src == '&' )
 
207
        {
 
208
            if( !strncasecmp( src, "&#xe0;", 6 ) ) *dst++ = 'ļæ½';
 
209
            else if( !strncasecmp( src, "&#xee;", 6 ) ) *dst++ = 'ļæ½';
 
210
            else if( !strncasecmp( src, "&apos;", 6 ) ) *dst++ = '\'';
 
211
            else if( !strncasecmp( src, "&#xe8;", 6 ) ) *dst++ = 'ļæ½';
 
212
            else if( !strncasecmp( src, "&#xe9;", 6 ) ) *dst++ = 'ļæ½';
 
213
            else if( !strncasecmp( src, "&#xea;", 6 ) ) *dst++ = 'ļæ½';
 
214
            else
 
215
            {
 
216
                *dst++ = '?';
 
217
            }
 
218
            src += 6;
 
219
        }
 
220
        else
 
221
        {
 
222
            *dst++ = *src++;
 
223
        }
 
224
    }
 
225
 
 
226
    *dst = '\0';
 
227
}
 
228
 
 
229
/*****************************************************************************
 
230
 * ParseLine: read a "line" from the file and add any entries found
 
231
 * to the playlist. Returns:
 
232
 * 0 if nothing was found
 
233
 * 1 if a URI was found (it is then copied in psz_data)
 
234
 * 2 if a name was found (  "  )
 
235
 *
 
236
 * XXX psz_data has the same length that psz_line so no problem if you don't
 
237
 * expand it
 
238
 *    psz_line is \0 terminated
 
239
 *****************************************************************************/
 
240
static int ParseLine( input_thread_t *p_input, char *psz_line, char *psz_data,
 
241
                      vlc_bool_t *pb_next )
 
242
{
 
243
    demux_sys_t   *p_m3u = p_input->p_demux_data;
 
244
    char          *psz_bol, *psz_name;
 
245
 
 
246
    psz_bol = psz_line;
 
247
 
 
248
    *pb_next = VLC_FALSE;
 
249
 
 
250
    /* Remove unnecessary tabs or spaces at the beginning of line */
 
251
    while( *psz_bol == ' ' || *psz_bol == '\t' ||
 
252
           *psz_bol == '\n' || *psz_bol == '\r' )
 
253
    {
 
254
        psz_bol++;
 
255
    }
 
256
 
 
257
    if( p_m3u->i_type == TYPE_M3U )
 
258
    {
 
259
        /* Check for comment line */
 
260
        if( *psz_bol == '#' )
 
261
        {
 
262
            while( *psz_bol &&
 
263
                   strncasecmp( psz_bol, "EXTINF:",
 
264
                                sizeof("EXTINF:") - 1 ) &&
 
265
                   strncasecmp( psz_bol, "EXTVLCOPT:",
 
266
                                sizeof("EXTVLCOPT:") - 1 ) ) psz_bol++;
 
267
 
 
268
            if( !*psz_bol ) return 0;
 
269
 
 
270
            if( !strncasecmp( psz_bol, "EXTINF:", sizeof("EXTINF:") - 1 ) )
 
271
            {
 
272
                psz_bol = strchr( psz_bol, ',' );
 
273
                if ( !psz_bol ) return 0;
 
274
                psz_bol++;
 
275
 
 
276
                /* From now, we have a name line */
 
277
                strcpy( psz_data , psz_bol );
 
278
                return 2;
 
279
            }
 
280
            else
 
281
            {
 
282
                psz_bol = strchr( psz_bol, ':' );
 
283
                if ( !psz_bol ) return 0;
 
284
                psz_bol++;
 
285
 
 
286
                strcpy( psz_data , psz_bol );
 
287
                return 3;
 
288
            }
 
289
        }
 
290
        /* If we don't have a comment, the line is directly the URI */
 
291
    }
 
292
    else if ( p_m3u->i_type == TYPE_PLS )
 
293
    {
 
294
        /* We are dealing with .pls files from shoutcast
 
295
         * We are looking for lines like "File1=http://..." */
 
296
        if( !strncasecmp( psz_bol, "File", sizeof("File") - 1 ) )
 
297
        {
 
298
            psz_bol += sizeof("File") - 1;
 
299
            psz_bol = strchr( psz_bol, '=' );
 
300
            if ( !psz_bol ) return 0;
 
301
            psz_bol++;
 
302
        }
 
303
        else
 
304
        {
 
305
            return 0;
 
306
        }
 
307
    }
 
308
    else if ( p_m3u->i_type == TYPE_ASX )
 
309
    {
 
310
        /* We are dealing with ASX files.
 
311
         * We are looking for "<ref href=" xml markups that
 
312
         * begins with "mms://", "http://" or "file://" */
 
313
        char *psz_eol;
 
314
 
 
315
        while( *psz_bol &&
 
316
               strncasecmp( psz_bol, "ref", sizeof("ref") - 1 ) )
 
317
            psz_bol++;
 
318
 
 
319
        if( !*psz_bol ) return 0;
 
320
 
 
321
        while( *psz_bol &&
 
322
               strncasecmp( psz_bol, "href", sizeof("href") - 1 ) )
 
323
            psz_bol++;
 
324
 
 
325
        if( !*psz_bol ) return 0;
 
326
 
 
327
        while( *psz_bol &&
 
328
               strncasecmp( psz_bol, "mms://",
 
329
                            sizeof("mms://") - 1 ) &&
 
330
               strncasecmp( psz_bol, "mmsu://",
 
331
                            sizeof("mmsu://") - 1 ) &&
 
332
               strncasecmp( psz_bol, "mmst://",
 
333
                            sizeof("mmst://") - 1 ) &&
 
334
               strncasecmp( psz_bol, "http://",
 
335
                            sizeof("http://") - 1 ) &&
 
336
               strncasecmp( psz_bol, "file://",
 
337
                            sizeof("file://") - 1 ) )
 
338
            psz_bol++;
 
339
 
 
340
        if( !*psz_bol ) return 0;
 
341
 
 
342
        psz_eol = strchr( psz_bol, '"');
 
343
        if( !psz_eol )
 
344
          return 0;
 
345
 
 
346
        *psz_eol = '\0';
 
347
    }
 
348
    else if ( p_m3u->i_type == TYPE_HTML )
 
349
    {
 
350
        /* We are dealing with a html file with embedded
 
351
         * video.  We are looking for "<param name="filename"
 
352
         * value=" html markups that begin with "http://" */
 
353
        char *psz_eol;
 
354
 
 
355
        while( *psz_bol &&
 
356
               strncasecmp( psz_bol, "param", sizeof("param") - 1 ) )
 
357
            psz_bol++;
 
358
 
 
359
        if( !*psz_bol ) return 0;
 
360
 
 
361
        while( *psz_bol &&
 
362
               strncasecmp( psz_bol, "filename", sizeof("filename") - 1 ) )
 
363
            psz_bol++;
 
364
 
 
365
        if( !*psz_bol ) return 0;
 
366
 
 
367
        while( *psz_bol &&
 
368
               strncasecmp( psz_bol, "http://",
 
369
                            sizeof("http://") - 1 ) )
 
370
            psz_bol++;
 
371
 
 
372
        if( !*psz_bol ) return 0;
 
373
 
 
374
        psz_eol = strchr( psz_bol, '"');
 
375
        if( !psz_eol )
 
376
          return 0;
 
377
 
 
378
        *psz_eol = '\0';
 
379
 
 
380
    }
 
381
    else if ( p_m3u->i_type == TYPE_B4S )
 
382
    {
 
383
 
 
384
        char *psz_eol;
 
385
 
 
386
        msg_Dbg( p_input, "b4s line=%s", psz_line );
 
387
        /* We are dealing with a B4S file from Winamp 3 */
 
388
 
 
389
        /* First, search for name *
 
390
         * <Name>Blabla</Name> */
 
391
 
 
392
        if( strstr ( psz_bol, "<Name>" ) )
 
393
        {
 
394
            /* We have a name */
 
395
            while ( *psz_bol &&
 
396
                    strncasecmp( psz_bol,"Name",sizeof("Name") -1 ) )
 
397
                psz_bol++;
 
398
 
 
399
            if( !*psz_bol ) return 0;
 
400
 
 
401
            psz_bol = psz_bol + 5 ;
 
402
            /* We are now at the beginning of the name */
 
403
 
 
404
            if( !psz_bol ) return 0;
 
405
 
 
406
 
 
407
            psz_eol = strchr(psz_bol, '<' );
 
408
            if( !psz_eol) return 0;
 
409
 
 
410
            *psz_eol='\0';
 
411
 
 
412
            XMLSpecialChars( psz_bol );
 
413
 
 
414
            strcpy( psz_data, psz_bol );
 
415
            return 2;
 
416
        }
 
417
        else if( strstr( psz_bol, "</entry>" ) || strstr( psz_bol, "</Entry>" ))
 
418
        {
 
419
            *pb_next = VLC_TRUE;
 
420
            return 0;
 
421
        }
 
422
 
 
423
         /* We are looking for <entry Playstring="blabla"> */
 
424
 
 
425
 
 
426
        while ( *psz_bol &&
 
427
                strncasecmp( psz_bol,"Playstring",sizeof("Playstring") -1 ) )
 
428
            psz_bol++;
 
429
 
 
430
        if( !*psz_bol ) return 0;
 
431
 
 
432
        psz_bol = strchr( psz_bol, '=' );
 
433
        if ( !psz_bol ) return 0;
 
434
 
 
435
        psz_bol += 2;
 
436
 
 
437
        psz_eol= strchr(psz_bol, '"');
 
438
        if( !psz_eol ) return 0;
 
439
 
 
440
        *psz_eol= '\0';
 
441
 
 
442
        /* Handle the XML special characters */
 
443
        XMLSpecialChars( psz_bol );
 
444
    }
 
445
    else
 
446
    {
 
447
        msg_Warn( p_input, "unknown file type" );
 
448
        return 0;
 
449
    }
 
450
 
 
451
    /* empty line */
 
452
    if ( !*psz_bol ) return 0;
 
453
 
 
454
    /*
 
455
     * From now on, we know we've got a meaningful line
 
456
     */
 
457
 
 
458
    /* check for a protocol name */
 
459
    /* for URL, we should look for "://"
 
460
     * for MRL (Media Resource Locator) ([[<access>][/<demux>]:][<source>]),
 
461
     * we should look for ":"
 
462
     * so we end up looking simply for ":"*/
 
463
    /* PB: on some file systems, ':' are valid characters though*/
 
464
    psz_name = psz_bol;
 
465
    while( *psz_name && *psz_name!=':' )
 
466
    {
 
467
        psz_name++;
 
468
    }
 
469
#ifdef WIN32
 
470
    if ( *psz_name && ( psz_name == psz_bol + 1 ) )
 
471
    {
 
472
        /* if it is not an URL,
 
473
         * as it is unlikely to be an MRL (PB: if it is ?)
 
474
         * it should be an absolute file name with the drive letter */
 
475
        if ( *(psz_name+1) == '/' )/* "*:/" */
 
476
        {
 
477
            if ( *(psz_name+2) != '/' )/* not "*://" */
 
478
                while ( *psz_name ) *psz_name++;/* so now (*psz_name==0) */
 
479
        }
 
480
        else while ( *psz_name ) *psz_name++;/* "*:*"*/
 
481
    }
 
482
#endif
 
483
 
 
484
    /* if the line doesn't specify a protocol name,
 
485
     * check if the line has an absolute or relative path */
 
486
#ifndef WIN32
 
487
    if( !*psz_name && *psz_bol != '/' )
 
488
         /* If this line doesn't begin with a '/' */
 
489
#else
 
490
    if( !*psz_name
 
491
            && *psz_bol!='/'
 
492
            && *psz_bol!='\\'
 
493
            && *(psz_bol+1)!=':' )
 
494
         /* if this line doesn't begin with
 
495
          *  "/" or "\" or "*:" or "*:\" or "*:/" or "\\" */
 
496
#endif
 
497
    {
 
498
        /* assume the path is relative to the path of the m3u file. */
 
499
        char *psz_path = strdup( p_input->psz_name );
 
500
 
 
501
#ifndef WIN32
 
502
        psz_name = strrchr( psz_path, '/' );
 
503
#else
 
504
        psz_name = strrchr( psz_path, '\\' );
 
505
        if ( ! psz_name ) psz_name = strrchr( psz_path, '/' );
 
506
#endif
 
507
        if( psz_name ) *psz_name = '\0';
 
508
        else *psz_path = '\0';
 
509
#ifndef WIN32
 
510
        psz_name = malloc( strlen(psz_path) + strlen(psz_bol) + 2 );
 
511
        sprintf( psz_name, "%s/%s", psz_path, psz_bol );
 
512
#else
 
513
        if ( *psz_path != '\0' )
 
514
        {
 
515
            psz_name = malloc( strlen(psz_path) + strlen(psz_bol) + 2 );
 
516
            sprintf( psz_name, "%s\\%s", psz_path, psz_bol );
 
517
        }
 
518
        else psz_name = strdup( psz_bol );
 
519
#endif
 
520
        free( psz_path );
 
521
    }
 
522
    else
 
523
    {
 
524
        psz_name = strdup( psz_bol );
 
525
    }
 
526
 
 
527
    strcpy(psz_data, psz_name ) ;
 
528
 
 
529
    free( psz_name );
 
530
 
 
531
    if( p_m3u->i_type != TYPE_B4S )
 
532
    {
 
533
       *pb_next = VLC_TRUE;
 
534
    }
 
535
 
 
536
    return 1;
 
537
}
 
538
 
 
539
static void ProcessLine ( input_thread_t *p_input, playlist_t *p_playlist,
 
540
                          char *psz_line,
 
541
                          char **ppsz_uri, char **ppsz_name,
 
542
                          int *pi_options, char ***pppsz_options,
 
543
                          int *pi_position )
 
544
{
 
545
    char          psz_data[MAX_LINE];
 
546
    vlc_bool_t    b_next;
 
547
 
 
548
    switch( ParseLine( p_input, psz_line, psz_data, &b_next ) )
 
549
    {
 
550
        case 1:
 
551
            if( *ppsz_uri )
 
552
            {
 
553
                free( *ppsz_uri );
 
554
            }
 
555
            *ppsz_uri = strdup( psz_data );
 
556
            break;
 
557
        case 2:
 
558
            if( *ppsz_name )
 
559
            {
 
560
                free( *ppsz_name );
 
561
            }
 
562
            *ppsz_name = strdup( psz_data );
 
563
            break;
 
564
        case 3:
 
565
            (*pi_options)++;
 
566
            *pppsz_options = realloc( *pppsz_options,
 
567
                                      sizeof(char *) * *pi_options );
 
568
            (*pppsz_options)[*pi_options - 1] = strdup( psz_data );
 
569
            break;
 
570
        case 0:
 
571
        default:
 
572
            break;
 
573
    }
 
574
 
 
575
    if( b_next && *ppsz_uri )
 
576
    {
 
577
        playlist_AddExt( p_playlist, *ppsz_uri, *ppsz_name,
 
578
                         PLAYLIST_INSERT, *pi_position,
 
579
                         -1, (const char **)*pppsz_options, *pi_options );
 
580
 
 
581
        (*pi_position)++;
 
582
        if( *ppsz_name ) free( *ppsz_name ); *ppsz_name = NULL;
 
583
        free( *ppsz_uri ); *ppsz_uri  = NULL;
 
584
 
 
585
        for( ; *pi_options; (*pi_options)-- )
 
586
        {
 
587
            free( (*pppsz_options)[*pi_options - 1] );
 
588
            if( *pi_options == 1 ) free( *pppsz_options );
 
589
        }
 
590
        *pppsz_options = NULL;
 
591
    }
 
592
}
 
593
 
 
594
/*****************************************************************************
 
595
 * Demux: reads and demuxes data packets
 
596
 *****************************************************************************
 
597
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 
598
 *****************************************************************************/
 
599
static int Demux ( input_thread_t *p_input )
 
600
{
 
601
    demux_sys_t   *p_m3u = p_input->p_demux_data;
 
602
 
 
603
    data_packet_t *p_data;
 
604
    char          psz_line[MAX_LINE];
 
605
    char          *p_buf, eol_tok;
 
606
    int           i_size, i_bufpos, i_linepos = 0;
 
607
    playlist_t    *p_playlist;
 
608
    vlc_bool_t    b_discard = VLC_FALSE;
 
609
 
 
610
    char          *psz_name = NULL;
 
611
    char          *psz_uri  = NULL;
 
612
    int           i_options = 0;
 
613
    char          **ppsz_options = NULL;
 
614
 
 
615
    int           i_position;
 
616
 
 
617
    p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
 
618
                                                 FIND_ANYWHERE );
 
619
    if( !p_playlist )
 
620
    {
 
621
        msg_Err( p_input, "can't find playlist" );
 
622
        return -1;
 
623
    }
 
624
 
 
625
    p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
 
626
    i_position = p_playlist->i_index + 1;
 
627
 
 
628
    /* Depending on wether we are dealing with an m3u/asf file, the end of
 
629
     * line token will be different */
 
630
    if( p_m3u->i_type == TYPE_ASX || p_m3u->i_type == TYPE_HTML )
 
631
        eol_tok = '>';
 
632
    else
 
633
        eol_tok = '\n';
 
634
 
 
635
    while( ( i_size = input_SplitBuffer( p_input, &p_data, MAX_LINE ) ) > 0 )
 
636
    {
 
637
        i_bufpos = 0; p_buf = p_data->p_payload_start;
 
638
 
 
639
        while( i_size )
 
640
        {
 
641
            /* Build a line < MAX_LINE */
 
642
            while( p_buf[i_bufpos] != eol_tok && i_size )
 
643
            {
 
644
                if( i_linepos == MAX_LINE || b_discard == VLC_TRUE )
 
645
                {
 
646
                    /* line is bigger than MAX_LINE, discard it */
 
647
                    i_linepos = 0;
 
648
                    b_discard = VLC_TRUE;
 
649
                }
 
650
                else
 
651
                {
 
652
                    if ( eol_tok != '\n' || p_buf[i_bufpos] != '\r' )
 
653
                    {
 
654
                        psz_line[i_linepos] = p_buf[i_bufpos];
 
655
                        i_linepos++;
 
656
                    }
 
657
                }
 
658
 
 
659
                i_size--; i_bufpos++;
 
660
            }
 
661
 
 
662
            /* Check if we need more data */
 
663
            if( !i_size ) continue;
 
664
 
 
665
            i_size--; i_bufpos++;
 
666
            b_discard = VLC_FALSE;
 
667
 
 
668
            /* Check for empty line */
 
669
            if( !i_linepos ) continue;
 
670
 
 
671
            psz_line[i_linepos] = '\0';
 
672
            i_linepos = 0;
 
673
 
 
674
            ProcessLine( p_input, p_playlist, psz_line, &psz_uri, &psz_name,
 
675
                         &i_options, &ppsz_options, &i_position );
 
676
        }
 
677
 
 
678
        input_DeletePacket( p_input->p_method_data, p_data );
 
679
    }
 
680
 
 
681
    if ( i_linepos && b_discard != VLC_TRUE && eol_tok == '\n' )
 
682
    {
 
683
        psz_line[i_linepos] = '\0';
 
684
 
 
685
        ProcessLine( p_input, p_playlist, psz_line, &psz_uri, &psz_name,
 
686
                     &i_options, &ppsz_options, &i_position );
 
687
 
 
688
        /* Is there a pendding uri without b_next */
 
689
        if( psz_uri )
 
690
        {
 
691
            playlist_AddExt( p_playlist, psz_uri, psz_name,
 
692
                             PLAYLIST_INSERT, i_position,
 
693
                             -1, (const char **)ppsz_options, i_options );
 
694
        }
 
695
    }
 
696
 
 
697
    if( psz_uri ) free( psz_uri );
 
698
    if( psz_name ) free( psz_name );
 
699
    for( ; i_options; i_options-- )
 
700
    {
 
701
        free( ppsz_options[i_options - 1] );
 
702
        if( i_options == 1 ) free( ppsz_options );
 
703
    }
 
704
 
 
705
    vlc_object_release( p_playlist );
 
706
 
 
707
    return 0;
 
708
}