[vlc-commits] commit: libvlc_Quit: support using a callback ( Rémi Denis-Courmont )
git at videolan.org
git at videolan.org
Sun May 30 19:52:34 CEST 2010
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun May 30 20:17:27 2010 +0300| [6197b056e6f9bd026012db6f1512bbd981e27442] | committer: 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.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6197b056e6f9bd026012db6f1512bbd981e27442
---
src/Makefile.am | 1 +
src/control/libvlc_internal.h | 1 +
src/interface/interface.c | 2 -
src/libvlc.c | 36 +-------------
src/libvlc.h | 17 ++++++
src/libvlccore.sym | 1 +
src/misc/exit.c | 110 +++++++++++++++++++++++++++++++++++++++++
7 files changed, 132 insertions(+), 36 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index 5ce3214..8a23506 100644
--- a/src/Makefile.am
+++ b/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 \
diff --git a/src/control/libvlc_internal.h b/src/control/libvlc_internal.h
index 7ab347d..c079f8d 100644
--- a/src/control/libvlc_internal.h
+++ b/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 * ) ;
diff --git a/src/interface/interface.c b/src/interface/interface.c
index ba9240b..9268391 100644
--- a/src/interface/interface.c
+++ b/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
diff --git a/src/libvlc.c b/src/libvlc.c
index 3d78cde..9affe8c 100644
--- a/src/libvlc.c
+++ b/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 ) )
/*****************************************************************************
diff --git a/src/libvlc.h b/src/libvlc.h
index a9fd3d1..873b73c 100644
--- a/src/libvlc.h
+++ b/src/libvlc.h
@@ -94,6 +94,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)
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 6767a6b..d8cd222 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -234,6 +234,7 @@ libvlc_InternalDestroy
libvlc_InternalInit
libvlc_InternalWait
libvlc_Quit
+libvlc_SetExitHandler
LocaleFree
make_URI
make_path
diff --git a/src/misc/exit.c b/src/misc/exit.c
new file mode 100644
index 0000000..65c3809
--- /dev/null
+++ b/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 );
+}
More information about the vlc-commits
mailing list