1 /* PipeWire
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 PIPEWIRE_LOG_H
26 #define PIPEWIRE_LOG_H
27 
28 #include <spa/support/log.h>
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /** \defgroup pw_log Logging
35  *
36  * \brief Logging functions of PipeWire
37  *
38  * Logging is performed to stdout and stderr. Trace logging is performed
39  * in a lockfree ringbuffer and written out from the main thread as to not
40  * block the realtime threads.
41  */
42 
43 /**
44  * \addtogroup pw_log
45  * \{
46  */
47 /** The global log level */
48 extern enum spa_log_level pw_log_level;
49 
50 extern struct spa_log_topic *PW_LOG_TOPIC_DEFAULT;
51 
52 /** Configure a logging module. This is usually done automatically
53  * in pw_init() but you can install a custom logger before calling
54  * pw_init(). */
55 void pw_log_set(struct spa_log *log);
56 
57 /** Get the log interface */
58 struct spa_log *pw_log_get(void);
59 
60 /** Configure the logging level */
61 void pw_log_set_level(enum spa_log_level level);
62 
63 /** Log a message for a topic */
64 void
65 pw_log_logt(enum spa_log_level level,
66 	    const struct spa_log_topic *topic,
67 	    const char *file,
68 	    int line, const char *func,
69 	    const char *fmt, ...) SPA_PRINTF_FUNC(6, 7);
70 
71 /** Log a message for a topic */
72 void
73 pw_log_logtv(enum spa_log_level level,
74 	     const struct spa_log_topic *topic,
75 	     const char *file,
76 	     int line, const char *func,
77 	     const char *fmt, va_list args) SPA_PRINTF_FUNC(6, 0);
78 
79 
80 
81 /** Log a message for the default topic */
82 void
83 pw_log_log(enum spa_log_level level,
84 	   const char *file,
85 	   int line, const char *func,
86 	   const char *fmt, ...) SPA_PRINTF_FUNC(5, 6);
87 
88 /** Log a message for the default topic */
89 void
90 pw_log_logv(enum spa_log_level level,
91 	    const char *file,
92 	    int line, const char *func,
93 	    const char *fmt, va_list args) SPA_PRINTF_FUNC(5, 0);
94 
95 /** Initialize the log topic. The returned topic is owned by the pipewire
96  * context and the topic must not be modified or freed.
97  * Do not use this function directly, use one of PW_LOG_TOPIC_* instead.
98  *
99  * \see PW_LOG_TOPIC_STATIC
100  * \see PW_LOG_TOPIC_EXTERN
101  * \see PW_LOG_TOPIC
102  */
103 void
104 _pw_log_topic_new(struct spa_log_topic *topic);
105 
106 /**
107  * Declare a static log topic named \a var. The usual usage is:
108  * \code
109  *  PW_LOG_TOPIC_STATIC(my_topic);
110  *  #define PW_LOG_TOPIC_DEFAULT my_topic
111  *
112  *  void foo() {
113  *      pw_log_debug("bar");
114  *  }
115  * \endcode
116  */
117 #define PW_LOG_TOPIC_STATIC(var, topic) \
118   static struct spa_log_topic var##__LINE__ = SPA_LOG_TOPIC(0, topic); \
119   static struct spa_log_topic *var = &(var##__LINE__)
120 
121 /**
122  * Declare a static log topic named \a var.
123  * See \ref PW_LOG_TOPIC_STATIC for an example usage.
124  */
125 #define PW_LOG_TOPIC_EXTERN(var) \
126   extern struct spa_log_topic *var
127 
128 /**
129  * Declare a static log topic named \a var.
130  * See \ref PW_LOG_TOPIC_STATIC for an example usage.
131  */
132 #define PW_LOG_TOPIC(var, topic) \
133   struct spa_log_topic var##__LINE__ = SPA_LOG_TOPIC(0, topic); \
134   struct spa_log_topic *var = &(var##__LINE__)
135 
136 #define PW_LOG_TOPIC_INIT(var) \
137    spa_log_topic_init(pw_log_get(), var);
138 
139 /** Check if a loglevel is enabled */
140 #define pw_log_level_enabled(lev) (pw_log_level >= (lev))
141 #define pw_log_topic_enabled(lev,t) ((t) && (t)->has_custom_level ? (t)->level >= (lev) : pw_log_level_enabled((lev)))
142 
143 
144 #define pw_logt(lev,topic,...)							\
145 ({										\
146 	if (SPA_UNLIKELY(pw_log_topic_enabled(lev,topic)))			\
147 		pw_log_logt(lev,topic,__FILE__,__LINE__,__func__,__VA_ARGS__);	\
148 })
149 
150 #define pw_log(lev,...) pw_logt(lev,PW_LOG_TOPIC_DEFAULT,__VA_ARGS__)
151 
152 #define pw_log_error(...)   pw_log(SPA_LOG_LEVEL_ERROR,__VA_ARGS__)
153 #define pw_log_warn(...)    pw_log(SPA_LOG_LEVEL_WARN,__VA_ARGS__)
154 #define pw_log_info(...)    pw_log(SPA_LOG_LEVEL_INFO,__VA_ARGS__)
155 #define pw_log_debug(...)   pw_log(SPA_LOG_LEVEL_DEBUG,__VA_ARGS__)
156 #define pw_log_trace(...)   pw_log(SPA_LOG_LEVEL_TRACE,__VA_ARGS__)
157 
158 #define pw_logt_error(t,...)   pw_logt(SPA_LOG_LEVEL_ERROR,t,__VA_ARGS__)
159 #define pw_logt_warn(t,...)    pw_logt(SPA_LOG_LEVEL_WARN,t,__VA_ARGS__)
160 #define pw_logt_info(t,...)    pw_logt(SPA_LOG_LEVEL_INFO,t,__VA_ARGS__)
161 #define pw_logt_debug(t,...)   pw_logt(SPA_LOG_LEVEL_DEBUG,t,__VA_ARGS__)
162 #define pw_logt_trace(t,...)   pw_logt(SPA_LOG_LEVEL_TRACE,t,__VA_ARGS__)
163 
164 #ifndef FASTPATH
165 #define pw_log_trace_fp(...)   pw_log(SPA_LOG_LEVEL_TRACE,__VA_ARGS__)
166 #else
167 #define pw_log_trace_fp(...)
168 #endif
169 
170 /**
171  * \}
172  */
173 
174 #ifdef __cplusplus
175 }
176 #endif
177 #endif /* PIPEWIRE_LOG_H */
178