Commit 63d1c692 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Push log message formatting to subscribers

This avoids allocating memory and formatting debug messages when none
of the subscribers care about them.
parent b17eb18e
...@@ -56,12 +56,10 @@ enum msg_item_type ...@@ -56,12 +56,10 @@ enum msg_item_type
*/ */
typedef struct typedef struct
{ {
unsigned i_type; /**< Message type, see @ref msg_item_type */
uintptr_t i_object_id; /**< Emitter (temporaly) unique object ID or 0 */ uintptr_t i_object_id; /**< Emitter (temporaly) unique object ID or 0 */
const char *psz_object_type; /**< Emitter object type name */ const char *psz_object_type; /**< Emitter object type name */
const char *psz_module; /**< Emitter module (source code) */ const char *psz_module; /**< Emitter module (source code) */
const char *psz_header; /**< Additional header (used by VLM media) */ const char *psz_header; /**< Additional header (used by VLM media) */
char *psz_msg; /**< Message text */
} msg_item_t; } msg_item_t;
/** /**
...@@ -91,7 +89,8 @@ VLC_API void vlc_vaLog(vlc_object_t *, int, ...@@ -91,7 +89,8 @@ VLC_API void vlc_vaLog(vlc_object_t *, int,
* Message logging callback signature. * Message logging callback signature.
* Accepts one private data pointer, the message, and an overrun counter. * Accepts one private data pointer, the message, and an overrun counter.
*/ */
typedef void (*msg_callback_t) (void *, const msg_item_t *); typedef void (*msg_callback_t) (void *, int, const msg_item_t *,
const char *, va_list);
VLC_API msg_subscription_t *vlc_Subscribe(msg_callback_t, void *) VLC_USED; VLC_API msg_subscription_t *vlc_Subscribe(msg_callback_t, void *) VLC_USED;
VLC_API void vlc_Unsubscribe(msg_subscription_t *); VLC_API void vlc_Unsubscribe(msg_subscription_t *);
......
...@@ -192,7 +192,12 @@ struct intf_sys_t ...@@ -192,7 +192,12 @@ struct intf_sys_t
int i_box_idx; // selected line int i_box_idx; // selected line
msg_subscription_t *p_sub; // message bank subscription msg_subscription_t *p_sub; // message bank subscription
msg_item_t *msgs[50]; // ring buffer struct
{
int type;
msg_item_t *item;
char *msg;
} msgs[50]; // ring buffer
int i_msgs; int i_msgs;
int i_verbosity; int i_verbosity;
vlc_mutex_t msg_lock; vlc_mutex_t msg_lock;
...@@ -1064,12 +1069,13 @@ static int DrawMessages(intf_thread_t *p_intf) ...@@ -1064,12 +1069,13 @@ static int DrawMessages(intf_thread_t *p_intf)
i = p_sys->i_msgs; i = p_sys->i_msgs;
for(;;) for(;;)
{ {
msg_item_t *msg = p_sys->msgs[i]; msg_item_t *msg = p_sys->msgs[i].item;
if (msg) if (msg)
{ {
if (p_sys->b_color) if (p_sys->b_color)
color_set(msg->i_type + C_INFO, NULL); color_set(p_sys->msgs[i].type + C_INFO, NULL);
MainBoxWrite(p_sys, l++, "[%s] %s", msg->psz_module, msg->psz_msg); MainBoxWrite(p_sys, l++, "[%s] %s", msg->psz_module,
p_sys->msgs[i].msg);
} }
if (++i == sizeof p_sys->msgs / sizeof *p_sys->msgs) if (++i == sizeof p_sys->msgs / sizeof *p_sys->msgs)
...@@ -1813,11 +1819,9 @@ static void HandleKey(intf_thread_t *p_intf) ...@@ -1813,11 +1819,9 @@ static void HandleKey(intf_thread_t *p_intf)
static msg_item_t *msg_Copy (const msg_item_t *msg) static msg_item_t *msg_Copy (const msg_item_t *msg)
{ {
msg_item_t *copy = (msg_item_t *)xmalloc (sizeof (*copy)); msg_item_t *copy = (msg_item_t *)xmalloc (sizeof (*copy));
copy->i_type = msg->i_type;
copy->i_object_id = msg->i_object_id; copy->i_object_id = msg->i_object_id;
copy->psz_object_type = msg->psz_object_type; copy->psz_object_type = msg->psz_object_type;
copy->psz_module = strdup (msg->psz_module); copy->psz_module = strdup (msg->psz_module);
copy->psz_msg = strdup (msg->psz_msg);
copy->psz_header = msg->psz_header ? strdup (msg->psz_header) : NULL; copy->psz_header = msg->psz_header ? strdup (msg->psz_header) : NULL;
return copy; return copy;
} }
...@@ -1826,25 +1830,30 @@ static void msg_Free (msg_item_t *msg) ...@@ -1826,25 +1830,30 @@ static void msg_Free (msg_item_t *msg)
{ {
free ((char *)msg->psz_module); free ((char *)msg->psz_module);
free ((char *)msg->psz_header); free ((char *)msg->psz_header);
free (msg->psz_msg);
free (msg); free (msg);
} }
static void MsgCallback(void *data, const msg_item_t *msg) static void MsgCallback(void *data, int type, const msg_item_t *msg,
const char *format, va_list ap)
{ {
intf_sys_t *p_sys = data; intf_sys_t *p_sys = data;
char *text;
if (p_sys->i_verbosity < 0 if (p_sys->i_verbosity < 0
|| p_sys->i_verbosity < (msg->i_type - VLC_MSG_ERR)) || p_sys->i_verbosity < (type - VLC_MSG_ERR)
|| vasprintf(&text, format, ap) == -1)
return; return;
vlc_mutex_lock(&p_sys->msg_lock); vlc_mutex_lock(&p_sys->msg_lock);
if (p_sys->msgs[p_sys->i_msgs]) p_sys->msgs[p_sys->i_msgs].type = type;
msg_Free(p_sys->msgs[p_sys->i_msgs]); if (p_sys->msgs[p_sys->i_msgs].item != NULL)
p_sys->msgs[p_sys->i_msgs++] = msg_Copy(msg); msg_Free(p_sys->msgs[p_sys->i_msgs].item);
p_sys->msgs[p_sys->i_msgs].item = msg_Copy(msg);
free(p_sys->msgs[p_sys->i_msgs].msg);
p_sys->msgs[p_sys->i_msgs].msg = text;
if (p_sys->i_msgs == (sizeof p_sys->msgs / sizeof *p_sys->msgs)) if (++p_sys->i_msgs == (sizeof p_sys->msgs / sizeof *p_sys->msgs))
p_sys->i_msgs = 0; p_sys->i_msgs = 0;
vlc_mutex_unlock(&p_sys->msg_lock); vlc_mutex_unlock(&p_sys->msg_lock);
...@@ -1965,8 +1974,10 @@ static void Close(vlc_object_t *p_this) ...@@ -1965,8 +1974,10 @@ static void Close(vlc_object_t *p_this)
vlc_mutex_destroy(&p_sys->msg_lock); vlc_mutex_destroy(&p_sys->msg_lock);
vlc_mutex_destroy(&p_sys->pl_lock); vlc_mutex_destroy(&p_sys->pl_lock);
for(unsigned i = 0; i < sizeof p_sys->msgs / sizeof *p_sys->msgs; i++) for(unsigned i = 0; i < sizeof p_sys->msgs / sizeof *p_sys->msgs; i++)
if (p_sys->msgs[i]) {
msg_Free(p_sys->msgs[i]); if (p_sys->msgs[i].item)
msg_Free(p_sys->msgs[i].item);
free(p_sys->msgs[i].msg);
}
free(p_sys); free(p_sys);
} }
...@@ -48,7 +48,7 @@ enum { ...@@ -48,7 +48,7 @@ enum {
class MsgEvent : public QEvent class MsgEvent : public QEvent
{ {
public: public:
MsgEvent( const msg_item_t * ); MsgEvent( int, const msg_item_t *, const char * );
int priority; int priority;
uintptr_t object_id; uintptr_t object_id;
...@@ -58,14 +58,14 @@ public: ...@@ -58,14 +58,14 @@ public:
QString text; QString text;
}; };
MsgEvent::MsgEvent( const msg_item_t *msg ) MsgEvent::MsgEvent( int type, const msg_item_t *msg, const char *text )
: QEvent( (QEvent::Type)MsgEvent_Type ), : QEvent( (QEvent::Type)MsgEvent_Type ),
priority( msg->i_type ), priority( type ),
object_id( msg->i_object_id ), object_id( msg->i_object_id ),
object_type( qfu(msg->psz_object_type) ), object_type( qfu(msg->psz_object_type) ),
header( qfu(msg->psz_header) ), header( qfu(msg->psz_header) ),
module( qfu(msg->psz_module) ), module( qfu(msg->psz_module) ),
text( qfu(msg->psz_msg) ) text( qfu(text) )
{ {
} }
...@@ -299,15 +299,19 @@ void MessagesDialog::tabChanged( int i ) ...@@ -299,15 +299,19 @@ void MessagesDialog::tabChanged( int i )
updateButton->setVisible( i == 1 ); updateButton->setVisible( i == 1 );
} }
void MessagesDialog::MsgCallback( void *self, const msg_item_t *item ) void MessagesDialog::MsgCallback( void *self, int type, const msg_item_t *item,
const char *format, va_list ap )
{ {
MessagesDialog *dialog = (MessagesDialog *)self; MessagesDialog *dialog = (MessagesDialog *)self;
char *str;
int verbosity = vlc_atomic_get( &dialog->verbosity ); int verbosity = vlc_atomic_get( &dialog->verbosity );
if( verbosity < 0 || verbosity < (item->i_type - VLC_MSG_ERR) ) if( verbosity < 0 || verbosity < (type - VLC_MSG_ERR)
|| unlikely(vasprintf( &str, format, ap ) == -1) )
return; return;
int canc = vlc_savecancel(); int canc = vlc_savecancel();
QApplication::postEvent( dialog, new MsgEvent( item ) ); QApplication::postEvent( dialog, new MsgEvent( type, item, str ) );
vlc_restorecancel( canc ); vlc_restorecancel( canc );
free( str );
} }
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "util/qvlcframe.hpp" #include "util/qvlcframe.hpp"
#include "util/singleton.hpp" #include "util/singleton.hpp"
#include "ui/messages_panel.h" #include "ui/messages_panel.h"
#include <stdarg.h>
class QTabWidget; class QTabWidget;
class QPushButton; class QPushButton;
...@@ -53,7 +54,8 @@ private: ...@@ -53,7 +54,8 @@ private:
void sinkMessage( const MsgEvent * ); void sinkMessage( const MsgEvent * );
vlc_atomic_t verbosity; vlc_atomic_t verbosity;
static void MsgCallback( void *, const msg_item_t * ); static void MsgCallback( void *, int, const msg_item_t *, const char *,
va_list );
QStringList filter; QStringList filter;
bool filterDefault; bool filterDefault;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <vlc_fs.h> #include <vlc_fs.h>
#include <vlc_charset.h> #include <vlc_charset.h>
#include <stdarg.h>
#include <assert.h> #include <assert.h>
#define MODE_TEXT 0 #define MODE_TEXT 0
...@@ -88,11 +89,11 @@ struct intf_sys_t ...@@ -88,11 +89,11 @@ struct intf_sys_t
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * ); static void Close ( vlc_object_t * );
static void Overflow (void *p_sys, const msg_item_t *p_item); static void Overflow (void *, int, const msg_item_t *, const char *, va_list);
static void TextPrint ( const msg_item_t *, FILE * ); static void TextPrint (FILE *, int, const msg_item_t *, const char *);
static void HtmlPrint ( const msg_item_t *, FILE * ); static void HtmlPrint (FILE *, int, const msg_item_t *, const char *);
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
static void SyslogPrint ( const msg_item_t *); static void SyslogPrint (int, const msg_item_t *, const char *);
#endif #endif
/***************************************************************************** /*****************************************************************************
...@@ -359,49 +360,42 @@ static void Close( vlc_object_t *p_this ) ...@@ -359,49 +360,42 @@ static void Close( vlc_object_t *p_this )
/** /**
* Log a message * Log a message
*/ */
static void Overflow (void *opaque, const msg_item_t *p_item) static void Overflow (void *opaque, int type, const msg_item_t *p_item,
const char *format, va_list ap)
{ {
intf_thread_t *p_intf = opaque; intf_thread_t *p_intf = opaque;
intf_sys_t *p_sys = p_intf->p_sys; intf_sys_t *p_sys = p_intf->p_sys;
char *str;
/* TODO: cache value... */
int verbosity = var_InheritInteger( p_intf, "log-verbose" ); int verbosity = var_InheritInteger( p_intf, "log-verbose" );
if (verbosity == -1) if (verbosity == -1)
verbosity = var_InheritInteger( p_intf, "verbose" ); verbosity = var_InheritInteger( p_intf, "verbose" );
switch( p_item->i_type ) if( verbosity < 0 || verbosity < (type - VLC_MSG_ERR)
{ || vasprintf( &str, format, ap) == -1 )
case VLC_MSG_INFO: return;
case VLC_MSG_ERR:
if( verbosity < 0 ) return;
break;
case VLC_MSG_WARN:
if( verbosity < 1 ) return;
break;
case VLC_MSG_DBG:
if( verbosity < 2 ) return;
break;
}
int canc = vlc_savecancel(); int canc = vlc_savecancel();
switch( p_sys->i_mode ) switch( p_sys->i_mode )
{ {
case MODE_HTML: case MODE_HTML:
HtmlPrint( p_item, p_sys->p_file ); HtmlPrint( p_sys->p_file, type, p_item, str );
break; break;
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
case MODE_SYSLOG: case MODE_SYSLOG:
SyslogPrint( p_item ); SyslogPrint( type, p_item, str );
break; break;
#endif #endif
case MODE_TEXT: case MODE_TEXT:
default: default:
TextPrint( p_item, p_sys->p_file ); TextPrint( p_sys->p_file, type, p_item, str );
break; break;
} }
vlc_restorecancel( canc ); vlc_restorecancel( canc );
free( str );
} }
static const char ppsz_type[4][11] = { static const char ppsz_type[4][11] = {
...@@ -411,29 +405,31 @@ static const char ppsz_type[4][11] = { ...@@ -411,29 +405,31 @@ static const char ppsz_type[4][11] = {
" debug: ", " debug: ",
}; };
static void TextPrint( const msg_item_t *p_msg, FILE *p_file ) static void TextPrint( FILE *stream, int type, const msg_item_t *item,
const char *str )
{ {
utf8_fprintf( p_file, "%s%s%s\n", p_msg->psz_module, utf8_fprintf( stream, "%s%s%s\n", item->psz_module,
ppsz_type[p_msg->i_type], p_msg->psz_msg ); ppsz_type[type], str );
} }
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
static void SyslogPrint( const msg_item_t *p_msg ) static void SyslogPrint( int type, const msg_item_t *item, const char *str )
{ {
static const int i_prio[4] = { LOG_INFO, LOG_ERR, LOG_WARNING, LOG_DEBUG }; static const int i_prio[4] = { LOG_INFO, LOG_ERR, LOG_WARNING, LOG_DEBUG };
int i_priority = i_prio[p_msg->i_type]; int i_priority = i_prio[type];
if( p_msg->psz_header ) if( item->psz_header != NULL )
syslog( i_priority, "[%s] %s%s%s", p_msg->psz_header, syslog( i_priority, "[%s] %s%s%s", item->psz_header,
p_msg->psz_module, ppsz_type[p_msg->i_type], p_msg->psz_msg ); item->psz_module, ppsz_type[type], str );
else else
syslog( i_priority, "%s%s%s", syslog( i_priority, "%s%s%s",
p_msg->psz_module, ppsz_type[p_msg->i_type], p_msg->psz_msg ); item->psz_module, ppsz_type[type], str );
} }
#endif #endif
static void HtmlPrint( const msg_item_t *p_msg, FILE *p_file ) static void HtmlPrint( FILE *stream, int type, const msg_item_t *item,
const char *str )
{ {
static const char ppsz_color[4][30] = { static const char ppsz_color[4][30] = {
"<span style=\"color: #ffffff\">", "<span style=\"color: #ffffff\">",
...@@ -442,7 +438,6 @@ static void HtmlPrint( const msg_item_t *p_msg, FILE *p_file ) ...@@ -442,7 +438,6 @@ static void HtmlPrint( const msg_item_t *p_msg, FILE *p_file )
"<span style=\"color: #aaaaaa\">", "<span style=\"color: #aaaaaa\">",
}; };
fprintf( p_file, "%s%s%s%s</span>\n", p_msg->psz_module, fprintf( stream, "%s%s%s%s</span>\n", item->psz_module,
ppsz_type[p_msg->i_type], ppsz_color[p_msg->i_type], ppsz_type[type], ppsz_color[type], str );
p_msg->psz_msg );
} }
...@@ -129,8 +129,9 @@ void vlc_Log (vlc_object_t *obj, int type, const char *module, ...@@ -129,8 +129,9 @@ void vlc_Log (vlc_object_t *obj, int type, const char *module,
va_end (args); va_end (args);
} }
static void PrintColorMsg (void *, const msg_item_t *); static void PrintColorMsg (void *, int, const msg_item_t *,
static void PrintMsg (void *, const msg_item_t *); const char *, va_list);
static void PrintMsg (void *, int, const msg_item_t *, const char *, va_list);
/** /**
* Emit a log message. This function is the variable argument list equivalent * Emit a log message. This function is the variable argument list equivalent
...@@ -204,24 +205,12 @@ void vlc_vaLog (vlc_object_t *obj, int type, const char *module, ...@@ -204,24 +205,12 @@ void vlc_vaLog (vlc_object_t *obj, int type, const char *module,
} }
#endif #endif
/* Convert message to string */
static const char nomemstr[] = "<not enough memory to format message>";
char *str;
if (unlikely(vasprintf (&str, format, args) == -1))
str = (char *)nomemstr;
uselocale (locale);
freelocale (c);
/* Fill message information fields */ /* Fill message information fields */
msg_item_t msg; msg_item_t msg;
msg.i_type = type;
msg.i_object_id = (uintptr_t)obj; msg.i_object_id = (uintptr_t)obj;
msg.psz_object_type = obj->psz_object_type; msg.psz_object_type = obj->psz_object_type;
msg.psz_module = module; msg.psz_module = module;
msg.psz_msg = str;
msg.psz_header = NULL; msg.psz_header = NULL;
for (vlc_object_t *o = obj; o != NULL; o = o->p_parent) for (vlc_object_t *o = obj; o != NULL; o = o->p_parent)
...@@ -234,18 +223,26 @@ void vlc_vaLog (vlc_object_t *obj, int type, const char *module, ...@@ -234,18 +223,26 @@ void vlc_vaLog (vlc_object_t *obj, int type, const char *module,
/* Pass message to subscribers */ /* Pass message to subscribers */
libvlc_priv_t *priv = libvlc_priv (obj->p_libvlc); libvlc_priv_t *priv = libvlc_priv (obj->p_libvlc);
va_list ap;
va_copy (ap, args);
if (priv->b_color) if (priv->b_color)
PrintColorMsg (&priv->i_verbose, &msg); PrintColorMsg (&priv->i_verbose, type, &msg, format, ap);
else else
PrintMsg (&priv->i_verbose, &msg); PrintMsg (&priv->i_verbose, type, &msg, format, ap);
va_end (ap);
vlc_rwlock_rdlock (&msg_lock); vlc_rwlock_rdlock (&msg_lock);
for (msg_subscription_t *sub = msg_head; sub != NULL; sub = sub->next) for (msg_subscription_t *sub = msg_head; sub != NULL; sub = sub->next)
sub->func (sub->opaque, &msg); {
va_copy (ap, args);
sub->func (sub->opaque, type, &msg, format, ap);
va_end (ap);
}
vlc_rwlock_unlock (&msg_lock); vlc_rwlock_unlock (&msg_lock);
if (likely(str != (char *)nomemstr)) uselocale (locale);
free (str); freelocale (c);
} }
static const char msg_type[4][9] = { "", " error", " warning", " debug" }; static const char msg_type[4][9] = { "", " error", " warning", " debug" };
...@@ -257,11 +254,11 @@ static const char msg_type[4][9] = { "", " error", " warning", " debug" }; ...@@ -257,11 +254,11 @@ static const char msg_type[4][9] = { "", " error", " warning", " debug" };
#define GRAY "\033[0m" #define GRAY "\033[0m"
static const char msg_color[4][8] = { WHITE, RED, YELLOW, GRAY }; static const char msg_color[4][8] = { WHITE, RED, YELLOW, GRAY };
static void PrintColorMsg (void *d, const msg_item_t *p_item) static void PrintColorMsg (void *d, int type, const msg_item_t *p_item,
const char *format, va_list ap)
{ {
const int *pverbose = d; const int *pverbose = d;
FILE *stream = stderr; FILE *stream = stderr;
int type = p_item->i_type;
if (*pverbose < 0 || *pverbose < (type - VLC_MSG_ERR)) if (*pverbose < 0 || *pverbose < (type - VLC_MSG_ERR))
return; return;
...@@ -272,9 +269,10 @@ static void PrintColorMsg (void *d, const msg_item_t *p_item) ...@@ -272,9 +269,10 @@ static void PrintColorMsg (void *d, const msg_item_t *p_item)
fprintf (stream, "["GREEN"%p"GRAY"] ", (void *)p_item->i_object_id); fprintf (stream, "["GREEN"%p"GRAY"] ", (void *)p_item->i_object_id);
if (p_item->psz_header != NULL) if (p_item->psz_header != NULL)
utf8_fprintf (stream, "[%s] ", p_item->psz_header); utf8_fprintf (stream, "[%s] ", p_item->psz_header);
utf8_fprintf (stream, "%s %s%s: %s%s"GRAY"\n", p_item->psz_module, utf8_fprintf (stream, "%s %s%s: %s", p_item->psz_module,
p_item->psz_object_type, msg_type[type], msg_color[type], p_item->psz_object_type, msg_type[type], msg_color[type]);
p_item->psz_msg); utf8_vfprintf (stream, format, ap);
fputs (GRAY"\n", stream);
#if defined (WIN32) || defined (__OS2__) #if defined (WIN32) || defined (__OS2__)
fflush (stream); fflush (stream);
#endif #endif
...@@ -282,11 +280,11 @@ static void PrintColorMsg (void *d, const msg_item_t *p_item) ...@@ -282,11 +280,11 @@ static void PrintColorMsg (void *d, const msg_item_t *p_item)
vlc_restorecancel (canc); vlc_restorecancel (canc);
} }
static void PrintMsg (void *d, const msg_item_t *p_item) static void PrintMsg (void *d, int type, const msg_item_t *p_item,
const char *format, va_list ap)
{ {
const int *pverbose = d; const int *pverbose = d;
FILE *stream = stderr; FILE *stream = stderr;
int type = p_item->i_type;
if (*pverbose < 0 || *pverbose < (type - VLC_MSG_ERR)) if (*pverbose < 0 || *pverbose < (type - VLC_MSG_ERR))
return; return;
...@@ -297,8 +295,10 @@ static void PrintMsg (void *d, const msg_item_t *p_item) ...@@ -297,8 +295,10 @@ static void PrintMsg (void *d, const msg_item_t *p_item)
fprintf (stream, "[%p] ", (void *)p_item->i_object_id); fprintf (stream, "[%p] ", (void *)p_item->i_object_id);
if (p_item->psz_header != NULL) if (p_item->psz_header != NULL)
utf8_fprintf (stream, "[%s] ", p_item->psz_header); utf8_fprintf (stream, "[%s] ", p_item->psz_header);
utf8_fprintf (stream, "%s %s%s: %s\n", p_item->psz_module, utf8_fprintf (stream, "%s %s%s: ", p_item->psz_module,
p_item->psz_object_type, msg_type[type], p_item->psz_msg); p_item->psz_object_type, msg_type[type]);
utf8_vfprintf (stream, format, ap);
fputc_unlocked ('\n', stream);
#if defined (WIN32) || defined (__OS2__) #if defined (WIN32) || defined (__OS2__)
fflush (stream); fflush (stream);
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment