X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Fplaylist%2Fxspf.c;h=e1178b2f94bc90cdf9332e4e63132a5b6a2a2548;hb=6dd5c5cb5418b321d0f04b4d9265bb4537ba2812;hp=1c8a2016504fbff929e0ea16792fc8bef34a6963;hpb=51880eb16eed467a21c34b9e4bb962d1bd6a5be7;p=vlc diff --git a/modules/misc/playlist/xspf.c b/modules/misc/playlist/xspf.c index 1c8a201650..e1178b2f94 100644 --- a/modules/misc/playlist/xspf.c +++ b/modules/misc/playlist/xspf.c @@ -26,23 +26,29 @@ * \file modules/misc/playlist/xspf.c * \brief XSPF playlist export functions */ -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include #include #include #include #include #include +#include #include #include "xspf.h" +#include + /** * \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 E_(xspf_export_playlist)( vlc_object_t *p_this ) +int xspf_export_playlist( vlc_object_t *p_this ) { const playlist_t *p_playlist = (playlist_t *)p_this; const playlist_export_t *p_export = @@ -71,8 +77,8 @@ int E_(xspf_export_playlist)( vlc_object_t *p_this ) if( psz_temp && *psz_temp ) { fprintf( p_export->p_file, "\t%s\n", psz_temp ); - free( psz_temp ); } + free( psz_temp ); /* export all items in a flat format */ fprintf( p_export->p_file, "\t\n" ); @@ -85,7 +91,7 @@ int E_(xspf_export_playlist)( vlc_object_t *p_this ) fprintf( p_export->p_file, "\t\n" ); /* export the tree structure in */ - fprintf( p_export->p_file, "\t\n" ); + fprintf( p_export->p_file, "\t\n" ); i_count = 0; for( i = 0; i < p_node->i_children; i++ ) { @@ -111,6 +117,8 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file, { char *psz; char *psz_temp; + int i; + mtime_t i_duration; if( !p_item ) return; @@ -139,23 +147,27 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file, ( *p_i_count )++; /* -> the location */ - if( p_item->p_input->psz_uri && *p_item->p_input->psz_uri ) + + char *psz_uri = input_item_GetURI( p_item->p_input ); + + if( psz_uri && *psz_uri ) { - psz = assertUTF8URI( p_item->p_input->psz_uri ); + psz = assertUTF8URI( psz_uri ); fprintf( p_file, "\t\t\t%s\n", psz ); free( psz ); } /* -> the name/title (only if different from uri)*/ - if( p_item->p_input->psz_name && - p_item->p_input->psz_uri && - strcmp( p_item->p_input->psz_uri, p_item->p_input->psz_name ) ) + char *psz_name = input_item_GetTitle( p_item->p_input ); + if( psz_name && psz_uri && strcmp( psz_uri, psz_name ) ) { - psz_temp = convert_xml_special_chars( p_item->p_input->psz_name ); + psz_temp = convert_xml_special_chars( psz_name ); if( *psz_temp ) fprintf( p_file, "\t\t\t%s\n", psz_temp ); free( psz_temp ); } + free( psz_name ); + free( psz_uri ); if( p_item->p_input->p_meta == NULL ) { @@ -163,11 +175,10 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file, } /* -> the artist/creator */ - psz = input_item_GetArtist( p_item->p_input ) ? - strdup( input_item_GetArtist( p_item->p_input ) ): - strdup( "" ); + psz = input_item_GetArtist( p_item->p_input ); + if( psz == NULL ) psz = strdup( "" ); psz_temp = convert_xml_special_chars( psz ); - if( psz ) free( psz ); + free( psz ); if( *psz_temp ) { fprintf( p_file, "\t\t\t%s\n", psz_temp ); @@ -175,11 +186,10 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file, free( psz_temp ); /* -> the album */ - psz = input_item_GetAlbum( p_item->p_input ) ? - strdup( input_item_GetAlbum( p_item->p_input ) ): - strdup( "" ); + psz = input_item_GetAlbum( p_item->p_input ); + if( psz == NULL ) psz = strdup( "" ); psz_temp = convert_xml_special_chars( psz ); - if( psz ) free( psz ); + free( psz ); if( *psz_temp ) { fprintf( p_file, "\t\t\t%s\n", psz_temp ); @@ -187,36 +197,55 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file, free( psz_temp ); /* -> the track number */ - psz = input_item_GetTrackNum( p_item->p_input ) ? - strdup( input_item_GetTrackNum( p_item->p_input ) ): - strdup( "" ); - if( psz ) + psz = input_item_GetTrackNum( p_item->p_input ); + if( psz == NULL ) psz = strdup( "" ); + if( psz && *psz ) { - if( *psz ) - { - fprintf( p_file, "\t\t\t%i\n", atoi( psz ) ); - } - free( psz ); + int i_tracknum = atoi( psz ); + if( i_tracknum > 0 ) + fprintf( p_file, "\t\t\t%i\n", i_tracknum ); } + free( psz ); /* -> the description */ - psz = input_item_GetDescription( p_item->p_input ) ? - strdup( input_item_GetDescription( p_item->p_input ) ): - strdup( "" ); + psz = input_item_GetDescription( p_item->p_input ); + if( psz == NULL ) psz = strdup( "" ); psz_temp = convert_xml_special_chars( psz ); - if( psz ) free( psz ); + free( psz ); if( *psz_temp ) { fprintf( p_file, "\t\t\t%s\n", psz_temp ); } free( psz_temp ); + psz = input_item_GetArtURL( p_item->p_input ); + if( psz == NULL ) psz = strdup( "" ); + if( !EMPTY_STR( psz ) ) + { + psz_uri = assertUTF8URI( psz ); + fprintf( p_file, "\t\t\t%s\n", psz_uri ); + free( psz_uri ); + } + free( psz ); + + /* export the input's options (bookmarks, ...) in */ + fprintf( p_file, "\t\t\t\n" ); + for( i = 0; i < p_item->p_input->i_options; i++ ) + { + fprintf( p_file, "\t\t\t\t\n", + p_item->p_input->ppsz_options[i][0] == ':' ? + p_item->p_input->ppsz_options[i] + 1 : + p_item->p_input->ppsz_options[i] ); + } + fprintf( p_file, "\t\t\t\n" ); + xspfexportitem_end: /* -> the duration */ - if( p_item->p_input->i_duration > 0 ) + i_duration = input_item_GetDuration( p_item->p_input ); + if( i_duration > 0 ) { fprintf( p_file, "\t\t\t%ld\n", - (long)(p_item->p_input->i_duration / 1000) ); + (long)(i_duration / 1000) ); } fprintf( p_file, "\t\t\n" ); @@ -242,7 +271,7 @@ static void xspf_extension_item( playlist_item_t *p_item, FILE *p_file, char *psz_temp; psz_temp = convert_xml_special_chars( p_item->p_input->psz_name ); fprintf( p_file, "\t\t\n", - *psz_temp ? p_item->p_input->psz_name : "" ); + *psz_temp ? psz_temp : "" ); free( psz_temp ); for( i = 0; i < p_item->i_children; i++ ) @@ -273,7 +302,7 @@ static char *assertUTF8URI( char *psz_name ) { char *psz_ret = NULL; /**< the new result buffer to return */ char *psz_s = NULL, *psz_d = NULL; /**< src & dest pointers for URI conversion */ - vlc_bool_t b_name_is_uri = VLC_FALSE; + bool b_uri_is_file = false; /**< we do additional %-encoding if the URI is a file:// one */ if( !psz_name || !*psz_name ) return NULL; @@ -290,16 +319,24 @@ static char *assertUTF8URI( char *psz_name ) return NULL; /** \todo check for a valid scheme part preceding the colon */ - if( strchr( psz_s, ':' ) ) + size_t i_delim = strcspn( psz_s, ":" ); + if( i_delim != strlen( psz_s ) ) { - psz_d = psz_ret; - b_name_is_uri = VLC_TRUE; + i_delim++; /* skip the ':' */ + strncpy( psz_ret, psz_s, i_delim ); + psz_d = psz_ret + i_delim; + + if( !strncmp( psz_s, "file://", 7 ) ) + b_uri_is_file = true; + + psz_s += i_delim; } /* assume "file" scheme if no scheme-part is included */ else { strcpy( psz_ret, "file://" ); psz_d = psz_ret + 7; + b_uri_is_file = true; } while( *psz_s ) @@ -310,7 +347,18 @@ static char *assertUTF8URI( char *psz_name ) *psz_s == '>' || *psz_s == '&' || *psz_s == ' ' || - ( *psz_s == '%' && !b_name_is_uri ) ) + *psz_s == '+' || + *psz_s == '%' || + ( b_uri_is_file && ( + *psz_s == ':' || + *psz_s == '"' || + *psz_s == '?' || + *psz_s == '#' || + *psz_s == '[' || + *psz_s == ']' || + *psz_s == '@' ) + ) + ) { *psz_d++ = '%'; *psz_d++ = hexchars[(*psz_s >> 4) & B00001111];