[vlc-devel] [PATCH 1/2] libvlc: added a formatted log callback

Jeremy Vignelles jeremy.vignelles at dev3i.fr
Fri May 17 11:29:27 CEST 2019


> Le 17 mai 2019 à 11:14, Romain Vimont <rom1v at videolabs.io> a écrit :
> 
> 
> 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 must 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?

I'd prefer that format, but we would need to store my context options in libvlc_instance_t.log, and there would be two callbacks there, and I don't know all the implications of modifying that structure.

> > +
> >  /*** 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
> _______________________________________________
> 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