1 |
/* |
2 |
SDL - Simple DirectMedia Layer |
3 |
Copyright (C) 1997-2011 Sam Lantinga |
4 |
|
5 |
This library is free software; you can redistribute it and/or |
6 |
modify it under the terms of the GNU Lesser General Public |
7 |
License as published by the Free Software Foundation; either |
8 |
version 2.1 of the License, or (at your option) any later version. |
9 |
|
10 |
This library is distributed in the hope that it will be useful, |
11 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 |
Lesser General Public License for more details. |
14 |
|
15 |
You should have received a copy of the GNU Lesser General Public |
16 |
License along with this library; if not, write to the Free Software |
17 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 |
|
19 |
Sam Lantinga |
20 |
slouken@libsdl.org |
21 |
*/ |
22 |
#include "SDL_config.h" |
23 |
|
24 |
/* Simple log messages in SDL */ |
25 |
|
26 |
#include "SDL_log.h" |
27 |
|
28 |
#if HAVE_STDIO_H |
29 |
#include <stdio.h> |
30 |
#endif |
31 |
|
32 |
#if defined(__WIN32__) |
33 |
#include "core/windows/SDL_windows.h" |
34 |
#elif defined(__ANDROID__) |
35 |
#include <android/log.h> |
36 |
#endif |
37 |
|
38 |
#define DEFAULT_PRIORITY SDL_LOG_PRIORITY_CRITICAL |
39 |
#define DEFAULT_APPLICATION_PRIORITY SDL_LOG_PRIORITY_INFO |
40 |
|
41 |
typedef struct SDL_LogLevel |
42 |
{ |
43 |
int category; |
44 |
SDL_LogPriority priority; |
45 |
struct SDL_LogLevel *next; |
46 |
} SDL_LogLevel; |
47 |
|
48 |
/* The default log output function */ |
49 |
static void SDL_LogOutput(void *userdata, |
50 |
int category, SDL_LogPriority priority, |
51 |
const char *message); |
52 |
|
53 |
static SDL_LogLevel *SDL_loglevels; |
54 |
static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; |
55 |
static SDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY; |
56 |
static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput; |
57 |
static void *SDL_log_userdata = NULL; |
58 |
|
59 |
static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = { |
60 |
NULL, |
61 |
"VERBOSE", |
62 |
"DEBUG", |
63 |
"INFO", |
64 |
"WARN", |
65 |
"ERROR", |
66 |
"CRITICAL" |
67 |
}; |
68 |
|
69 |
#ifdef __ANDROID__ |
70 |
static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = { |
71 |
"APP", |
72 |
"ERROR", |
73 |
"SYSTEM", |
74 |
"AUDIO", |
75 |
"VIDEO", |
76 |
"RENDER", |
77 |
"INPUT" |
78 |
}; |
79 |
|
80 |
static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = { |
81 |
ANDROID_LOG_VERBOSE, |
82 |
ANDROID_LOG_DEBUG, |
83 |
ANDROID_LOG_INFO, |
84 |
ANDROID_LOG_WARN, |
85 |
ANDROID_LOG_ERROR, |
86 |
ANDROID_LOG_FATAL |
87 |
}; |
88 |
#endif /* __ANDROID__ */ |
89 |
|
90 |
|
91 |
void |
92 |
SDL_LogSetAllPriority(SDL_LogPriority priority) |
93 |
{ |
94 |
SDL_LogLevel *entry; |
95 |
|
96 |
for (entry = SDL_loglevels; entry; entry = entry->next) { |
97 |
entry->priority = priority; |
98 |
} |
99 |
SDL_application_priority = SDL_default_priority = priority; |
100 |
} |
101 |
|
102 |
void |
103 |
SDL_LogSetPriority(int category, SDL_LogPriority priority) |
104 |
{ |
105 |
SDL_LogLevel *entry; |
106 |
|
107 |
for (entry = SDL_loglevels; entry; entry = entry->next) { |
108 |
if (entry->category == category) { |
109 |
entry->priority = priority; |
110 |
return; |
111 |
} |
112 |
} |
113 |
|
114 |
/* Create a new entry */ |
115 |
entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry)); |
116 |
if (entry) { |
117 |
entry->category = category; |
118 |
entry->priority = priority; |
119 |
entry->next = SDL_loglevels; |
120 |
SDL_loglevels = entry; |
121 |
} |
122 |
} |
123 |
|
124 |
SDL_LogPriority |
125 |
SDL_LogGetPriority(int category) |
126 |
{ |
127 |
SDL_LogLevel *entry; |
128 |
|
129 |
for (entry = SDL_loglevels; entry; entry = entry->next) { |
130 |
if (entry->category == category) { |
131 |
return entry->priority; |
132 |
} |
133 |
} |
134 |
|
135 |
if (category == SDL_LOG_CATEGORY_APPLICATION) { |
136 |
return SDL_application_priority; |
137 |
} else { |
138 |
return SDL_default_priority; |
139 |
} |
140 |
} |
141 |
|
142 |
void |
143 |
SDL_LogResetPriorities(void) |
144 |
{ |
145 |
SDL_LogLevel *entry; |
146 |
|
147 |
while (SDL_loglevels) { |
148 |
entry = SDL_loglevels; |
149 |
SDL_loglevels = entry->next; |
150 |
SDL_free(entry); |
151 |
} |
152 |
|
153 |
SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; |
154 |
SDL_default_priority = DEFAULT_PRIORITY; |
155 |
} |
156 |
|
157 |
void |
158 |
SDL_Log(const char *fmt, ...) |
159 |
{ |
160 |
va_list ap; |
161 |
|
162 |
va_start(ap, fmt); |
163 |
SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap); |
164 |
va_end(ap); |
165 |
} |
166 |
|
167 |
void |
168 |
SDL_LogVerbose(int category, const char *fmt, ...) |
169 |
{ |
170 |
va_list ap; |
171 |
|
172 |
va_start(ap, fmt); |
173 |
SDL_LogMessageV(category, SDL_LOG_PRIORITY_VERBOSE, fmt, ap); |
174 |
va_end(ap); |
175 |
} |
176 |
|
177 |
void |
178 |
SDL_LogDebug(int category, const char *fmt, ...) |
179 |
{ |
180 |
va_list ap; |
181 |
|
182 |
va_start(ap, fmt); |
183 |
SDL_LogMessageV(category, SDL_LOG_PRIORITY_DEBUG, fmt, ap); |
184 |
va_end(ap); |
185 |
} |
186 |
|
187 |
void |
188 |
SDL_LogInfo(int category, const char *fmt, ...) |
189 |
{ |
190 |
va_list ap; |
191 |
|
192 |
va_start(ap, fmt); |
193 |
SDL_LogMessageV(category, SDL_LOG_PRIORITY_INFO, fmt, ap); |
194 |
va_end(ap); |
195 |
} |
196 |
|
197 |
void |
198 |
SDL_LogWarn(int category, const char *fmt, ...) |
199 |
{ |
200 |
va_list ap; |
201 |
|
202 |
va_start(ap, fmt); |
203 |
SDL_LogMessageV(category, SDL_LOG_PRIORITY_WARN, fmt, ap); |
204 |
va_end(ap); |
205 |
} |
206 |
|
207 |
void |
208 |
SDL_LogError(int category, const char *fmt, ...) |
209 |
{ |
210 |
va_list ap; |
211 |
|
212 |
va_start(ap, fmt); |
213 |
SDL_LogMessageV(category, SDL_LOG_PRIORITY_ERROR, fmt, ap); |
214 |
va_end(ap); |
215 |
} |
216 |
|
217 |
void |
218 |
SDL_LogCritical(int category, const char *fmt, ...) |
219 |
{ |
220 |
va_list ap; |
221 |
|
222 |
va_start(ap, fmt); |
223 |
SDL_LogMessageV(category, SDL_LOG_PRIORITY_CRITICAL, fmt, ap); |
224 |
va_end(ap); |
225 |
} |
226 |
|
227 |
void |
228 |
SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt, ...) |
229 |
{ |
230 |
va_list ap; |
231 |
|
232 |
va_start(ap, fmt); |
233 |
SDL_LogMessageV(category, priority, fmt, ap); |
234 |
va_end(ap); |
235 |
} |
236 |
|
237 |
#ifdef __ANDROID__ |
238 |
static const char * |
239 |
GetCategoryPrefix(int category) |
240 |
{ |
241 |
if (category < SDL_LOG_CATEGORY_RESERVED1) { |
242 |
return SDL_category_prefixes[category]; |
243 |
} |
244 |
if (category < SDL_LOG_CATEGORY_CUSTOM) { |
245 |
return "RESERVED"; |
246 |
} |
247 |
return "CUSTOM"; |
248 |
} |
249 |
#endif /* __ANDROID__ */ |
250 |
|
251 |
void |
252 |
SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap) |
253 |
{ |
254 |
char *message; |
255 |
|
256 |
/* Nothing to do if we don't have an output function */ |
257 |
if (!SDL_log_function) { |
258 |
return; |
259 |
} |
260 |
|
261 |
/* Make sure we don't exceed array bounds */ |
262 |
if (priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) { |
263 |
return; |
264 |
} |
265 |
|
266 |
/* See if we want to do anything with this message */ |
267 |
if (priority < SDL_LogGetPriority(category)) { |
268 |
return; |
269 |
} |
270 |
|
271 |
message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE); |
272 |
if (!message) { |
273 |
return; |
274 |
} |
275 |
SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap); |
276 |
SDL_log_function(SDL_log_userdata, category, priority, message); |
277 |
SDL_stack_free(message); |
278 |
} |
279 |
|
280 |
static void |
281 |
SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, |
282 |
const char *message) |
283 |
{ |
284 |
#if defined(__WIN32__) |
285 |
/* Way too many allocations here, urgh */ |
286 |
{ |
287 |
char *output; |
288 |
size_t length; |
289 |
LPTSTR tstr; |
290 |
|
291 |
length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1; |
292 |
output = SDL_stack_alloc(char, length); |
293 |
SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message); |
294 |
tstr = WIN_UTF8ToString(output); |
295 |
OutputDebugString(tstr); |
296 |
SDL_free(tstr); |
297 |
SDL_stack_free(output); |
298 |
} |
299 |
#elif defined(__ANDROID__) |
300 |
{ |
301 |
char tag[32]; |
302 |
|
303 |
SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category)); |
304 |
__android_log_write(SDL_android_priority[priority], tag, message); |
305 |
} |
306 |
#endif |
307 |
#if HAVE_STDIO_H |
308 |
fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message); |
309 |
#endif |
310 |
} |
311 |
|
312 |
void |
313 |
SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata) |
314 |
{ |
315 |
if (callback) { |
316 |
*callback = SDL_log_function; |
317 |
} |
318 |
if (userdata) { |
319 |
*userdata = SDL_log_userdata; |
320 |
} |
321 |
} |
322 |
|
323 |
void |
324 |
SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata) |
325 |
{ |
326 |
SDL_log_function = callback; |
327 |
SDL_log_userdata = userdata; |
328 |
} |
329 |
|
330 |
/* vi: set ts=4 sw=4 expandtab: */ |