1 /*****************************************************************************
2 * file.c: file logger plugin
3 *****************************************************************************
4 * Copyright (C) 2002-2008 the VideoLAN team
5 * Copyright © 2007-2015 Rémi Denis-Courmont
7 * Authors: Samuel Hocevar <sam@zoy.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
28 #define VLC_MODULE_LICENSE VLC_LICENSE_GPL_2_PLUS
29 #include <vlc_common.h>
30 #include <vlc_plugin.h>
32 //#include <vlc_charset.h>
38 static const char msg_type[4][9] = { "", " error", " warning", " debug" };
47 #define TEXT_FILENAME "vlc-log.txt"
48 #define TEXT_HEADER "\xEF\xBB\xBF" /* UTF-8 BOM */ \
49 "-- logger module started --\n"
50 #define TEXT_FOOTER "-- logger module stopped --\n"
52 static void LogText(void *opaque, int type, const vlc_log_t *meta,
53 const char *format, va_list ap)
55 vlc_logger_sys_t *sys = opaque;
56 FILE *stream = sys->stream;
58 if (sys->verbosity < type)
61 int canc = vlc_savecancel();
64 fprintf(stream, "%s%s: ", meta->psz_module, msg_type[type]);
65 vfprintf(stream, format, ap);
66 putc_unlocked('\n', stream);
69 vlc_restorecancel(canc);
72 #define HTML_FILENAME "vlc-log.html"
74 "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n" \
75 " \"http://www.w3.org/TR/html4/strict.dtd\">\n" \
78 " <title>vlc log</title>\n" \
79 " <meta http-equiv=\"Content-Type\"" \
80 " content=\"text/html; charset=UTF-8\">\n" \
82 " <body style=\"background-color: #000000; color: #aaaaaa;\">\n" \
84 " <strong>-- logger module started --</strong>\n"
86 " <strong>-- logger module stopped --</strong>\n" \
91 static void LogHtml(void *opaque, int type, const vlc_log_t *meta,
92 const char *format, va_list ap)
94 static const unsigned color[4] = {
95 0xffffff, 0xff6666, 0xffff66, 0xaaaaaa,
97 vlc_logger_sys_t *sys = opaque;
98 FILE *stream = sys->stream;
100 if (sys->verbosity < type)
103 int canc = vlc_savecancel();
106 fprintf(stream, "%s%s: <span style=\"color: #%06x\">",
107 meta->psz_module, msg_type[type], color[type]);
108 /* FIXME: encode special ASCII characters */
109 vfprintf(stream, format, ap);
110 fputs("</span>\n", stream);
113 vlc_restorecancel(canc);
116 static vlc_log_cb Open(vlc_object_t *obj, void **restrict sysp)
118 if (!var_InheritBool(obj, "file-logging"))
121 int verbosity = var_InheritInteger(obj, "log-verbose");
123 verbosity = var_InheritInteger(obj, "verbose");
125 return NULL; /* nothing to log */
127 verbosity += VLC_MSG_ERR;
129 vlc_logger_sys_t *sys = malloc(sizeof (*sys));
130 if (unlikely(sys == NULL))
133 const char *filename = TEXT_FILENAME;
134 const char *header = TEXT_HEADER;
136 vlc_log_cb cb = LogText;
137 sys->footer = TEXT_FOOTER;
138 sys->verbosity = verbosity;
140 char *mode = var_InheritString(obj, "logmode");
143 if (!strcmp(mode, "html"))
145 filename = HTML_FILENAME;
146 header = HTML_HEADER;
148 sys->footer = HTML_FOOTER;
150 else if (strcmp(mode, "text"))
151 msg_Warn(obj, "invalid log mode \"%s\"", mode);
155 char *path = var_InheritString(obj, "logfile");
159 char *home = config_GetUserDir(VLC_HOME_DIR);
162 if (asprintf(&path, "%s/Library/Logs/%s", home, path) == -1)
171 /* Open the log file and remove any buffering for the stream */
172 msg_Dbg(obj, "opening logfile `%s'", filename);
173 sys->stream = vlc_fopen(filename, "at");
174 if (sys->stream == NULL)
176 msg_Err(obj, "error opening log file `%s': %s", filename,
177 vlc_strerror_c(errno) );
184 setvbuf(sys->stream, NULL, _IONBF, 0);
185 fputs(header, sys->stream);
191 static void Close(void *opaque)
193 vlc_logger_sys_t *sys = opaque;
195 fputs(sys->footer, sys->stream);
200 static const char *const mode_list[] = { "text", "html" };
201 static const char *const mode_list_text[] = { N_("Text"), N_("HTML") };
203 #define FILE_LOG_TEXT N_("Log to file")
204 #define FILE_LOG_LONGTEXT N_("Log all VLC messages to a text file.")
206 #define LOGMODE_TEXT N_("Log format")
207 #define LOGMODE_LONGTEXT N_("Specify the logging format.")
209 #define LOGVERBOSE_TEXT N_("Verbosity")
210 #define LOGVERBOSE_LONGTEXT N_("Select the verbosity to use for log or -1 to " \
211 "use the same verbosity given by --verbose.")
214 set_shortname(N_("Logger"))
215 set_description(N_("File logger"))
216 set_category(CAT_ADVANCED)
217 set_subcategory(SUBCAT_ADVANCED_MISC)
218 set_capability("logger", 15)
219 set_callbacks(Open, Close)
221 add_bool("file-logging", false, FILE_LOG_TEXT, FILE_LOG_LONGTEXT, false)
222 add_savefile("logfile", NULL,
223 N_("Log filename"), N_("Specify the log filename."), false)
224 add_string("logmode", "text", LOGMODE_TEXT, LOGMODE_LONGTEXT, false)
225 change_string_list(mode_list, mode_list_text)
226 add_integer("log-verbose", -1, LOGVERBOSE_TEXT, LOGVERBOSE_LONGTEXT,