[vlc-devel] [PATCH 1/2] libvlc: added a formatted log callback
Romain Vimont
rom1v at videolabs.io
Fri May 17 11:14:43 CEST 2019
On Fri, May 17, 2019 at 10:05:00AM +0200, Jérémy VIGNELLES wrote:
> ---
> include/vlc/libvlc.h | 64 ++++++++++++++++++++++++++++++++++++++++++++
> lib/libvlc.sym | 3 +++
> lib/log.c | 55 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 122 insertions(+)
>
> diff --git a/include/vlc/libvlc.h b/include/vlc/libvlc.h
> index 1c2550fe3b..1b21c2da66 100644
> --- a/include/vlc/libvlc.h
> +++ b/include/vlc/libvlc.h
> @@ -433,6 +433,26 @@ LIBVLC_API void libvlc_log_get_object(const libvlc_log_t *ctx,
> typedef void (*libvlc_log_cb)(void *data, int level, const libvlc_log_t *ctx,
> const char *fmt, va_list args);
>
> +/**
> + * Callback prototype for LibVLC preformatted log message handler.
> + *
> + * \param data data pointer as given to libvlc_log_set()
> + * \param level message level (@ref libvlc_log_level)
> + * \param ctx message context (meta-information about the message)
> + * \param message the message, already formatted
> + * \note Log message handlers <b>must</b> be thread-safe.
> + * \warning The message context pointer, and the message string parameters
> + * are only valid until the callback returns.
> + */
> +typedef void (*libvlc_log_preformatted_cb)(void *data, int level, const libvlc_log_t *ctx,
> + const char *message);
> +
> +/**
> + * Structure that represents the context to pass to the @ref libvlc_log_set_preformatted function
> + * \note This structure is opaque, use @ref libvlc_log_preformatted_context_new to allocate one
> + */
> +typedef struct libvlc_log_preformatted_context_t libvlc_log_preformatted_context_t;
> +
> /**
> * Unsets the logging callback.
> *
> @@ -468,6 +488,50 @@ LIBVLC_API void libvlc_log_unset( libvlc_instance_t *p_instance );
> LIBVLC_API void libvlc_log_set( libvlc_instance_t *p_instance,
> libvlc_log_cb cb, void *data );
>
> +/**
> + * Creates a structure for formatted log data
> + *
> + * \param p_instance libvlc instance
> + * \param min_level the callback will only be called if the message level is above this level, 0 means "get all messages"
> + * \param cb callback function pointer
> + * \param data opaque data pointer for the callback function
> + *
> + * \note You must release the result at the end of the logging, with @ref libvlc_log_preformatted_context_release
> + *
> + * \version LibVLC 4.0.0 or later
> + */
> +LIBVLC_API libvlc_log_preformatted_context_t* libvlc_log_preformatted_context_new (libvlc_instance_t *p_instance, int min_level,
> + libvlc_log_preformatted_cb cb, void *data );
> +
> +/**
> + * Destroys a structure for formatted log data created with @ref libvlc_log_preformatted_context_new
> + *
> + * \param p_instance libvlc instance
> + * \param data The log context for the preformatted callback, allocated with @ref libvlc_log_preformatted_context_new
> + *
> + * \version LibVLC 4.0.0 or later
> + */
> +LIBVLC_API void libvlc_log_preformatted_context_release (libvlc_instance_t *p_instance, libvlc_log_preformatted_context_t* data);
> +
> +/**
> + * Sets the logging callback for a LibVLC instance, that takes a preformatted message as input.
> + *
> + * This function is thread-safe: it will wait for any pending callbacks
> + * invocation to complete.
> + *
> + * \param p_instance libvlc instance
> + * \param min_level the callback will only be called if the message level is above this level, 0 means "get all messages"
> + * \param cb callback function pointer
> + * \param data opaque context pointer for the callback function
> + *
> + * \note Some log messages (especially debug) are emitted by LibVLC while
> + * is being initialized. These messages cannot be captured with this interface.
> + *
> + * \warning A deadlock may occur if this function is called from the callback.
> + *
> + * \version LibVLC 4.0.0 or later
> + */
> +LIBVLC_API void libvlc_log_set_preformatted (libvlc_instance_t *p_instance, libvlc_log_preformatted_context_t* data );
>
> /**
> * Sets up logging to a file.
> diff --git a/lib/libvlc.sym b/lib/libvlc.sym
> index 51a45688de..04fae622a9 100644
> --- a/lib/libvlc.sym
> +++ b/lib/libvlc.sym
> @@ -56,8 +56,11 @@ libvlc_get_fullscreen
> libvlc_get_version
> libvlc_log_get_context
> libvlc_log_get_object
> +libvlc_log_preformatted_context_new
> +libvlc_log_preformatted_context_release
> libvlc_log_set
> libvlc_log_set_file
> +libvlc_log_set_preformatted
> libvlc_log_unset
> libvlc_media_add_option
> libvlc_media_add_option_flag
> diff --git a/lib/log.c b/lib/log.c
> index 66e0d996d1..62d88ce064 100644
> --- a/lib/log.c
> +++ b/lib/log.c
> @@ -93,6 +93,61 @@ void libvlc_log_set (libvlc_instance_t *inst, libvlc_log_cb cb, void *data)
> vlc_LogSet(inst->p_libvlc_int, &libvlc_log_ops, inst);
> }
>
> +/*** Helpers for logging to preformatted callback ***/
> +typedef struct libvlc_log_preformatted_context_t {
> + libvlc_log_preformatted_cb cb;
> + void* original_data;
> + int min_level;
> +} libvlc_log_preformatted_context_t;
> +
> +/**
> + * The real log callback, that takes a format+va_list as input, formats the message, and pass it to the preformatted callback
> + */
> +static void libvlc_preformatted_log (void *data, int level, const libvlc_log_t *log,
> + const char *fmt, va_list ap)
> +{
> + libvlc_log_preformatted_context_t *log_data = (libvlc_log_preformatted_context_t *)data;
> + if(level >= log_data->min_level)
> + {
> + char* msg;
> + int msgSize = vasprintf(&msg, fmt, ap);
> + if (unlikely(msgSize < 0))
> + return;
> +
> + log_data->cb(log_data->original_data, level, log, msg);
> + free(msg);
> + }
> +}
> +
> +libvlc_log_preformatted_context_t* libvlc_log_preformatted_context_new (libvlc_instance_t *p_instance, int min_level,
> + libvlc_log_preformatted_cb cb, void *data )
> +{
> + (void)p_instance;
> + libvlc_log_preformatted_context_t *p_new = malloc (sizeof (*p_new));
> + if (unlikely(p_new == NULL))
> + return NULL;
> +
> + p_new->cb = cb;
> + p_new->min_level = min_level;
> + p_new->original_data = data;
> +
> + return p_new;
> +}
> +
> +void libvlc_log_preformatted_context_release (libvlc_instance_t *p_instance, libvlc_log_preformatted_context_t* data)
> +{
> + if(p_instance->log.data == data)
> + {// The log context is currently in use, unset the log before
> + libvlc_log_unset (p_instance);
> + }
> + free(data);
> +}
> +
> +void libvlc_log_set_preformatted (libvlc_instance_t *p_instance, libvlc_log_preformatted_context_t* data )
> +{
> + libvlc_log_set (p_instance, libvlc_preformatted_log, data);
> +}
Would it be possible not to expose libvlc_log_preformatted_context_t?
For example:
void libvlc_log_set_preformatted(libvlc_instance_t *p_instance,
int min_level,
libvlc_log_preformatted_cb cb,
void *data);
and handle the destruction internally when the logger is replaced or
libvlc_instance_t is destroyed?
> +
> /*** Helpers for logging to files ***/
> static void libvlc_log_file (void *data, int level, const libvlc_log_t *log,
> const char *fmt, va_list ap)
> --
> 2.21.0.windows.1
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list