Exemple #1
0
/**
 * Recursively follow the playlist
 * @param p_export: the export structure
 * @param p_root: the current node
 */
static void DoChildren( playlist_export_t *p_export, playlist_item_t *p_root )
{
    /* Go through the playlist and add items */
    for( int i = 0; i < p_root->i_children ; i++)
    {
        playlist_item_t *p_current = p_root->pp_children[i];
        assert( p_current );

        if( p_current->i_flags & PLAYLIST_SAVE_FLAG )
            continue;

        if( p_current->i_children >= 0 )
        {
            DoChildren( p_export, p_current );
            continue;
        }

        char* psz_name = NULL;
        char *psz_tmp = input_item_GetName( p_current->p_input );
        if( psz_tmp )
            psz_name = vlc_xml_encode( psz_tmp );
        free( psz_tmp );

        if( psz_name )
        {
            char* psz_artist = NULL;
            psz_tmp = input_item_GetArtist( p_current->p_input );
            if( psz_tmp )
                psz_artist = vlc_xml_encode( psz_tmp );
            free( psz_tmp );

            mtime_t i_duration = input_item_GetDuration( p_current->p_input );
            int min = ( i_duration / 1000000 ) / 60;
            int sec = ( i_duration / 1000000 ) - min * 60;

            // Print the artist if we have one
            if( psz_artist && *psz_artist )
                fprintf( p_export->p_file, "    <li>%s - %s (%02d:%02d)</li>\n", psz_artist, psz_name, min, sec );
            else
                fprintf( p_export->p_file, "    <li>%s (%2d:%2d)</li>\n", psz_name, min, sec );

            free( psz_artist );
        }
        free( psz_name );
    }
}
Exemple #2
0
static char *input_xml( input_item_t *p_item, char *(*func)(input_item_t *) )
{
    char *tmp = func( p_item );
    if( tmp == NULL )
        return NULL;
    char *ret = vlc_xml_encode( tmp );
    free( tmp );
    return ret;
}
Exemple #3
0
/**
 * \brief Prints the XSPF header to file, writes each item by xspf_export_item()
 * and closes the open xml elements
 * \param p_this the VLC playlist object
 * \return VLC_SUCCESS if some memory is available, otherwise VLC_ENONMEM
 */
