build-time config option for VR mode
[vrtris] / src / logger.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include "logger.h"
5 #include "osd.h"
6
7 #if defined(unix) || defined(__unix__) || defined(__APPLE__)
8 #include <unistd.h>
9 #elif defined(WIN32)
10 #include <windows.h>
11 #endif
12
13 #define UI_MSG_TIMEOUT 4000
14
15 enum { LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_FATAL, LOG_DEBUG };
16
17 static int typecolor(int type);
18 static const char *typeprefix(int type);
19
20 static FILE *fp;
21 static FILE *logfile;
22
23 static void logmsg(int type, const char *fmt, va_list ap)
24 {
25         va_list ap_orig;
26
27         if(!fp) fp = stdout;
28
29         va_copy(ap_orig, ap);
30
31 #if defined(unix) || defined(__unix__) || (defined(__APPLE__) && !defined(TARGET_IPHONE))
32         if(isatty(fileno(fp)) && type != LOG_INFO) {
33                 int c = typecolor(type);
34                 fprintf(fp, "\033[%dm", c);
35                 vfprintf(fp, fmt, ap);
36                 fprintf(fp, "\033[0m");
37         } else
38 #endif
39         {
40                 fprintf(fp, "%s", typeprefix(type));
41                 vfprintf(fp, fmt, ap);
42         }
43         if(type == LOG_ERROR || type == LOG_FATAL || type == LOG_DEBUG) {
44                 fflush(fp);
45         }
46
47         if(logfile) {
48                 va_end(ap);
49                 va_copy(ap, ap_orig);
50                 fprintf(logfile, "%s", typeprefix(type));
51                 vfprintf(logfile, fmt, ap);
52         }
53
54 #ifdef WIN32
55         if(type == LOG_FATAL) {
56                 static char msgbuf[1024];
57                 vsnprintf(msgbuf, sizeof msgbuf - 1, fmt, ap_orig);
58                 msgbuf[sizeof msgbuf - 1] = 0;
59                 MessageBox(0, msgbuf, "Fatal error", MB_OK | MB_ICONSTOP);
60         }
61 #endif
62
63         va_end(ap_orig);
64 }
65
66 static void close_logfile(void)
67 {
68         if(logfile) fclose(logfile);
69 }
70
71 void set_log_file(const char *fname)
72 {
73         static int init_once;
74
75         close_logfile();
76         logfile = fopen(fname, "w");
77
78         if(!init_once) {
79                 atexit(close_logfile);
80                 init_once = 1;
81         }
82 }
83
84 void info_log(const char *fmt, ...)
85 {
86         va_list ap;
87
88         va_start(ap, fmt);
89         logmsg(LOG_INFO, fmt, ap);
90         va_end(ap);
91 }
92
93 void warning_log(const char *fmt, ...)
94 {
95         va_list ap;
96
97         va_start(ap, fmt);
98         logmsg(LOG_WARNING, fmt, ap);
99         va_end(ap);
100
101         va_start(ap, fmt);
102         show_messagev(UI_MSG_TIMEOUT, 1.0, 0.8, 0.1, fmt, ap);
103         va_end(ap);
104 }
105
106 void error_log(const char *fmt, ...)
107 {
108         va_list ap;
109
110         va_start(ap, fmt);
111         logmsg(LOG_ERROR, fmt, ap);
112         va_end(ap);
113
114         va_start(ap, fmt);
115         show_messagev(UI_MSG_TIMEOUT, 1.0, 0.1, 0.1, fmt, ap);
116         va_end(ap);
117 }
118
119 void fatal_log(const char *fmt, ...)
120 {
121         va_list ap;
122
123         va_start(ap, fmt);
124         logmsg(LOG_FATAL, fmt, ap);
125         va_end(ap);
126 }
127
128 void debug_log(const char *fmt, ...)
129 {
130         va_list ap;
131
132         va_start(ap, fmt);
133         logmsg(LOG_DEBUG, fmt, ap);
134         va_end(ap);
135 }
136
137 enum {
138         BLACK = 0,
139         RED,
140         GREEN,
141         YELLOW,
142         BLUE,
143         MAGENTA,
144         CYAN,
145         WHITE
146 };
147
148 #define ANSI_FGCOLOR(x) (30 + (x))
149 #define ANSI_BGCOLOR(x) (40 + (x))
150
151 static int typecolor(int type)
152 {
153         switch(type) {
154         case LOG_ERROR:
155                 return ANSI_FGCOLOR(RED);
156         case LOG_FATAL:
157                 return ANSI_FGCOLOR(RED);       // TODO differentiate from LOG_ERROR
158         case LOG_WARNING:
159                 return ANSI_FGCOLOR(YELLOW);
160         case LOG_DEBUG:
161                 return ANSI_FGCOLOR(MAGENTA);
162         default:
163                 break;
164         }
165         return 37;
166 }
167
168 static const char *typeprefix(int type)
169 {
170         switch(type) {
171         case LOG_ERROR:
172                 return "E: ";
173         case LOG_FATAL:
174                 return "F: ";
175         case LOG_WARNING:
176                 return "W: ";
177         case LOG_DEBUG:
178                 return "D: ";
179         default:
180                 break;
181         }
182         return "";
183 }