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