]> git.sesse.net Git - vlc/blob - modules/demux/playlist/m3u.c
Remove debug message
[vlc] / modules / demux / playlist / m3u.c
1 /*****************************************************************************
2  * m3u.c : M3U playlist format import
3  *****************************************************************************
4  * Copyright (C) 2004 VideoLAN
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *          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_M3U: main import function
50  *****************************************************************************/
51 int Import_M3U( 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         return VLC_EGENERIC;
61     }
62     psz_ext = strrchr ( p_demux->psz_path, '.' );
63
64     if( !strncmp( p_peek, "#EXTM3U", 7 ) )
65     {
66         ;
67     }
68     else if( ( psz_ext && !strcasecmp( psz_ext, ".m3u") ) ||
69              ( psz_ext && !strcasecmp( psz_ext, ".ram") ) ||
70              /* A .ram file can contain a single rtsp link */
71              ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "m3u") ) )
72     {
73         ;
74     }
75     else
76     {
77         return VLC_EGENERIC;
78     }
79     msg_Dbg( p_demux, "found valid M3U playlist file");
80
81     p_demux->pf_control = Control;
82     p_demux->pf_demux = Demux;
83     p_demux->p_sys = malloc( sizeof(demux_sys_t) );
84     if( p_demux->p_sys == NULL )
85     {
86         msg_Err( p_demux, "Out of memory" );
87         return VLC_ENOMEM;
88     }
89     p_demux->p_sys->psz_prefix = FindPrefix( p_demux );
90
91     return VLC_SUCCESS;
92 }
93
94 /*****************************************************************************
95  * Deactivate: frees unused data
96  *****************************************************************************/
97 void Close_M3U( vlc_object_t *p_this )
98 {
99     demux_t *p_demux = (demux_t *)p_this;
100
101     if( p_demux->p_sys->psz_prefix ) free( p_demux->p_sys->psz_prefix );
102     free( p_demux->p_sys );
103 }
104
105 static int Demux( demux_t *p_demux )
106 {
107     playlist_t *p_playlist;
108     char       *psz_line;
109
110     char *psz_name = NULL;
111     mtime_t i_duration = -1;
112     char **ppsz_options = NULL;
113     int i_options = 0, i;
114
115     playlist_item_t *p_item, *p_current;
116
117     vlc_bool_t b_play;
118
119     vlc_bool_t b_cleanup = VLC_FALSE;
120
121     p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST,
122                                                  FIND_PARENT );
123     if( !p_playlist )
124     {
125         msg_Err( p_demux, "can't find playlist" );
126         return -1;
127     }
128
129     b_play = FindItem( p_demux, p_playlist, &p_current );
130
131     playlist_ItemToNode( p_playlist, p_current );
132     p_current->input.i_type = ITEM_TYPE_PLAYLIST;
133
134     psz_line = stream_ReadLine( p_demux->s );
135     while( psz_line )
136     {
137         char *psz_parse = psz_line;
138
139         /* Skip leading tabs and spaces */
140         while( *psz_parse == ' ' || *psz_parse == '\t' ||
141                *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++;
142
143         if( *psz_parse == '#' )
144         {
145             /* Parse extra info */
146
147             /* Skip leading tabs and spaces */
148             while( *psz_parse == ' ' || *psz_parse == '\t' ||
149                    *psz_parse == '\n' || *psz_parse == '\r' ||
150                    *psz_parse == '#' ) psz_parse++;
151
152             if( !*psz_parse ) goto error;
153
154             if( !strncasecmp( psz_parse, "EXTINF:", sizeof("EXTINF:") -1 ) )
155             {
156                 /* Extended info */
157                 char *psz_duration;
158                 psz_parse += sizeof("EXTINF:") - 1;
159                 while( *psz_parse == '\t' || *psz_parse == ' ' ) psz_parse++;
160
161                 psz_duration = psz_parse;
162                 psz_parse = strchr( psz_parse, ',' );
163                 if( psz_parse )
164                 {
165                     *psz_parse = '\0';
166                     psz_parse++;
167                     psz_name = strdup( psz_parse );
168                     i_duration = atoi( psz_duration );
169                     if( i_duration != -1 ) i_duration *= 1000000;
170                 }
171             }
172             else if( !strncasecmp( psz_parse, "EXTVLCOPT:",
173                                    sizeof("EXTVLCOPT:") -1 ) )
174
175             {
176                 /* VLC Option */
177                 char *psz_option;
178                 psz_parse += sizeof("EXTVLCOPT:") -1;
179                 if( !*psz_parse ) goto error;
180
181                 psz_option = strdup( psz_parse );
182                 if( psz_option )
183                     INSERT_ELEM( ppsz_options, i_options, i_options,
184                                  psz_option );
185             }
186         }
187         else if( *psz_parse )
188         {
189             char *psz_mrl =
190                 ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix );
191
192             b_cleanup = VLC_TRUE;
193             if( !psz_mrl ) goto error;
194
195             p_item = playlist_ItemNew( p_playlist, psz_mrl, psz_name );
196             for( i = 0; i< i_options; i++ )
197             {
198                 playlist_ItemAddOption( p_item, ppsz_options[i] );
199             }
200             p_item->input.i_duration = i_duration;
201
202             playlist_NodeAddItem( p_playlist, p_item,
203                                   p_current->pp_parents[0]->i_view,
204                                   p_current, PLAYLIST_APPEND,
205                                   PLAYLIST_END );
206
207             /* We need to declare the parents of the node as the
208              *                  * same of the parent's ones */
209             playlist_CopyParents( p_current, p_item );
210
211             vlc_input_item_CopyOptions( &p_current->input,
212                                         &p_item->input );
213
214             free( psz_mrl );
215         }
216
217  error:
218
219         /* Fetch another line */
220         free( psz_line );
221         psz_line = stream_ReadLine( p_demux->s );
222         if( !psz_line ) b_cleanup = VLC_TRUE;
223
224         if( b_cleanup )
225         {
226             /* Cleanup state */
227             while( i_options-- ) free( ppsz_options[i_options] );
228             if( ppsz_options ) free( ppsz_options );
229             ppsz_options = NULL; i_options = 0;
230             if( psz_name ) free( psz_name );
231             psz_name = NULL;
232             i_duration = -1;
233
234             b_cleanup = VLC_FALSE;
235         }
236     }
237
238     /* Go back and play the playlist */
239     if( b_play )
240     {
241         playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
242                           p_playlist->status.i_view,
243                           p_playlist->status.p_item, NULL );
244     }
245
246     vlc_object_release( p_playlist );
247     return VLC_SUCCESS;
248 }
249
250 static int Control( demux_t *p_demux, int i_query, va_list args )
251 {
252     return VLC_EGENERIC;
253 }