~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to modules/demux/m3u.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

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-2006 the VideoLAN team
5
 
 * $Id: 161136aacaa2919403ebccf6d912896e440d2721 $
6
 
 *
7
 
 * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
8
 
 *          Gildas Bazin <gbazin@videolan.org>
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 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
 
#define TYPE_WMP 6
47
 
#define TYPE_RTSP 7
48
 
 
49
 
struct demux_sys_t
50
 
{
51
 
    int i_type;                                   /* playlist type (m3u/asx) */
52
 
};
53
 
 
54
 
/*****************************************************************************
55
 
 * Local prototypes
56
 
 *****************************************************************************/
57
 
static int  Activate  ( vlc_object_t * );
58
 
static void Deactivate( vlc_object_t * );
59
 
static int  Demux     ( demux_t * );
60
 
static int  Control   ( demux_t *, int, va_list );
61
 
 
62
 
/*****************************************************************************
63
 
 * Module descriptor
64
 
 *****************************************************************************/
65
 
vlc_module_begin();
66
 
    set_category( CAT_INPUT );
67
 
    set_subcategory( SUBCAT_INPUT_DEMUX );
68
 
    set_description( _("Playlist metademux") );
69
 
    set_capability( "demux2", 5 );
70
 
    set_callbacks( Activate, Deactivate );
71
 
    add_shortcut( "m3u" );
72
 
    add_shortcut( "asx" );
73
 
    add_shortcut( "html" );
74
 
    add_shortcut( "pls" );
75
 
    add_shortcut( "b4s" );
76
 
vlc_module_end();
77
 
 
78
 
/*****************************************************************************
79
 
 * Activate: initializes m3u demux structures
80
 
 *****************************************************************************/
81
 
static int Activate( vlc_object_t * p_this )
82
 
{
83
 
    demux_t *p_demux = (demux_t *)p_this;
84
 
    char    *psz_ext;
85
 
    int     i_type  = TYPE_UNKNOWN;
86
 
    int     i_type2 = TYPE_UNKNOWN;
87
 
 
88
 
    p_demux->pf_control = Control;
89
 
    p_demux->pf_demux = Demux;
90
 
 
91
 
    /* Check for m3u/asx file extension or if the demux has been forced */
92
 
    psz_ext = strrchr ( p_demux->psz_path, '.' );
93
 
 
94
 
    if( ( psz_ext && !strcasecmp( psz_ext, ".m3u") ) ||
95
 
        /* a .ram file can contain a single rtsp link */
96
 
        ( psz_ext && !strcasecmp( psz_ext, ".ram") ) ||
97
 
        ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "m3u") ) )
98
 
    {
99
 
        i_type = TYPE_M3U;
100
 
    }
101
 
    else if( ( psz_ext && !strcasecmp( psz_ext, ".asx") ) ||
102
 
             ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "asx") ) )
103
 
    {
104
 
        i_type = TYPE_ASX;
105
 
    }
106
 
    else if( ( psz_ext && !strcasecmp( psz_ext, ".html") ) ||
107
 
             ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "html") ) )
108
 
    {
109
 
        i_type = TYPE_HTML;
110
 
    }
111
 
    else if( ( psz_ext && !strcasecmp( psz_ext, ".pls") ) ||
112
 
             ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "pls") ) )
113
 
    {
114
 
        i_type = TYPE_PLS;
115
 
    }
116
 
    else if( ( psz_ext && !strcasecmp( psz_ext, ".b4s") ) ||
117
 
             ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "b4s") ) )
118
 
    {
119
 
        i_type = TYPE_B4S;
120
 
    }
121
 
 
122
 
    /* we had no luck looking at the file extension, 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
 
    /* We double check for file != m3u as some asx are just m3u file */
127
 
    if( i_type != TYPE_M3U )
