]> git.sesse.net Git - vlc/blob - modules/logger/file.c
vlc_plugin: fix non-LGPL plugins meta infos
[vlc] / modules / logger / file.c
1 /*****************************************************************************
2  * file.c: file logger plugin
3  *****************************************************************************
4  * Copyright (C) 2002-2008 the VideoLAN team
5  * Copyright © 2007-2015 Rémi Denis-Courmont
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #define VLC_MODULE_LICENSE VLC_LICENSE_GPL_2_PLUS
29 #include <vlc_common.h>
30 #include <vlc_plugin.h>
31 #include <vlc_fs.h>
32 //#include <vlc_charset.h>
33
34 #include <stdarg.h>
35 #include <assert.h>
36 #include <errno.h>
37
38 static const char msg_type[4][9] = { "", " error", " warning", " debug" };
39
40 typedef struct
41 {
42     FILE *stream;
43     const char *footer;
44     int verbosity;
45 } vlc_logger_sys_t;
46
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"
51
52 static void LogText(void *opaque, int type, const vlc_log_t *meta,
53                     const char *format, va_list ap)
54 {
55     vlc_logger_sys_t *sys = opaque;
56     FILE *stream = sys->stream;
57
58     if (sys->verbosity < type)
59         return;
60
61     int canc = vlc_savecancel();
62
63     flockfile(stream);
64     fprintf(stream, "%s%s: ", meta->psz_module, msg_type[type]);
65     vfprintf(stream, format, ap);
66     putc_unlocked('\n', stream);
67     funlockfile(stream);
68
69     vlc_restorecancel(canc);
70 }
71
72 #define HTML_FILENAME "vlc-log.html"
73 #define HTML_HEADER \
74     "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n" \
75     "  \"http://www.w3.org/TR/html4/strict.dtd\">\n" \
76     "<html>\n" \
77     "  <head>\n" \
78     "    <title>vlc log</title>\n" \
79     "    <meta http-equiv=\"Content-Type\"" \
80              " content=\"text/html; charset=UTF-8\">\n" \
81     "  </head>\n" \
82     "  <body style=\"background-color: #000000; color: #aaaaaa;\">\n" \
83     "    <pre>\n" \
84     "      <strong>-- logger module started --</strong>\n"
85 #define HTML_FOOTER \
86     "      <strong>-- logger module stopped --</strong>\n" \
87     "    </pre>\n" \
88     "  </body>\n" \
89     "</html>\n"
90
91 static void LogHtml(void *opaque, int type, const vlc_log_t *meta,
92                     const char *format, va_list ap)
93 {
94     static const unsigned color[4] = {
95         0xffffff, 0xff6666, 0xffff66, 0xaaaaaa,
96     };
97     vlc_logger_sys_t *sys = opaque;
98     FILE *stream = sys->stream;
99
100     if (sys->verbosity < type)
101         return;
102
103     int canc = vlc_savecancel();
104
105     flockfile(stream);
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);
111     funlockfile(stream);
112
113     vlc_restorecancel(canc);
114 }
115
116 static vlc_log_cb Open(vlc_object_t *obj, void **restrict sysp)
117 {
118     if (!var_InheritBool(obj, "file-logging"))
119         return NULL;
120
121     int verbosity = var_InheritInteger(obj, "log-verbose");
122     if (verbosity == -1)
123         verbosity = var_InheritInteger(obj, "verbose");
124     if (verbosity < 0)
125         return NULL; /* nothing to log */
126
127     verbosity += VLC_MSG_ERR;
128
129     vlc_logger_sys_t *sys = malloc(sizeof (*sys));
130     if (unlikely(sys == NULL))
131         return NULL;
132
133     const char *filename = TEXT_FILENAME;
134     const char *header = TEXT_HEADER;
135
136     vlc_log_cb cb = LogText;
137     sys->footer = TEXT_FOOTER;
138     sys->verbosity = verbosity;
139
140     char *mode = var_InheritString(obj, "logmode");
141     if (mode != NULL)
142     {
143         if (!strcmp(mode, "html"))
144         {
145             filename = HTML_FILENAME;
146             header = HTML_HEADER;
147             cb = LogHtml;
148             sys->footer = HTML_FOOTER;
149         }
150         else if (strcmp(mode, "text"))
151             msg_Warn(obj, "invalid log mode \"%s\"", mode);
152         free(mode);
153     }
154
155     char *path = var_InheritString(obj, "logfile");
156 #ifdef __APPLE__
157     if (path == NULL)
158     {
159         char *home = config_GetUserDir(VLC_HOME_DIR);
160         if (home != NULL)
161         {
162             if (asprintf(&path, "%s/Library/Logs/%s", home, path) == -1)
163                 path = NULL;
164             free(home);
165         }
166     }
167 #endif
168     if (path != NULL)
169         filename = path;
170
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)
175     {
176         msg_Err(obj, "error opening log file `%s': %s", filename,
177                 vlc_strerror_c(errno) );
178         free(path);
179         free(sys);
180         return NULL;
181     }
182     free(path);
183
184     setvbuf(sys->stream, NULL, _IONBF, 0);
185     fputs(header, sys->stream);
186
187     *sysp = sys;
188     return cb;
189 }
190
191 static void Close(void *opaque)
192 {
193     vlc_logger_sys_t *sys = opaque;
194
195     fputs(sys->footer, sys->stream);
196     fclose(sys->stream);
197     free(sys);
198 }
199
200 static const char *const mode_list[] = { "text", "html" };
201 static const char *const mode_list_text[] = { N_("Text"), N_("HTML") };
202
203 #define FILE_LOG_TEXT N_("Log to file")
204 #define FILE_LOG_LONGTEXT N_("Log all VLC messages to a text file.")
205
206 #define LOGMODE_TEXT N_("Log format")
207 #define LOGMODE_LONGTEXT N_("Specify the logging format.")
208
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.")
212
213 vlc_module_begin()
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)
220
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,
227                 false)
228 vlc_module_end ()