pls.c 7.7 KB
Newer Older
1 2 3
/*****************************************************************************
 * pls.c : PLS playlist format import
 *****************************************************************************
4
 * Copyright (C) 2004 the VideoLAN team
5
 * $Id$
6
 *
7
 * Authors: Clément Stenac <zorglub@videolan.org>
8
 * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
Antoine Cellerier's avatar
Antoine Cellerier committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 24 25 26 27 28
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <vlc/vlc.h>
29
#include <vlc/input.h>
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
#include <vlc/intf.h>

#include "playlist.h"

struct demux_sys_t
{
    char *psz_prefix;
};

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static int Demux( demux_t *p_demux);
static int Control( demux_t *p_demux, int i_query, va_list args );

/*****************************************************************************
 * Import_PLS: main import function
 *****************************************************************************/
48
int E_(Import_PLS)( vlc_object_t *p_this )
49 50 51
{
    demux_t *p_demux = (demux_t *)p_this;
    uint8_t *p_peek;
52
    CHECK_PEEK( p_peek, 10 );
53

54
    if( POKE( p_peek, "[playlist]", 10 ) || POKE( p_peek, "[Reference]", 10 ) ||
55
        isExtension( p_demux, ".pls" )   || isDemux( p_demux, "pls" ) )
56 57 58
    {
        ;
    }
59 60
    else return VLC_EGENERIC;

61
    STANDARD_DEMUX_INIT_MSG(  "found valid PLS playlist file");
62
    p_demux->p_sys->psz_prefix = E_(FindPrefix)( p_demux );
63 64 65 66 67 68 69

    return VLC_SUCCESS;
}

/*****************************************************************************
 * Deactivate: frees unused data
 *****************************************************************************/
70
void E_(Close_PLS)( vlc_object_t *p_this )
71 72 73 74 75 76 77 78 79 80 81 82
{
    demux_t *p_demux = (demux_t *)p_this;
    if( p_demux->p_sys->psz_prefix )
    {
        free( p_demux->p_sys->psz_prefix );
    }
    free( p_demux->p_sys );
}

static int Demux( demux_t *p_demux )
{
    mtime_t        i_duration = -1;
83
    char          *psz_name = NULL;
84 85
    char          *psz_line;
    char          *psz_mrl = NULL;
86
    char          *psz_mrl_orig = NULL;
87 88 89 90 91 92
    char          *psz_key;
    char          *psz_value;
    int            i_item = -1;
    int            i_new_item = 0;
    int            i_key_length;

93
    INIT_PLAYLIST_STUFF;
94

95 96
    while( ( psz_line = stream_ReadLine( p_demux->s ) ) )
    {
97
        if( !strncasecmp( psz_line, "[playlist]", sizeof("[playlist]")-1 ) ||
98
            !strncasecmp( psz_line, "[Reference]", sizeof("[Reference]")-1 ) )
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
        {
            free( psz_line );
            continue;
        }
        psz_key = psz_line;
        psz_value = strchr( psz_line, '=' );
        if( psz_value )
        {
            *psz_value='\0';
            psz_value++;
        }
        else
        {
            msg_Warn( p_demux, "invalid line in pls file" );
            free( psz_line );
            continue;
        }
        if( !strcasecmp( psz_key, "version" ) )
        {
            msg_Dbg( p_demux, "pls file version: %s", psz_value );
            free( psz_line );
            continue;
        }
        /* find the number part of of file1, title1 or length1 etc */
        i_key_length = strlen( psz_key );
124
        if( i_key_length >= 4 ) /* Ref1 type case */
125
        {
126 127
            i_new_item = atoi( psz_key + 3 );
            if( i_new_item == 0 && i_key_length >= 5 ) /* file1 type case */
128
            {
129 130
                i_new_item = atoi( psz_key + 4 );
                if( i_new_item == 0 && i_key_length >= 6 ) /* title1 type case */
131
                {
132 133 134 135 136
                    i_new_item = atoi( psz_key + 5 );
                    if( i_new_item == 0 && i_key_length >= 7 ) /* length1 type case */
                    {
                        i_new_item = atoi( psz_key + 6 );
                    }
137 138 139 140 141
                }
            }
        }
        if( i_new_item == 0 )
        {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
142
            msg_Warn( p_demux, "couldn't find number of items" );
143 144 145 146 147 148 149 150 151 152 153 154
            free( psz_line );
            continue;
        }
        if( i_item == -1 )
        {
            i_item = i_new_item;
        }
        /* we found a new item, insert the previous */
        if( i_item != i_new_item )
        {
            if( psz_mrl )
            {
155 156
                p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name,
                                            0, NULL, -1 );
157
                input_ItemCopyOptions( p_current->p_input, p_input );
158 159 160
                playlist_AddWhereverNeeded( p_playlist, p_input, p_current,
                                p_item_in_category, (i_parent_id > 0 ) ?
                                VLC_TRUE: VLC_FALSE, PLAYLIST_APPEND );
161 162 163 164 165 166 167 168 169 170 171 172 173 174
            }
            else
            {
                msg_Warn( p_demux, "no file= part found for item %d", i_item );
            }
            if( psz_name )
            {
                free( psz_name );
                psz_name = NULL;
            }
            i_duration = -1;
            i_item = i_new_item;
            i_new_item = 0;
        }
175 176
        if( !strncasecmp( psz_key, "file", sizeof("file") -1 ) ||
            !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) )
177
        {
178
            psz_mrl_orig =
179
            psz_mrl = E_(ProcessMRL)( psz_value, p_demux->p_sys->psz_prefix );
180 181 182 183 184 185 186 187 188 189 190

            if( !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) )
            {
                if( !strncasecmp( psz_mrl, "http://", sizeof("http://") -1 ) )
                {
                    psz_mrl++;
                    psz_mrl[0] = 'm';
                    psz_mrl[1] = 'm';
                    psz_mrl[2] = 's';
                }
            }
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
        }
        else if( !strncasecmp( psz_key, "title", sizeof("title") -1 ) )
        {
            psz_name = strdup( psz_value );
        }
        else if( !strncasecmp( psz_key, "length", sizeof("length") -1 ) )
        {
            i_duration = atoi( psz_value );
            if( i_duration != -1 )
            {
                i_duration *= 1000000;
            }
        }
        else
        {
            msg_Warn( p_demux, "unknown key found in pls file: %s", psz_key );
        }
        free( psz_line );
    }
    /* Add last object */
    if( psz_mrl )
    {
213
        p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name,0, NULL, -1 );
214
        input_ItemCopyOptions( p_current->p_input, p_input );
215 216 217
        playlist_AddWhereverNeeded( p_playlist, p_input, p_current,
                                p_item_in_category, (i_parent_id > 0 ) ?
                                VLC_TRUE: VLC_FALSE, PLAYLIST_APPEND );
218
        free( psz_mrl_orig );
219 220 221 222 223 224 225 226 227 228 229 230
        psz_mrl = NULL;
    }
    else
    {
        msg_Warn( p_demux, "no file= part found for item %d", i_item );
    }
    if( psz_name )
    {
        free( psz_name );
        psz_name = NULL;
    }

231
    HANDLE_PLAY_AND_RELEASE;
232 233 234 235 236 237 238
    return VLC_SUCCESS;
}

static int Control( demux_t *p_demux, int i_query, va_list args )
{
    return VLC_EGENERIC;
}