128
 
    {
129
 
        char *p_peek;
130
 
        int i_size = stream_Peek( p_demux->s, (uint8_t **)&p_peek, MAX_LINE );
131
 
        i_size -= sizeof("[Reference]") - 1;
132
 
 
133
 
        if( i_size > 0 )
134
 
        {
135
 
            while( i_size &&
136
 
                   strncasecmp(p_peek, "[playlist]", sizeof("[playlist]") - 1)
137
 
                   && strncasecmp( p_peek, "[Reference]", sizeof("[Reference]") - 1 )
138
 
                   && strncasecmp( p_peek, "<html>", sizeof("<html>") - 1 )
139
 
                   && strncasecmp( p_peek, "<asx", sizeof("<asx") - 1 )
140
 
                   && strncasecmp( p_peek, "rtsptext", sizeof("rtsptext") - 1 )
141
 
                   && strncasecmp( p_peek, "<?xml", sizeof("<?xml") -1 ) )
142
 
            {
143
 
                p_peek++;
144
 
                i_size--;
145
 
            }
146
 
            if( !i_size )
147
 
            {
148
 
                ;
149
 
            }
150
 
            else if( !strncasecmp( p_peek, "[playlist]", sizeof("[playlist]") -1 ) )
151
 
            {
152
 
                i_type2 = TYPE_PLS;
153
 
            }
154
 
            else if( !strncasecmp( p_peek, "[Reference]", sizeof("[Reference]") -1 ) )
155
 
            {
156
 
                i_type2 = TYPE_WMP;
157
 
            }
158
 
            else if( !strncasecmp( p_peek, "<html>", sizeof("<html>") -1 ) )
159
 
            {
160
 
                i_type2 = TYPE_HTML;
161
 
            }
162
 
            else if( !strncasecmp( p_peek, "<asx", sizeof("<asx") -1 ) )
163
 
            {
164
 
                i_type2 = TYPE_ASX;
165
 
            }
166
 
            else if( !strncasecmp( p_peek, "rtsptext", sizeof("rtsptext") -1 ) )
167
 
            {
168
 
                i_type2 = TYPE_RTSP;
169
 
            }
170
 
#if 0
171
 
            else if( !strncasecmp( p_peek, "<?xml", sizeof("<?xml") -1 ) )
172
 
            {
173
 
                i_type2 = TYPE_B4S;
174
 
            }
175
 
#endif
176
 
        }
177
 
    }
178
 
    if( i_type == TYPE_UNKNOWN && i_type2 == TYPE_UNKNOWN)
179
 
    {
180
 
        return VLC_EGENERIC;
181
 
    }
182
 
    if( i_type  != TYPE_UNKNOWN && i_type2 == TYPE_UNKNOWN )
183
 
    {
184
 
        i_type = TYPE_M3U;
185
 
    }
186
 
    else
187
 
    {
188
 
        i_type = i_type2;
189
 
    }
190
 
 
191
 
    /* Allocate p_m3u */
192
 
    p_demux->p_sys = malloc( sizeof( demux_sys_t ) );
193
 
    p_demux->p_sys->i_type = i_type;
194
 
    msg_Dbg( p_this, "playlist type: %d - %d", i_type, i_type2 );
195
 
 
196
 
    return VLC_SUCCESS;
197
 
}
198
 
 
199
 
/*****************************************************************************
200
 
 * Deactivate: frees unused data
201
 
 *****************************************************************************/
202
 
static void Deactivate( vlc_object_t *p_this )
203
 
{
204
 
    demux_t *p_demux = (demux_t *)p_this;
205
 
    free( p_demux->p_sys );
206
 
}
207
 
 
208
 
/*****************************************************************************
209
 
 * XMLSpecialChars: Handle the special chars in a XML file.
210
 
 * ***************************************************************************/
211
 
static void XMLSpecialChars ( char *str )
212
 
