]> git.sesse.net Git - vlc/blob - modules/demux/playlist/pls.c
Don't only play the playlist in playlist demuxers (Closes #84)
[vlc] / modules / demux / playlist / pls.c
1 /*****************************************************************************
2  * pls.c : PLS playlist format import
3  *****************************************************************************
4  * Copyright (C) 2004 VideoLAN
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29
30 #include <vlc/vlc.h>
31 #include <vlc/input.h>
32 #include <vlc/intf.h>
33
34 #include <errno.h>                                                 /* ENOMEM */
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 Import_PLS( vlc_object_t *p_this )
52 {
53     demux_t *p_demux = (demux_t *)p_this;
54
55     uint8_t *p_peek;
56     char    *psz_ext;
57
58     if( stream_Peek( p_demux->s , &p_peek, 7 ) < 7 ) return VLC_EGENERIC;
59     psz_ext = strrchr ( p_demux->psz_path, '.' );
60
61     if( !strncasecmp( p_peek, "[playlist]", 10 ) )
62     {
63         ;
64     }
65     else if( ( psz_ext && !strcasecmp( psz_ext, ".pls") ) ||
66              ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "pls") ) )
67     {
68         ;
69     }
70     else return VLC_EGENERIC;
71
72     msg_Dbg( p_demux, "found valid PLS playlist file");
73
74     p_demux->pf_control = Control;
75     p_demux->pf_demux = Demux;
76     p_demux->p_sys = malloc( sizeof(demux_sys_t) );
77     if( p_demux->p_sys == NULL )
78     {
79         msg_Err( p_demux, "Out of memory" );
80         return VLC_ENOMEM;
81     }
82     p_demux->p_sys->psz_prefix = FindPrefix( p_demux );
83
84     return VLC_SUCCESS;
85 }
86
87 /*****************************************************************************
88  * Deactivate: frees unused data
89  *****************************************************************************/
90 void Close_PLS( vlc_object_t *p_this )
91 {
92     demux_t *p_demux = (demux_t *)p_this;
93     if( p_demux->p_sys->psz_prefix )
94     {
95         free( p_demux->p_sys->psz_prefix );
96     }
97     free( p_demux->p_sys );
98 }
99
100 static int Demux( demux_t *p_demux )
101 {
102     mtime_t        i_duration = -1;
103     char          *psz_name = NULL;
104     char          *psz_line;
105     char          *psz_mrl = NULL;
106     char          *psz_key;
107     char          *psz_value;
108     playlist_t    *p_playlist;
109     int            i_position;
110     int            i_item = -1;
111     int            i_new_item = 0;
112     int            i_key_length;
113     playlist_item_t *p_parent;
114     vlc_bool_t b_play;
115
116     p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST,
117                                                  FIND_PARENT );
118     if( !p_playlist )
119     {
120         msg_Err( p_demux, "can't find playlist" );
121         return -1;
122     }
123
124     b_play = FindItem( p_demux, p_playlist, &p_parent );
125     p_parent->input.i_type = ITEM_TYPE_PLAYLIST;
126
127     /* Change the item to a node */
128     if( p_parent->i_children == -1)
129     {
130         playlist_ItemToNode( p_playlist,p_parent );
131     }
132
133     while( ( psz_line = stream_ReadLine( p_demux->s ) ) )
134     {
135         if( !strncasecmp( psz_line, "[playlist]", sizeof("[playlist]")-1 ) )
136         {
137             free( psz_line );
138             continue;
139         }
140         psz_key = psz_line;
141         psz_value = strchr( psz_line, '=' );
142         if( psz_value )
143         {
144             *psz_value='\0';
145             psz_value++;
146         }
147         else
148         {
149             msg_Warn( p_demux, "invalid line in pls file" );
150             free( psz_line );
151             continue;
152         }
153         if( !strcasecmp( psz_key, "version" ) )
154         {
155             msg_Dbg( p_demux, "pls file version: %s", psz_value );
156             free( psz_line );
157             continue;
158         }
159         /* find the number part of of file1, title1 or length1 etc */
160         i_key_length = strlen( psz_key );
161         if( i_key_length >= 5 ) /* file1 type case */
162         {
163             i_new_item = atoi( psz_key + 4 );
164             if( i_new_item == 0 && i_key_length >= 6 ) /* title1 type case */
165             {
166                 i_new_item = atoi( psz_key + 5 );
167                 if( i_new_item == 0 && i_key_length >= 7 ) /* length1 type case */
168                 {
169                     i_new_item = atoi( psz_key + 6 );
170                 }
171             }
172         }
173         if( i_new_item == 0 )
174         {
175             msg_Warn( p_demux, "couldn't find number of items" );
176             free( psz_line );
177             continue;
178         }
179         if( i_item == -1 )
180         {
181             i_item = i_new_item;
182         }
183         /* we found a new item, insert the previous */
184         if( i_item != i_new_item )
185         {
186             if( psz_mrl )
187             {
188                 playlist_item_t *p_item = playlist_ItemNew( p_playlist, psz_mrl,
189                                                             psz_name );
190
191                 playlist_NodeAddItem( p_playlist,p_item,
192                                       p_parent->pp_parents[0]->i_view,
193                                       p_parent,
194                                       PLAYLIST_APPEND, PLAYLIST_END );
195
196                 playlist_CopyParents( p_parent, p_item );
197                 if( i_duration != -1 )
198                 {
199                     //playlist_SetDuration( p_playlist, i_position, i_duration );
200                 }
201                 i_position++;
202                 free( psz_mrl );
203                 psz_mrl = NULL;
204
205                 vlc_input_item_CopyOptions( &p_parent->input,
206                                             &p_item->input );
207             }
208             else
209             {
210                 msg_Warn( p_demux, "no file= part found for item %d", i_item );
211             }
212             if( psz_name )
213             {
214                 free( psz_name );
215                 psz_name = NULL;
216             }
217             i_duration = -1;
218             i_item = i_new_item;
219             i_new_item = 0;
220         }
221         if( !strncasecmp( psz_key, "file", sizeof("file") -1 ) )
222         {
223             psz_mrl = ProcessMRL( psz_value, p_demux->p_sys->psz_prefix );
224         }
225         else if( !strncasecmp( psz_key, "title", sizeof("title") -1 ) )
226         {
227             psz_name = strdup( psz_value );
228         }
229         else if( !strncasecmp( psz_key, "length", sizeof("length") -1 ) )
230         {
231             i_duration = atoi( psz_value );
232             if( i_duration != -1 )
233             {
234                 i_duration *= 1000000;
235             }
236         }
237         else
238         {
239             msg_Warn( p_demux, "unknown key found in pls file: %s", psz_key );
240         }
241         free( psz_line );
242     }
243     /* Add last object */
244     if( psz_mrl )
245     {
246         playlist_item_t *p_item = playlist_ItemNew( p_playlist, psz_mrl,
247                                                     psz_name );
248
249         playlist_NodeAddItem( p_playlist,p_item,
250                               p_parent->pp_parents[0]->i_view,
251                               p_parent,
252                               PLAYLIST_APPEND, PLAYLIST_END );
253
254         playlist_CopyParents( p_parent, p_item );
255         if( i_duration != -1 )
256         {
257             //playlist_SetDuration( p_playlist, i_position, i_duration );
258         }
259         free( psz_mrl );
260         psz_mrl = NULL;
261
262         vlc_input_item_CopyOptions( &p_parent->input,
263                                     &p_item->input );
264     }
265     else
266     {
267         msg_Warn( p_demux, "no file= part found for item %d", i_item );
268     }
269     if( psz_name )
270     {
271         free( psz_name );
272         psz_name = NULL;
273     }
274
275     if( b_play && p_playlist->status.p_item &&
276         p_playlist->status.p_item->i_children > 0 )
277     {
278         playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
279                           p_playlist->status.i_view,
280                           p_playlist->status.p_item,
281                           p_playlist->status.p_item->pp_children[0] );
282     }
283     vlc_object_release( p_playlist );
284     return VLC_SUCCESS;
285 }
286
287 static int Control( demux_t *p_demux, int i_query, va_list args )
288 {
289     return VLC_EGENERIC;
290 }