From e996cbefaf0f8db55513071b9678242e0a7733da Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 9 Aug 2009 18:03:57 +0300 Subject: [PATCH] LibVLC: per-thread error message API --- include/vlc/libvlc.h | 44 ++++++++++++ src/Makefile.am | 1 + src/control/core.c | 18 ++++- src/control/error.c | 131 ++++++++++++++++++++++++++++++++++ src/control/libvlc_internal.h | 4 ++ src/libvlc.sym | 4 ++ 6 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 src/control/error.c diff --git a/include/vlc/libvlc.h b/include/vlc/libvlc.h index 4f27ad9f4c..f4663eb28f 100644 --- a/include/vlc/libvlc.h +++ b/include/vlc/libvlc.h @@ -58,6 +58,7 @@ extern "C" { # endif +#include #include /***************************************************************************** @@ -117,6 +118,49 @@ libvlc_exception_get_message( const libvlc_exception_t *p_exception ); /**@} */ +/***************************************************************************** + * Error handling + *****************************************************************************/ +/** \defgroup libvlc_error libvlc_error + * \ingroup libvlc_core + * LibVLC error handling + * @{ + */ + +/** + * A human-readable error message for the last LibVLC error in the calling + * thread. The resulting string is valid until another error occurs (at least + * until the next LibVLC call). + * + * @warning + * This will be NULL if there was no error. + */ +const char *libvlc_errmsg (void); + +/** + * Clears the LibVLC error status for the current thread. This is optional. + * By default, the error status is automatically overriden when a new error + * occurs, and destroyed when the thread exits. + */ +void libvlc_clearerr (void); + +/** + * Sets the LibVLC error status and message for the current thread. + * Any previous error is overriden. + * @return a nul terminated string in any case + */ +const char *libvlc_vprinterr (const char *fmt, va_list ap); + +/** + * Sets the LibVLC error status and message for the current thread. + * Any previous error is overriden. + * @return a nul terminated string in any case + */ +const char *libvlc_printerr (const char *fmt, ...); + +/**@} */ + + /***************************************************************************** * Core handling *****************************************************************************/ diff --git a/src/Makefile.am b/src/Makefile.am index 30a3da64bb..bbbe84852c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -460,6 +460,7 @@ SOURCES_libvlc_control = \ control/media_list_view_internal.h \ control/media_player_internal.h \ control/core.c \ + control/error.c \ control/log.c \ control/playlist.c \ control/vlm.c \ diff --git a/src/control/core.c b/src/control/core.c index a96ff039d0..3a67a82ba1 100644 --- a/src/control/core.c +++ b/src/control/core.c @@ -111,11 +111,22 @@ libvlc_instance_t * libvlc_new( int argc, const char *const *argv, { libvlc_instance_t *p_new; int i_ret; + + libvlc_init_threads (); + libvlc_int_t *p_libvlc_int = libvlc_InternalCreate(); - if( !p_libvlc_int ) RAISENULL( "VLC initialization failed" ); + if( !p_libvlc_int ) + { + libvlc_deinit_threads (); + RAISENULL( "VLC initialization failed" ); + } p_new = malloc( sizeof( libvlc_instance_t ) ); - if( !p_new ) RAISENULL( "Out of memory" ); + if( !p_new ) + { + libvlc_deinit_threads (); + RAISENULL( "Out of memory" ); + } const char *my_argv[argc + 2]; @@ -132,6 +143,8 @@ libvlc_instance_t * libvlc_new( int argc, const char *const *argv, { libvlc_InternalDestroy( p_libvlc_int ); free( p_new ); + libvlc_deinit_threads (); + if( i_ret == VLC_EEXITSUCCESS ) return NULL; else @@ -181,6 +194,7 @@ void libvlc_release( libvlc_instance_t *p_instance ) libvlc_InternalCleanup( p_instance->p_libvlc_int ); libvlc_InternalDestroy( p_instance->p_libvlc_int ); free( p_instance ); + libvlc_deinit_threads (); } } diff --git a/src/control/error.c b/src/control/error.c new file mode 100644 index 0000000000..f9a3f695ac --- /dev/null +++ b/src/control/error.c @@ -0,0 +1,131 @@ +/***************************************************************************** + * error.c: Error handling for libvlc + ***************************************************************************** + * Copyright (C) 2009 Rémi Denis-Courmont + * + * 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. + *****************************************************************************/ + +#include "libvlc_internal.h" + +#include +#include +#include +#include + + +static const char oom[] = "Out of memory"; +/* TODO: use only one thread-specific key for whole libvlc */ +static vlc_threadvar_t context; + +static void libvlc_setup_threads (bool init) +{ + static vlc_mutex_t lock = VLC_STATIC_MUTEX; + static uintptr_t refs = 0; + + vlc_mutex_lock (&lock); + if (init) + { + if (refs++ == 0) + vlc_threadvar_create (&context, free); + } + else + { + assert (refs > 0); + if (--refs == 0) + vlc_threadvar_delete (&context); + } + vlc_mutex_unlock (&lock); +} + +void libvlc_init_threads (void) +{ + libvlc_setup_threads (true); +} + +void libvlc_deinit_threads (void) +{ + libvlc_setup_threads (false); +} + +static char *get_error (void) +{ + return vlc_threadvar_get (context); +} + +static void free_error (void) +{ + char *msg = get_error (); + if (msg != oom) + free (msg); +} + +/** + * Gets a human-readable error message for the last LibVLC error in the calling + * thread. The resulting string is valid until another error occurs (at least + * until the next LibVLC call). + * + * @return NULL if there was no error, a nul-terminated string otherwise. + */ +const char *libvlc_errmsg (void) +{ + return get_error (); +} + +/** + * Clears the LibVLC error status for the current thread. This is optional. + * By default, the error status is automatically overriden when a new error + * occurs, and destroyed when the thread exits. + */ +void libvlc_clearerr (void) +{ + free_error (); + vlc_threadvar_set (context, NULL); +} + +/** + * Sets the LibVLC error status and message for the current thread. + * Any previous error is overriden. + * @return a nul terminated string (always) + */ +const char *libvlc_vprinterr (const char *fmt, va_list ap) +{ + char *msg; + + assert (fmt != NULL); + if (vasprintf (&msg, fmt, ap) == -1) + msg = (char *)oom; + + free_error (); + vlc_threadvar_set (context, msg); + return msg; +} + +/** + * Sets the LibVLC error status and message for the current thread. + * Any previous error is overriden. + * @return a nul terminated string (always) + */ +const char *libvlc_printerr (const char *fmt, ...) +{ + va_list ap; + const char *msg; + + va_start (ap, fmt); + msg = libvlc_vprinterr (fmt, ap); + va_end (ap); + return msg; +} + diff --git a/src/control/libvlc_internal.h b/src/control/libvlc_internal.h index 6f338ce3fb..8ad972a787 100644 --- a/src/control/libvlc_internal.h +++ b/src/control/libvlc_internal.h @@ -83,6 +83,10 @@ struct libvlc_instance_t * Other internal functions ***************************************************************************/ +/* Thread context */ +void libvlc_init_threads (void); +void libvlc_deinit_threads (void); + /* Events */ libvlc_event_manager_t * libvlc_event_manager_new( void * p_obj, libvlc_instance_t * p_libvlc_inst, diff --git a/src/libvlc.sym b/src/libvlc.sym index 7e5cbb82e6..b41e21481f 100644 --- a/src/libvlc.sym +++ b/src/libvlc.sym @@ -1,3 +1,7 @@ +libvlc_errmsg +libvlc_clearerr +libvlc_printerr +libvlc_vprinterr libvlc_add_intf libvlc_audio_output_device_count libvlc_audio_output_device_id -- 2.39.2