{
213
 
    char *src = str;
214
 
    char *dst = str;
215
 
 
216
 
    while( *src )
217
 
    {
218
 
        if( *src == '&' )
219
 
        {
220
 
            /* FIXME:
221
 
             * - should probably accept any sequence, rather than only those
222
 
             *   commonly found in French.
223
 
             * - output may have to be UTF-8 encoded (cannot assume Latin-1)
224
 
             */
225
 
            if( !strncasecmp( src, "&#xe0;", 6 ) ) *dst++ = '\xe0';
226
 
            else if( !strncasecmp( src, "&#xee;", 6 ) ) *dst++ = '\xee';
227
 
            else if( !strncasecmp( src, "&apos;", 6 ) ) *dst++ = '\'';
228
 
            else if( !strncasecmp( src, "&#xe8;", 6 ) ) *dst++ = '\xe8';
229
 
            else if( !strncasecmp( src, "&#xe9;", 6 ) ) *dst++ = '\xe9';
230
 
            else if( !strncasecmp( src, "&#xea;", 6 ) ) *dst++ = '\xea';
231
 
            else
232
 
            {
233
 
                *dst++ = '?';
234
 
            }
235
 
            src += 6;
236
 
        }
237
 
        else
238
 
        {
239
 
            *dst++ = *src++;
240
 
        }
241
 
    }
242
 
 
243
 
    *dst = '\0';
244
 
}
245
 
 
246
 
/*****************************************************************************
247
 
 * ParseLine: read a "line" from the file and add any entries found
248
 
 * to the playlist. Returns:
249
 
 * 0 if nothing was found
250
 
 * 1 if a URI was found (it is then copied in psz_data)
251
 
 * 2 if a name was found (  "  )
252
 
 *
253
 
 * XXX psz_data has the same length that psz_line so no problem if you don't
254
 
 * expand it
255
 
 *    psz_line is \0 terminated
256
 
 *****************************************************************************/
257
 
static int ParseLine( demux_t *p_demux, char *psz_line, char *psz_data,
258
 
                      vlc_bool_t *pb_done )
259
 
{
260
 
    demux_sys_t *p_m3u = p_demux->p_sys;
261
 
    char        *psz_bol, *psz_name;
262
 
 
263
 
    psz_bol = psz_line;
264
 
    *pb_done = VLC_FALSE;
265
 
 
266
 
    /* Remove unnecessary tabs or spaces at the beginning of line */
267
 
    while( *psz_bol == ' ' || *psz_bol == '\t' ||
268
 
           *psz_bol == '\n' || *psz_bol == '\r' )
269
 
    {
270
 
        psz_bol++;
271
 
    }
272
 
 
273
 
    if( p_m3u->i_type == TYPE_M3U )
274
 
    {
275
 
        /* Check for comment line */
276
 
        if( *psz_bol == '#' )
277
 
        {
278
 
            while( *psz_bol &&
279
 
                   strncasecmp( psz_bol, "EXTINF:",
280
 
                                sizeof("EXTINF:") - 1 ) &&
281
 
                   strncasecmp( psz_bol, "EXTVLCOPT:",
282
 
                                sizeof("EXTVLCOPT:") - 1 ) ) psz_bol++;
283
 
 
284
 
            if( !*psz_bol ) return 0;
285
 
 
286
 
            if( !strncasecmp( psz_bol, "EXTINF:", sizeof("EXTINF:") - 1 ) )
287
 
            {
288
 
                psz_bol = strchr( psz_bol, ',' );
289
 
                if ( !psz_bol ) return 0;
290
 
                psz_bol++;
291
 
 
292
 
                /* From now, we have a name line */
293
 
                strcpy( psz_data , psz_bol );
294
 
                return 2;
295
 
            }
296
 
            else
297
 
            {
298
 
                psz_bol = strchr( psz_bol, ':' );
299
 
                if ( !psz_bol ) return 0;
300
 
                psz_bol++;
301
 
 
302
 
                strcpy( psz_data , psz_bol );
303
 
                return 3;
304
 
            }
305
 
        }
306
 
        /* If we don't have a comment, the line is directly the URI */
307
 
    }
308
 
    else if( p_m3u->i_type == TYPE_PLS )
309
 
    {
310
 
        /* We are dealing with .pls files from shoutcast
311
 
         * We are looking for lines like "File1=http://..." */
312
 
        if( !strncasecmp( psz_bol, "File", sizeof("File") - 1 ) )
313
 
        {
314
 
            psz_bol += sizeof("File") - 1;
315
 
            psz_bol = strchr( psz_bol, '=' );
316
 
            if ( !psz_bol ) return 0;
317
 
            psz_bol++;
318
 
        }
319
 
        else
320
 
        {
321
 
            return 0;
322
 
        }
323
 
    }
324
 
    else if( p_m3u->i_type == TYPE_WMP )
325
 
    {
326
 
        /* We are dealing with some weird WMP stream playlist format
327
 
         * Hurray for idiotic M$. Lines look like: "Ref1=http://..." */
328
 
        if( !strncasecmp( psz_bol, "Ref", sizeof("Ref") - 1 ) )
329
 
        {
330
 
            psz_bol += sizeof("Ref") - 1;
331
 
            psz_bol = strchr( psz_bol, '=' );
332
 
            if ( !psz_bol ) return 0;
333
 
            psz_bol++;
334
 
            if( !strncasecmp( psz_bol, "http://", sizeof("http://") -1 ) )
335
 
            {
336
 
                psz_bol++;
337
 
                psz_bol[0] = 'm'; psz_bol[1] = 'm'; psz_bol[2] = 's';
338
 
            }
339
 
        }
340
 
        else
341
 
        {
342
 
            return 0;
343
 
        }
344
 
    }
345
 
    else if( p_m3u->i_type == TYPE_ASX )
346
 
    {
347
 
        /* We are dealing with ASX files.
348
 
         * We are looking for "<ref href=" xml markups that
349
 
         * begins with "mms://", "http://" or "file://" */
350
 
        char *psz_eol;
351
 
 
352
 
        while( *psz_bol &&
353
 
               strncasecmp( psz_bol, "ref", sizeof("ref") - 1 ) )
354
 
            psz_bol++;
355
 
 
356
 
        if( !*psz_bol ) return 0;
357
 
 
358
 
        while( *psz_bol &&
359
 
               strncasecmp( psz_bol, "href", sizeof("href") - 1 ) )
360
 
            psz_bol++;
361
 
 
362
 
        if( !*psz_bol ) return 0;
363
 
 
364
 
        while( *psz_bol &&
365
 
               strncasecmp( psz_bol, "mms://",
366
 
                            sizeof("mms://") - 1 ) &&
367
 
               strncasecmp( psz_bol, "mmsu://",
368
 
                            sizeof("mmsu://") - 1 ) &&
369
 
               strncasecmp( psz_bol, "mmst://",
370
 
                            sizeof("mmst://") - 1 ) &&
371
 
               strncasecmp( psz_bol, "http://",
372
 
                            sizeof("http://") - 1 ) &&
373
 
               strncasecmp( psz_bol, "file://",
374
 
                            sizeof("file://") - 1 ) )
375
 
            psz_bol++;
376
 
 
377
 
        if( !*psz_bol ) return 0;
378
 
 
379
 
        psz_eol = strchr( psz_bol, '"');
380
 
        if( !psz_eol )
381
 
          return 0;
382
 
 
383
 
        *psz_eol = '\0';
384
 
    }
385
 
    else if( p_m3u->i_type == TYPE_HTML )
386
 
    {
387
 
        /* We are dealing with a html file with embedded
388
 
         * video.  We are looking for "<param name="filename"
389
 
         * value=" html markups that begin with "http://" */
390
 
        char *psz_eol;
391
 
 
392
 
        while( *psz_bol &&
393
 
               strncasecmp( psz_bol, "param", sizeof("param") - 1 ) )
394
 
            psz_bol++;
395
 
 
396
 
        if( !*psz_bol ) return 0;
397
 
 
398
 
        while( *psz_bol &&
399
 
               strncasecmp( psz_bol, "filename", sizeof("filename") - 1 ) )
400
 
            psz_bol++;
401
 
 
402
 
        if( !*psz_bol ) return 0;
403
 
 
404
 
        while( *psz_bol &&
405
 
               strncasecmp( psz_bol, "http://",
406
 
                            sizeof("http://") - 1 ) )
407
 
            psz_bol++;
408
 
 
409
 
        if( !*psz_bol ) return 0;
410
 
 
411
 
        psz_eol = strchr( psz_bol, '"');
412
 
        if( !psz_eol )
413
 
          return 0;
414
 
 
415
 
        *psz_eol = '\0';
416
 
 
417
 
    }
418
 
    else if( p_m3u->i_type == TYPE_B4S )
419
 
    {
420
 
 
421
 
        char *psz_eol;
422
 
 
423
 
        msg_Dbg( p_demux, "b4s line=%s", psz_line );
424
 
        /* We are dealing with a B4S file from Winamp 3 */
425
 
 
426
 
        /* First, search for name *
427
 
         * <Name>Blabla</Name> */
428
 
 
429
 
        if( strstr ( psz_bol, "<Name>" ) )
430
 
        {
431
 
            /* We have a name */
432
 
            while ( *psz_bol &&
433
 
                    strncasecmp( psz_bol,"Name",sizeof("Name") -1 ) )
434
 
                psz_bol++;
435
 
 
436
 
            if( !*psz_bol ) return 0;
437
 
 
438
 
            psz_bol = psz_bol + 5 ;
439
 
            /* We are now at the beginning of the name */
440
 
 
441
 
            if( !psz_bol ) return 0;
442
 
 
443
 
 
444
 
            psz_eol = strchr(psz_bol, '<' );
445
 
            if( !psz_eol) return 0;
446
 
 
447
 
            *psz_eol='\0';
448
 
 
449
 
            XMLSpecialChars( psz_bol );
450
 
 
451
 
            strcpy( psz_data, psz_bol );
452
 
            return 2;
453
 
        }
454
 
        else if( strstr( psz_bol, "</entry>" ) || strstr( psz_bol, "</Entry>" ))
455
 
        {
456
 
            *pb_done = VLC_TRUE;
457
 
            return 0;
458
 
        }
459
 
 
460
 
        /* We are looking for <entry Playstring="blabla"> */
461
 
 
462
 
        while( *psz_bol &&
463
 
               strncasecmp( psz_bol,"Playstring",sizeof("Playstring") -1 ) )
464
 
            psz_bol++;
465
 
 
466
 
        if( !*psz_bol ) return 0;
467
 
 
468
 
        psz_bol = strchr( psz_bol, '=' );
469
 
        if ( !psz_bol ) return 0;
470
 
 
471
 
        psz_bol += 2;
472
 
 
473
 
        psz_eol= strchr(psz_bol, '"');
474
 
        if( !psz_eol ) return 0;
475
 
 
476
 
        *psz_eol= '\0';
477
 
 
478
 
        /* Handle the XML special characters */
479
 
        XMLSpecialChars( psz_bol );
480
 
    }
481
 
    else if( p_m3u->i_type == TYPE_RTSP )
482
 
    {
483
 
        /* We are dealing with rtsptext reference files
484
 
         * Ignore anthying that doesn't start with rtsp://..." */
485
 
        if( strncasecmp( psz_bol, "rtsp://", sizeof("rtsp://") - 1 ) )
486
 
        /* ignore */ return 0;
487
 
    }
488
 
    else
489
 
    {
490
 
        msg_Warn( p_demux, "unknown file type" );
491
 
        return 0;
492
 
    }
493
 
 
494
 
    /* empty line */
495
 
    if ( !*psz_bol ) return 0;
496
 
 
497
 
    /*
498
 
     * From now on, we know we've got a meaningful line
499
 
     */
500
 
 
501
 
    /* check for a protocol name */
502
 
    /* for URL, we should look for "://"
503
 
     * for MRL (Media Resource Locator) ([[<access>][/<demux>]:][<source>]),
504
 
     * we should look for ":"
505
 
     * so we end up looking simply for ":"*/
506
 
    /* PB: on some file systems, ':' are valid characters though*/
507
 
    psz_name = psz_bol;
508
 
    while( *psz_name && *psz_name!=':' )
509
 
    {
510
 
        psz_name++;
511
 
    }
512
 
#ifdef WIN32
513
 
    if ( *psz_name && ( psz_name == psz_bol + 1 ) )
514
 
    {
515
 
        /* if it is not an URL,
516
 
         * as it is unlikely to be an MRL (PB: if it is ?)
517
 
         * it should be an absolute file name with the drive letter */
518
 
        if ( *(psz_name+1) == '/' )/* "*:/" */
519
 
        {
520
 
            if ( *(psz_name+2) != '/' )/* not "*://" */
521
 
                while ( *psz_name ) *psz_name++;/* so now (*psz_name==0) */
522
 
        }
523
 
        else while ( *psz_name ) *psz_name++;/* "*:*"*/
524
 
    }
525
 
#endif
526
 
 
527
 
    /* if the line doesn't specify a protocol name,
528
 
     * check if the line has an absolute or relative path */
529
 
#ifndef WIN32
530
 
    if( !*psz_name && *psz_bol != '/' )
531
 
         /* If this line doesn't begin with a '/' */
532
 
#else
533
 
    if( !*psz_name
534
 
            && *psz_bol!='/'
535
 
            && *psz_bol!='\\'
536
 
            && *(psz_bol+1)!=':' )
537
 
         /* if this line doesn't begin with
538
 
          *  "/" or "\" or "*:" or "*:\" or "*:/" or "\\" */
539
 
#endif
540
 
    {
541
 
        /* assume the path is relative to the path of the m3u file. */
542
 
        char *psz_path = strdup( p_demux->psz_path );
543
 
 
544
 
#ifndef WIN32
545
 
        psz_name = strrchr( psz_path, '/' );
546
 
#else
547
 
        psz_name = strrchr( psz_path, '\\' );
548
 
        if ( ! psz_name ) psz_name = strrchr( psz_path, '/' );
549
 
#endif
550
 
        if( psz_name ) *psz_name = '\0';
551
 
        else *psz_path = '\0';
552
 
#ifndef WIN32
553
 
        psz_name = malloc( strlen(psz_path) + strlen(psz_bol) + 2 );
554
 
        sprintf( psz_name, "%s/%s", psz_path, psz_bol );
555
 
#else
556
 
        if ( *psz_path != '\0' )
557
 
        {
558
 
            psz_name = malloc( strlen(psz_path) + strlen(psz_bol) + 2 );
559
 
            sprintf( psz_name, "%s\\%s", psz_path, psz_bol );
560
 
        }
561
 
        else psz_name = strdup( psz_bol );
562
 
#endif
563
 
        free( psz_path );
564
 
    }
565
 
    else
566
 
    {
567
 
        psz_name = strdup( psz_bol );
568
 
    }
569
 
 
570
 
    strcpy(psz_data, psz_name ) ;
571
 
 
572
 
    free( psz_name );
573
 
 
574
 
    if( p_m3u->i_type != TYPE_B4S )
575
 
    {
576
 
       *pb_done = VLC_TRUE;
577
 
    }
578
 
 
579
 
    return 1;
580
 
}
581
 
 
582
 
