示例#1
0
文件: qtl.c 项目: IAPark/vlc
static int ReadDir( stream_t *p_demux, input_item_node_t *p_subitems )
{
    xml_reader_t *p_xml_reader;
    input_item_t *p_input;
    int i_ret = -1;

    /* List of all possible attributes. The only required one is "src" */
    bool b_autoplay = false;
    bool b_controller = true;
    qtl_fullscreen_t fullscreen = false;
    char *psz_href = NULL;
    bool b_kioskmode = false;
    qtl_loop_t loop = LOOP_FALSE;
    int i_movieid = -1;
    char *psz_moviename = NULL;
    bool b_playeveryframe = false;
    char *psz_qtnext = NULL;
    bool b_quitwhendone = false;
    char *psz_src = NULL;
    char *psz_mimetype = NULL;
    int i_volume = 100;

    p_xml_reader = xml_ReaderCreate( p_demux, p_demux->p_source );
    if( !p_xml_reader )
        goto error;

    for( int i = 0;; ++i ) /* locate root node */
    {
        const char *node;
        if( i == ROOT_NODE_MAX_DEPTH ||
            xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM )
        {
            msg_Err( p_demux, "unable to locate root-node" );
            goto error;
        }

        if( strcmp( node, "embed" ) == 0 )
            break; /* found it */

        msg_Dbg( p_demux, "invalid root node <%s>, trying next (%d / %d)",
                           node, i + 1, ROOT_NODE_MAX_DEPTH );
    }

    const char *attrname, *value;
    while( (attrname = xml_ReaderNextAttr( p_xml_reader, &value )) != NULL )
    {
        if( !strcmp( attrname, "autoplay" ) )
            b_autoplay = !strcmp( value, "true" );
        else if( !strcmp( attrname, "controller" ) )
            b_controller = !strcmp( attrname, "false" );
        else if( !strcmp( attrname, "fullscreen" ) )
        {
            if( !strcmp( value, "double" ) )
                fullscreen = FULLSCREEN_DOUBLE;
            else if( !strcmp( value, "half" ) )
                fullscreen = FULLSCREEN_HALF;
            else if( !strcmp( value, "current" ) )
                fullscreen = FULLSCREEN_CURRENT;
            else if( !strcmp( value, "full" ) )
                fullscreen = FULLSCREEN_FULL;
            else
                fullscreen = FULLSCREEN_NORMAL;
        }
        else if( !strcmp( attrname, "href" ) )
        {
            free( psz_href );
            psz_href = strdup( value );
        }
        else if( !strcmp( attrname, "kioskmode" ) )
            b_kioskmode = !strcmp( value, "true" );
        else if( !strcmp( attrname, "loop" ) )
        {
            if( !strcmp( value, "true" ) )
                loop = LOOP_TRUE;
            else if( !strcmp( value, "palindrome" ) )
                loop = LOOP_PALINDROME;
            else
                loop = LOOP_FALSE;
        }
        else if( !strcmp( attrname, "movieid" ) )
            i_movieid = atoi( value );
        else if( !strcmp( attrname, "moviename" ) )
        {
            free( psz_moviename );
            psz_moviename = strdup( value );
        }
        else if( !strcmp( attrname, "playeveryframe" ) )
            b_playeveryframe = !strcmp( value, "true" );
        else if( !strcmp( attrname, "qtnext" ) )
        {
            free( psz_qtnext );
            psz_qtnext = strdup( value );
        }
        else if( !strcmp( attrname, "quitwhendone" ) )
            b_quitwhendone = !strcmp( value, "true" );
        else if( !strcmp( attrname, "src" ) )
        {
            free( psz_src );
            psz_src = strdup( value );
        }
        else if( !strcmp( attrname, "mimetype" ) )
        {
            free( psz_mimetype );
            psz_mimetype = strdup( value );
        }
        else if( !strcmp( attrname, "volume" ) )
            i_volume = atoi( value );
        else
            msg_Dbg( p_demux, "Attribute %s with value %s isn't valid",
                     attrname, value );
    }

    msg_Dbg( p_demux, "autoplay: %s (unused by VLC)",
             b_autoplay ? "true": "false" );
    msg_Dbg( p_demux, "controller: %s (unused by VLC)",
             b_controller ? "true": "false" );
    msg_Dbg( p_demux, "fullscreen: %s (unused by VLC)",
             ppsz_fullscreen[fullscreen] );
    msg_Dbg( p_demux, "href: %s", psz_href );
    msg_Dbg( p_demux, "kioskmode: %s (unused by VLC)",
             b_kioskmode ? "true":"false" );
    msg_Dbg( p_demux, "loop: %s (unused by VLC)", ppsz_loop[loop] );
    msg_Dbg( p_demux, "movieid: %d (unused by VLC)", i_movieid );
    msg_Dbg( p_demux, "moviename: %s", psz_moviename );
    msg_Dbg( p_demux, "playeverframe: %s (unused by VLC)",
             b_playeveryframe ? "true":"false" );
    msg_Dbg( p_demux, "qtnext: %s", psz_qtnext );
    msg_Dbg( p_demux, "quitwhendone: %s (unused by VLC)",
             b_quitwhendone ? "true":"false" );
    msg_Dbg( p_demux, "src: %s", psz_src );
    msg_Dbg( p_demux, "mimetype: %s", psz_mimetype );
    msg_Dbg( p_demux, "volume: %d (unused by VLC)", i_volume );


    if( !psz_src )
    {
        msg_Err( p_demux, "Mandatory attribute 'src' not found" );
    }
    else
    {
        p_input = input_item_New( psz_src, psz_moviename );
#define SADD_INFO( type, field ) if( field ) { input_item_AddInfo( \
                    p_input, "QuickTime Media Link", type, "%s", field ) ; }
        SADD_INFO( "href", psz_href );
        SADD_INFO( _("Mime"), psz_mimetype );
        input_item_node_AppendItem( p_subitems, p_input );
        input_item_Release( p_input );
        if( psz_qtnext )
        {
            vlc_xml_decode( psz_qtnext );
            p_input = input_item_New( psz_qtnext, NULL );
            input_item_node_AppendItem( p_subitems, p_input );
            input_item_Release( p_input );
        }
    }

    i_ret = 0; /* Needed for correct operation of go back */

