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