src/SDL_log.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Feb 2011 22:37:15 -0800
changeset 5262 b530ef003506
parent 5235 1e28342cb15d
child 5348 16202b090a63
permissions -rwxr-xr-x
Happy 2011! :)
     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_LogInfo(int category, const char *fmt, ...)
   179 {
   180     va_list ap;
   181 
   182     va_start(ap, fmt);
   183     SDL_LogMessageV(category, SDL_LOG_PRIORITY_INFO, fmt, ap);
   184     va_end(ap);
   185 }
   186 
   187 void
   188 SDL_LogWarn(int category, const char *fmt, ...)
   189 {
   190     va_list ap;
   191 
   192     va_start(ap, fmt);
   193     SDL_LogMessageV(category, SDL_LOG_PRIORITY_WARN, fmt, ap);
   194     va_end(ap);
   195 }
   196 
   197 void
   198 SDL_LogError(int category, const char *fmt, ...)
   199 {
   200     va_list ap;
   201 
   202     va_start(ap, fmt);
   203     SDL_LogMessageV(category, SDL_LOG_PRIORITY_ERROR, fmt, ap);
   204     va_end(ap);
   205 }
   206 
   207 void
   208 SDL_LogCritical(int category, const char *fmt, ...)
   209 {
   210     va_list ap;
   211 
   212     va_start(ap, fmt);
   213     SDL_LogMessageV(category, SDL_LOG_PRIORITY_CRITICAL, fmt, ap);
   214     va_end(ap);
   215 }
   216 
   217 void
   218 SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt, ...)
   219 {
   220     va_list ap;
   221 
   222     va_start(ap, fmt);
   223     SDL_LogMessageV(category, priority, fmt, ap);
   224     va_end(ap);
   225 }
   226 
   227 #ifdef __ANDROID__
   228 static const char *
   229 GetCategoryPrefix(int category)
   230 {
   231     if (category < SDL_LOG_CATEGORY_RESERVED1) {
   232         return SDL_category_prefixes[category];
   233     }
   234     if (category < SDL_LOG_CATEGORY_CUSTOM) {
   235         return "RESERVED";
   236     }
   237     return "CUSTOM";
   238 }
   239 #endif /* __ANDROID__ */
   240 
   241 void
   242 SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
   243 {
   244     char *message;
   245 
   246     /* Nothing to do if we don't have an output function */
   247     if (!SDL_log_function) {
   248         return;
   249     }
   250 
   251     /* Make sure we don't exceed array bounds */
   252     if (priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) {
   253         return;
   254     }
   255 
   256     /* See if we want to do anything with this message */
   257     if (priority < SDL_LogGetPriority(category)) {
   258         return;
   259     }
   260 
   261     message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
   262     if (!message) {
   263         return;
   264     }
   265     SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap);
   266     SDL_log_function(SDL_log_userdata, category, priority, message);
   267     SDL_stack_free(message);
   268 }
   269 
   270 static void
   271 SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
   272               const char *message)
   273 {
   274 #if defined(__WIN32__)
   275     /* Way too many allocations here, urgh */
   276     {
   277         char *output;
   278         size_t length;
   279         LPTSTR tstr;
   280 
   281         length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
   282         output = SDL_stack_alloc(char, length);
   283         SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
   284         tstr = WIN_UTF8ToString(output);
   285         OutputDebugString(tstr);
   286         SDL_free(tstr);
   287         SDL_stack_free(output);
   288     }
   289 #elif defined(__ANDROID__)
   290     {
   291         char tag[32];
   292 
   293         SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
   294         __android_log_write(SDL_android_priority[priority], tag, message);
   295     }
   296 #endif
   297 #if HAVE_STDIO_H
   298     fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
   299 #endif
   300 }
   301 
   302 void
   303 SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata)
   304 {
   305     if (callback) {
   306         *callback = SDL_log_function;
   307     }
   308     if (userdata) {
   309         *userdata = SDL_log_userdata;
   310     }
   311 }
   312 
   313 void
   314 SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata)
   315 {
   316     SDL_log_function = callback;
   317     SDL_log_userdata = userdata;
   318 }
   319 
   320 /* vi: set ts=4 sw=4 expandtab: */