static void ProcessLine ( demux_t *p_demux, playlist_t *p_playlist,
583
 
                          playlist_item_t *p_parent,
584
 
                          char *psz_line, char **ppsz_uri, char **ppsz_name,
585
 
                          int *pi_options, char ***pppsz_options,
586
 
                          vlc_bool_t b_flush )
587
 
{
588
 
    char psz_data[MAX_LINE];
589
 
    vlc_bool_t b_done;
590
 
 
591
 
    switch( ParseLine( p_demux, psz_line, psz_data, &b_done ) )
592
 
    {
593
 
        case 1:
594
 
            if( *ppsz_uri ) free( *ppsz_uri );
595
 
            *ppsz_uri = strdup( psz_data );
596
 
            break;
597
 
        case 2:
598
 
            if( *ppsz_name ) free( *ppsz_name );
599
 
            *ppsz_name = strdup( psz_data );
600
 
            break;
601
 
        case 3:
602
 
            (*pi_options)++;
603
 
            *pppsz_options = realloc( *pppsz_options,
604
 
                                      sizeof(char *) * *pi_options );
605
 
            (*pppsz_options)[*pi_options - 1] = strdup( psz_data );
606
 
            break;
607
 
        case 0:
608
 
        default:
609
 
            break;
610
 
    }
611
 
 
612
 
    if( (b_done || b_flush) && *ppsz_uri )
613
 
    {
614
 
        playlist_item_t *p_item =
615
 
            playlist_ItemNew( p_playlist, *ppsz_uri, *ppsz_name );
616
 
        int i;
617
 
 
618
 
        for( i = 0; i < *pi_options; i++ )
619
 
        {
620
 
            playlist_ItemAddOption( p_item, *pppsz_options[i] );
621
 
        }
622
 
 
623
 
        playlist_NodeAddItem( p_playlist, p_item,
624
 
                              p_parent->pp_parents[0]->i_view,
625
 
                              p_parent, PLAYLIST_APPEND, PLAYLIST_END );
626
 
 
627
 
        /* We need to declare the parents of the node as the
628
 
         * same of the parent's ones */
629
 
        playlist_CopyParents( p_parent, p_item );
630
 
 
631
 
        vlc_input_item_CopyOptions( &p_parent->input, &p_item->input );
632
 
 
633
 
        if( *ppsz_name ) free( *ppsz_name ); *ppsz_name = NULL;
634
 
        free( *ppsz_uri ); *ppsz_uri  = NULL;
635
 
 
636
 
        for( ; *pi_options; (*pi_options)-- )
637
 
        {
638
 
            free( (*pppsz_options)[*pi_options - 1] );
639
 
            if( *pi_options == 1 ) free( *pppsz_options );
640
 
        }
641
 
        *pppsz_options = NULL;
642
 
    }
643
 
}
644
 
 
645
 
