mp_msg: introduce new log functions and macros

This has two goals:
1. Getting rid of global variables to make the core library-safe.
2. Getting rid of all the MSGT_* constants and the inconsistent
   prefixes spread throughout the source code.

Both goals are not immediately reached with this commit. It's a huge
transition that will take time. There are over >2500 mp_msg calls in the
source, which all have to be replaced for this to work.

The inconsistent prefixes are in particular annoying. Lots of code
manually prefixes messages, e.g. mp_msg(MSGT_VO, MSGL_V, "[vo] ...").
Sometimes the prefixes don't even follow this convention (for example
vo_direct3d.c uses "<vo_direct3d>" as prefix). This commit allows
automatically adding prefixes on request, so consistency will
hopefully improve.

For now, this commit adds unused stuff, and behavior should not change.

In mplayer.c, move the GetCpuCaps() call, because that used mp_msg()
before mp_msg_init() was run.
This commit is contained in:
wm4 2013-07-31 21:40:30 +02:00
parent d1de1e090f
commit 88d79fc00d
5 changed files with 255 additions and 66 deletions

View File

@ -113,7 +113,9 @@ enum {
};
typedef struct MPContext {
struct mpv_global *global;
struct MPOpts *opts;
struct mp_log *log;
struct m_config *mconfig;
struct input_ctx *input;
struct osd_state *osd;

View File

@ -21,8 +21,12 @@
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "talloc.h"
#include "config.h"
#include "core/mpv_global.h"
#include "osdep/getch2.h"
#include "osdep/io.h"
@ -39,6 +43,25 @@
bool mp_msg_stdout_in_use = 0;
struct mp_log_root {
/* This should, at some point, contain all mp_msg related state, instead
* of having global variables (at least as long as we don't want to
* control the terminal, which is global anyway). But for now, there is
* not much. */
struct mpv_global *global;
};
struct mp_log {
struct mp_log_root *root;
const char *prefix;
const char *verbose_prefix;
int legacy_mod;
};
// should not exist
static bool initialized;
static struct mp_log *legacy_logs[MSGT_MAX];
/* maximum message length of mp_msg */
#define MSGSIZE_MAX 6144
@ -74,7 +97,7 @@ static int mp_msg_docolor(void) {
return mp_msg_cancolor && mp_msg_color;
}
void mp_msg_init(void){
static void mp_msg_do_init(void){
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO cinfo;
DWORD cmode = 0;
@ -121,6 +144,11 @@ int mp_msg_test(int mod, int lev)
return lev <= (mp_msg_levels[mod] == -2 ? mp_msg_level_all + verbose : mp_msg_levels[mod]);
}
bool mp_msg_test_log(struct mp_log *log, int lev)
{
return mp_msg_test(log->legacy_mod, lev);
}
static void set_msg_color(FILE* stream, int lev)
{
static const int v_colors[10] = {9, 1, 3, 3, -1, -1, 2, 8, 8, 8};
@ -153,78 +181,30 @@ static void set_msg_color(FILE* stream, int lev)
}
}
static void print_msg_module(FILE* stream, int mod)
static void print_msg_module(FILE* stream, struct mp_log *log)
{
static const char *module_text[MSGT_MAX] = {
"GLOBAL",
"CPLAYER",
"GPLAYER",
"VIDEOOUT",
"AUDIOOUT",
"DEMUXER",
"DS",
"DEMUX",
"HEADER",
"AVSYNC",
"AUTOQ",
"CFGPARSER",
"DECAUDIO",
"DECVIDEO",
"SEEK",
"WIN32",
"OPEN",
"DVD",
"PARSEES",
"LIRC",
"STREAM",
"CACHE",
"MENCODER",
"XACODEC",
"TV",
"OSDEP",
"SPUDEC",
"PLAYTREE",
"INPUT",
"VFILTER",
"OSD",
"NETWORK",
"CPUDETECT",
"CODECCFG",
"SWS",
"VOBSUB",
"SUBREADER",
"AFILTER",
"NETST",
"MUXER",
"OSDMENU",
"IDENTIFY",
"RADIO",
"ASS",
"LOADER",
"STATUSLINE",
};
int mod = log->legacy_mod;
int c2 = (mod + 1) % 15 + 1;
if (!mp_msg_module)
return;
#ifdef _WIN32
HANDLE *wstream = stream == stderr ? hSTDERR : hSTDOUT;
if (mp_msg_docolor())
SetConsoleTextAttribute(wstream, ansi2win32[c2&7] | FOREGROUND_INTENSITY);
fprintf(stream, "%9s", module_text[mod]);
fprintf(stream, "%9s", log->verbose_prefix);
if (mp_msg_docolor())
SetConsoleTextAttribute(wstream, stdoutAttrs);
#else
if (mp_msg_docolor())
fprintf(stream, "\033[%d;3%dm", c2 >> 3, c2 & 7);
fprintf(stream, "%9s", module_text[mod]);
fprintf(stream, "%9s", log->verbose_prefix);
if (mp_msg_docolor())
fprintf(stream, "\033[0;37m");
#endif
fprintf(stream, ": ");
}
void mp_msg_va(int mod, int lev, const char *format, va_list va)
static void mp_msg_log_va(struct mp_log *log, int lev, const char *format,
va_list va)
{
char tmp[MSGSIZE_MAX];
FILE *stream =
@ -233,7 +213,7 @@ void mp_msg_va(int mod, int lev, const char *format, va_list va)
// indicates if last line printed was a status line
static int statusline;
if (!mp_msg_test(mod, lev)) return; // do not display
if (!mp_msg_test_log(log, lev)) return; // do not display
vsnprintf(tmp, MSGSIZE_MAX, format, va);
tmp[MSGSIZE_MAX-2] = '\n';
tmp[MSGSIZE_MAX-1] = 0;
@ -245,9 +225,17 @@ void mp_msg_va(int mod, int lev, const char *format, va_list va)
fprintf(stderr, "\n");
statusline = lev == MSGL_STATUS;
if (header)
print_msg_module(stream, mod);
set_msg_color(stream, lev);
if (header) {
if (mp_msg_module) {
print_msg_module(stream, log);
set_msg_color(stream, lev);
} else if (lev >= MSGL_V || verbose) {
fprintf(stream, "[%s] ", log->verbose_prefix);
} else if (log->prefix) {
fprintf(stream, "[%s] ", log->prefix);
}
}
size_t len = strlen(tmp);
header = len && (tmp[len-1] == '\n' || tmp[len-1] == '\r');
@ -266,6 +254,13 @@ void mp_msg_va(int mod, int lev, const char *format, va_list va)
fflush(stream);
}
void mp_msg_va(int mod, int lev, const char *format, va_list va)
{
assert(initialized);
assert(mod >= 0 && mod < MSGT_MAX);
mp_msg_log_va(legacy_logs[mod], lev, format, va);
}
void mp_msg(int mod, int lev, const char *format, ...)
{
va_list va;
@ -334,3 +329,143 @@ void mp_tmsg(int mod, int lev, const char *format, ...)
mp_msg_va(mod, lev, mp_gtext(format), va);
va_end(va);
}
// legacy names
static const char *module_text[MSGT_MAX] = {
"global",
"cplayer",
"gplayer",
"vo",
"ao",
"demuxer",
"ds",
"demux",
"header",
"avsync",
"autoq",
"cfgparser",
"decaudio",
"decvideo",
"seek",
"win32",
"open",
"dvd",
"parsees",
"lirc",
"stream",
"cache",
"mencoder",
"xacodec",
"tv",
"osdep",
"spudec",
"playtree",
"input",
"vf",
"osd",
"network",
"cpudetect",
"codeccfg",
"sws",
"vobsub",
"subreader",
"af",
"netst",
"muxer",
"osdmenu",
"identify",
"radio",
"ass",
"loader",
"statusline",
"teletext",
};
// Create a new log context, which uses talloc_ctx as talloc parent, and parent
// as logical parent.
// The name is the prefix put before the output. It's usually prefixed by the
// parent's name. If the name starts with "/", the parent's name is not
// prefixed (except in verbose mode), and if it starts with "!", the name is
// printed at all (except in verbose mode).
struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent,
const char *name)
{
assert(parent);
assert(name);
struct mp_log *log = talloc_zero(talloc_ctx, struct mp_log);
log->root = parent->root;
if (name[0] == '!') {
name = &name[1];
} else if (name[0] == '/') {
name = &name[1];
log->prefix = talloc_strdup(log, name);
} else {
log->prefix = parent->prefix
? talloc_asprintf(log, "%s/%s", parent->prefix, name)
: talloc_strdup(log, name);
}
log->verbose_prefix = parent->prefix
? talloc_asprintf(log, "%s/%s", parent->prefix, name)
: talloc_strdup(log, name);
if (log->prefix && !log->prefix[0])
log->prefix = NULL;
if (!log->verbose_prefix[0])
log->verbose_prefix = "global";
log->legacy_mod = parent->legacy_mod;
for (int n = 0; n < MSGT_MAX; n++) {
if (module_text[n] && strcmp(name, module_text[n]) == 0) {
log->legacy_mod = n;
break;
}
}
return log;
}
void mp_msg_init(struct mpv_global *global)
{
assert(!initialized);
assert(!global->log);
struct mp_log_root *root = talloc_zero(NULL, struct mp_log_root);
root->global = global;
struct mp_log dummy = { .root = root };
struct mp_log *log = mp_log_new(root, &dummy, "");
for (int n = 0; n < MSGT_MAX; n++) {
char name[80];
snprintf(name, sizeof(name), "!%s", module_text[n]);
legacy_logs[n] = mp_log_new(root, log, name);
}
mp_msg_do_init();
global->log = log;
initialized = true;
}
struct mpv_global *mp_log_get_global(struct mp_log *log)
{
return log->root->global;
}
void mp_msg_uninit(struct mpv_global *global)
{
talloc_free(global->log->root);
global->log = NULL;
initialized = false;
}
void mp_msg_log(struct mp_log *log, int lev, const char *format, ...)
{
va_list va;
va_start(va, format);
mp_msg_log_va(log, lev, format, va);
va_end(va);
}
void mp_tmsg_log(struct mp_log *log, int lev, const char *format, ...)
{
va_list va;
va_start(va, format);
mp_msg_log_va(log, lev, mp_gtext(format), va);
va_end(va);
}

