X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fservices_discovery%2Fbonjour.c;h=0110e016b0f81d5cfbed5933d4fab0e799d0d385;hb=12efa4ae18f835561237a886bedcab642a668c97;hp=54750087bda98f1f456a4e957ab47cc705ecbc6e;hpb=a0d5817970dc86f78140de2759385597029bea2d;p=vlc diff --git a/modules/services_discovery/bonjour.c b/modules/services_discovery/bonjour.c index 54750087bd..0110e016b0 100644 --- a/modules/services_discovery/bonjour.c +++ b/modules/services_discovery/bonjour.c @@ -1,7 +1,7 @@ /***************************************************************************** * bonjour.c: Bonjour services discovery module ***************************************************************************** - * Copyright (C) 2005 the VideoLAN team + * Copyright (C) 2005-2009 the VideoLAN team * $Id$ * * Authors: Jon Lech Johansen @@ -18,19 +18,25 @@ * * 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() */ -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include #include -#include +#include +#include +#include #include #include @@ -42,14 +48,18 @@ static int Open ( vlc_object_t * ); static void Close( vlc_object_t * ); -vlc_module_begin(); - set_shortname( "Bonjour" ); - set_description( _("Bonjour services") ); - set_category( CAT_PLAYLIST ); - set_subcategory( SUBCAT_PLAYLIST_SD ); - set_capability( "services_discovery", 0 ); - set_callbacks( Open, Close ); -vlc_module_end(); +VLC_SD_PROBE_HELPER("bonjour", "Bonjour services", SD_CAT_LAN) + +vlc_module_begin () + set_shortname( "Bonjour" ) + set_description( N_("Bonjour services") ) + set_category( CAT_PLAYLIST ) + set_subcategory( SUBCAT_PLAYLIST_SD ) + set_capability( "services_discovery", 0 ) + set_callbacks( Open, Close ) + + VLC_SD_PROBE_SUBMODULE +vlc_module_end () /***************************************************************************** * Local structures @@ -57,22 +67,16 @@ vlc_module_end(); struct services_discovery_sys_t { - /* playlist node */ - playlist_item_t *p_node; - playlist_t *p_playlist; - - AvahiSimplePoll *simple_poll; + AvahiThreadedPoll *poll; AvahiClient *client; AvahiServiceBrowser *sb; + vlc_dictionary_t services_name_to_input_item; }; /***************************************************************************** * Local prototypes *****************************************************************************/ -/* Main functions */ - static void Run ( services_discovery_t *p_intf ); - /***************************************************************************** * client_callback *****************************************************************************/ @@ -82,10 +86,11 @@ static void client_callback( AvahiClient *c, AvahiClientState state, services_discovery_t *p_sd = ( services_discovery_t* )userdata; services_discovery_sys_t *p_sys = p_sd->p_sys; - if( state == AVAHI_CLIENT_DISCONNECTED ) + if( state == AVAHI_CLIENT_FAILURE && + (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) ) { msg_Err( p_sd, "avahi client disconnected" ); - avahi_simple_poll_quit( p_sys->simple_poll ); + avahi_threaded_poll_quit( p_sys->poll ); } } @@ -104,12 +109,16 @@ static void resolve_callback( const AvahiAddress *address, uint16_t port, AvahiStringList *txt, + AvahiLookupResultFlags flags, void* userdata ) { services_discovery_t *p_sd = ( services_discovery_t* )userdata; services_discovery_sys_t *p_sys = p_sd->p_sys; + + VLC_UNUSED(interface); VLC_UNUSED(host_name); + VLC_UNUSED(flags); - if( event == AVAHI_RESOLVER_TIMEOUT ) + if( event == AVAHI_RESOLVER_FAILURE ) { msg_Err( p_sd, "failed to resolve service '%s' of type '%s' in domain '%s'", @@ -119,38 +128,64 @@ static void resolve_callback( { char a[128]; char *psz_uri = NULL; - AvahiStringList *asl; - playlist_item_t *p_item = NULL; + char *psz_addr = NULL; + AvahiStringList *asl = NULL; + input_item_t *p_input = NULL; msg_Dbg( p_sd, "service '%s' of type '%s' in domain '%s'", name, type, domain ); avahi_address_snprint(a, (sizeof(a)/sizeof(a[0]))-1, address); + if( protocol == AVAHI_PROTO_INET6 ) + if( asprintf( &psz_addr, "[%s]", a ) == -1 ) + return; - asl = avahi_string_list_find( txt, "path" ); + if( txt != NULL ) + asl = avahi_string_list_find( txt, "path" ); if( asl != NULL ) { size_t size; char *key = NULL; char *value = NULL; - if( avahi_string_list_get_pair( asl, &key, &value, &size ) == 0 ) - asprintf( &psz_uri, "http://%s:%d%s", a, port, value ); + if( avahi_string_list_get_pair( asl, &key, &value, &size ) == 0 && + value != NULL ) + { + if( asprintf( &psz_uri, "http://%s:%d%s", + psz_addr != NULL ? psz_addr : a, port, value ) == -1 ) + { + free( psz_addr ); + return; + } + } + if( key != NULL ) + avahi_free( (void *)key ); + if( value != NULL ) + avahi_free( (void *)value ); } else { - asprintf( &psz_uri, "http://%s:%d", a, port ); + if( asprintf( &psz_uri, "http://%s:%d", + psz_addr != NULL ? psz_addr : a, port ) == -1 ) + { + free( psz_addr ); + return; + } } + free( psz_addr ); + if( psz_uri != NULL ) - p_item = playlist_ItemNew( p_sd, psz_uri, name ); - if( p_item != NULL ) { - p_item->i_flags &= ~PLAYLIST_SKIP_FLAG; - - playlist_NodeAddItem( p_sys->p_playlist, p_item, - VIEW_CATEGORY, p_sys->p_node, - PLAYLIST_APPEND, PLAYLIST_END ); + p_input = input_item_New( p_sd, psz_uri, name ); + free( psz_uri ); } + if( p_input != NULL ) + { + vlc_dictionary_insert( &p_sys->services_name_to_input_item, + name, p_input ); + services_discovery_AddItem( p_sd, p_input, NULL /* no category */ ); + vlc_gc_decref( p_input ); + } } avahi_service_resolver_free( r ); @@ -167,33 +202,39 @@ static void browse_callback( const char *name, const char *type, const char *domain, + AvahiLookupResultFlags flags, void* userdata ) { + VLC_UNUSED(b); + VLC_UNUSED(flags); services_discovery_t *p_sd = ( services_discovery_t* )userdata; services_discovery_sys_t *p_sys = p_sd->p_sys; - if( event == AVAHI_BROWSER_NEW ) { if( avahi_service_resolver_new( p_sys->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, + 0, resolve_callback, userdata ) == NULL ) { msg_Err( p_sd, "failed to resolve service '%s': %s", name, avahi_strerror( avahi_client_errno( p_sys->client ) ) ); } } - else + else if( name ) { - playlist_item_t *p_item; - - p_item = playlist_ChildSearchName( p_sys->p_node, name ); - if( p_item == NULL ) - { + /** \todo Store the input id and search it, rather than searching the items */ + input_item_t *p_item; + p_item = vlc_dictionary_value_for_key( + &p_sys->services_name_to_input_item, + name ); + if( !p_item ) msg_Err( p_sd, "failed to find service '%s' in playlist", name ); - } else { - playlist_Delete( p_sys->p_playlist, p_item->input.i_id ); + services_discovery_RemoveItem( p_sd, p_item ); + vlc_dictionary_remove_value_for_key( + &p_sys->services_name_to_input_item, + name, NULL, NULL ); } } } @@ -205,29 +246,23 @@ static int Open( vlc_object_t *p_this ) { services_discovery_t *p_sd = ( services_discovery_t* )p_this; services_discovery_sys_t *p_sys; - playlist_view_t *p_view; - vlc_value_t val; int err; - p_sd->p_sys = p_sys = (services_discovery_sys_t *)malloc( - sizeof( services_discovery_sys_t ) ); - if( p_sd->p_sys == NULL ) - { - msg_Err( p_sd, "out of memory" ); - return VLC_EGENERIC; - } + p_sd->p_sys = p_sys = calloc( 1, sizeof( services_discovery_sys_t ) ); + if( !p_sys ) + return VLC_ENOMEM; - memset( p_sys, 0, sizeof(*p_sys) ); + vlc_dictionary_init( &p_sys->services_name_to_input_item, 1 ); - p_sys->simple_poll = avahi_simple_poll_new(); - if( p_sys->simple_poll == NULL ) + p_sys->poll = avahi_threaded_poll_new(); + if( p_sys->poll == NULL ) { - msg_Err( p_sd, "failed to create avahi simple poll" ); + msg_Err( p_sd, "failed to create Avahi threaded poll" ); goto error; } - p_sys->client = avahi_client_new( avahi_simple_poll_get(p_sys->simple_poll), - client_callback, p_sd, &err ); + p_sys->client = avahi_client_new( avahi_threaded_poll_get(p_sys->poll), + 0, client_callback, p_sd, &err ); if( p_sys->client == NULL ) { msg_Err( p_sd, "failed to create avahi client: %s", @@ -238,46 +273,25 @@ static int Open( vlc_object_t *p_this ) p_sys->sb = avahi_service_browser_new( p_sys->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_vlc-http._tcp", NULL, - browse_callback, p_sd ); + 0, browse_callback, p_sd ); if( p_sys->sb == NULL ) { msg_Err( p_sd, "failed to create avahi service browser" ); goto error; } - /* Create our playlist node */ - p_sys->p_playlist = (playlist_t *)vlc_object_find( p_sd, - VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( !p_sys->p_playlist ) - { - msg_Warn( p_sd, "unable to find playlist, cancelling"); - goto error; - } - - p_view = playlist_ViewFind( p_sys->p_playlist, VIEW_CATEGORY ); - p_sys->p_node = playlist_NodeCreate( p_sys->p_playlist, VIEW_CATEGORY, - _("Bonjour"), p_view->p_root ); - - p_sys->p_node->i_flags |= PLAYLIST_RO_FLAG; - val.b_bool = VLC_TRUE; - var_Set( p_sys->p_playlist, "intf-change", val ); - - p_sd->pf_run = Run; - return VLC_SUCCESS; error: - if( p_sys->p_playlist != NULL ) - vlc_object_release( p_sys->p_playlist ); if( p_sys->sb != NULL ) avahi_service_browser_free( p_sys->sb ); if( p_sys->client != NULL ) avahi_client_free( p_sys->client ); - if( p_sys->simple_poll != NULL ) - avahi_simple_poll_free( p_sys->simple_poll ); + if( p_sys->poll != NULL ) + avahi_threaded_poll_free( p_sys->poll ); - free( (void *)p_sys ); + vlc_dictionary_clear( &p_sys->services_name_to_input_item, NULL, NULL ); + free( p_sys ); return VLC_EGENERIC; } @@ -292,27 +306,8 @@ static void Close( vlc_object_t *p_this ) avahi_service_browser_free( p_sys->sb ); avahi_client_free( p_sys->client ); - avahi_simple_poll_free( p_sys->simple_poll ); - - playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node, VLC_TRUE, VLC_TRUE ); - vlc_object_release( p_sys->p_playlist ); + avahi_threaded_poll_free( p_sys->poll ); + vlc_dictionary_clear( &p_sys->services_name_to_input_item, NULL, NULL ); free( p_sys ); } - -/***************************************************************************** - * Run: main thread - *****************************************************************************/ -static void Run( services_discovery_t *p_sd ) -{ - services_discovery_sys_t *p_sys = p_sd->p_sys; - - while( !p_sd->b_die ) - { - if( avahi_simple_poll_iterate( p_sys->simple_poll, 100 ) != 0 ) - { - msg_Err( p_sd, "poll iterate failed" ); - break; - } - } -}