]> git.sesse.net Git - vlc/blob - modules/demux/playlist/pls.c
649be46f6f22ae6d1ea7caac14a011baa4910f60
[vlc] / modules / demux / playlist / pls.c
1 /*****************************************************************************
2  * pls.c : PLS playlist format import
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc/vlc.h>
33 #include <vlc_demux.h>
34
35 #include "playlist.h"
36
37 struct demux_sys_t
38 {
39     char *psz_prefix;
40 };
41
42 /*****************************************************************************
43  * Local prototypes
44  *****************************************************************************/
45 static int Demux( demux_t *p_demux);
46 static int Control( demux_t *p_demux, int i_query, va_list args );
47
48 /*****************************************************************************
49  * Import_PLS: main import function
50  *****************************************************************************/
51 int E_(Import_PLS)( vlc_object_t *p_this )
52 {
53     demux_t *p_demux = (demux_t *)p_this;
54     const uint8_t *p_peek;
55     CHECK_PEEK( p_peek, 10 );
56
57     if( POKE( p_peek, "[playlist]", 10 ) || POKE( p_peek, "[Reference]", 10 ) ||
58         demux2_IsPathExtension( p_demux, ".pls" )   || demux2_IsForced( p_demux, "pls" ) )
59     {
60         ;
61     }
62     else return VLC_EGENERIC;
63
64     STANDARD_DEMUX_INIT_MSG(  "found valid PLS playlist file");
65     p_demux->p_sys->psz_prefix = E_(FindPrefix)( p_demux );
66
67     return VLC_SUCCESS;
68 }
69
70 /*****************************************************************************
71  * Deactivate: frees unused data
72  *****************************************************************************/
73 void E_(Close_PLS)( vlc_object_t *p_this )
74 {
75     demux_t *p_demux = (demux_t *)p_this;
76     if( p_demux->p_sys->psz_prefix )
77     {
78         free( p_demux->p_sys->psz_prefix );
79     }
80     free( p_demux->p_sys );
81 }
82
83 static int Demux( demux_t *p_demux )
84 {
85     mtime_t        i_duration = -1;
86     char          *psz_name = NULL;
87     char          *psz_line;
88     char          *psz_mrl = NULL;
89     char          *psz_mrl_orig = NULL;
90     char          *psz_key;
91     char          *psz_value;
92     int            i_item = -1;
93     int            i_new_item = 0;
94     int            i_key_length;
95     input_item_t *p_input;
96
97     INIT_PLAYLIST_STUFF;
98
99     while( ( psz_line = stream_ReadLine( p_demux->s ) ) )
100     {
101         if( !strncasecmp( psz_line, "[playlist]", sizeof("[playlist]")-1 ) ||
102             !strncasecmp( psz_line, "[Reference]", sizeof("[Reference]")-1 ) )
103         {
104             free( psz_line );
105             continue;
106         }
107         psz_key = psz_line;
108         psz_value = strchr( psz_line, '=' );
109         if( psz_value )
110         {
111             *psz_value='\0';
112             psz_value++;
113         }
114         else
115         {
116             msg_Warn( p_demux, "invalid line in pls file" );
117             free( psz_line );
118             continue;
119         }
120         if( !strcasecmp( psz_key, "version" ) )
121         {
122             msg_Dbg( p_demux, "pls file version: %s", psz_value );
123             free( psz_line );
124             continue;
125         }
126         if( !strcasecmp( psz_key, "numberofentries" ) )
127         {
128             msg_Dbg( p_demux, "pls should have %d entries", atoi(psz_value) );
129             free( psz_line);
130             continue;
131         }
132         /* find the number part of of file1, title1 or length1 etc */
133         i_key_length = strlen( psz_key );
134         if( i_key_length >= 4 ) /* Ref1 type case */
135         {
136             i_new_item = atoi( psz_key + 3 );
137             if( i_new_item == 0 && i_key_length >= 5 ) /* file1 type case */
138             {
139                 i_new_item = atoi( psz_key + 4 );
140                 if( i_new_item == 0 && i_key_length >= 6 ) /* title1 type case */
141                 {
142                     i_new_item = atoi( psz_key + 5 );
143                     if( i_new_item == 0 && i_key_length >= 7 ) /* length1 type case */
144                     {
145                         i_new_item = atoi( psz_key + 6 );
146                     }
147                 }
148             }
149         }
150         if( i_new_item == 0 )
151         {
152             msg_Warn( p_demux, "couldn't find number of items" );
153             free( psz_line );
154             continue;
155         }
156         if( i_item == -1 )
157         {
158             i_item = i_new_item;
159         }
160         /* we found a new item, insert the previous */
161         if( i_item != i_new_item )
162         {
163             if( psz_mrl )
164             {
165                 p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name,
166                                             0, NULL, -1 );
167                 input_ItemCopyOptions( p_current_input, p_input );
168                 input_ItemAddSubItem( p_current_input, p_input );
169                 vlc_gc_decref( p_input );
170             }
171             else
172             {
173                 msg_Warn( p_demux, "no file= part found for item %d", i_item );
174             }
175             if( psz_name )
176             {
177                 free( psz_name );
178                 psz_name = NULL;
179             }
180             i_duration = -1;
181             i_item = i_new_item;
182             i_new_item = 0;
183         }
184         if( !strncasecmp( psz_key, "file", sizeof("file") -1 ) ||
185             !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) )
186         {
187             if( psz_mrl_orig )
188                 free( psz_mrl_orig );
189             psz_mrl_orig =
190             psz_mrl = E_(ProcessMRL)( psz_value, p_demux->p_sys->psz_prefix );
191
192             if( !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) )
193             {
194                 if( !strncasecmp( psz_mrl, "http://", sizeof("http://") -1 ) )
195                 {
196                     psz_mrl++;
197                     psz_mrl[0] = 'm';
198                     psz_mrl[1] = 'm';
199                     psz_mrl[2] = 's';
200                 }
201             }
202         }
203         else if( !strncasecmp( psz_key, "title", sizeof("title") -1 ) )
204         {
205             if( psz_name )
206                 free( psz_name );
207             psz_name = strdup( psz_value );
208         }
209         else if( !strncasecmp( psz_key, "length", sizeof("length") -1 ) )
210         {
211             i_duration = atoi( psz_value );
212             if( i_duration != -1 )
213             {
214                 i_duration *= 1000000;
215             }
216         }
217         else
218         {
219             msg_Warn( p_demux, "unknown key found in pls file: %s", psz_key );
220         }
221         free( psz_line );
222     }
223     /* Add last object */
224     if( psz_mrl )
225     {
226         p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name,0, NULL, -1 );
227         input_ItemCopyOptions( p_current_input, p_input );
228         input_ItemAddSubItem( p_current_input, p_input );
229         vlc_gc_decref( p_input );
230         free( psz_mrl_orig );
231         psz_mrl = NULL;
232     }
233     else
234     {
235         msg_Warn( p_demux, "no file= part found for item %d", i_item );
236     }
237     if( psz_name )
238     {
239         free( psz_name );
240         psz_name = NULL;
241     }
242
243     HANDLE_PLAY_AND_RELEASE;
244     return 0; /* Needed for correct operation of go back */
245 }
246
247 static int Control( demux_t *p_demux, int i_query, va_list args )
248 {
249     VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args);
250     return VLC_EGENERIC;
251 }