error:
    if( p_xml_reader )
        xml_ReaderDelete( p_xml_reader );

    free( psz_href );
    free( psz_moviename );
    free( psz_qtnext );
    free( psz_src );
    free( psz_mimetype );
    return i_ret;
}
示例#2
0
文件: shoutcast.c 项目: Kafay/vlc
/* radio stations:
 * <stationlist>
 *   <tunein base="/sbin/tunein-station.pls"></tunein>
 *   <station name="the name"
 *            mt="mime type"
 *            id="the id"
 *            br="bit rate"
 *            genre="A big genre string"
 *            ct="current track name/author/..."
 *            lc="listener count"></station>
 * </stationlist>
 *
 * TV stations:
 * <stationlist>
 *   <tunein base="/sbin/tunein-station.pls"></tunein>
 *   <station name="the name"
 *            id="the id"
 *            br="bit rate"
 *            rt="rating"
 *            load="server load ?"
 *            ct="current track name/author/..."
 *            genre="A big genre string"
 *            lc="listener count"></station>
 * </stationlist>
 **/
static int DemuxStation( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    input_item_t *p_input;

    char *psz_base = NULL; /* */

    char *psz_name = NULL; /* genre name */
    char *psz_mt = NULL; /* mime type */
    char *psz_id = NULL; /* id */
    char *psz_br = NULL; /* bit rate */
    char *psz_genre = NULL; /* genre */
    char *psz_ct = NULL; /* current track */
    char *psz_lc = NULL; /* listener count */

    /* If these are set then it's *not* a radio but a TV */
    char *psz_rt = NULL; /* rating for shoutcast TV */
    char *psz_load = NULL; /* load for shoutcast TV */

    char *psz_eltname = NULL; /* tag name */

    while( xml_ReaderRead( p_sys->p_xml_reader ) == 1 )
    {
        int i_type;

        // Get the node type
        i_type = xml_ReaderNodeType( p_sys->p_xml_reader );
        switch( i_type )
        {
            // Error
            case -1:
                return -1;
                break;

            case XML_READER_STARTELEM:
                // Read the element name
                psz_eltname = xml_ReaderName( p_sys->p_xml_reader );
                if( !psz_eltname ) return -1;

                // Read the attributes
                if( !strcmp( psz_eltname, "tunein" ) )
                {
                    while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS )
                    {
                        char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader );
                        char *psz_attrvalue =
                            xml_ReaderValue( p_sys->p_xml_reader );
                        if( !psz_attrname || !psz_attrvalue )
                        {
                            free( psz_eltname );
                            free( psz_attrname );
                            free( psz_attrvalue );
                            return -1;
                        }

                        GET_VALUE( base )
                        else
                        {
                            msg_Warn( p_demux,
                                      "unexpected attribure %s in element %s",
                                      psz_attrname, psz_eltname );
                        }
                        free( psz_attrname );
                        free( psz_attrvalue );
                    }
                }
                else if( !strcmp( psz_eltname, "station" ) )
                {
                    while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS )
                    {
                        char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader );
                        char *psz_attrvalue =
                            xml_ReaderValue( p_sys->p_xml_reader );
                        if( !psz_attrname || !psz_attrvalue )
                        {
                            free( psz_eltname );
                            free( psz_attrname );
                            free( psz_attrvalue );
                            return -1;
                        }

                        GET_VALUE( name )
                        else GET_VALUE( mt )
                        else GET_VALUE( id )
                        else GET_VALUE( br )
                        else GET_VALUE( genre )
                        else GET_VALUE( ct )
                        else GET_VALUE( lc )
                        else GET_VALUE( rt )
                        else GET_VALUE( load )
                        else
                        {
                            msg_Warn( p_demux,
                                      "unexpected attribute %s in element %s",
                                      psz_attrname, psz_eltname );
                        }
                        free( psz_attrname );
                        free( psz_attrvalue );
                    }
                }
                free( psz_eltname );
                break;

            case XML_READER_TEXT:
                break;

            // End element
            case XML_READER_ENDELEM:
                // Read the element name
                psz_eltname = xml_ReaderName( p_sys->p_xml_reader );
                if( !psz_eltname ) return -1;
                if( !strcmp( psz_eltname, "station" ) &&
                    ( psz_base || ( psz_rt && psz_load &&
                    ( p_sys->b_adult || strcmp( psz_rt, "NC17" ) ) ) ) )
                {
                    char *psz_mrl = NULL;
                    if( psz_rt || psz_load )
                    {
                        /* tv */
                        if( asprintf( &psz_mrl, SHOUTCAST_TV_TUNEIN_URL "%s",
                                 psz_id ) == -1)
                            psz_mrl = NULL;
                    }
                    else
                    {
                        /* radio */
                        if( asprintf( &psz_mrl, SHOUTCAST_TUNEIN_BASE_URL "%s?id=%s",
                             psz_base, psz_id ) == -1 )
                            psz_mrl = NULL;
                    }
                    p_input = input_item_New( p_demux, psz_mrl, psz_name );
                    input_item_CopyOptions( p_sys->p_current_input, p_input );
                    free( psz_mrl );

#define SADD_INFO( type, field ) \
                    if( field ) \
                        input_item_AddInfo( p_input, _("Shoutcast"), \
                                            vlc_gettext(type), "%s", field )
                    SADD_INFO( N_("Mime"), psz_mt );
                    SADD_INFO( N_("Bitrate"), psz_br );
                    SADD_INFO( N_("Listeners"), psz_lc );
                    SADD_INFO( N_("Load"), psz_load );
                    if( psz_genre )
                        input_item_SetGenre( p_input, psz_genre );
                    if( psz_ct )
                        input_item_SetNowPlaying( p_input, psz_ct );
                    if( psz_rt )
                        input_item_SetRating( p_input, psz_rt );
                    input_item_AddSubItem( p_sys->p_current_input, p_input );
                    vlc_gc_decref( p_input );
                    FREENULL( psz_name );
                    FREENULL( psz_mt );
                    FREENULL( psz_id );
                    FREENULL( psz_br );
                    FREENULL( psz_genre );
                    FREENULL( psz_ct );
                    FREENULL( psz_lc );
                    FREENULL( psz_rt );
                }
                free( psz_eltname );
                break;
        }
    }
