X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fplaylist%2Fshoutcast.c;h=a8c2e5d92c02eb56fb4079917617d2d73b3ec192;hb=HEAD;hp=c04a12849a3c991024f3845ae7ee0346c2c976ba;hpb=acb5da732a27b6c7e8d6e05c2e183d4ae49a9ea9;p=vlc diff --git a/modules/demux/playlist/shoutcast.c b/modules/demux/playlist/shoutcast.c index c04a12849a..a8c2e5d92c 100644 --- a/modules/demux/playlist/shoutcast.c +++ b/modules/demux/playlist/shoutcast.c @@ -25,74 +25,46 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* malloc(), free() */ -#include /* isspace() */ -#include -#include -#include - -#include /* ENOMEM */ -#include "playlist.h" -#include "vlc_xml.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -struct demux_sys_t -{ - playlist_t *p_playlist; - playlist_item_t *p_current; +#include +#include - xml_t *p_xml; - xml_reader_t *p_xml_reader; -}; +#include "playlist.h" +#include /* duplicate from modules/services_discovery/shout.c */ #define SHOUTCAST_BASE_URL "http/shout-winamp://www.shoutcast.com/sbin/newxml.phtml" #define SHOUTCAST_TUNEIN_BASE_URL "http://www.shoutcast.com" +#define SHOUTCAST_TV_TUNEIN_URL "http://www.shoutcast.com/sbin/tunein-tvstation.pls?id=" /***************************************************************************** * Local prototypes *****************************************************************************/ static int Demux( demux_t *p_demux); static int Control( demux_t *p_demux, int i_query, va_list args ); -#if 0 -static void ShoutcastAdd( playlist_t *p_playlist, playlist_item_t* p_genre, - playlist_item_t *p_bitrate, playlist_item_t *p_item, - char *psz_genre, char *psz_bitrate ); -#endif -static int DemuxGenre( demux_t *p_demux ); -static int DemuxStation( demux_t *p_demux ); +static int DemuxGenre( demux_t *p_demux, xml_reader_t *p_xml_reader, + input_item_node_t *p_input_node ); +static int DemuxStation( demux_t *p_demux, xml_reader_t *p_xml_reader, + input_item_node_t *p_input_node, bool b_adult ); /***************************************************************************** * Import_Shoutcast: main import function *****************************************************************************/ -int E_(Import_Shoutcast)( vlc_object_t *p_this ) +int Import_Shoutcast( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t *)p_this; - demux_sys_t *p_sys; - char *psz_ext; - - psz_ext = strrchr ( p_demux->psz_path, '.' ); - - if( !p_demux->psz_demux || strcmp(p_demux->psz_demux, "shout-winamp") ) - { + if( !demux_IsForced( p_demux, "shout-winamp" ) ) return VLC_EGENERIC; - } - msg_Dbg( p_demux, "using shoutcast playlist import"); - p_demux->pf_control = Control; p_demux->pf_demux = Demux; - p_demux->p_sys = p_sys = malloc( sizeof(demux_sys_t) ); - if( p_sys == NULL ) - { - msg_Err( p_demux, "out of memory" ); - return VLC_ENOMEM; - } - - p_sys->p_playlist = NULL; - p_sys->p_xml = NULL; - p_sys->p_xml_reader = NULL; + p_demux->pf_control = Control; + msg_Dbg( p_demux, "using shoutcast playlist reader" ); return VLC_SUCCESS; } @@ -100,65 +72,28 @@ int E_(Import_Shoutcast)( vlc_object_t *p_this ) /***************************************************************************** * Deactivate: frees unused data *****************************************************************************/ -void E_(Close_Shoutcast)( vlc_object_t *p_this ) +void Close_Shoutcast( vlc_object_t *p_this ) { - demux_t *p_demux = (demux_t *)p_this; - demux_sys_t *p_sys = p_demux->p_sys; - - if( p_sys->p_playlist ) - vlc_object_release( p_sys->p_playlist ); - if( p_sys->p_xml_reader ) - xml_ReaderDelete( p_sys->p_xml, p_sys->p_xml_reader ); - if( p_sys->p_xml ) - xml_Delete( p_sys->p_xml ); - free( p_sys ); + (void)p_this; } static int Demux( demux_t *p_demux ) { - demux_sys_t *p_sys = p_demux->p_sys; - playlist_t *p_playlist; - - vlc_bool_t b_play; - - xml_t *p_xml; - xml_reader_t *p_xml_reader; - + xml_reader_t *p_xml_reader = NULL; char *psz_eltname = NULL; + int i_ret = -1; + input_item_t *p_current_input = GetCurrentItem(p_demux); + input_item_node_t *p_input_node = NULL; + p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); + if( !p_xml_reader ) + goto error; - p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( !p_playlist ) - { - msg_Err( p_demux, "can't find playlist" ); - return -1; - } - p_sys->p_playlist = p_playlist; - - b_play = E_(FindItem)( p_demux, p_playlist, &p_sys->p_current ); - - msg_Warn( p_demux, "item: %s", p_sys->p_current->input.psz_name ); - playlist_ItemToNode( p_playlist, p_sys->p_current ); - p_sys->p_current->input.i_type = ITEM_TYPE_PLAYLIST; - - p_xml = p_sys->p_xml = xml_Create( p_demux ); - if( !p_xml ) return -1; - -/* psz_eltname = stream_ReadLine( p_demux->s ); - if( psz_eltname ) free( psz_eltname ); - psz_eltname = 0;*/ - - p_xml_reader = xml_ReaderCreate( p_xml, p_demux->s ); - if( !p_xml_reader ) return -1; - p_sys->p_xml_reader = p_xml_reader; - - /* xml */ /* check root node */ if( xml_ReaderRead( p_xml_reader ) != 1 ) { msg_Err( p_demux, "invalid file (no root node)" ); - return -1; + goto error; } if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM || @@ -168,142 +103,143 @@ static int Demux( demux_t *p_demux ) { msg_Err( p_demux, "invalid root node %i, %s", xml_ReaderNodeType( p_xml_reader ), psz_eltname ); - if( psz_eltname ) free( psz_eltname ); - return -1; + goto error; } + p_input_node = input_item_node_Create( p_current_input ); + if( !strcmp( psz_eltname, "genrelist" ) ) { /* we're reading a genre list */ - if( DemuxGenre( p_demux ) ) return -1; + if( DemuxGenre( p_demux, p_xml_reader, p_input_node ) ) + goto error; } else { /* we're reading a station list */ - if( DemuxStation( p_demux ) ) return -1; + if( DemuxStation( p_demux, p_xml_reader, p_input_node, + var_InheritBool( p_demux, "shoutcast-show-adult" ) ) ) + goto error; } - free( psz_eltname ); - /* Go back and play the playlist */ - if( b_play && p_playlist->status.p_item && - p_playlist->status.p_item->i_children > 0 ) - { - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - p_playlist->status.i_view, - p_playlist->status.p_item, - p_playlist->status.p_item->pp_children[0] ); - } + input_item_node_PostAndDelete( p_input_node ); + p_input_node = NULL; - vlc_object_release( p_playlist ); - p_sys->p_playlist = NULL; - return VLC_SUCCESS; + i_ret = 0; /* Needed for correct operation of go back */ + +error: + if( p_xml_reader ) + xml_ReaderDelete( p_xml_reader ); + free( psz_eltname ); + if( p_input_node ) input_item_node_Delete( p_input_node ); + vlc_gc_decref(p_current_input); + return i_ret; } #define GET_VALUE( a ) \ if( !strcmp( psz_attrname, #a ) ) \ { \ - psz_ ## a = strdup( psz_attrvalue ); \ + free(psz_ ## a); \ + psz_ ## a = psz_attrvalue; \ } /* * * ... * **/ -static int DemuxGenre( demux_t *p_demux ) +static int DemuxGenre( demux_t *p_demux, xml_reader_t *p_xml_reader, + input_item_node_t *p_input_node ) { - demux_sys_t *p_sys = p_demux->p_sys; char *psz_name = NULL; /* genre name */ - char *psz_eltname = NULL; /* tag name */ + int i_ret = -1; - while( xml_ReaderRead( p_sys->p_xml_reader ) == 1 ) + while( xml_ReaderRead( p_xml_reader ) == 1 ) { - int i_type; - // Get the node type - i_type = xml_ReaderNodeType( p_sys->p_xml_reader ); - switch( i_type ) + switch( xml_ReaderNodeType( p_xml_reader ) ) { // Error case -1: - return -1; - break; + goto error; case XML_READER_STARTELEM: + { // Read the element name - if( psz_eltname ) free( psz_eltname ); - psz_eltname = xml_ReaderName( p_sys->p_xml_reader ); - if( !psz_eltname ) return -1; - + char *psz_eltname = xml_ReaderName( p_xml_reader ); + if( !psz_eltname ) + goto error; if( !strcmp( psz_eltname, "genre" ) ) { // Read the attributes - while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS ) + while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { - char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader ); + char *psz_attrname = xml_ReaderName( p_xml_reader ); char *psz_attrvalue = - xml_ReaderValue( p_sys->p_xml_reader ); - if( !psz_attrname || !psz_attrvalue ) return -1; + xml_ReaderValue( p_xml_reader ); + if( !psz_attrname || !psz_attrvalue ) + { + free( psz_attrname ); + free( psz_attrvalue ); + free( psz_eltname ); + break; + } GET_VALUE( name ) else { msg_Warn( p_demux, - "unexpected attribure %s in element %s", - psz_attrname, - psz_eltname ); + "unexpected attribute %s in element %s", + psz_attrname, psz_eltname ); + free( psz_attrvalue ); } 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 - free( psz_eltname ); - psz_eltname = xml_ReaderName( p_sys->p_xml_reader ); - if( !psz_eltname ) return -1; + char *psz_eltname = xml_ReaderName( p_xml_reader ); + if( !psz_eltname ) + goto error; + if( !strcmp( psz_eltname, "genre" ) ) { - playlist_item_t *p_item; - char *psz_mrl = malloc( strlen( SHOUTCAST_BASE_URL ) - + strlen( "?genre=" ) + strlen( psz_name ) + 1 ); - sprintf( psz_mrl, SHOUTCAST_BASE_URL "?genre=%s", - psz_name ); - p_item = playlist_ItemNew( p_sys->p_playlist, psz_mrl, - psz_name ); - free( psz_mrl ); - playlist_NodeAddItem( p_sys->p_playlist, p_item, - p_sys->p_current->pp_parents[0]->i_view, - p_sys->p_current, PLAYLIST_APPEND, - PLAYLIST_END ); - - /* We need to declare the parents of the node as the - * * same of the parent's ones */ - playlist_CopyParents( p_sys->p_current, p_item ); - - vlc_input_item_CopyOptions( &p_sys->p_current->input, - &p_item->input ); - -#define FREE(a) if( a ) free( a ); a = NULL; - FREE( psz_name ); -#undef FREE + char* psz_mrl; + if( asprintf( &psz_mrl, SHOUTCAST_BASE_URL "?genre=%s", + psz_name ) != -1 ) + { + input_item_t *p_input; + p_input = input_item_New( p_demux, psz_mrl, psz_name ); + input_item_CopyOptions( p_input_node->p_item, p_input ); + free( psz_mrl ); + input_item_node_AppendItem( p_input_node, p_input ); + vlc_gc_decref( p_input ); + } + FREENULL( psz_name ); } free( psz_eltname ); - psz_eltname = strdup(""); - break; + } } } - return 0; + i_ret = 0; + +error: + free( psz_name ); + return i_ret; } -/* +/* radio stations: + * * * * + * + * TV stations: + * + * + * + * **/ -static int DemuxStation( demux_t *p_demux ) +static int DemuxStation( demux_t *p_demux, xml_reader_t *p_xml_reader, + input_item_node_t *p_input_node, bool b_adult ) { - demux_sys_t *p_sys = p_demux->p_sys; - char *psz_base = NULL; /* */ char *psz_name = NULL; /* genre name */ @@ -328,15 +276,18 @@ static int DemuxStation( demux_t *p_demux ) 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 ) + while( xml_ReaderRead( p_xml_reader ) == 1 ) { int i_type; - printf("AAA\n"); // Get the node type - i_type = xml_ReaderNodeType( p_sys->p_xml_reader ); + i_type = xml_ReaderNodeType( p_xml_reader ); switch( i_type ) { // Error @@ -346,40 +297,50 @@ static int DemuxStation( demux_t *p_demux ) case XML_READER_STARTELEM: // Read the element name - if( psz_eltname ) free( psz_eltname ); - psz_eltname = xml_ReaderName( p_sys->p_xml_reader ); + psz_eltname = xml_ReaderName( 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 ) + while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { - char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader ); + char *psz_attrname = xml_ReaderName( p_xml_reader ); char *psz_attrvalue = - xml_ReaderValue( p_sys->p_xml_reader ); - if( !psz_attrname || !psz_attrvalue ) return -1; + xml_ReaderValue( 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 ); + "unexpected attribute %s in element %s", + psz_attrname, psz_eltname ); + free( psz_attrvalue ); } free( psz_attrname ); - free( psz_attrvalue ); } } else if( !strcmp( psz_eltname, "station" ) ) { - while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS ) + while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { - char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader ); + char *psz_attrname = xml_ReaderName( p_xml_reader ); char *psz_attrvalue = - xml_ReaderValue( p_sys->p_xml_reader ); - if( !psz_attrname || !psz_attrvalue ) return -1; + xml_ReaderValue( 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 ) @@ -388,17 +349,19 @@ static int DemuxStation( demux_t *p_demux ) 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 attribure %s in element %s", - psz_attrname, - psz_eltname ); + "unexpected attribute %s in element %s", + psz_attrname, psz_eltname ); + free( psz_attrvalue ); } free( psz_attrname ); - free( psz_attrvalue ); } } + free( psz_eltname ); break; case XML_READER_TEXT: @@ -407,87 +370,62 @@ static int DemuxStation( demux_t *p_demux ) // End element case XML_READER_ENDELEM: // Read the element name - free( psz_eltname ); - psz_eltname = xml_ReaderName( p_sys->p_xml_reader ); + psz_eltname = xml_ReaderName( p_xml_reader ); if( !psz_eltname ) return -1; - if( !strcmp( psz_eltname, "station" ) && psz_base ) + if( !strcmp( psz_eltname, "station" ) && + ( psz_base || ( psz_rt && psz_load && + ( b_adult || strcmp( psz_rt, "NC17" ) ) ) ) ) { - playlist_item_t *p_item; - char *psz_mrl = malloc( strlen( SHOUTCAST_TUNEIN_BASE_URL ) - + strlen( psz_base ) + strlen( "?id=" ) - + strlen( psz_id ) + 1 ); - sprintf( psz_mrl, SHOUTCAST_TUNEIN_BASE_URL "%s?id=%s", - psz_base, psz_id ); - p_item = playlist_ItemNew( p_sys->p_playlist, psz_mrl, - psz_name ); - free( psz_mrl ); - - if( psz_mt ) - { - vlc_input_item_AddInfo( &p_item->input, - _( "Shoutcast" ), - _( "Mime type" ), - "%s", - psz_mt ); - } - else if( psz_br ) - { - vlc_input_item_AddInfo( &p_item->input, - _( "Shoutcast" ), - _( "Bitrate" ), - "%s", - psz_br ); - } - else if( psz_genre ) + char *psz_mrl = NULL; + if( psz_rt || psz_load ) { - vlc_input_item_AddInfo( &p_item->input, - _(VLC_META_INFO_CAT), - _(VLC_META_GENRE), - "%s", - psz_genre ); + /* tv */ + if( asprintf( &psz_mrl, SHOUTCAST_TV_TUNEIN_URL "%s", + psz_id ) == -1) + psz_mrl = NULL; } - else if( psz_ct ) + else { - vlc_input_item_AddInfo( &p_item->input, - _(VLC_META_INFO_CAT), - _(VLC_META_NOW_PLAYING), - "%s", - psz_ct ); - } - else if( psz_lc ) - { - vlc_input_item_AddInfo( &p_item->input, - _( "Shoutcast" ), - _( "Listeners" ), - "%s", - psz_lc ); + /* radio */ + if( asprintf( &psz_mrl, SHOUTCAST_TUNEIN_BASE_URL "%s?id=%s", + psz_base, psz_id ) == -1 ) + psz_mrl = NULL; } - playlist_NodeAddItem( p_sys->p_playlist, p_item, - p_sys->p_current->pp_parents[0]->i_view, - p_sys->p_current, PLAYLIST_APPEND, - PLAYLIST_END ); - - /* We need to declare the parents of the node as the - * * same of the parent's ones */ - playlist_CopyParents( p_sys->p_current, p_item ); - - vlc_input_item_CopyOptions( &p_sys->p_current->input, - &p_item->input ); - -#define FREE(a) if( a ) free( a ); a = NULL; - FREE( psz_name ); - FREE( psz_mt ) - FREE( psz_id ) - FREE( psz_br ) - FREE( psz_genre ) - FREE( psz_ct ) - FREE( psz_lc ) -#undef FREE + /* Create the item */ + input_item_t *p_input; + p_input = input_item_New( p_demux, 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 ); } free( psz_eltname ); - psz_eltname = strdup(""); - break; } } @@ -496,5 +434,6 @@ static int DemuxStation( demux_t *p_demux ) static int Control( demux_t *p_demux, int i_query, va_list args ) { + VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args); return VLC_EGENERIC; }