1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #ifndef _RADIOLOGGER_H_ |
|
19 #define _RADIOLOGGER_H_ |
|
20 |
|
21 // System includes |
|
22 #include <QObject> |
|
23 |
|
24 /** |
|
25 * Logging level macro definitions |
|
26 * Level 1 - No level macro needed. The trace is shown when logging is on. |
|
27 * Level 2 - Wrap log line with LEVEL2 macro. Traces of level 1 and 2 are shown. |
|
28 * Level 3 - Wrap log line with LEVEL3 macro. Traces of level 1, 2 and 3 are shown. |
|
29 */ |
|
30 #if LOGGING_LEVEL == 2 |
|
31 # define LEVEL2( expr ) expr |
|
32 # define LEVEL3( expr ) |
|
33 #elif LOGGING_LEVEL == 3 |
|
34 # define LEVEL2( expr ) expr |
|
35 # define LEVEL3( expr ) expr |
|
36 #else |
|
37 # define LEVEL2( expr ) |
|
38 # define LEVEL3( expr ) |
|
39 #endif |
|
40 |
|
41 #if LOGGED_COMPONENT == 2 |
|
42 # define LOGMARKER "FMRadioHsWidget:" |
|
43 # define WRAPPER_DLL_EXPORT |
|
44 #else |
|
45 # define LOGMARKER "FMRadio:" |
|
46 # ifdef BUILD_WRAPPER_DLL |
|
47 # define WRAPPER_DLL_EXPORT Q_DECL_EXPORT |
|
48 # else |
|
49 # define WRAPPER_DLL_EXPORT Q_DECL_IMPORT |
|
50 # endif |
|
51 #endif |
|
52 |
|
53 class WRAPPER_DLL_EXPORT RadioLogger |
|
54 { |
|
55 public: |
|
56 |
|
57 enum Mode { Normal, MethodEnter, MethodExit, DecIndent }; |
|
58 |
|
59 static void initCombinedLogger(); |
|
60 static void releaseCombinedLogger(); |
|
61 |
|
62 static void logMsg( const char* msg, Mode mode = Normal ); |
|
63 |
|
64 private: |
|
65 RadioLogger(); |
|
66 ~RadioLogger(); |
|
67 }; |
|
68 |
|
69 // ============================================================================ |
|
70 // START TIMESTAMP LOGGING |
|
71 // ============================================================================ |
|
72 |
|
73 #ifdef TIMESTAMP_LOGGING_ENABLED |
|
74 |
|
75 #include <QTime> |
|
76 #include <QDebug> |
|
77 |
|
78 /** |
|
79 * Timestamp logging macro. |
|
80 * When the macro is defined, timestamp logging is on |
|
81 * |
|
82 * Example. These lines in the code... |
|
83 * LOG_TIMESTAMP( "Start operation" ); |
|
84 * ... |
|
85 * LOG_TIMESTAMP( "End operation" ); |
|
86 * |
|
87 * ... print the following log lines |
|
88 * FMRadio: Start operation "14:13:09.042" |
|
89 * FMRadio: End operation "14:13:09.250" |
|
90 */ |
|
91 //#define LOG_TIMESTAMP(comment) do{ qDebug() << LOGMARKER << comment << QTime::currentTime().toString("hh:mm:ss.zzz"); }while(0) |
|
92 #define LOG_TIMESTAMP(comment) LOG_FORMAT( comment ## " %s", GETSTRING( QTime::currentTime().toString("hh:mm:ss.zzz") ) ) |
|
93 |
|
94 #else |
|
95 |
|
96 #define LOG_TIMESTAMP(comment) |
|
97 |
|
98 #endif // TIMESTAMP_LOGGING_ENABLED |
|
99 |
|
100 // ============================================================================ |
|
101 // END TIMESTAMP LOGGING |
|
102 // ============================================================================ |
|
103 |
|
104 // ============================================================================ |
|
105 // START FULL LOGGING |
|
106 // ============================================================================ |
|
107 |
|
108 #ifdef LOGGING_ENABLED |
|
109 |
|
110 #include <QtGlobal> |
|
111 #include <QDebug> |
|
112 |
|
113 // Macro to hide a function variable that is used only when debugging is enabled. |
|
114 // Expands to the variable name when debugging is enabled and to nothing when it is not |
|
115 #if LOGGING_LEVEL == 2 |
|
116 # define DEBUGVAR( var ) var |
|
117 # define DEBUGVAR2( var ) var |
|
118 # define DEBUGVAR3( var ) |
|
119 #elif LOGGING_LEVEL == 3 |
|
120 # define DEBUGVAR( var ) var |
|
121 # define DEBUGVAR2( var ) var |
|
122 # define DEBUGVAR3( var ) var |
|
123 #else |
|
124 # define DEBUGVAR( var ) var |
|
125 # define DEBUGVAR2( var ) |
|
126 # define DEBUGVAR3( var ) |
|
127 #endif |
|
128 |
|
129 // UI logs can be combined with engine logs by making the UI feed its log prints into |
|
130 // the engine logger. This requires that we initialize the radio engine utils right here |
|
131 // because the engine won't start up until much later. This is a bit ugly since the macros |
|
132 // call Symbian code directly, but it was considered to be worth it to see UI and engine |
|
133 // traces in the same file. |
|
134 #if defined COMBINE_WITH_ENGINE_LOGGER && defined LOGGING_ENABLED && !defined BUILD_WIN32 |
|
135 # include "../../../radioengine/utils/api/mradioenginelogger.h" |
|
136 # include "../../../radioengine/utils/api/radioengineutils.h" |
|
137 # define WRITELOG(msg) RadioLogger::logMsg( msg ); |
|
138 # define WRITELOG_METHOD_ENTER(msg) RadioLogger::logMsg( GETSTRING( msg ), RadioLogger::MethodEnter ); |
|
139 # define WRITELOG_METHOD_EXIT(msg) RadioLogger::logMsg( GETSTRING( msg ), RadioLogger::MethodExit ); |
|
140 # define LOGGER_DEC_INDENT RadioLogger::logMsg( "", RadioLogger::DecIndent ); |
|
141 # define WRITELOG_GETSTRING(msg) WRITELOG( GETSTRING( msg ) ) |
|
142 # define INIT_COMBINED_LOGGER RadioLogger::initCombinedLogger(); |
|
143 # define RELEASE_COMBINED_LOGGER RadioLogger::releaseCombinedLogger(); |
|
144 #else |
|
145 # define WRITELOG(msg) qDebug() << LOGMARKER << msg; |
|
146 # define WRITELOG_METHOD_ENTER(msg) WRITELOG(msg) |
|
147 # define WRITELOG_METHOD_EXIT(msg) WRITELOG(msg) |
|
148 # define WRITELOG_GETSTRING(msg) WRITELOG(msg) |
|
149 # define LOGGER_INC_INDENT |
|
150 # define LOGGER_DEC_INDENT |
|
151 # define INIT_COMBINED_LOGGER |
|
152 # define RELEASE_COMBINED_LOGGER |
|
153 #endif |
|
154 |
|
155 // Macro that simply logs a string |
|
156 // Example: |
|
157 // LOG( "This is a test" ); |
|
158 #define LOG(string) do{ WRITELOG( string ) }while(0) |
|
159 |
|
160 // Helper macro to get a const char* out of a QString so that it can be logged. Can be used with LOG_FORMAT() |
|
161 #define GETSTRING(qstring) qstring.toAscii().constData() |
|
162 |
|
163 // Macro that logs a string with multiple parameters |
|
164 // Examples: |
|
165 // LOG_FORMAT( "This is an integer %d, and this is a float with two digits %.2f", 42, 3.14 ); |
|
166 // LOG_FORMAT( "This is a QString %s", GETSTRING(someQString) ); |
|
167 #define LOG_FORMAT(fmt,args...) do{ QString tmp; WRITELOG_GETSTRING( tmp.sprintf(fmt,args) ) }while(0) |
|
168 |
|
169 // Macro that logs function enter, exit and exception |
|
170 // Example (Simply put it in the beginning of a function): |
|
171 // LOG_METHOD; |
|
172 // Output: |
|
173 // -> SomeFunction(int,const char*) |
|
174 // <- SomeFunction(int,const char*) |
|
175 // <- SomeFunction(int,const char*): Exception raised! |
|
176 #define LOG_METHOD MethodLogger ___methodLogger( __PRETTY_FUNCTION__, "" ) |
|
177 |
|
178 // Same as the previous function logging macro with the addition of logging the return value |
|
179 // Note! The return value can only be retrieved in the emulator. |
|
180 // Example (Simply put it in the beginning of a function): |
|
181 // LOG_METHOD_RET( "%d" ); |
|
182 // Output: |
|
183 // -> SomeFunction(int,const char*) |
|
184 // <- SomeFunction(int,const char*) returning 42 |
|
185 #define LOG_METHOD_RET(fmt) MethodLogger ___methodLogger( __PRETTY_FUNCTION__, fmt ) |
|
186 |
|
187 // Logs function enter but does not log exit or leave. This is meant to be lighter than LOG_METHOD macro |
|
188 #define LOG_METHOD_ENTER LOG_FORMAT( "Enter: %s", __PRETTY_FUNCTION__ ) |
|
189 |
|
190 // Assert macro for logging. If the condition is false, the expression is performed |
|
191 // Example: |
|
192 // LOG_ASSERT( thisMustBeTrue, LOG_FORMAT( "OMG! That was not true: %d", thisMustBeTrue ) ); |
|
193 #define LOG_ASSERT(cond,expr) do{ if (!cond) { expr; } }while(0) |
|
194 |
|
195 // Macro to log slot function caller by its class name. |
|
196 #define LOG_SLOT_CALLER do { \ |
|
197 QObject* caller = sender(); \ |
|
198 if ( caller ) { \ |
|
199 LOG_FORMAT( "SLOT %s called by %s. Objectname: %s", __PRETTY_FUNCTION__, \ |
|
200 caller->metaObject()->className(), GETSTRING( caller->objectName() ) ); \ |
|
201 } else { \ |
|
202 LOG_FORMAT( "SLOT %s called as regular function. ", __PRETTY_FUNCTION__ ); \ |
|
203 } \ |
|
204 } while (0) |
|
205 |
|
206 // Class declaration |
|
207 class WRAPPER_DLL_EXPORT MethodLogger |
|
208 { |
|
209 public: |
|
210 |
|
211 MethodLogger( const char* function, const char* format ); |
|
212 ~MethodLogger(); |
|
213 |
|
214 private: |
|
215 |
|
216 const char* mFunction; |
|
217 const char* mFormat; |
|
218 |
|
219 }; |
|
220 |
|
221 #else // LOGGING_ENABLED |
|
222 |
|
223 # define LOG(string) |
|
224 # define GETSTRING(qstring) |
|
225 # define LOG_FORMAT(fmt,args...) |
|
226 # define LOG_METHOD |
|
227 # define LOG_METHOD_RET(fmt) |
|
228 # define LOG_METHOD_ENTER |
|
229 # define LOG_ASSERT(cond,expr) |
|
230 # define DEBUGVAR(a) |
|
231 # define DEBUGVAR2(a) |
|
232 # define DEBUGVAR3(a) |
|
233 # define LOG_SLOT_CALLER |
|
234 # define INIT_COMBINED_LOGGER |
|
235 # define RELEASE_COMBINED_LOGGER |
|
236 |
|
237 |
|
238 // Dummy class |
|
239 class WRAPPER_DLL_EXPORT MethodLogger |
|
240 { |
|
241 public: |
|
242 MethodLogger( const char*, const char* ); |
|
243 ~MethodLogger(); |
|
244 }; |
|
245 |
|
246 #endif // LOGGING_ENABLED |
|
247 |
|
248 #ifdef TRACE_TO_FILE |
|
249 |
|
250 # define INSTALL_MESSAGE_HANDLER FileLogger::installMessageHandler(QString(TRACE_OUTPUT_FILE), FILTER_BY_LOGMARKER); |
|
251 # define UNINSTALL_MESSAGE_HANDLER FileLogger::uninstallMessageHandler(); |
|
252 |
|
253 // Class declaration |
|
254 class WRAPPER_DLL_EXPORT FileLogger |
|
255 { |
|
256 public: |
|
257 |
|
258 static void installMessageHandler( const QString& fileName, bool filterByMarker = true ); |
|
259 static void uninstallMessageHandler(); |
|
260 |
|
261 private: |
|
262 |
|
263 static void handleMessage( QtMsgType type, const char* msg ); |
|
264 |
|
265 }; |
|
266 |
|
267 #else |
|
268 # define INSTALL_MESSAGE_HANDLER |
|
269 # define UNINSTALL_MESSAGE_HANDLER |
|
270 #endif // TRACE_TO_FILE |
|
271 |
|
272 // ============================================================================ |
|
273 // END FULL LOGGING |
|
274 // ============================================================================ |
|
275 |
|
276 class Radio |
|
277 { |
|
278 Radio(); |
|
279 ~Radio(); |
|
280 public: |
|
281 |
|
282 // ============================================================================ |
|
283 // SIGNAL/SLOT CONNECT CHECKER |
|
284 // ============================================================================ |
|
285 static bool connect( const QObject* sender, const char* signal, |
|
286 const QObject* receiver, const char* member, |
|
287 Qt::ConnectionType type = Qt::AutoConnection ) |
|
288 { |
|
289 bool connected = QObject::connect( sender, signal, receiver, member, type ); |
|
290 |
|
291 #ifdef CONNECT_TEST_MODE |
|
292 |
|
293 if ( !connected ) { |
|
294 LOG( "Failed to make a signal-slot connection!" ); |
|
295 LOG_FORMAT( "sender: %s", sender->metaObject()->className() ); |
|
296 LOG_FORMAT( "signal: %s", signal ); |
|
297 LOG_FORMAT( "receiver: %s", receiver->metaObject()->className() ); |
|
298 LOG_FORMAT( "slot/signal: %s", signal ); |
|
299 |
|
300 #if CONNECT_TEST_MODE == 2 |
|
301 Q_ASSERT( false ); |
|
302 #endif |
|
303 |
|
304 // ---------------------------------------------------------------- |
|
305 // SIGNAL-SLOT CONNECT FAILED! |
|
306 // ---------------------------------------------------------------- |
|
307 } |
|
308 |
|
309 #endif |
|
310 |
|
311 return connected; |
|
312 } |
|
313 |
|
314 // ============================================================================ |
|
315 // SIGNAL/SLOT DISCONNECT CHECKER |
|
316 // ============================================================================ |
|
317 static bool disconnect( const QObject* sender, const char* signal, |
|
318 const QObject* receiver, const char* member ) |
|
319 { |
|
320 bool disconnected = QObject::disconnect( sender, signal, receiver, member ); |
|
321 |
|
322 #ifdef CONNECT_TEST_MODE |
|
323 |
|
324 if ( !disconnected ) { |
|
325 LOG( "Failed to disconnect a signal-slot connection!" ); |
|
326 LOG_FORMAT( "sender: %s", sender->metaObject()->className() ); |
|
327 LOG_FORMAT( "signal: %s", signal ); |
|
328 LOG_FORMAT( "receiver: %s", receiver->metaObject()->className() ); |
|
329 LOG_FORMAT( "slot/signal: %s", signal ); |
|
330 |
|
331 #if CONNECT_TEST_MODE == 2 |
|
332 Q_ASSERT( false ); |
|
333 #endif |
|
334 |
|
335 // ---------------------------------------------------------------- |
|
336 // SIGNAL-SLOT DISCONNECT FAILED! |
|
337 // ---------------------------------------------------------------- |
|
338 } |
|
339 |
|
340 #endif |
|
341 |
|
342 return disconnected; |
|
343 } |
|
344 }; |
|
345 |
|
346 #ifdef ENABLE_ASSERTS |
|
347 |
|
348 #define RADIO_ASSERT(cond,where,what) Q_ASSERT_X(cond,where,what) |
|
349 |
|
350 #else |
|
351 # ifdef LOGGING_ENABLED |
|
352 # define RADIO_ASSERT(cond,where,what) \ |
|
353 do { \ |
|
354 if ( !cond ) { \ |
|
355 LOG_FORMAT( "ASSERT Failed! %s, %s", where, what ); \ |
|
356 } \ |
|
357 } while ( false ) |
|
358 # else |
|
359 # define RADIO_ASSERT(cond,where,what) |
|
360 # endif // LOGGING_ENABLED |
|
361 #endif // ENABLE_ASSERTS |
|
362 |
|
363 #endif // _RADIOLOGGER_H_ |
|