X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finterface%2Finterface.c;h=ba9240b0c875c423f9392d52e033eaff483a77a0;hb=a440126cfb7322950d14f7029dd424c4f4bd41ad;hp=766c521690be68dc1b81de0a110172cda28d7366;hpb=156dd2adfd686140ee7cafc272a5cc2d5c644150;p=vlc diff --git a/src/interface/interface.c b/src/interface/interface.c index 766c521690..ba9240b0c8 100644 --- a/src/interface/interface.c +++ b/src/interface/interface.c @@ -37,6 +37,7 @@ # include "config.h" #endif +#include #include #include @@ -58,19 +59,7 @@ static void * MonitorLibVLCDeath( vlc_object_t *p_this ); static int AddIntfCallback( vlc_object_t *, char const *, vlc_value_t , vlc_value_t , void * ); -/** - * Destroy the interface after the main loop endeed. - * - * @param p_obj: the interface thread - */ -static void intf_Destroy( vlc_object_t *obj ) -{ - intf_thread_t *p_intf = (intf_thread_t *)obj; - - free( p_intf->psz_intf ); - config_ChainDestroy( p_intf->p_cfg ); -} - +static vlc_mutex_t lock = VLC_STATIC_MUTEX; #undef intf_Create /** @@ -82,10 +71,13 @@ static void intf_Destroy( vlc_object_t *obj ) */ int intf_Create( vlc_object_t *p_this, const char *psz_module ) { + libvlc_int_t *p_libvlc = p_this->p_libvlc; intf_thread_t * p_intf; + static const char psz_type[] = "interface"; /* Allocate structure */ - p_intf = vlc_object_create( p_this, VLC_OBJECT_INTF ); + p_intf = vlc_custom_create( p_libvlc, sizeof( *p_intf ), + VLC_OBJECT_GENERIC, psz_type ); if( !p_intf ) return VLC_ENOMEM; @@ -114,9 +106,8 @@ int intf_Create( vlc_object_t *p_this, const char *psz_module ) var_AddCallback( p_intf, "intf-add", AddIntfCallback, NULL ); - /* Attach interface to its parent object */ - vlc_object_attach( p_intf, p_this ); - vlc_object_set_destructor( p_intf, intf_Destroy ); + /* Attach interface to LibVLC */ + vlc_object_attach( p_intf, p_libvlc ); #if defined( __APPLE__ ) || defined( WIN32 ) p_intf->b_should_run_on_first_thread = false; #endif @@ -134,8 +125,7 @@ int intf_Create( vlc_object_t *p_this, const char *psz_module ) if( p_intf->p_module == NULL ) { msg_Err( p_intf, "no suitable interface module" ); - vlc_object_release( p_intf ); - return VLC_EGENERIC; + goto error; } #if defined( __APPLE__ ) || defined( WIN32 ) @@ -147,51 +137,79 @@ int intf_Create( vlc_object_t *p_this, const char *psz_module ) VLC_THREAD_PRIORITY_LOW ) ) { msg_Err( p_intf, "cannot spawn libvlc death monitoring thread" ); - vlc_object_release( p_intf ); - return VLC_ENOMEM; + vlc_mutex_unlock( &lock ); + goto error; } - RunInterface( VLC_OBJECT(p_intf) ); + assert( p_intf->pf_run ); + p_intf->pf_run( p_intf ); - /* Make sure our MonitorLibVLCDeath thread exit */ - vlc_object_kill( p_intf ); /* It is monitoring libvlc, not the p_intf */ vlc_object_kill( p_intf->p_libvlc ); - vlc_thread_join( p_intf ); - - vlc_object_detach( p_intf ); - vlc_object_release( p_intf ); - return VLC_SUCCESS; } + else #endif /* Run the interface in a separate thread */ - if( vlc_thread_create( p_intf, "interface", RunInterface, + if( p_intf->pf_run + && vlc_thread_create( p_intf, "interface", RunInterface, VLC_THREAD_PRIORITY_LOW ) ) { msg_Err( p_intf, "cannot spawn interface thread" ); - vlc_object_release( p_intf ); - return VLC_EGENERIC; + vlc_mutex_unlock( &lock ); + goto error; } + p_intf->p_next = libvlc_priv( p_libvlc )->p_intf; + libvlc_priv( p_libvlc )->p_intf = p_intf; + vlc_mutex_unlock( &lock ); + return VLC_SUCCESS; + +error: + if( p_intf->p_module ) + module_unneed( p_intf, p_intf->p_module ); + config_ChainDestroy( p_intf->p_cfg ); + free( p_intf->psz_intf ); + vlc_object_release( p_intf ); + return VLC_EGENERIC; } /** - * Stops the interface thread - * - * This function asks the interface thread to stop - * @param p_intf the interface thread + * Stops and destroys all interfaces + * @param p_libvlc the LibVLC instance */ -void intf_StopThread( intf_thread_t *p_intf ) +void intf_DestroyAll( libvlc_int_t *p_libvlc ) { - /* Tell the interface to die */ - vlc_object_kill( p_intf ); - vlc_thread_join( p_intf ); + intf_thread_t *p_first; - module_unneed( p_intf, p_intf->p_module ); -} + assert( !vlc_object_alive( p_libvlc ) ); + + vlc_mutex_lock( &lock ); + p_first = libvlc_priv( p_libvlc )->p_intf; +#ifndef NDEBUG + libvlc_priv( p_libvlc )->p_intf = NULL; +#endif + vlc_mutex_unlock( &lock ); + + /* Tell the interfaces to die */ + for( intf_thread_t *p_intf = p_first; p_intf; p_intf = p_intf->p_next ) + vlc_object_kill( p_intf ); + + /* Cleanup the interfaces */ + for( intf_thread_t *p_intf = p_first; p_intf != NULL; ) + { + intf_thread_t *p_next = p_intf->p_next; + if( p_intf->pf_run ) + vlc_thread_join( p_intf ); + module_unneed( p_intf, p_intf->p_module ); + free( p_intf->psz_intf ); + config_ChainDestroy( p_intf->p_cfg ); + vlc_object_release( p_intf ); + p_intf = p_next; + } +} /* Following functions are local */ @@ -204,10 +222,7 @@ static void* RunInterface( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; - /* Give control to the interface */ - if( p_intf->pf_run ) - p_intf->pf_run( p_intf ); - + p_intf->pf_run( p_intf ); return NULL; } @@ -242,7 +257,7 @@ static int AddIntfCallback( vlc_object_t *p_this, char const *psz_cmd, if( asprintf( &psz_intf, "%s,none", newval.psz_string ) == -1 ) return VLC_ENOMEM; - int ret = intf_Create( p_this->p_libvlc, psz_intf ); + int ret = intf_Create( VLC_OBJECT(p_this->p_libvlc), psz_intf ); free( psz_intf ); if( ret ) msg_Err( p_this, "interface \"%s\" initialization failed",