Commit 6197b056 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

libvlc_Quit: support using a callback

This is more flexible than the current libvlc_InternalWait() which
requires a thread that does nothing for the whole lifetime of VLC.
parent a440126c
...@@ -428,6 +428,7 @@ SOURCES_libvlc_common = \ ...@@ -428,6 +428,7 @@ SOURCES_libvlc_common = \
misc/cpu.c \ misc/cpu.c \
misc/action.c \ misc/action.c \
misc/epg.c \ misc/epg.c \
misc/exit.c \
config/configuration.h \ config/configuration.h \
config/core.c \ config/core.c \
config/chain.c \ config/chain.c \
......
...@@ -50,6 +50,7 @@ VLC_EXPORT (void, libvlc_InternalDestroy, ( libvlc_int_t * ) ); ...@@ -50,6 +50,7 @@ VLC_EXPORT (void, libvlc_InternalDestroy, ( libvlc_int_t * ) );
VLC_EXPORT (int, libvlc_InternalAddIntf, ( libvlc_int_t *, const char * ) ); VLC_EXPORT (int, libvlc_InternalAddIntf, ( libvlc_int_t *, const char * ) );
VLC_EXPORT (void, libvlc_InternalWait, ( libvlc_int_t * ) ); VLC_EXPORT (void, libvlc_InternalWait, ( libvlc_int_t * ) );
VLC_EXPORT (void, libvlc_SetExitHandler, ( libvlc_int_t *, void (*) (void *), void * ) );
typedef void (*libvlc_vlm_release_func_t)( libvlc_instance_t * ) ; typedef void (*libvlc_vlm_release_func_t)( libvlc_instance_t * ) ;
......
...@@ -182,8 +182,6 @@ void intf_DestroyAll( libvlc_int_t *p_libvlc ) ...@@ -182,8 +182,6 @@ void intf_DestroyAll( libvlc_int_t *p_libvlc )
{ {
intf_thread_t *p_first; intf_thread_t *p_first;
assert( !vlc_object_alive( p_libvlc ) );
vlc_mutex_lock( &lock ); vlc_mutex_lock( &lock );
p_first = libvlc_priv( p_libvlc )->p_intf; p_first = libvlc_priv( p_libvlc )->p_intf;
#ifndef NDEBUG #ifndef NDEBUG
......
...@@ -273,6 +273,7 @@ libvlc_int_t * libvlc_InternalCreate( void ) ...@@ -273,6 +273,7 @@ libvlc_int_t * libvlc_InternalCreate( void )
/* Initialize mutexes */ /* Initialize mutexes */
vlc_mutex_init( &priv->timer_lock ); vlc_mutex_init( &priv->timer_lock );
vlc_ExitInit( &priv->exit );
return p_libvlc; return p_libvlc;
error: error:
...@@ -1073,6 +1074,7 @@ void libvlc_InternalDestroy( libvlc_int_t *p_libvlc ) ...@@ -1073,6 +1074,7 @@ void libvlc_InternalDestroy( libvlc_int_t *p_libvlc )
msg_Destroy (priv->msg_bank); msg_Destroy (priv->msg_bank);
/* Destroy mutexes */ /* Destroy mutexes */
vlc_ExitDestroy( &priv->exit );
vlc_mutex_destroy( &priv->timer_lock ); vlc_mutex_destroy( &priv->timer_lock );
#ifndef NDEBUG /* Hack to dump leaked objects tree */ #ifndef NDEBUG /* Hack to dump leaked objects tree */
...@@ -1121,40 +1123,6 @@ int libvlc_InternalAddIntf( libvlc_int_t *p_libvlc, char const *psz_module ) ...@@ -1121,40 +1123,6 @@ int libvlc_InternalAddIntf( libvlc_int_t *p_libvlc, char const *psz_module )
return ret; return ret;
} }
#ifndef WIN32
static vlc_mutex_t exit_lock = VLC_STATIC_MUTEX;
static vlc_cond_t exiting = VLC_STATIC_COND;
#else
extern vlc_mutex_t super_mutex;
extern vlc_cond_t super_variable;
# define exit_lock super_mutex
# define exiting super_variable
#endif
/**
* Waits until the LibVLC instance gets an exit signal. Normally, this happens
* when the user "exits" an interface plugin.
*/
void libvlc_InternalWait( libvlc_int_t *p_libvlc )
{
vlc_mutex_lock( &exit_lock );
while( vlc_object_alive( p_libvlc ) )
vlc_cond_wait( &exiting, &exit_lock );
vlc_mutex_unlock( &exit_lock );
}
/**
* Posts an exit signal to LibVLC instance. This will normally initiate the
* cleanup and destroy process. It should only be called on behalf of the user.
*/
void libvlc_Quit( libvlc_int_t *p_libvlc )
{
vlc_mutex_lock( &exit_lock );
vlc_object_kill( p_libvlc );
vlc_cond_broadcast( &exiting );
vlc_mutex_unlock( &exit_lock );
}
#if defined( ENABLE_NLS ) && (defined (__APPLE__) || defined (WIN32)) && \ #if defined( ENABLE_NLS ) && (defined (__APPLE__) || defined (WIN32)) && \
( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) ) ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
/***************************************************************************** /*****************************************************************************
......
...@@ -93,6 +93,20 @@ const char* msg_StackMsg ( void ); ...@@ -93,6 +93,20 @@ const char* msg_StackMsg ( void );
*/ */
char *vlc_fix_readdir (const char *); char *vlc_fix_readdir (const char *);
/*
* LibVLC exit event handling
*/
typedef struct vlc_exit
{
vlc_mutex_t lock;
void (*handler) (void *);
void *opaque;
bool killed;
} vlc_exit_t;
void vlc_ExitInit( vlc_exit_t * );
void vlc_ExitDestroy( vlc_exit_t * );
/* /*
* LibVLC objects stuff * LibVLC objects stuff
*/ */
...@@ -210,6 +224,9 @@ typedef struct libvlc_priv_t ...@@ -210,6 +224,9 @@ typedef struct libvlc_priv_t
/* Objects tree */ /* Objects tree */
vlc_mutex_t structure_lock; vlc_mutex_t structure_lock;
/* Exit callback */
vlc_exit_t exit;
} libvlc_priv_t; } libvlc_priv_t;
static inline libvlc_priv_t *libvlc_priv (libvlc_int_t *libvlc) static inline libvlc_priv_t *libvlc_priv (libvlc_int_t *libvlc)
......
...@@ -234,6 +234,7 @@ libvlc_InternalDestroy ...@@ -234,6 +234,7 @@ libvlc_InternalDestroy
libvlc_InternalInit libvlc_InternalInit
libvlc_InternalWait libvlc_InternalWait
libvlc_Quit libvlc_Quit
libvlc_SetExitHandler
LocaleFree LocaleFree
make_URI make_URI
make_path make_path
......
/*****************************************************************************
* quit.c: LibVLC termination event
*****************************************************************************
* Copyright (C) 2009-2010 the VideoLAN team
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_interface.h>
#include "libvlc.h"
#include "control/libvlc_internal.h"
void vlc_ExitInit( vlc_exit_t *exit )
{
vlc_mutex_init( &exit->lock );
exit->handler = NULL;
exit->opaque = NULL;
exit->killed = false;
}
void vlc_ExitDestroy( vlc_exit_t *exit )
{
vlc_mutex_destroy( &exit->lock );
}
/**
* Registers a callback for the LibVLC exit event.
*
* @note This function conflicts with libvlc_InternalWait().
* Use either or none of them, but not both.
*/
void libvlc_SetExitHandler( libvlc_int_t *p_libvlc, void (*handler) (void *),
void *opaque )
{
vlc_exit_t *exit = &libvlc_priv( p_libvlc )->exit;
vlc_mutex_lock( &exit->lock );
if( exit->killed ) /* already exited! (race condition) */
handler( opaque );
exit->handler = handler;
exit->opaque = opaque;
vlc_mutex_unlock( &exit->lock );
}
/**
* Posts an exit signal to LibVLC instance. This only emits a notification to
* the main thread. It might take a while before the actual cleanup occurs.
* This function should only be called on behalf of the user.
*/
void libvlc_Quit( libvlc_int_t *p_libvlc )
{
vlc_exit_t *exit = &libvlc_priv( p_libvlc )->exit;
vlc_mutex_lock( &exit->lock );
if( !exit->killed )
{
msg_Dbg( p_libvlc, "exiting" );
exit->killed = true;
if( exit->handler != NULL )
exit->handler( exit->opaque );
}
vlc_mutex_unlock( &exit->lock );
}
static void exit_wakeup( void *data )
{
vlc_cond_signal( data );
}
/**
* Waits until the LibVLC instance gets an exit signal.
* This normally occurs when the user "exits" an interface plugin. But it can
* also be triggered by the special vlc://quit item, the update checker, or
* the playlist engine.
*/
void libvlc_InternalWait( libvlc_int_t *p_libvlc )
{
vlc_exit_t *exit = &libvlc_priv( p_libvlc )->exit;
vlc_cond_t wait;
vlc_cond_init( &wait );
vlc_mutex_lock( &exit->lock );
exit->handler = exit_wakeup;
exit->opaque = &wait;
while( !exit->killed )
vlc_cond_wait( &wait, &exit->lock );
vlc_mutex_unlock( &exit->lock );
vlc_cond_destroy( &wait );
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment