]> git.sesse.net Git - vlc/blob - modules/demux/playlist/pls.c
Merge branch 'master' of git@git.videolan.org:vlc
[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         demux_IsPathExtension( p_demux, ".pls" )   || demux_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     free( p_demux->p_sys->psz_prefix );
77     free( p_demux->p_sys );
78 }
79
80 static int Demux( demux_t *p_demux )
81 {
82     mtime_t        i_duration = -1;
83     char          *psz_name = NULL;
84     char          *psz_line;
85     char          *psz_mrl = NULL;
86     char          *psz_mrl_orig = NULL;
87     char          *psz_key;
88     char          *psz_value;
89     int            i_item = -1;
90     int            i_new_item = 0;
91     int            i_key_length;
92     input_item_t *p_input;
93
94     INIT_PLAYLIST_STUFF;
95
96     while( ( psz_line = stream_ReadLine( p_demux->s ) ) )
97     {
98         if( !strncasecmp( psz_line, "[playlist]", sizeof("[playlist]")-1 ) ||
99             !strncasecmp( psz_line, "[Reference]", sizeof("[Reference]")-1 ) )
100         {
101             free( psz_line );
102             continue;
103         }
104         psz_key = psz_line;
105         psz_value = strchr( psz_line, '=' );
106         if( psz_value )
107         {
108             *psz_value='\0';
109             psz_value++;
110         }
111         else
112         {
113             msg_Warn( p_demux, "invalid line in pls file" );
114             free( psz_line );
115             continue;
116         }
117         if( !strcasecmp( psz_key, "version" ) )
118         {
119             msg_Dbg( p_demux, "pls file version: %s", psz_value );
120             free( psz_line );
121             continue;
122         }
123         if( !strcasecmp( psz_key, "numberofentries" ) )
124         {
125             msg_Dbg( p_demux, "pls should have %d entries", atoi(psz_value) );
126             free( psz_line);
127             continue;
128         }
129         /* find the number part of of file1, title1 or length1 etc */
130         i_key_length = strlen( psz_key );
131         if( i_key_length >= 4 ) /* Ref1 type case */
132         {
133             i_new_item = atoi( psz_key + 3 );
134             if( i_new_item == 0 && i_key_length >= 5 ) /* file1 type case */
135             {
136                 i_new_item = atoi( psz_key + 4 );
137                 if( i_new_item == 0 && i_key_length >= 6 ) /* title1 type case */
138                 {
139                     i_new_item = atoi( psz_key + 5 );
140                     if( i_new_item == 0 && i_key_length >= 7 ) /* length1 type case */
141                     {
142                         i_new_item = atoi( psz_key + 6 );
143                     }
144                 }
145             }
146         }
147         if( i_new_item == 0 )
148         {
149             msg_Warn( p_demux, "couldn't find number of items" );
150             free( psz_line );
151             continue;
152         }
153         if( i_item == -1 )
154         {
155             i_item = i_new_item;
156         }
157         /* we found a new item, insert the previous */
158         if( i_item != i_new_item )
159         {
160             if( psz_mrl )
161             {
162                 p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name,
163                                             0, NULL, -1 );
164                 input_ItemCopyOptions( p_current_input, p_input );
165                 input_ItemAddSubItem( p_current_input, p_input );
166                 vlc_gc_decref( p_input );
167             }
168             else
169             {
170                 msg_Warn( p_demux, "no file= part found for item %d", i_item );
171             }
172             free( psz_name );
173             psz_name = NULL;
174             i_duration = -1;
175             i_item = i_new_item;
176             i_new_item = 0;
177         }
178         if( !strncasecmp( psz_key, "file", sizeof("file") -1 ) ||
179             !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) )
180         {
181             free( psz_mrl_orig );
182             psz_mrl_orig =
183             psz_mrl = E_(ProcessMRL)( psz_value, p_demux->p_sys->psz_prefix );
184
185             if( !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) )
186             {
187                 if( !strncasecmp( psz_mrl, "http://", sizeof("http://") -1 ) )
188                 {
189                     psz_mrl++;
190                     psz_mrl[0] = 'm';
191                     psz_mrl[1] = 'm';
192                     psz_mrl[2] = 's';
193                 }
194             }
195         }
196         else if( !strncasecmp( psz_key, "title", sizeof("title") -1 ) )
197         {
198             free( psz_name );
199             psz_name = strdup( psz_value );
200         }
201         else if( !strncasecmp( psz_key, "length", sizeof("length") -1 ) )
202         {
203             i_duration = atoi( psz_value );
204             if( i_duration != -1 )
205             {
206                 i_duration *= 1000000;
207             }
208         }
209         else
210         {
211             msg_Warn( p_demux, "unknown key found in pls file: %s", psz_key );
212         }
213         free( psz_line );
214     }
215     /* Add last object */
216     if( psz_mrl )
217     {
218         p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name,0, NULL, -1 );
219         input_ItemCopyOptions( p_current_input, p_input );
220         input_ItemAddSubItem( p_current_input, p_input );
221         vlc_gc_decref( p_input );
222         free( psz_mrl_orig );
223         psz_mrl = NULL;
224     }
225     else
226     {
227         msg_Warn( p_demux, "no file= part found for item %d", i_item );
228     }
229     free( psz_name );
230     psz_name = NULL;
231
232     HANDLE_PLAY_AND_RELEASE;
233     return 0; /* Needed for correct operation of go back */
234 }
235
236 static int Control( demux_t *p_demux, int i_query, va_list args )
237 {
238     VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args);
239     return VLC_EGENERIC;
240 }