示例#3
0
文件: qtl.c 项目: AsamQi/vlc
static int Demux( demux_t *p_demux )
{
    xml_reader_t *p_xml_reader;
    const char *node;
    input_item_t *p_input;
    int i_ret = -1;

    /* List of all possible attributes. The only required one is "src" */
    bool b_autoplay = false;
    bool b_controler = true;
    qtl_fullscreen_t fullscreen = false;
    char *psz_href = NULL;
    bool b_kioskmode = false;
    qtl_loop_t loop = LOOP_FALSE;
    int i_movieid = -1;
    char *psz_moviename = NULL;
    bool b_playeveryframe = false;
    char *psz_qtnext = NULL;
    bool b_quitwhendone = false;
    char *psz_src = NULL;
    char *psz_mimetype = NULL;
    int i_volume = 100;

    input_item_t *p_current_input = GetCurrentItem(p_demux);

    p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s );
    if( !p_xml_reader )
        goto error;

    /* check root node */
    if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM
     || strcmp( node, "embed" ) )
    {
        msg_Err( p_demux, "invalid root node <%s>", node );

        /* second line has <?quicktime tag ... so we try to skip it */
        msg_Dbg( p_demux, "trying to read one more node" );
        if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM
         || strcmp( node, "embed" ) )
        {
            msg_Err( p_demux, "invalid root node <%s>", node );
            goto error;
        }
    }

    const char *attrname, *value;
    while( (attrname = xml_ReaderNextAttr( p_xml_reader, &value )) != NULL )
    {
        if( !strcmp( attrname, "autoplay" ) )
            b_autoplay = !strcmp( value, "true" );
        else if( !strcmp( attrname, "controler" ) )
            b_controler = !strcmp( attrname, "false" );
        else if( !strcmp( attrname, "fullscreen" ) )
        {
            if( !strcmp( value, "double" ) )
                fullscreen = FULLSCREEN_DOUBLE;
            else if( !strcmp( value, "half" ) )
                fullscreen = FULLSCREEN_HALF;
            else if( !strcmp( value, "current" ) )
                fullscreen = FULLSCREEN_CURRENT;
            else if( !strcmp( value, "full" ) )
                fullscreen = FULLSCREEN_FULL;
            else
                fullscreen = FULLSCREEN_NORMAL;
        }
        else if( !strcmp( attrname, "href" ) )
        {
            free( psz_href );
            psz_href = strdup( value );
        }
        else if( !strcmp( attrname, "kioskmode" ) )
            b_kioskmode = !strcmp( value, "true" );
        else if( !strcmp( attrname, "loop" ) )
        {
            if( !strcmp( value, "true" ) )
                loop = LOOP_TRUE;
            else if( !strcmp( value, "palindrome" ) )
                loop = LOOP_PALINDROME;
            else
                loop = LOOP_FALSE;
        }
        else if( !strcmp( attrname, "movieid" ) )
            i_movieid = atoi( value );
        else if( !strcmp( attrname, "moviename" ) )
        {
            free( psz_moviename );
            psz_moviename = strdup( value );
        }
        else if( !strcmp( attrname, "playeveryframe" ) )
            b_playeveryframe = !strcmp( value, "true" );
        else if( !strcmp( attrname, "qtnext" ) )
        {
            free( psz_qtnext );
            psz_qtnext = strdup( value );
        }
        else if( !strcmp( attrname, "quitwhendone" ) )
            b_quitwhendone = !strcmp( value, "true" );
        else if( !strcmp( attrname, "src" ) )
        {
            free( psz_src );
            psz_src = strdup( value );
        }
        else if( !strcmp( attrname, "mimetype" ) )
        {
            free( psz_mimetype );
            psz_mimetype = strdup( value );
        }
        else if( !strcmp( attrname, "volume" ) )
            i_volume = atoi( value );
        else
            msg_Dbg( p_demux, "Attribute %s with value %s isn't valid",
                     attrname, value );
    }

    msg_Dbg( p_demux, "autoplay: %s (unused by VLC)",
             b_autoplay ? "true": "false" );
    msg_Dbg( p_demux, "controler: %s (unused by VLC)",
             b_controler ? "true": "false" );
    msg_Dbg( p_demux, "fullscreen: %s (unused by VLC)",
             ppsz_fullscreen[fullscreen] );
    msg_Dbg( p_demux, "href: %s", psz_href );
    msg_Dbg( p_demux, "kioskmode: %s (unused by VLC)",
             b_kioskmode ? "true":"false" );
    msg_Dbg( p_demux, "loop: %s (unused by VLC)", ppsz_loop[loop] );
    msg_Dbg( p_demux, "movieid: %d (unused by VLC)", i_movieid );
    msg_Dbg( p_demux, "moviename: %s", psz_moviename );
    msg_Dbg( p_demux, "playeverframe: %s (unused by VLC)",
             b_playeveryframe ? "true":"false" );
    msg_Dbg( p_demux, "qtnext: %s", psz_qtnext );
    msg_Dbg( p_demux, "quitwhendone: %s (unused by VLC)",
             b_quitwhendone ? "true":"false" );
    msg_Dbg( p_demux, "src: %s", psz_src );
    msg_Dbg( p_demux, "mimetype: %s", psz_mimetype );
    msg_Dbg( p_demux, "volume: %d (unused by VLC)", i_volume );


    if( !psz_src )
    {
        msg_Err( p_demux, "Mandatory attribute 'src' not found" );
    }
    else
    {
        input_item_node_t *p_subitems = input_item_node_Create( p_current_input );
        p_input = input_item_New( psz_src, psz_moviename );
#define SADD_INFO( type, field ) if( field ) { input_item_AddInfo( \
                    p_input, "QuickTime Media Link", type, "%s", field ) ; }
        SADD_INFO( "href", psz_href );
        SADD_INFO( _("Mime"), psz_mimetype );
        input_item_node_AppendItem( p_subitems, p_input );
        vlc_gc_decref( p_input );
        if( psz_qtnext )
        {
            p_input = input_item_New( psz_qtnext, NULL );
            input_item_node_AppendItem( p_subitems, p_input );
            vlc_gc_decref( p_input );
        }
        input_item_node_PostAndDelete( p_subitems );
    }

    i_ret = 0; /* Needed for correct operation of go back */

