1 /*****************************************************************************
2 * m3u.c: a meta demux to parse m3u and asx playlists
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: m3u.c,v 1.4 2002/11/18 13:08:35 gbazin Exp $
7 * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
8 * Gildas Bazin <gbazin@netcourrier.com>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
29 #include <string.h> /* strdup() */
33 #include <vlc/input.h>
34 #include <vlc_playlist.h>
36 #include <sys/types.h>
38 /*****************************************************************************
39 * Constants and structures
40 *****************************************************************************/
48 int i_type; /* playlist type (m3u/asx) */
51 /*****************************************************************************
53 *****************************************************************************/
54 static int Activate ( vlc_object_t * );
55 static void Deactivate( vlc_object_t * );
56 static int Demux ( input_thread_t * );
58 /*****************************************************************************
60 *****************************************************************************/
62 set_description( "m3u/asx metademux" );
63 set_capability( "demux", 10 );
64 set_callbacks( Activate, Deactivate );
65 add_shortcut( "m3u" );
66 add_shortcut( "asx" );
69 /*****************************************************************************
70 * Activate: initializes m3u demux structures
71 *****************************************************************************/
72 static int Activate( vlc_object_t * p_this )
74 input_thread_t *p_input = (input_thread_t *)p_this;
79 /* Initialize access plug-in structures. */
80 if( p_input->i_mtu == 0 )
83 p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
86 p_input->pf_demux = Demux;
87 p_input->pf_rewind = NULL;
89 /* Check for m3u/asx file extension */
90 psz_ext = strrchr ( p_input->psz_name, '.' );
91 if( !strcasecmp( psz_ext, ".m3u") ||
92 ( p_input->psz_demux && !strncmp(p_input->psz_demux, "m3u", 3) ) )
96 else if( !strcasecmp( psz_ext, ".asx") ||
97 ( p_input->psz_demux && !strncmp(p_input->psz_demux, "asx", 3) ) )
106 if( !( p_m3u = malloc( sizeof( demux_sys_t ) ) ) )
108 msg_Err( p_input, "out of memory" );
111 p_input->p_demux_data = p_m3u;
113 p_m3u->i_type = i_type;
118 /*****************************************************************************
119 * Deactivate: frees unused data
120 *****************************************************************************/
121 static void Deactivate( vlc_object_t *p_this )
123 input_thread_t *p_input = (input_thread_t *)p_this;
124 demux_sys_t *p_m3u = (demux_sys_t *)p_input->p_demux_data ;
129 /*****************************************************************************
130 * Demux: reads and demuxes data packets
131 *****************************************************************************
132 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
133 *****************************************************************************/
134 static int Demux ( input_thread_t *p_input )
136 data_packet_t *p_data;
137 char *p_buf, psz_line[MAX_LINE], *psz_bol, *psz_name, eol_tok;
138 int i_size, i_bufpos, i_linepos = 0;
139 playlist_t *p_playlist;
140 vlc_bool_t b_discard = VLC_FALSE;
142 demux_sys_t *p_m3u = (demux_sys_t *)p_input->p_demux_data;
144 p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
148 msg_Err( p_input, "can't find playlist" );
152 p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
154 /* Depending on wether we are dealing with an m3u/asf file, the end of
155 * line token will be different */
156 if( p_m3u->i_type == TYPE_ASX )
161 while( ( i_size = input_SplitBuffer( p_input, &p_data, MAX_LINE ) ) > 0 )
163 i_bufpos = 0; p_buf = p_data->p_payload_start;
167 /* Build a line < MAX_LINE */
168 while( p_buf[i_bufpos] != eol_tok && i_size )
170 if( i_linepos == MAX_LINE || b_discard == VLC_TRUE )
172 /* line is bigger than MAX_LINE, discard it */
174 b_discard = VLC_TRUE;
178 psz_line[i_linepos] = p_buf[i_bufpos];
182 i_size--; i_bufpos++;
185 /* Check if we need more data */
186 if( !i_size ) continue;
188 i_size--; i_bufpos++;
189 b_discard = VLC_FALSE;
191 /* Check for empty line */
192 if( !i_linepos ) continue;
194 psz_line[i_linepos] = '\0';
198 /* Remove unnecessary tabs or spaces at the beginning of line */
199 while( *psz_bol == ' ' || *psz_bol == '\t' ||
200 *psz_bol == '\n' || *psz_bol == '\r' )
203 if( p_m3u->i_type == TYPE_M3U )
205 /* Check for comment line */
206 if( *psz_bol == '#' )
207 /*line is comment or extended info, ignored for now */
212 /* We are dealing with ASX files.
213 * We are looking for "href" or "param" html markups that
214 * begins with "mms://" */
218 strncasecmp( psz_bol, "href", sizeof("href") - 1 ) &&
219 strncasecmp( psz_bol, "param", sizeof("param") - 1 ) )
222 if( !*psz_bol ) continue;
224 while( *psz_bol && strncasecmp( psz_bol, "mms://",
225 sizeof("mms://") - 1 ) )
228 if( !*psz_bol ) continue;
230 psz_eol = strchr( psz_bol, '"');
238 * From now on, we know we've got a meaningful line
241 /* Check if the line has an absolute or relative path */
243 while( *psz_name && strncmp( psz_bol, "://", sizeof("://") - 1 ) )
250 /* the line doesn't specify a protocol name.
251 * If this line doesn't begin with a '/' then assume the path
252 * is relative to the path of the m3u file. */
253 char *psz_path = strdup( p_input->psz_name );
255 psz_name = strrchr( psz_path, '/' );
256 if( psz_name ) *psz_name = '\0';
257 else *psz_path = '\0';
258 psz_name = malloc( strlen(psz_path) + strlen(psz_bol) + 2 );
259 sprintf( psz_name, "%s/%s", psz_path, psz_bol );
264 psz_name = strdup( psz_bol );
267 playlist_Add( p_playlist, psz_name,
268 PLAYLIST_APPEND, PLAYLIST_END );
275 input_DeletePacket( p_input->p_method_data, p_data );
278 vlc_object_release( p_playlist );