X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fservices_discovery%2Fshout.c;h=fbf9983f03db05c6f4ac13a9bf030ee7001a4870;hb=27d483e9ef7a451397d7857251c8d67097661f1d;hp=0973ffaae4f63ea095115a83bfaba2bd29cd3ae7;hpb=85b29bdc288a1573d43bd524908be5748a9b3640;p=vlc diff --git a/modules/services_discovery/shout.c b/modules/services_discovery/shout.c index 0973ffaae4..fbf9983f03 100644 --- a/modules/services_discovery/shout.c +++ b/modules/services_discovery/shout.c @@ -1,10 +1,12 @@ /***************************************************************************** * shout.c: Shoutcast services discovery module ***************************************************************************** - * Copyright (C) 2005 VideoLAN (Centrale Réseaux) and its contributors + * Copyright (C) 2005-2007 the VideoLAN team * $Id$ * - * Authors: Sigmund Augdal + * Authors: Sigmund Augdal Helberg + * Antoine Cellerier + * Pierre d'Herbemont * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,189 +20,230 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Includes *****************************************************************************/ -#include /* malloc(), free() */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include -#include +#include +#include -#include +/***************************************************************************** + * Module descriptor + *****************************************************************************/ -#include "network.h" +enum type_e { ShoutRadio = 0, ShoutTV = 1, Freebox = 2, FrenchTV = 3 }; -#include /* ENOMEM */ +static int Open( vlc_object_t *, enum type_e ); +static void Close( vlc_object_t * ); -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_SYS_TIME_H -# include -#endif +struct shout_item_t +{ + const char *psz_url; + const char *psz_name; + const char *ppsz_options[2]; + const struct shout_item_t * p_children; +}; -/************************************************************************ - * Macros and definitions - ************************************************************************/ +#define endItem( ) { NULL, NULL, { NULL }, NULL } +#define item( title, url ) { url, title, { NULL }, NULL } +#define itemWithOption( title, url, option ) { url, title, { option, NULL }, NULL } +#define itemWithChildren( title, children ) { "vlc:skip", title, { NULL }, children } -#define MAX_LINE_LENGTH 256 +/* WARN: We support only two levels */ +static const struct shout_item_t p_frenchtv_canalplus[] = { + itemWithOption( N_("Les Guignols"), "http://www.canalplus.fr/index.php?pid=1784", "http-forward-cookies" ), + endItem() +}; + +static const struct shout_item_t p_frenchtv[] = { + itemWithChildren( N_("Canal +"), p_frenchtv_canalplus ), + endItem() +}; -/***************************************************************************** - * Module descriptor - *****************************************************************************/ +static const struct shout_item_t p_items[] = { + item( N_("Shoutcast Radio"), "http/shout-winamp://www.shoutcast.com/sbin/newxml.phtml" ), + item( N_("Shoutcast TV"), "http/shout-winamp://www.shoutcast.com/sbin/newtvlister.phtml?alltv=1" ), + item( N_("Freebox TV"), "http://mafreebox.freebox.fr/freeboxtv/playlist.m3u" ), + itemWithChildren(N_("French TV"), p_frenchtv ), + endItem() +}; + +#undef endItem +#undef item +#undef itemWithOptions +#undef itemWithChildren -/* Callbacks */ - static int Open ( vlc_object_t * ); - static void Close( vlc_object_t * ); +struct shout_category_t { + services_discovery_t * p_sd; + const char * psz_category; +}; -#define LIMIT_TEXT N_("Maximum number of shoutcast servers to be listed") -#define LIMIT_LONGTEXT LIMIT_TEXT +/* Main functions */ +#define OPEN( type ) \ +static int Open ## type ( vlc_object_t *p_this ) \ +{ \ + msg_Dbg( p_this, "Starting " #type ); \ + return Open( p_this, type ); \ +} + +OPEN( ShoutRadio ) +OPEN( ShoutTV ) +OPEN( Freebox ) +OPEN( FrenchTV ) vlc_module_begin(); - set_shortname( "Shoutcast"); - set_description( _("Shoutcast radio listings") ); set_category( CAT_PLAYLIST ); set_subcategory( SUBCAT_PLAYLIST_SD ); - add_integer( "shoutcast-limit", 1000, NULL, LIMIT_TEXT, - LIMIT_LONGTEXT, VLC_TRUE ); - - set_capability( "services_discovery", 0 ); - set_callbacks( Open, Close ); + add_obsolete_integer( "shoutcast-limit" ); + + set_shortname( "Shoutcast"); + set_description( _("Shoutcast radio listings") ); + set_capability( "services_discovery", 0 ); + set_callbacks( OpenShoutRadio, Close ); + add_shortcut( "shoutcast" ); + + add_submodule(); + set_shortname( "ShoutcastTV" ); + set_description( _("Shoutcast TV listings") ); + set_capability( "services_discovery", 0 ); + set_callbacks( OpenShoutTV, Close ); + add_shortcut( "shoutcasttv" ); + + add_submodule(); + set_shortname( "frenchtv"); + set_description( _("French TV") ); + set_capability( "services_discovery", 0 ); + set_callbacks( OpenFrenchTV, Close ); + add_shortcut( "frenchtv" ); + + add_submodule(); + set_shortname( "Freebox"); + set_description( _("Freebox TV listing (French ISP free.fr services)") ); + set_capability( "services_discovery", 0 ); + set_callbacks( OpenFreebox, Close ); + add_shortcut( "freebox" ); vlc_module_end(); -/***************************************************************************** - * Local structures - *****************************************************************************/ - -struct services_discovery_sys_t -{ - /* playlist node */ - playlist_item_t *p_node; - input_thread_t *p_input; - -}; - /***************************************************************************** * Local prototypes *****************************************************************************/ -/* Main functions */ - static void Run ( services_discovery_t *p_intf ); +static void Run( services_discovery_t *p_sd ); + /***************************************************************************** * Open: initialize and create stuff *****************************************************************************/ -static int Open( vlc_object_t *p_this ) +static int Open( vlc_object_t *p_this, enum type_e i_type ) { services_discovery_t *p_sd = ( services_discovery_t* )p_this; - services_discovery_sys_t *p_sys = malloc( - sizeof( services_discovery_sys_t ) ); - - vlc_value_t val; - playlist_t *p_playlist; - playlist_view_t *p_view; - playlist_item_t *p_item; - - int i_limit; - char *psz_shoutcast_url; - char *psz_shoutcast_title; - + services_discovery_SetLocalizedName( p_sd, _(p_items[i_type].psz_name) ); p_sd->pf_run = Run; - p_sd->p_sys = p_sys; + p_sd->p_sys = (void *)i_type; + return VLC_SUCCESS; +} - /* Create our playlist node */ - p_playlist = (playlist_t *)vlc_object_find( p_sd, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( !p_playlist ) - { - msg_Warn( p_sd, "unable to find playlist, cancelling"); - return VLC_EGENERIC; - } +/***************************************************************************** + * ItemAdded: + *****************************************************************************/ +static void ItemAdded( const vlc_event_t * p_event, void * user_data ) +{ + struct shout_category_t * params = user_data; + services_discovery_AddItem( params->p_sd, + p_event->u.input_item_subitem_added.p_new_child, + params->psz_category ); +} - i_limit = config_GetInt( p_this->p_libvlc, "shoutcast-limit" ); - #define SHOUTCAST_BASE_URL "http/shout-b4s://shoutcast.com/sbin/xmllister.phtml?service=vlc&no_compress=1&limit=" - psz_shoutcast_url = (char *)malloc( strlen( SHOUTCAST_BASE_URL ) + 20 ); - psz_shoutcast_title = (char *)malloc( 6 + 20 ); - - sprintf( psz_shoutcast_url, SHOUTCAST_BASE_URL "%d", i_limit ); - sprintf( psz_shoutcast_title, "Top %d", i_limit ); - - p_view = playlist_ViewFind( p_playlist, VIEW_CATEGORY ); - p_sys->p_node = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, - _("Shoutcast"), p_view->p_root ); - p_item = playlist_ItemNew( p_playlist, psz_shoutcast_url, - psz_shoutcast_title ); - free( psz_shoutcast_url ); - free( psz_shoutcast_title ); - playlist_NodeAddItem( p_playlist, p_item, - p_sys->p_node->pp_parents[0]->i_view, - p_sys->p_node, 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_node, p_item ); - +/***************************************************************************** + * CreateInputItemFromShoutItem: + *****************************************************************************/ +static input_item_t * CreateInputItemFromShoutItem( services_discovery_t *p_sd, + const struct shout_item_t * p_item ) +{ + int i; + /* Create the item */ + input_item_t *p_input = input_ItemNewExt( p_sd, + p_item->psz_url, _(p_item->psz_name), + 0, NULL, -1 ); + + /* Copy options */ + for( i = 0; p_item->ppsz_options[i] != NULL; i++ ) + input_ItemAddOption( p_input, p_item->ppsz_options[i] ); + input_ItemAddOption( p_input, "no-playlist-autostart" ); + + return p_input; +} - p_sys->p_input = input_CreateThread( p_playlist, &p_item->input ); +/***************************************************************************** + * AddSubitemsOfShoutItemURL: + *****************************************************************************/ +static void AddSubitemsOfShoutItemURL( services_discovery_t *p_sd, + const struct shout_item_t * p_item, + const char * psz_category ) +{ + struct shout_category_t category = { p_sd, psz_category }; - p_sys->p_node->i_flags |= PLAYLIST_RO_FLAG; - val.b_bool = VLC_TRUE; - var_Set( p_playlist, "intf-change", val ); + /* Create the item */ + input_item_t *p_input = CreateInputItemFromShoutItem( p_sd, p_item ); - vlc_object_release( p_playlist ); + /* Read every subitems, and add them in ItemAdded */ + vlc_event_attach( &p_input->event_manager, vlc_InputItemSubItemAdded, + ItemAdded, &category ); + input_Read( p_sd, p_input, true ); + vlc_event_detach( &p_input->event_manager, vlc_InputItemSubItemAdded, + ItemAdded, &category ); - return VLC_SUCCESS; + vlc_gc_decref( p_input ); } /***************************************************************************** - * Close: + * Run: *****************************************************************************/ -static void Close( vlc_object_t *p_this ) +static void Run( services_discovery_t *p_sd ) { - services_discovery_t *p_sd = ( services_discovery_t* )p_this; - services_discovery_sys_t *p_sys = p_sd->p_sys; - playlist_t *p_playlist = (playlist_t *) vlc_object_find( p_sd, - VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); - if( p_sd->p_sys->p_input ) + enum type_e i_type = (enum type_e)p_sd->p_sys; + int i, j; + + if( !p_items[i_type].p_children ) { - input_StopThread( p_sd->p_sys->p_input ); - input_DestroyThread( p_sd->p_sys->p_input ); - vlc_object_detach( p_sd->p_sys->p_input ); - vlc_object_destroy( p_sd->p_sys->p_input ); - p_sd->p_sys->p_input = NULL; + AddSubitemsOfShoutItemURL( p_sd, &p_items[i_type], NULL ); + return; } - if( p_playlist ) + for( i = 0; p_items[i_type].p_children[i].psz_name; i++ ) { - playlist_NodeDelete( p_playlist, p_sys->p_node, VLC_TRUE, VLC_TRUE ); - vlc_object_release( p_playlist ); + const struct shout_item_t * p_subitem = &p_items[i_type].p_children[i]; + if( !p_subitem->p_children ) + { + AddSubitemsOfShoutItemURL( p_sd, p_subitem, p_subitem->psz_name ); + continue; + } + for( j = 0; p_subitem->p_children[j].psz_name; j++ ) + { + input_item_t *p_input = CreateInputItemFromShoutItem( p_sd, &p_subitem->p_children[j] ); + services_discovery_AddItem( p_sd, + p_input, + p_subitem->psz_name ); + vlc_gc_decref( p_input ); + } } - free( p_sys ); } /***************************************************************************** - * Run: main thread + * Close: *****************************************************************************/ -static void Run( services_discovery_t *p_sd ) +static void Close( vlc_object_t *p_this ) { - while( !p_sd->b_die ) - { - if( p_sd->p_sys->p_input && - ( p_sd->p_sys->p_input->b_eof || p_sd->p_sys->p_input->b_error ) ) - { - input_StopThread( p_sd->p_sys->p_input ); - input_DestroyThread( p_sd->p_sys->p_input ); - vlc_object_detach( p_sd->p_sys->p_input ); - vlc_object_destroy( p_sd->p_sys->p_input ); - p_sd->p_sys->p_input = NULL; - } - msleep( 100000 ); - } + VLC_UNUSED(p_this); }