pls.c 7.88 KB
Newer Older
sigmunau's avatar
sigmunau committed
1
2
3
/*****************************************************************************
 * pls.c : PLS playlist format import
 *****************************************************************************
4
 * Copyright (C) 2004 the VideoLAN team
5
 * $Id$
sigmunau's avatar
sigmunau committed
6
 *
7
 * Authors: Clément Stenac <zorglub@videolan.org>
8
 * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
sigmunau's avatar
sigmunau committed
9
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
sigmunau's avatar
sigmunau committed
23
24
25
26
27
28
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <vlc/vlc.h>
zorglub's avatar
zorglub committed
29
#include <vlc_demux.h>
sigmunau's avatar
sigmunau committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

#include "playlist.h"

struct demux_sys_t
{
    char *psz_prefix;
};

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static int Demux( demux_t *p_demux);
static int Control( demux_t *p_demux, int i_query, va_list args );

/*****************************************************************************
 * Import_PLS: main import function
 *****************************************************************************/
47
int E_(Import_PLS)( vlc_object_t *p_this )
sigmunau's avatar
sigmunau committed
48
49
{
    demux_t *p_demux = (demux_t *)p_this;
50
    const uint8_t *p_peek;
51
    CHECK_PEEK( p_peek, 10 );
sigmunau's avatar
sigmunau committed
52

53
    if( POKE( p_peek, "[playlist]", 10 ) || POKE( p_peek, "[Reference]", 10 ) ||
54
        demux2_IsPathExtension( p_demux, ".pls" )   || demux2_IsForced( p_demux, "pls" ) )
sigmunau's avatar
sigmunau committed
55
56
57
    {
        ;
    }
58
59
    else return VLC_EGENERIC;

60
    STANDARD_DEMUX_INIT_MSG(  "found valid PLS playlist file");
61
    p_demux->p_sys->psz_prefix = E_(FindPrefix)( p_demux );
sigmunau's avatar
sigmunau committed
62
63
64
65
66
67
68

    return VLC_SUCCESS;
}

/*****************************************************************************
 * Deactivate: frees unused data
 *****************************************************************************/
69
void E_(Close_PLS)( vlc_object_t *p_this )
sigmunau's avatar
sigmunau committed
70
71
72
73
74
75
76
77
78
79
80
81
{
    demux_t *p_demux = (demux_t *)p_this;
    if( p_demux->p_sys->psz_prefix )
    {
        free( p_demux->p_sys->psz_prefix );
    }
    free( p_demux->p_sys );
}

