X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finterface%2Finterface.c;h=46192d83b024f6df25d1df530c5b2c9085f78ccb;hb=1ac60c8c90f7a724baa9d8d2eed21ed33be86d1b;hp=c8c97a71c6e3bf4652aee25ce49cb7cca26e1495;hpb=c047aa40ae206d1af4ec7f88d511e27d141db759;p=vlc diff --git a/src/interface/interface.c b/src/interface/interface.c index c8c97a71c6..46192d83b0 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,11 @@ 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; /* Allocate structure */ - p_intf = vlc_object_create( p_this, VLC_OBJECT_INTF ); + p_intf = vlc_object_create( p_libvlc, VLC_OBJECT_INTF ); if( !p_intf ) return VLC_ENOMEM; @@ -114,9 +104,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,13 +123,15 @@ 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( p_intf->pf_run == NULL ) - return VLC_SUCCESS; - + vlc_mutex_lock( &lock ); + if( !vlc_object_alive( p_libvlc ) ) + { + vlc_mutex_unlock( &lock ); + goto error; /* Too late! */ + } #if defined( __APPLE__ ) || defined( WIN32 ) /* Hack to get Mac OS X Cocoa runtime running * (it needs access to the main thread) */ @@ -150,49 +141,78 @@ 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; } + 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 ); } 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 ); - if( p_intf->pf_run ) - vlc_thread_join( p_intf ); + intf_thread_t *p_first; + + 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 ); - module_unneed( p_intf, p_intf->p_module ); + p_intf = p_next; + } } /* Following functions are local */ @@ -241,7 +261,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",