static vlc_bool_t FindItem( demux_t *p_demux, playlist_t *p_playlist,
646
 
                            playlist_item_t **pp_item )
647
 
{
648
 
     vlc_bool_t b_play;
649
 
 
650
 
     if( &p_playlist->status.p_item->input ==
651
 
         ((input_thread_t *)p_demux->p_parent)->input.p_item )
652
 
     {
653
 
         msg_Dbg( p_playlist, "starting playlist playback" );
654
 
         *pp_item = p_playlist->status.p_item;
655
 
         b_play = VLC_TRUE;
656
 
     }
657
 
     else
658
 
     {
659
 
         input_item_t *p_current =
660
 
             ((input_thread_t*)p_demux->p_parent)->input.p_item;
661
 
         *pp_item = playlist_LockItemGetByInput( p_playlist, p_current );
662
 
 
663
 
         if( !*pp_item )
664
 
             msg_Dbg( p_playlist, "unable to find item in playlist");
665
 
 
666
 
         b_play = VLC_FALSE;
667
 
     }
668
 
 
669
 
     return b_play;
670
 
}
671
 
 
672
 
/*****************************************************************************
673
 
 * Demux: reads and demuxes data packets
674
 
 *****************************************************************************
675
 
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
676
 
 *****************************************************************************/
677
 
static int Demux( demux_t *p_demux )
678
 
{
679
 
    demux_sys_t   *p_m3u = p_demux->p_sys;
680
 
 
681
 
    char          psz_line[MAX_LINE];
682
 
    char          p_buf[MAX_LINE], eol_tok;
683
 
    int           i_size, i_bufpos, i_linepos = 0;
684
 
    vlc_bool_t    b_discard = VLC_FALSE;
685
 
 
686
 
    char          *psz_name = NULL;
687
 
    char          *psz_uri  = NULL;
688
 
    int           i_options = 0;
689
 
    char          **ppsz_options = NULL;
690
 
 
691
 
    playlist_t      *p_playlist;
692
 
    playlist_item_t *p_parent;
693
 
    vlc_bool_t      b_play;
694
 
 
695
 
    p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST,
696
 
                                                 FIND_ANYWHERE );
697
 
    if( !p_playlist )
698
 
    {
699
 
        msg_Err( p_demux, "can't find playlist" );
700
 
        return -1;
701
 
    }
702
 
 
703
 
    b_play = FindItem( p_demux, p_playlist, &p_parent );
704
 
    playlist_ItemToNode( p_playlist, p_parent );
705
 
    p_parent->input.i_type = ITEM_TYPE_PLAYLIST;
