Browse Source

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.
pull/2/head
Rémi Denis-Courmont 16 years ago
parent
commit
6197b056e6
  1. 1
      src/Makefile.am
  2. 1
      src/control/libvlc_internal.h
  3. 2
      src/interface/interface.c
  4. 36
      src/libvlc.c
  5. 17
      src/libvlc.h
  6. 1
      src/libvlccore.sym
  7. 110
      src/misc/exit.c

1
src/Makefile.am

@ -428,6 +428,7 @@ SOURCES_libvlc_common = \
misc/cpu.c \
misc/action.c \
misc/epg.c \
misc/exit.c \
config/configuration.h \
config/core.c \
config/chain.c \

1
src/control/libvlc_internal.h

@ -50,6 +50,7 @@ VLC_EXPORT (void, libvlc_InternalDestroy, ( libvlc_int_t * ) );
VLC_EXPORT (int, libvlc_InternalAddIntf, ( libvlc_int_t *, const char * ) );
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 * ) ;

2
src/interface/interface.c

@ -182,8 +182,6 @@ void intf_DestroyAll( libvlc_int_t *p_libvlc )
{
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

36
src/libvlc.c

@ -273,6 +273,7 @@ libvlc_int_t * libvlc_InternalCreate( void )
/* Initialize mutexes */
vlc_mutex_init( &priv->timer_lock );
vlc_ExitInit( &priv->exit );
return p_libvlc;
error:
@ -1073,6 +1074,7 @@ void libvlc_InternalDestroy( libvlc_int_t *p_libvlc )
msg_Destroy (priv->msg_bank);
/* Destroy mutexes */
vlc_ExitDestroy( &priv->exit );
vlc_mutex_destroy( &priv->timer_lock );
#ifndef NDEBUG /* Hack to dump leaked objects tree */
@ -1121,40 +1123,6 @@ int libvlc_InternalAddIntf( libvlc_int_t *p_libvlc, char const *psz_module )
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)) && \
( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
/*****************************************************************************

17
src/libvlc.h

@ -93,6 +93,20 @@ const char* msg_StackMsg ( void );
*/
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
*/
@ -210,6 +224,9 @@ typedef struct libvlc_priv_t
/* Objects tree */
vlc_mutex_t structure_lock;
/* Exit callback */
vlc_exit_t exit;
} libvlc_priv_t;
static inline libvlc_priv_t *libvlc_priv (libvlc_int_t *libvlc)

1
src/libvlccore.sym

@ -234,6 +234,7 @@ libvlc_InternalDestroy
libvlc_InternalInit
libvlc_InternalWait
libvlc_Quit
libvlc_SetExitHandler
LocaleFree
make_URI
make_path

110
src/misc/exit.c

@ -0,0 +1,110 @@
/*****************************************************************************
* 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 );
}
Loading…
Cancel
Save