error:
    if( p_xml_reader )
        xml_ReaderDelete( p_xml_reader );

    vlc_gc_decref(p_current_input);

    free( psz_href );
    free( psz_moviename );
    free( psz_qtnext );
    free( psz_src );
    free( psz_mimetype );
    return i_ret;
}
/* radio stations:
 * <stationlist>
 *   <tunein base="/sbin/tunein-station.pls"></tunein>
 *   <station name="the name"
 *            mt="mime type"
 *            id="the id"
 *            br="bit rate"
 *            genre="A big genre string"
 *            ct="current track name/author/..."
 *            lc="listener count"></station>
 * </stationlist>
 *
 * TV stations:
 * <stationlist>
 *   <tunein base="/sbin/tunein-station.pls"></tunein>
 *   <station name="the name"
 *            id="the id"
 *            br="bit rate"
 *            rt="rating"
 *            load="server load ?"
 *            ct="current track name/author/..."
 *            genre="A big genre string"
 *            lc="listener count"></station>
 * </stationlist>
 **/
static int DemuxStation( demux_t *p_demux, xml_reader_t *p_xml_reader,
                         input_item_node_t *p_input_node, bool b_adult )
{
    char *psz_base = NULL; /* */

    char *psz_name = NULL; /* genre name */
    char *psz_mt = NULL; /* mime type */
    char *psz_id = NULL; /* id */
    char *psz_br = NULL; /* bit rate */
    char *psz_genre = NULL; /* genre */
    char *psz_ct = NULL; /* current track */
    char *psz_lc = NULL; /* listener count */

    /* If these are set then it's *not* a radio but a TV */
    char *psz_rt = NULL; /* rating for shoutcast TV */
    char *psz_load = NULL; /* load for shoutcast TV */

    const char *node; /* tag name */
    int i_type;

    while( (i_type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 )
    {
        switch( i_type )
        {
            case XML_READER_STARTELEM:
                // Read the attributes
                if( !strcmp( node, "tunein" ) )
                {
                    const char *name, *value;
                    while( (name = xml_ReaderNextAttr( p_xml_reader, &value )) )
                    {
                        if( !strcmp( name, "base" ) )
                        {
                            free( psz_base );
                            psz_base = strdup( value );
                        }
                        else
                            msg_Warn( p_demux,
                                      "unexpected attribute %s in <%s>",
                                      name, node );
                    }
                }
                else if( !strcmp( node, "station" ) )
                {
                    const char *name, *value;
                    while( (name = xml_ReaderNextAttr( p_xml_reader, &value )) )
                    {
                        char **p = NULL;
                        if( !strcmp( name, "name" ) )
                            p = &psz_name;
                        else if ( !strcmp( name, "mt" ) )
                            p = &psz_mt;
                        else if ( !strcmp( name, "id" ) )
                            p = &psz_id;
                        else if ( !strcmp( name, "br" ) )
                            p = &psz_br;
                        else if ( !strcmp( name, "genre" ) )
                            p = &psz_genre;
                        else if ( !strcmp( name, "ct" ) )
                            p = &psz_ct;
                        else if ( !strcmp( name, "lc" ) )
                            p = &psz_lc;
                        else if ( !strcmp( name, "rt" ) )
                            p = &psz_rt;
                        else if ( !strcmp( name, "load" ) )
                            p = &psz_load;
                        if( p != NULL )
                        {
                            free( *p );
                            *p = strdup( value );
                        }
                        else
                            msg_Warn( p_demux,
                                      "unexpected attribute %s in <%s>",
                                      name, node );
                    }
                }
                break;

            // End element
            case XML_READER_ENDELEM:
                if( !strcmp( node, "station" ) &&
                    ( psz_base || ( psz_rt && psz_load &&
                    ( b_adult || strcmp( psz_rt, "NC17" ) ) ) ) )
                {
                    char *psz_mrl = NULL;
                    if( psz_rt || psz_load )
                    {
                        /* tv */
                        if( asprintf( &psz_mrl, SHOUTCAST_TV_TUNEIN_URL "%s",
                                 psz_id ) == -1)
                            psz_mrl = NULL;
                    }
                    else
                    {
                        /* radio */
                        if( asprintf( &psz_mrl, SHOUTCAST_TUNEIN_BASE_URL "%s?id=%s",
                             psz_base, psz_id ) == -1 )
                            psz_mrl = NULL;
                    }

                    /* Create the item */
                    input_item_t *p_input;
                    p_input = input_item_New( psz_mrl, psz_name );
                    input_item_CopyOptions( p_input_node->p_item, p_input );
                    free( psz_mrl );

#define SADD_INFO( type, field ) \
                    if( field ) \
                        input_item_AddInfo( p_input, _("Shoutcast"), \
                                            vlc_gettext(type), "%s", field )
                    SADD_INFO( N_("Mime"), psz_mt );
                    SADD_INFO( N_("Bitrate"), psz_br );
                    SADD_INFO( N_("Listeners"), psz_lc );
                    SADD_INFO( N_("Load"), psz_load );
                    if( psz_genre )
                        input_item_SetGenre( p_input, psz_genre );
                    if( psz_ct )
                        input_item_SetNowPlaying( p_input, psz_ct );
                    if( psz_rt )
                        input_item_SetRating( p_input, psz_rt );
                    input_item_node_AppendItem( p_input_node, p_input );
                    vlc_gc_decref( p_input );
                    FREENULL( psz_base );
                    FREENULL( psz_name );
                    FREENULL( psz_mt );
                    FREENULL( psz_id );
                    FREENULL( psz_br );
                    FREENULL( psz_genre );
                    FREENULL( psz_ct );
                    FREENULL( psz_lc );
                    FREENULL( psz_rt );
                    FREENULL( psz_load );
                }
                break;
        }
    }
    /* FIXME: leaks on missing ENDELEMENT? */
    return 0;
}
示例#5
0
文件: gvp.c 项目: CSRedRat/vlc
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;

    char *psz_line;
    char *psz_attrvalue;

    char *psz_version = NULL;
    char *psz_url = NULL;
    char *psz_docid = NULL;
    int i_duration = -1;
    char *psz_title = NULL;
    char *psz_description = NULL;
    input_item_t *p_input;

    input_item_t *p_current_input = GetCurrentItem(p_demux);

    input_item_node_t *p_subitems = input_item_node_Create( p_current_input );

    p_sys->p_current_input = p_current_input;

    while( ( psz_line = stream_ReadLine( p_demux->s ) ) )
    {
        if( *psz_line == '#' )
        {
            /* This is a comment */
            free( psz_line );
            continue;
        }
        psz_attrvalue = strchr( psz_line, ':' );
        if( !psz_attrvalue )
        {
            msg_Dbg( p_demux, "Unable to parse line (%s)", psz_line );
            free( psz_line );
            continue;
        }
        *psz_attrvalue = '\0';
        psz_attrvalue++;
        if( !strcmp( psz_line, "gvp_version" ) )
        {
            psz_version = strdup( psz_attrvalue );
        }
        else if( !strcmp( psz_line, "url" ) )
        {
            psz_url = strdup( psz_attrvalue );
        }
        else if( !strcmp( psz_line, "docid" ) )
        {
            psz_docid = strdup( psz_attrvalue );
        }
        else if( !strcmp( psz_line, "duration" ) )
        {
            i_duration = atoi( psz_attrvalue );
        }
        else if( !strcmp( psz_line, "title" ) )
        {
            psz_title = strdup( psz_attrvalue );
        }
        else if( !strcmp( psz_line, "description" ) )
        {
            char *buf;
            if( !psz_description )
            {
                psz_description = strdup( psz_attrvalue );
            }
            else
            {
                /* handle multi-line descriptions */
                if( asprintf( &buf, "%s\n%s", psz_description, psz_attrvalue ) == -1 )
                    buf = NULL;
                free( psz_description );
                psz_description = buf;
            }
            /* remove ^M char at the end of the line (if any) */
            buf = psz_description + strlen( psz_description );
            if( buf != psz_description )
            {
                buf--;
                if( *buf == '\r' ) *buf = '\0';
            }
        }
        free( psz_line );
    }

    if( !psz_url )
    {
        msg_Err( p_demux, "URL not found" );
    }
    else
    {
        p_input = input_item_New( psz_url, psz_title );
#define SADD_INFO( type, field ) if( field ) { input_item_AddInfo( \
                    p_input, _("Google Video"), type, "%s", field ) ; }
        SADD_INFO( "gvp_version", psz_version );
        SADD_INFO( "docid", psz_docid );
        SADD_INFO( "description", psz_description );
        input_item_node_AppendItem( p_subitems, p_input );
        vlc_gc_decref( p_input );
    }

    input_item_node_PostAndDelete( p_subitems );

    vlc_gc_decref(p_current_input);

    free( psz_version );
    free( psz_url );
    free( psz_docid );
    free( psz_title );
    free( psz_description );

    return 0; /* Needed for correct operation of go back */
}