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

Jérémy VIGNELLES jeremy.vignelles at dev3i.fr
Fri May 17 10:05:00 CEST 2019


---
 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);
+}
+
 /*** 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



More information about the vlc-devel mailing list