X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=inline;f=modules%2Fmisc%2Fplaylist%2Fxspf.c;h=e1178b2f94bc90cdf9332e4e63132a5b6a2a2548;hb=6dd5c5cb5418b321d0f04b4d9265bb4537ba2812;hp=325b0bbb91b8558d29d13515348b2b70795248c7;hpb=6bc1500f97bf158ec4160570ff3d6173f8f67dc4;p=vlc diff --git a/modules/misc/playlist/xspf.c b/modules/misc/playlist/xspf.c index 325b0bbb91..e1178b2f94 100644 --- a/modules/misc/playlist/xspf.c +++ b/modules/misc/playlist/xspf.c @@ -26,20 +26,29 @@ * \file modules/misc/playlist/xspf.c * \brief XSPF playlist export functions */ -#include -#include -#include -#include "vlc_meta.h" -#include "vlc_strings.h" +#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 = @@ -68,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" ); @@ -82,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++ ) { @@ -108,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; @@ -122,31 +133,41 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file, return; } + /* don't write empty nodes */ + if( p_item->i_children == 0 ) + { + return; + } + /* leaves can be written directly */ fprintf( p_file, "\t\t\n" ); /* print identifier and increase the counter */ - fprintf( p_file, "\t\t\t%d\n", *p_i_count ); + fprintf( p_file, "\t\t\t%i\n", *p_i_count ); ( *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 ) { @@ -154,22 +175,10 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file, } /* -> the artist/creator */ - psz = p_item->p_input->p_meta->psz_artist ? - strdup( p_item->p_input->p_meta->psz_artist ): - strdup( "" ); - if( psz && !*psz ) - { - free( psz ); - psz = NULL; - } - if( !psz ) - { - psz = p_item->p_input->p_meta->psz_author ? - strdup( p_item->p_input->p_meta->psz_author ): - 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 ); @@ -177,11 +186,10 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file, free( psz_temp ); /* -> the album */ - psz = p_item->p_input->p_meta->psz_album ? - strdup( p_item->p_input->p_meta->psz_album ): - 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 ); @@ -189,24 +197,55 @@ static void xspf_export_item( playlist_item_t *p_item, FILE *p_file, free( psz_temp ); /* -> the track number */ - psz = p_item->p_input->p_meta->psz_tracknum ? - strdup( p_item->p_input->p_meta->psz_tracknum ): - 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 ); + if( psz == NULL ) psz = strdup( "" ); + psz_temp = convert_xml_special_chars( 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" ); @@ -226,13 +265,14 @@ static void xspf_extension_item( playlist_item_t *p_item, FILE *p_file, if( !p_item ) return; /* if we get a node here, we must traverse it */ - if( p_item->i_children > 0 ) + if( p_item->i_children >= 0 ) { int i; - - fprintf( p_file, "\t\t\n" ); - fprintf( p_file, "\t\t\t%s\n", - p_item->p_input->psz_name ); + char *psz_temp; + psz_temp = convert_xml_special_chars( p_item->p_input->psz_name ); + fprintf( p_file, "\t\t\n", + *psz_temp ? psz_temp : "" ); + free( psz_temp ); for( i = 0; i < p_item->i_children; i++ ) { @@ -245,7 +285,7 @@ static void xspf_extension_item( playlist_item_t *p_item, FILE *p_file, /* print leaf and increase the counter */ - fprintf( p_file, "\t\t\t\n", *p_i_count ); + fprintf( p_file, "\t\t\t\n", *p_i_count ); ( *p_i_count )++; return; @@ -262,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; @@ -279,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 ) @@ -299,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];