1 /* Simple Plugin API 2 * 3 * Copyright © 2018 Wim Taymans 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24 25 #ifndef SPA_LOG_H 26 #define SPA_LOG_H 27 28 #ifdef __cplusplus 29 extern "C" { 30 #endif 31 32 #include <stdarg.h> 33 34 #include <spa/utils/defs.h> 35 #include <spa/utils/hook.h> 36 37 enum spa_log_level { 38 SPA_LOG_LEVEL_NONE = 0, 39 SPA_LOG_LEVEL_ERROR, 40 SPA_LOG_LEVEL_WARN, 41 SPA_LOG_LEVEL_INFO, 42 SPA_LOG_LEVEL_DEBUG, 43 SPA_LOG_LEVEL_TRACE, 44 }; 45 46 /** 47 * The Log interface 48 */ 49 #define SPA_TYPE_INTERFACE_Log SPA_TYPE_INFO_INTERFACE_BASE "Log" 50 51 #define SPA_VERSION_LOG 0 52 53 struct spa_log { 54 /** the version of this log. This can be used to expand this 55 * structure in the future */ 56 struct spa_interface iface; 57 /** 58 * Logging level, everything above this level is not logged 59 */ 60 enum spa_log_level level; 61 }; 62 63 struct spa_log_methods { 64 #define SPA_VERSION_LOG_METHODS 0 65 uint32_t version; 66 /** 67 * Log a message with the given log level. 68 * 69 * \param log a spa_log 70 * \param level a spa_log_level 71 * \param file the file name 72 * \param line the line number 73 * \param func the function name 74 * \param fmt printf style format 75 * \param ... format arguments 76 */ 77 void (*log) (void *object, 78 enum spa_log_level level, 79 const char *file, 80 int line, 81 const char *func, 82 const char *fmt, ...) SPA_PRINTF_FUNC(6, 7); 83 84 /** 85 * Log a message with the given log level. 86 * 87 * \param log a spa_log 88 * \param level a spa_log_level 89 * \param file the file name 90 * \param line the line number 91 * \param func the function name 92 * \param fmt printf style format 93 * \param args format arguments 94 */ 95 void (*logv) (void *object, 96 enum spa_log_level level, 97 const char *file, 98 int line, 99 const char *func, 100 const char *fmt, 101 va_list args) SPA_PRINTF_FUNC(6, 0); 102 }; 103 104 #define spa_log_level_enabled(l,lev) ((l) && (l)->level >= (lev)) 105 106 #if defined(__USE_ISOC11) || defined(__USE_ISOC99) || \ 107 (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) 108 109 #define spa_log_log(l,lev,...) \ 110 ({ \ 111 struct spa_log *_l = l; \ 112 if (SPA_UNLIKELY(spa_log_level_enabled(_l, lev))) \ 113 spa_interface_call(&_l->iface, \ 114 struct spa_log_methods, log, 0, lev, \ 115 __VA_ARGS__); \ 116 }) 117 118 #define spa_log_logv(l,lev,...) \ 119 ({ \ 120 struct spa_log *_l = l; \ 121 if (SPA_UNLIKELY(spa_log_level_enabled(_l, lev))) \ 122 spa_interface_call(&_l->iface, \ 123 struct spa_log_methods, logv, 0, lev, \ 124 __VA_ARGS__); \ 125 }) 126 127 #define spa_log_error(l,...) spa_log_log(l,SPA_LOG_LEVEL_ERROR,__FILE__,__LINE__,__func__,__VA_ARGS__) 128 #define spa_log_warn(l,...) spa_log_log(l,SPA_LOG_LEVEL_WARN,__FILE__,__LINE__,__func__,__VA_ARGS__) 129 #define spa_log_info(l,...) spa_log_log(l,SPA_LOG_LEVEL_INFO,__FILE__,__LINE__,__func__,__VA_ARGS__) 130 #define spa_log_debug(l,...) spa_log_log(l,SPA_LOG_LEVEL_DEBUG,__FILE__,__LINE__,__func__,__VA_ARGS__) 131 #define spa_log_trace(l,...) spa_log_log(l,SPA_LOG_LEVEL_TRACE,__FILE__,__LINE__,__func__,__VA_ARGS__) 132 133 #ifndef FASTPATH 134 #define spa_log_trace_fp(l,...) spa_log_log(l,SPA_LOG_LEVEL_TRACE,__FILE__,__LINE__,__func__,__VA_ARGS__) 135 #else 136 #define spa_log_trace_fp(l,...) 137 #endif 138 139 #else 140 141 #define SPA_LOG_FUNC(name,lev) \ 142 static inline SPA_PRINTF_FUNC(2,3) void spa_log_##name (struct spa_log *l, const char *format, ...) \ 143 { \ 144 if (SPA_UNLIKELY(spa_log_level_enabled(l, lev))) { \ 145 va_list varargs; \ 146 va_start (varargs, format); \ 147 spa_interface_call(&l->iface, \ 148 struct spa_log_methods, logv, 0, lev, \ 149 __FILE__,__LINE__,__func__,format,varargs); \ 150 va_end (varargs); \ 151 } \ 152 } 153 154 SPA_LOG_FUNC(error, SPA_LOG_LEVEL_ERROR) 155 SPA_LOG_FUNC(warn, SPA_LOG_LEVEL_WARN) 156 SPA_LOG_FUNC(info, SPA_LOG_LEVEL_INFO) 157 SPA_LOG_FUNC(debug, SPA_LOG_LEVEL_DEBUG) 158 SPA_LOG_FUNC(trace, SPA_LOG_LEVEL_TRACE) 159 160 #ifndef FASTPATH 161 SPA_LOG_FUNC(trace_fp, SPA_LOG_LEVEL_TRACE) 162 #else 163 static inline void spa_log_trace_fp (struct spa_log *l, const char *format, ...) { } 164 #endif 165 166 #endif 167 168 /** keys can be given when initializing the logger handle */ 169 #define SPA_KEY_LOG_LEVEL "log.level" /**< the default log level */ 170 #define SPA_KEY_LOG_COLORS "log.colors" /**< enable colors in the logger */ 171 #define SPA_KEY_LOG_FILE "log.file" /**< log to the specified file instead of 172 * stderr. */ 173 #define SPA_KEY_LOG_TIMESTAMP "log.timestamp" /**< log timestamps */ 174 #define SPA_KEY_LOG_LINE "log.line" /**< log file and line numbers */ 175 176 #ifdef __cplusplus 177 } /* extern "C" */ 178 #endif 179 #endif /* SPA_LOG_H */ 180