706
 
 
707
 
    /* Depending on wether we are dealing with an m3u/asf file, the end of
708
 
     * line token will be different */
709
 
    if( p_m3u->i_type == TYPE_ASX || p_m3u->i_type == TYPE_HTML )
710
 
        eol_tok = '>';
711
 
    else
712
 
        eol_tok = '\n';
713
 
 
714
 
    while( ( i_size = stream_Read( p_demux->s, p_buf, MAX_LINE ) ) )
715
 
    {
716
 
        i_bufpos = 0;
717
 
 
718
 
        while( i_size )
719
 
        {
720
 
            /* Build a line < MAX_LINE */
721
 
            while( p_buf[i_bufpos] != eol_tok && i_size )
722
 
            {
723
 
                if( i_linepos == MAX_LINE || b_discard == VLC_TRUE )
724
 
                {
725
 
                    /* line is bigger than MAX_LINE, discard it */
726
 
                    i_linepos = 0;
727
 
                    b_discard = VLC_TRUE;
728
 
                }
729
 
                else
730
 
                {
731
 
                    if ( eol_tok != '\n' || p_buf[i_bufpos] != '\r' )
732
 
                    {
733
 
                        psz_line[i_linepos] = p_buf[i_bufpos];
734
 
                        i_linepos++;
735
 
                    }
736
 
                }
737
 
 
738
 
                i_size--; i_bufpos++;
739
 
            }
740
 
 
741
 
            /* Check if we need more data */
742
 
            if( !i_size ) continue;
743
 
 
744
 
            i_size--; i_bufpos++;
745
 
            b_discard = VLC_FALSE;
746
 
 
747
 
            /* Check for empty line */
748
 
            if( !i_linepos ) continue;
749
 
 
750
 
            psz_line[i_linepos] = '\0';
751
 
            i_linepos = 0;
752
 
 
753
 
            ProcessLine( p_demux, p_playlist, p_parent,
754
 
                         psz_line, &psz_uri, &psz_name,
755
 
                         &i_options, &ppsz_options, VLC_FALSE );
756
 
        }
757
 
    }
758
 
 
759
 
    if( i_linepos && b_discard != VLC_TRUE && eol_tok == '\n' )
760
 
    {
761
 
        psz_line[i_linepos] = '\0';
762
 
 
763
 
        ProcessLine( p_demux, p_playlist, p_parent,
764
 
                     psz_line, &psz_uri, &psz_name,
765
 
                     &i_options, &ppsz_options, VLC_TRUE );
766
 
    }
767
 
 
768
 
    if( psz_uri ) free( psz_uri );
769
 
    if( psz_name ) free( psz_name );
770
 
    for( ; i_options; i_options-- )
771
 
    {
772
 
        free( ppsz_options[i_options - 1] );
773
 
        if( i_options == 1 ) free( ppsz_options );
774
 
    }
775
 
 
776
 
    /* Go back and play the playlist */
777
 
    if( b_play )
778
 
    {
779
 
        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
780
 
                          p_playlist->status.i_view,
781
 
                          p_playlist->status.p_item, NULL );
782
 
    }
783
 
 
784
 
    vlc_object_release( p_playlist );
785
 
 
786
 
    return 0;
787
 
}
788
 
 
789
 
static int Control( demux_t *p_demux, int i_query, va_list args )
790
 
{
791
 
    return VLC_EGENERIC;
792
 
}