int xspf_export_playlist( vlc_object_t *p_this )
{
    const playlist_export_t *p_export = (playlist_export_t *)p_this;
    int               i, i_count;
    char             *psz_temp;
    playlist_item_t  *p_node = p_export->p_root;

    /* write XSPF XML header */
    fprintf( p_export->p_file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
    fprintf( p_export->p_file,
             "<playlist xmlns=\"http://xspf.org/ns/0/\" " \
              "xmlns:vlc=\"http://www.videolan.org/vlc/playlist/ns/0/\" " \
              "version=\"1\">\n" );

    if( !p_node ) return VLC_SUCCESS;

    /* save name of the playlist node */
    psz_temp = vlc_xml_encode( p_node->p_input->psz_name );
    if( *psz_temp )
    {
        fprintf(  p_export->p_file, "\t<title>%s</title>\n", psz_temp );
    }
    free( psz_temp );

    /* export all items in a flat format */
    fprintf( p_export->p_file, "\t<trackList>\n" );
    i_count = 0;
    for( i = 0; i < p_node->i_children; i++ )
    {
        xspf_export_item( p_node->pp_children[i], p_export->p_file,
                          &i_count );
    }
    fprintf( p_export->p_file, "\t</trackList>\n" );

    /* export the tree structure in <extension> */
    fprintf( p_export->p_file, "\t<extension application=\"" \
             "http://www.videolan.org/vlc/playlist/0\">\n" );
    i_count = 0;
    for( i = 0; i < p_node->i_children; i++ )
    {
        xspf_extension_item( p_node->pp_children[i], p_export->p_file,
                             &i_count, 2 );
    }
    fprintf( p_export->p_file, "\t</extension>\n" );

    /* close the header elements */
    fprintf( p_export->p_file, "</playlist>\n" );

    return VLC_SUCCESS;
}
Exemple #4
0
static void encode (const char *in, const char *out)
{
    char *buf;

    printf ("\"%s\" -> \"%s\" ?\n", in, out);
    buf = vlc_xml_encode (in);

    if (strcmp (buf, out))
    {
        printf (" ERROR: got \"%s\"\n", buf);
        exit (2);
    }
    free (buf);
}
Exemple #5
0
/**
 * \brief exports one item in extension to file and traverse if item is a node
 * \param p_item playlist item to export
 * \param p_file file to write xml-converted item to
 * \param p_i_count counter for track identifiers
 * \param i_depth identation depth
 */
static void xspf_extension_item( playlist_item_t *p_item, FILE *p_file,
                                 int *p_i_count, int i_depth )
{
    if( !p_item ) return;

    /* if we get a node here, we must traverse it */
    if( p_item->i_children >= 0 )
    {
        int i;
        char *psz_temp = NULL;
        if( p_item->p_input->psz_name )
            psz_temp = vlc_xml_encode( p_item->p_input->psz_name );
        for(int j=0;j<i_depth;j++)
            fprintf( p_file, "\t" );
        fprintf( p_file, "<vlc:node title=\"%s\">\n",
                 psz_temp ? psz_temp : "" );
        free( psz_temp );

        for( i = 0; i < p_item->i_children; i++ )
        {
            xspf_extension_item( p_item->pp_children[i], p_file, p_i_count, i_depth + 1 );
        }

        for(int j=0;j<i_depth;j++)
            fprintf( p_file, "\t" );
        fprintf( p_file, "</vlc:node>\n" );
        return;
    }

    /* print leaf and increase the counter */
    for(int j=0;j<i_depth;j++)
        fprintf( p_file, "\t" );
    fprintf( p_file, "<vlc:item tid=\"%i\"/>\n", *p_i_count );
    ( *p_i_count )++;

    return;
}
Exemple #6
0
/** **************************************************************************
 * \brief Write the XSPF playlist given the list of files
 *****************************************************************************/
static int WriteXSPF( char **pp_buffer, vlc_array_t *p_filenames,
                      const char *psz_zippath )
{
    char *psz_zip = strrchr( psz_zippath, DIR_SEP_CHAR );
    psz_zip = vlc_xml_encode( psz_zip ? (psz_zip+1) : psz_zippath );

    if( asprintf( pp_buffer, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
        "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\" "
                "xmlns:vlc=\"http://www.videolan.org/vlc/playlist/ns/0/\">\n"
                " <title>%s</title>\n"
                " <trackList>\n", psz_zip ) == -1)
        return -1;

    /* Root node */
    node *playlist = new_node( psz_zip );
    free( psz_zip );

    /* Encode the URI and append ZIP_SEP */
    char *psz_pathtozip;
    escapeToXml( &psz_pathtozip, psz_zippath );
    if( astrcatf( &psz_pathtozip, "%s", ZIP_SEP ) < 0 ) {
        free_all_node( playlist );
        return -1;
    }

    int i_track = 0;
    for( int i = 0; i < vlc_array_count( p_filenames ); ++i )
    {
        char *psz_name = (char*) vlc_array_item_at_index( p_filenames, i );
        int i_len = strlen( psz_name );

        if( !i_len ) continue;

        /* Is it a folder ? */
        if( psz_name[i_len-1] == '/' )
        {
            /* Do nothing */
        }
        else /* File */
        {
            /* Extract file name */
            char *psz_file = strrchr( psz_name, '/' );
            psz_file = vlc_xml_encode( psz_file ? (psz_file+1) : psz_name );

            /* Build full MRL */
            char *psz_path = strdup( psz_pathtozip );
            char *psz_escapedName;
            escapeToXml( &psz_escapedName, psz_name );
            if( astrcatf( &psz_path, "%s", psz_escapedName ) < 0 )
            {
                free( psz_escapedName );
                return -1;
            }
            free( psz_escapedName );

            /* Track information */
            if( astrcatf( pp_buffer,
                        "  <track>\n"
                        "   <location>zip://%s</location>\n"
                        "   <title>%s</title>\n"
                        "   <extension application=\"http://www.videolan.org/vlc/playlist/0\">\n"
                        "    <vlc:id>%d</vlc:id>\n"
                        "   </extension>\n"
                        "  </track>\n",
                        psz_path, psz_file, i_track ) < 0 ) return -1;

            free( psz_file );
            free( psz_path );

            /* Find the parent node */
            node *parent = findOrCreateParentNode( playlist, psz_name );
            assert( parent );

            /* Add the item to this node */
            item *tmp = parent->media;
            if( !tmp )
            {
                parent->media = new_item( i_track );
            }
            else
            {
                while( tmp->next )
                {
                    tmp = tmp->next;
                }
                tmp->next = new_item( i_track );
            }

            ++i_track;
        }
    }

    free( psz_pathtozip );

    /* Close tracklist, open the extension */
    if( astrcatf( pp_buffer,
        " </trackList>\n"
        " <extension application=\"http://www.videolan.org/vlc/playlist/0\">\n"
                ) < 0 ) return -1;

    /* Write the tree */
    if( nodeToXSPF( pp_buffer, playlist, true ) < 0 ) return -1;

    /* Close extension and playlist */
    if( astrcatf( pp_buffer, " </extension>\n</playlist>\n" ) < 0 ) return -1;

    /* printf( "%s", *pp_buffer ); */

    free_all_node( playlist );

    return VLC_SUCCESS;
}
Exemple #7
0
inline static node* new_node( char *name )
{
    node *n = (node*) calloc( 1, sizeof(node) );
    n->name = vlc_xml_encode( name );
    return n;
}
static int WriteCatalog( addons_storage_t *p_storage,
                         addon_entry_t **pp_entries, int i_entries )
{
    addon_entry_t *p_entry;
    char *psz_file;
    char *psz_file_tmp;
    char *psz_tempstring;
    char *psz_userdir = config_GetUserDir( VLC_DATA_DIR );
    if ( !psz_userdir ) return VLC_ENOMEM;

    if ( asprintf( &psz_file, "%s%s", psz_userdir, ADDONS_CATALOG ) < 1 )
    {
        free( psz_userdir );
        return VLC_ENOMEM;
    }
    free( psz_userdir );

    if ( asprintf( &psz_file_tmp, "%s.tmp%"PRIu32, psz_file, (uint32_t)getpid() ) < 1 )
    {
        free( psz_file );
        return VLC_ENOMEM;
    }

    char *psz_path = strdup( psz_file );
    if ( !psz_path )
    {
        free( psz_file );
        free( psz_file_tmp );
        return VLC_ENOMEM;
    }

    char *psz_buf = strrchr( psz_path, DIR_SEP_CHAR );
    if( psz_buf )
    {
        *++psz_buf = '\0';
        /* ensure directory exists */
        if( !EMPTY_STR( psz_path ) ) recursive_mkdir( VLC_OBJECT(p_storage), psz_path );
    }
    free( psz_path );

    FILE *p_catalog = vlc_fopen( psz_file_tmp, "wt" );
    if ( !p_catalog )
    {
        free( psz_file );
        free( psz_file_tmp );
        return VLC_EGENERIC;
    }

    /* write XML header */
    fprintf( p_catalog, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
    fprintf( p_catalog, "<videolan xmlns=\"http://videolan.org/ns/vlc/addons/1.0\">\n" );
    fprintf( p_catalog, "\t<addons>\n" );

    for ( int i=0; i<i_entries; i++ )
    {
        p_entry = pp_entries[i];
        vlc_mutex_lock( &p_entry->lock );
        psz_tempstring = NULL;

        if ( ( p_entry->e_state != ADDON_INSTALLED ) ||
             !( p_entry->e_flags & ADDON_MANAGEABLE ) )
        {
            vlc_mutex_unlock( &p_entry->lock );
            continue;
        }

        if ( p_entry->psz_source_module )
            psz_tempstring = vlc_xml_encode( p_entry->psz_source_module );

        char *psz_uuid = addons_uuid_to_psz( ( const addon_uuid_t * ) & p_entry->uuid );
        fprintf( p_catalog, "\t\t<addon source=\"%s\" type=\"%s\" id=\"%s\" "
                                 "downloads=\"%ld\" score=\"%d\"",
                 ( psz_tempstring ) ? psz_tempstring : "",
                 getTypePsz( p_entry->e_type ),
                 psz_uuid,
                 p_entry->i_downloads,
                 p_entry->i_score );
        free( psz_uuid );
        free( psz_tempstring );

        WRITE_WITH_ENTITIES( " version=\"%s\"", p_entry->psz_version )
        fprintf( p_catalog, ">\n" );

        WRITE_WITH_ENTITIES( "\t\t\t<name>%s</name>\n", p_entry->psz_name )
        WRITE_WITH_ENTITIES( "\t\t\t<summary>%s</summary>\n", p_entry->psz_summary )

        if ( p_entry->psz_description )
        {
            psz_tempstring = p_entry->psz_description;
            /* FIXME: do real escaping */
            while( ( psz_tempstring = strstr( psz_tempstring, "]]>" ) ) )
                *psz_tempstring = ' ';
            fprintf( p_catalog, "\t\t\t<description><![CDATA[%s]]></description>\n", p_entry->psz_description );
        }

        WRITE_WITH_ENTITIES( "\t\t\t<image>%s</image>\n", p_entry->psz_image_data )
        WRITE_WITH_ENTITIES( "\t\t\t<archive>%s</archive>\n", p_entry->psz_archive_uri )

        fprintf( p_catalog, "\t\t\t<authorship>\n" );
        WRITE_WITH_ENTITIES( "\t\t\t\t<creator>%s</creator>\n", p_entry->psz_author )
        WRITE_WITH_ENTITIES( "\t\t\t\t<sourceurl>%s</sourceurl>\n", p_entry->psz_source_uri )
        fprintf( p_catalog, "\t\t\t</authorship>\n" );

        FOREACH_ARRAY( addon_file_t *p_file, p_entry->files )
            psz_tempstring = vlc_xml_encode( p_file->psz_filename );
            fprintf( p_catalog, "\t\t\t<resource type=\"%s\">%s</resource>\n",
                     getTypePsz( p_file->e_filetype ), psz_tempstring );
            free( psz_tempstring );
        FOREACH_END();

        fprintf( p_catalog, "\t\t</addon>\n" );

        vlc_mutex_unlock( &p_entry->lock );
    }

    fprintf( p_catalog, "\t</addons>\n" );
    fprintf( p_catalog, "</videolan>\n" );
    fclose( p_catalog );

    int i_ret = vlc_rename( psz_file_tmp, psz_file );
    free( psz_file );
    free( psz_file_tmp );

    if( i_ret == -1 )
    {
        msg_Err( p_storage, "could not rename temp catalog: %s",
                 vlc_strerror_c(errno) );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Exemple #9
0
/**
 * \brief exports one item to file or traverse if item is a node
 * \param p_item playlist item to export
 * \param p_file file to write xml-converted item to
 * \param p_i_count counter for track identifiers
 */
static void xspf_export_item( playlist_item_t *p_item, FILE *p_file,
                              int *p_i_count )
{
    if( !p_item ) return;

    /* if we get a node here, we must traverse it */
    if( p_item->i_children > 0 )
    {
        for( int i = 0; i < p_item->i_children; i++ )
            xspf_export_item( p_item->pp_children[i], p_file, p_i_count );
        return;
    }

    /* don't write empty nodes */
    if( p_item->i_children == 0 )
        return;

    input_item_t *p_input = p_item->p_input;
    char *psz;
    mtime_t i_duration;

    /* leaves can be written directly */
    fputs( "\t\t<track>\n", p_file );

    /* -> the location */

    char *psz_uri = input_xml( p_input, input_item_GetURI );
    if( psz_uri && *psz_uri )
        fprintf( p_file, "\t\t\t<location>%s</location>\n", psz_uri );

    /* -> the name/title (only if different from uri)*/
    psz = input_xml( p_input, input_item_GetTitle );
    if( psz && strcmp( psz_uri, psz ) )
        fprintf( p_file, "\t\t\t<title>%s</title>\n", psz );
    free( psz );
    free( psz_uri );

    if( p_item->p_input->p_meta == NULL )
    {
        goto xspfexportitem_end;
    }

    /* -> the artist/creator */
    psz = input_xml( p_input, input_item_GetArtist );
    if( psz && *psz )
        fprintf( p_file, "\t\t\t<creator>%s</creator>\n", psz );
    free( psz );

    /* -> the album */
    psz = input_xml( p_input, input_item_GetAlbum );
    if( psz && *psz )
        fprintf( p_file, "\t\t\t<album>%s</album>\n", psz );
    free( psz );

    /* -> the track number */
    psz = input_xml( p_input, input_item_GetTrackNum );
    if( psz )
    {
        int i_tracknum = atoi( psz );

        free( psz );
        if( i_tracknum > 0 )
            fprintf( p_file, "\t\t\t<trackNum>%i</trackNum>\n", i_tracknum );
    }

    /* -> the description */
    psz = input_xml( p_input, input_item_GetDescription );
    if( psz && *psz )
        fprintf( p_file, "\t\t\t<annotation>%s</annotation>\n", psz );
    free( psz );

    psz = input_xml( p_input, input_item_GetURL );
    if( psz && *psz )
        fprintf( p_file, "\t\t\t<info>%s</info>\n", psz );
    free( psz );

    psz = input_xml( p_input, input_item_GetArtURL );
    if( psz && *psz )
        fprintf( p_file, "\t\t\t<image>%s</image>\n", psz );
    free( psz );

xspfexportitem_end:
    /* -> the duration */
    i_duration = input_item_GetDuration( p_item->p_input );
    if( i_duration > 0 )
        fprintf( p_file, "\t\t\t<duration>%"PRIu64"</duration>\n",
                 i_duration / 1000 );

    /* export the intenal id and the input's options (bookmarks, ...)
     * in <extension> */
    fputs( "\t\t\t<extension application=\""
           "http://www.videolan.org/vlc/playlist/0\">\n", p_file );

    /* print the id and increase the counter */
    fprintf( p_file, "\t\t\t\t<vlc:id>%i</vlc:id>\n", *p_i_count );
    ( *p_i_count )++;

    for( int i = 0; i < p_item->p_input->i_options; i++ )
    {
        char* psz_src = p_item->p_input->ppsz_options[i];
        char* psz_ret = NULL;

        if ( psz_src[0] == ':' )
            psz_src++;

        psz_ret = vlc_xml_encode( psz_src );
        if ( psz_ret == NULL )
            continue;

        fprintf( p_file, "\t\t\t\t<vlc:option>%s</vlc:option>\n", psz_ret );
        free( psz_ret );
    }
    fputs( "\t\t\t</extension>\n", p_file );
    fputs( "\t\t</track>\n", p_file );
}