static int Demux( demux_t *p_demux )
{
    mtime_t        i_duration = -1;
82
    char          *psz_name = NULL;
sigmunau's avatar
sigmunau committed
83
84
    char          *psz_line;
    char          *psz_mrl = NULL;
85
    char          *psz_mrl_orig = NULL;
sigmunau's avatar
sigmunau committed
86
87
88
89
90
    char          *psz_key;
    char          *psz_value;
    int            i_item = -1;
    int            i_new_item = 0;
    int            i_key_length;
91
    input_item_t *p_input;
sigmunau's avatar
sigmunau committed
92

93
    INIT_PLAYLIST_STUFF;
94

sigmunau's avatar
sigmunau committed
95
96
    while( ( psz_line = stream_ReadLine( p_demux->s ) ) )
    {
97
        if( !strncasecmp( psz_line, "[playlist]", sizeof("[playlist]")-1 ) ||
98
            !strncasecmp( psz_line, "[Reference]", sizeof("[Reference]")-1 ) )
sigmunau's avatar
sigmunau committed
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
        {
            free( psz_line );
            continue;
        }
        psz_key = psz_line;
        psz_value = strchr( psz_line, '=' );
        if( psz_value )
        {
            *psz_value='\0';
            psz_value++;
        }
        else
        {
            msg_Warn( p_demux, "invalid line in pls file" );
            free( psz_line );
            continue;
        }
        if( !strcasecmp( psz_key, "version" ) )
        {
            msg_Dbg( p_demux, "pls file version: %s", psz_value );
            free( psz_line );
            continue;
        }
122
123
        if( !strcasecmp( psz_key, "numberofentries" ) )
        {
124
            msg_Dbg( p_demux, "pls should have %d entries", atoi(psz_value) );
125
126
127
            free( psz_line);
            continue;
        }
sigmunau's avatar
sigmunau committed
128
129
        /* find the number part of of file1, title1 or length1 etc */
        i_key_length = strlen( psz_key );
130
        if( i_key_length >= 4 ) /* Ref1 type case */
sigmunau's avatar
sigmunau committed
131
        {
132
133
            i_new_item = atoi( psz_key + 3 );
            if( i_new_item == 0 && i_key_length >= 5 ) /* file1 type case */
sigmunau's avatar
sigmunau committed
134
            {
135
136
                i_new_item = atoi( psz_key + 4 );
                if( i_new_item == 0 && i_key_length >= 6 ) /* title1 type case */
sigmunau's avatar
sigmunau committed
137
                {
138
139
140
141
142
                    i_new_item = atoi( psz_key + 5 );
                    if( i_new_item == 0 && i_key_length >= 7 ) /* length1 type case */
                    {
                        i_new_item = atoi( psz_key + 6 );
                    }
sigmunau's avatar
sigmunau committed
143
144
145
146
147
                }
            }
        }
        if( i_new_item == 0 )
        {
hartman's avatar
hartman committed
148
            msg_Warn( p_demux, "couldn't find number of items" );
sigmunau's avatar
sigmunau committed
149
150
151
152
153
154
155
156
157
158
159
160
            free( psz_line );
            continue;
        }
        if( i_item == -1 )
        {
            i_item = i_new_item;
        }
        /* we found a new item, insert the previous */
        if( i_item != i_new_item )
        {
            if( psz_mrl )
            {
161
162
                p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name,
                                            0, NULL, -1 );
163
                input_ItemCopyOptions( p_current_input, p_input );
Rafaël Carré's avatar
Rafaël Carré committed
164
                input_ItemAddSubItem( p_current_input, p_input, VLC_FALSE );
165
                vlc_gc_decref( p_input );
sigmunau's avatar
sigmunau committed
166
167
168
169
170
171
172
173
174
175
176
177
178
179
            }
            else
            {
                msg_Warn( p_demux, "no file= part found for item %d", i_item );
            }
            if( psz_name )
            {
                free( psz_name );
                psz_name = NULL;
            }
            i_duration = -1;
            i_item = i_new_item;
            i_new_item = 0;
        }
180
181
        if( !strncasecmp( psz_key, "file", sizeof("file") -1 ) ||
            !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) )
sigmunau's avatar
sigmunau committed
182
        {
Laurent Aimar's avatar
Laurent Aimar committed
183
184
            if( psz_mrl_orig )
                free( psz_mrl_orig );
185
            psz_mrl_orig =
186
            psz_mrl = E_(ProcessMRL)( psz_value, p_demux->p_sys->psz_prefix );
187
188
189
190
191
192
193
194
195
196
197

            if( !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) )
            {
                if( !strncasecmp( psz_mrl, "http://", sizeof("http://") -1 ) )
                {
                    psz_mrl++;
                    psz_mrl[0] = 'm';
                    psz_mrl[1] = 'm';
                    psz_mrl[2] = 's';
                }
            }
sigmunau's avatar
sigmunau committed
198
199
200
        }
        else if( !strncasecmp( psz_key, "title", sizeof("title") -1 ) )
        {
Laurent Aimar's avatar
Laurent Aimar committed
201
202
            if( psz_name )
                free( psz_name );
sigmunau's avatar
sigmunau committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
            psz_name = strdup( psz_value );
        }
        else if( !strncasecmp( psz_key, "length", sizeof("length") -1 ) )
        {
            i_duration = atoi( psz_value );
            if( i_duration != -1 )
            {
                i_duration *= 1000000;
            }
        }
        else
        {
            msg_Warn( p_demux, "unknown key found in pls file: %s", psz_key );
        }
        free( psz_line );
    }
    /* Add last object */
    if( psz_mrl )
    {
222
        p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name,0, NULL, -1 );
223
        input_ItemCopyOptions( p_current_input, p_input );
Rafaël Carré's avatar
Rafaël Carré committed
224
        input_ItemAddSubItem( p_current_input, p_input, VLC_FALSE );
225
        vlc_gc_decref( p_input );
226
        free( psz_mrl_orig );
sigmunau's avatar
sigmunau committed
227
228
229
230
231
232
233
234
235
236
237
238
        psz_mrl = NULL;
    }
    else
    {
        msg_Warn( p_demux, "no file= part found for item %d", i_item );
    }
    if( psz_name )
    {
        free( psz_name );
        psz_name = NULL;
    }

239
    HANDLE_PLAY_AND_RELEASE;
240
    return 0; /* Needed for correct operation of go back */
sigmunau's avatar
sigmunau committed
241
242
243
244
245
246
}

static int Control( demux_t *p_demux, int i_query, va_list args )
{
    return VLC_EGENERIC;
}