View File

@ -20,6 +20,9 @@
#define MPLAYER_MP_MSG_H
#include <stdarg.h>
#include <stdbool.h>
struct mp_log;
// defined in mplayer.c
extern int verbose;
@ -126,10 +129,10 @@ extern int verbose;
#define MSGT_TELETEXT 46 // Teletext decoder
#define MSGT_MAX 64
#define MSGT_MAX 47
void mp_msg_init(void);
int mp_msg_test(int mod, int lev);
bool mp_msg_test_log(struct mp_log *log, int lev);
#include "config.h"
#include "core/mp_common.h"
@ -142,6 +145,34 @@ void mp_msg(int mod, int lev, const char *format, ... ) PRINTF_ATTRIBUTE(3, 4);
void mp_tmsg(int mod, int lev, const char *format, ... ) PRINTF_ATTRIBUTE(3, 4);
#define mp_dbg mp_msg
struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent,
const char *name);
void mp_msg_log(struct mp_log *log, int lev, const char *format, ...)
PRINTF_ATTRIBUTE(3, 4);
void mp_tmsg_log(struct mp_log *log, int lev, const char *format, ...)
PRINTF_ATTRIBUTE(3, 4);
// Convenience macros, typically called with a pointer to a context struct
// as first argument, which has a "struct mp_log log;" member.
#define MP_MSG(obj, lev, ...) mp_msg_log((obj)->log, lev, __VA_ARGS__)
#define MP_MSGT(obj, lev, ...) mp_msgt_log((obj)->log, lev, __VA_ARGS__)
#define MP_FATAL(obj, ...) MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
#define MP_ERR(obj, ...) MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
#define MP_WARN(obj, ...) MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
#define MP_INFO(obj, ...) MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
#define MP_VERBOSE(obj, ...) MP_MSG(obj, MSGL_V, __VA_ARGS__)
#define MP_DBG(obj, ...) MP_MSG(obj, MSGL_DGB2, __VA_ARGS__)
#define MP_TRACE(obj, ...) MP_MSG(obj, MSGL_DGB5, __VA_ARGS__)
struct mpv_global;
void mp_msg_init(struct mpv_global *global);
void mp_msg_uninit(struct mpv_global *global);
struct mpv_global *mp_log_get_global(struct mp_log *log);
extern bool mp_msg_stdout_in_use;
#endif /* MPLAYER_MP_MSG_H */

