0b4a053ad2ed4bfa037a7fd2d86524bc85203dc1
[vlc.git] / modules / demux / playlist / playlist.c
1 /*****************************************************************************
2  * playlist.c :  Playlist import module
3  *****************************************************************************
4  * Copyright (C) 2004 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_demux.h>
34 #include <vlc_url.h>
35
36 #if defined( _WIN32 ) || defined( __OS2__ )
37 # include <ctype.h>                          /* isalpha */
38 #endif
39 #include <assert.h>
40
41 #include "playlist.h"
42
43 /*****************************************************************************
44  * Module descriptor
45  *****************************************************************************/
46 #define SHOW_ADULT_TEXT N_( "Show shoutcast adult content" )
47 #define SHOW_ADULT_LONGTEXT N_( "Show NC17 rated video streams when " \
48                 "using shoutcast video playlists." )
49
50 #define SKIP_ADS_TEXT N_( "Skip ads" )
51 #define SKIP_ADS_LONGTEXT N_( "Use playlist options usually used to prevent " \
52     "ads skipping to detect ads and prevent adding them to the playlist." )
53
54 vlc_module_begin ()
55     add_shortcut( "playlist" )
56     set_category( CAT_INPUT )
57     set_subcategory( SUBCAT_INPUT_DEMUX )
58
59     add_obsolete_integer( "parent-item" ) /* removed since 1.1.0 */
60
61     add_bool( "playlist-skip-ads", true,
62               SKIP_ADS_TEXT, SKIP_ADS_LONGTEXT, false )
63
64     set_shortname( N_("Playlist") )
65     set_description( N_("Playlist") )
66     add_submodule ()
67         set_description( N_("M3U playlist import") )
68         add_shortcut( "playlist", "m3u", "m3u8", "m3u-open" )
69         set_capability( "demux", 10 )
70         set_callbacks( Import_M3U, Close_M3U )
71     add_submodule ()
72         set_description( N_("RAM playlist import") )
73         add_shortcut( "playlist", "ram-open" )
74         set_capability( "demux", 10 )
75         set_callbacks( Import_RAM, Close_RAM )
76     add_submodule ()
77         set_description( N_("PLS playlist import") )
78         add_shortcut( "playlist", "pls-open" )
79         set_capability( "demux", 10 )
80         set_callbacks( Import_PLS, Close_PLS )
81     add_submodule ()
82         set_description( N_("B4S playlist import") )
83         add_shortcut( "playlist", "b4s-open", "shout-b4s" )
84         set_capability( "demux", 10 )
85         set_callbacks( Import_B4S, NULL )
86     add_submodule ()
87         set_description( N_("DVB playlist import") )
88         add_shortcut( "playlist", "dvb-open" )
89         set_capability( "demux", 10 )
90         set_callbacks( Import_DVB, NULL )
91     add_submodule ()
92         set_description( N_("Podcast parser") )
93         add_shortcut( "playlist", "podcast" )
94         set_capability( "demux", 10 )
95         set_callbacks( Import_podcast, NULL )
96     add_submodule ()
97         set_description( N_("XSPF playlist import") )
98         add_shortcut( "playlist", "xspf-open" )
99         set_capability( "demux", 10 )
100         set_callbacks( Import_xspf, Close_xspf )
101     add_submodule ()
102         set_description( N_("New winamp 5.2 shoutcast import") )
103         add_shortcut( "playlist", "shout-winamp" )
104         set_capability( "demux", 10 )
105         set_callbacks( Import_Shoutcast, NULL )
106         add_bool( "shoutcast-show-adult", false,
107                    SHOW_ADULT_TEXT, SHOW_ADULT_LONGTEXT, false )
108     add_submodule ()
109         set_description( N_("ASX playlist import") )
110         add_shortcut( "playlist", "asx-open" )
111         set_capability( "demux", 10 )
112         set_callbacks( Import_ASX, Close_ASX )
113     add_submodule ()
114         set_description( N_("Kasenna MediaBase parser") )
115         add_shortcut( "playlist", "sgimb" )
116         set_capability( "demux", 10 )
117         set_callbacks( Import_SGIMB, Close_SGIMB )
118     add_submodule ()
119         set_description( N_("QuickTime Media Link importer") )
120         add_shortcut( "playlist", "qtl" )
121         set_capability( "demux", 10 )
122         set_callbacks( Import_QTL, NULL )
123     add_submodule ()
124         set_description( N_("Google Video Playlist importer") )
125         add_shortcut( "playlist", "gvp" )
126         set_capability( "demux", 10 )
127         set_callbacks( Import_GVP, Close_GVP )
128     add_submodule ()
129         set_description( N_("Dummy IFO demux") )
130         add_shortcut( "playlist" )
131         set_capability( "demux", 12 )
132         set_callbacks( Import_IFO, NULL )
133     add_submodule ()
134         set_description( N_("iTunes Music Library importer") )
135         add_shortcut( "playlist", "itml" )
136         set_capability( "demux", 10 )
137         set_callbacks( Import_iTML, Close_iTML )
138     add_submodule ()
139         set_description( N_("WPL playlist import") )
140         add_shortcut( "playlist", "wpl" )
141         set_capability( "demux", 10 )
142         set_callbacks( Import_WPL, Close_WPL )
143     add_submodule ()
144         set_description( N_("ZPL playlist import") )
145         add_shortcut( "playlist", "zpl" )
146         set_capability( "demux", 10 )
147         set_callbacks( Import_ZPL, Close_ZPL )
148 vlc_module_end ()
149
150 int Control(demux_t *demux, int query, va_list args)
151 {
152     (void) demux; (void) query; (void) args;
153     return VLC_EGENERIC;
154 }
155
156 input_item_t * GetCurrentItem(demux_t *p_demux)
157 {
158     input_thread_t *p_input_thread = demux_GetParentInput( p_demux );
159     input_item_t *p_current_input = input_GetItem( p_input_thread );
160     vlc_gc_incref(p_current_input);
161     vlc_object_release(p_input_thread);
162     return p_current_input;
163 }
164
165 /**
166  * Find directory part of the path to the playlist file, in case of
167  * relative paths inside
168  */
169 char *FindPrefix( demux_t *p_demux )
170 {
171     char *psz_url;
172
173     if( asprintf( &psz_url, "%s://%s", p_demux->psz_access,
174                   p_demux->psz_location ) == -1 )
175         return NULL;
176
177     char *psz_file = strrchr( psz_url, '/' );
178     assert( psz_file != NULL );
179     psz_file[1] = '\0';
180
181     return psz_url;
182 }
183
184 /**
185  * Add the directory part of the playlist file to the start of the
186  * mrl, if the mrl is a relative file path
187  */
188 char *ProcessMRL( const char *psz_mrl, const char *psz_prefix )
189 {
190     /* Check for a protocol name.
191      * for URL, we should look for "://"
192      * for MRL (Media Resource Locator) ([[<access>][/<demux>]:][<source>]),
193      * we should look for ":", so we end up looking simply for ":"
194      * PB: on some file systems, ':' are valid characters though */
195
196     /* Simple cases first */
197     if( !psz_mrl || !*psz_mrl )
198         return NULL;
199     if( !psz_prefix || !*psz_prefix )
200         goto uri;
201
202     /* Check if the line specifies an absolute path */
203     /* FIXME: that's wrong if the playlist is not a local file */
204     if( *psz_mrl == DIR_SEP_CHAR )
205         goto uri;
206 #if defined( _WIN32 ) || defined( __OS2__ )
207     /* Drive letter (this assumes URL scheme are not a single character) */
208     if( isalpha((unsigned char)psz_mrl[0]) && psz_mrl[1] == ':' )
209         goto uri;
210 #endif
211     if( strstr( psz_mrl, "://" ) )
212         return strdup( psz_mrl );
213
214     /* This a relative path, prepend the prefix */
215     char *ret;
216     char *postfix = encode_URI_component( psz_mrl );
217     /* FIXME: postfix may not be encoded correctly (esp. slashes) */
218     if( postfix == NULL
219      || asprintf( &ret, "%s%s", psz_prefix, postfix ) == -1 )
220         ret = NULL;
221     free( postfix );
222     return ret;
223
224 uri:
225     return vlc_path2uri( psz_mrl, NULL );
226 }
227
228 /**
229  * Checks stream Content-Type against a known one
230  */
231 bool CheckContentType( stream_t * p_stream, const char * psz_ctype )
232 {
233     char *psz_check = stream_ContentType( p_stream );
234     if( !psz_check ) return false;
235
236     int i_len = strlen( psz_check );
237     if ( i_len == 0 )
238     {
239         free( psz_check );
240         return false;
241     }
242
243     /* check for Content-Type: foo-type; charset=... */
244     const char * psz_sep = strchr( psz_check, ';' );
245     if ( psz_sep )
246         i_len = __MIN( i_len, psz_sep - psz_check );
247
248     int i_res = strncasecmp( psz_check, psz_ctype, i_len );
249     free( psz_check );
250
251     return ( i_res == 0 ) ? true : false;
252 }