src/SDL_log.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 19 Feb 2011 11:23:56 -0800
changeset 5348 16202b090a63
parent 5262 b530ef003506
child 5535 96594ac5fd1a
permissions -rw-r--r--
Added missing log debug function
     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: */