View File

@ -63,6 +63,7 @@
#include <errno.h>
#include "core/mpv_global.h"
#include "core/mp_msg.h"
#include "av_log.h"
@ -585,6 +586,8 @@ static MP_NORETURN void exit_player(struct MPContext *mpctx,
// must be last since e.g. mp_msg uses option values
// that will be freed by this.
mp_msg_uninit(mpctx->global);
talloc_free(mpctx);
#ifdef CONFIG_COCOA
@ -4562,8 +4565,6 @@ static void osdep_preinit(int *p_argc, char ***p_argv)
if (enable_talloc && strcmp(enable_talloc, "1") == 0)
talloc_enable_leak_report();
GetCpuCaps(&gCpuCaps);
#ifdef __MINGW32__
mp_get_converted_argv(p_argc, p_argv);
#endif
@ -4603,10 +4604,6 @@ static int mpv_main(int argc, char *argv[])
.playlist = talloc_struct(mpctx, struct playlist, {0}),
};
mp_msg_init();
init_libav();
screenshot_init(mpctx);
// Create the config context and register the options
mpctx->mconfig = m_config_new(mpctx, sizeof(struct MPOpts),
&mp_default_opts, mp_opts, NULL);
@ -4616,6 +4613,18 @@ static int mpv_main(int argc, char *argv[])
struct MPOpts *opts = mpctx->opts;
mpctx->global = talloc_zero(mpctx, struct mpv_global);
mpctx->global->opts = opts;
// Nothing must call mp_msg() before this
mp_msg_init(mpctx->global);
mpctx->log = mp_log_new(mpctx, mpctx->global->log, "!mpv");
init_libav();
GetCpuCaps(&gCpuCaps);
screenshot_init(mpctx);
// Preparse the command line
m_config_preparse_command_line(mpctx->mconfig, argc, argv);

12
core/mpv_global.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef MPV_MPV_H
#define MPV_MPV_H
// This should be accessed by glue code only, never normal code.
// The only purpose of this is to make mpv library-safe.
// Think hard before adding new members.
struct mpv_global {
struct MPOpts *opts;
struct mp_log *log;
};
#endif