Add a new playlist module whose job is to output pf_readdir modules items to the...
[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     add_submodule ()
149         set_description( N_("Directory import") )
150         add_shortcut( "playlist", "directory" )
151         set_capability( "demux", 10 )
152         set_callbacks( Import_Dir, Close_Dir )
153 vlc_module_end ()
154
155 int Control(demux_t *demux, int query, va_list args)
156 {
157     (void) demux; (void) query; (void) args;
158     return VLC_EGENERIC;
159 }
160
161 input_item_t * GetCurrentItem(demux_t *p_demux)
162 {
163     input_thread_t *p_input_thread = demux_GetParentInput( p_demux );
164     input_item_t *p_current_input = input_GetItem( p_input_thread );
165     vlc_gc_incref(p_current_input);
166     vlc_object_release(p_input_thread);
167     return p_current_input;
168 }
169
170 /**
171  * Find directory part of the path to the playlist file, in case of
172  * relative paths inside
173  */
174 char *FindPrefix( demux_t *p_demux )
175 {
176     char *psz_url;
177
178     if( asprintf( &psz_url, "%s://%s", p_demux->psz_access,
179                   p_demux->psz_location ) == -1 )
180         return NULL;
181
182     char *psz_file = strrchr( psz_url, '/' );
183     assert( psz_file != NULL );
184     psz_file[1] = '\0';
185
186     return psz_url;
187 }
188
189 /**
190  * Add the directory part of the playlist file to the start of the
191  * mrl, if the mrl is a relative file path
192  */
193 char *ProcessMRL( const char *psz_mrl, const char *psz_prefix )
194 {
195     /* Check for a protocol name.
196      * for URL, we should look for "://"
197      * for MRL (Media Resource Locator) ([[<access>][/<demux>]:][<source>]),
198      * we should look for ":", so we end up looking simply for ":"
199      * PB: on some file systems, ':' are valid characters though */
200
201     /* Simple cases first */
202     if( !psz_mrl || !*psz_mrl )
203         return NULL;
204     if( !psz_prefix || !*psz_prefix )
205         goto uri;
206
207     /* Check if the line specifies an absolute path */
208     /* FIXME: that's wrong if the playlist is not a local file */
209     if( *psz_mrl == DIR_SEP_CHAR )
210         goto uri;
211 #if defined( _WIN32 ) || defined( __OS2__ )
212     /* Drive letter (this assumes URL scheme are not a single character) */
213     if( isalpha((unsigned char)psz_mrl[0]) && psz_mrl[1] == ':' )
214         goto uri;
215 #endif
216     if( strstr( psz_mrl, "://" ) )
217         return strdup( psz_mrl );
218
219     /* This a relative path, prepend the prefix */
220     char *ret;
221     char *postfix = encode_URI_component( psz_mrl );
222     /* FIXME: postfix may not be encoded correctly (esp. slashes) */
223     if( postfix == NULL
224      || asprintf( &ret, "%s%s", psz_prefix, postfix ) == -1 )
225         ret = NULL;
226     free( postfix );
227     return ret;
228
229 uri:
230     return vlc_path2uri( psz_mrl, NULL );
231 }
232
233 /**
234  * Checks stream Content-Type against a known one
235  */
236 bool CheckContentType( stream_t * p_stream, const char * psz_ctype )
237 {
238     char *psz_check = stream_ContentType( p_stream );
239     if( !psz_check ) return false;
240
241     int i_len = strlen( psz_check );
242     if ( i_len == 0 )
243     {
244         free( psz_check );
245         return false;
246     }
247
248     /* check for Content-Type: foo-type; charset=... */
249     const char * psz_sep = strchr( psz_check, ';' );
250     if ( psz_sep )
251         i_len = __MIN( i_len, psz_sep - psz_check );
252
253     int i_res = strncasecmp( psz_check, psz_ctype, i_len );
254     free( psz_check );
255
256     return ( i_res == 0 ) ? true : false;
257 }