Revert previous commit, was incorrect
[amarok.git] / src / debug.h
blob86beb9db9c2defbac05333ef768eacf0a606c87a
1 // Author: Max Howell <max.howell@methylblue.com>, (C) 2003-5
2 // Author: Mark Kretschmann <kretschmann@kde.org>, (C) 2007
3 // Copyright: See COPYING file that comes with this distribution
4 //
6 #ifndef AMAROK_DEBUG_H
7 #define AMAROK_DEBUG_H
9 // We always want debug output available at runtime
10 #undef QT_NO_DEBUG_OUTPUT
11 #undef KDE_NO_DEBUG_OUTPUT
13 #include <KGlobal>
14 #include <KConfig>
15 #include <KConfigGroup>
16 #include <kdebug.h>
17 #include <QApplication>
18 #include <QMutex>
19 #include <QObject>
21 #include <iostream>
22 #include <sys/time.h>
24 #include "amarok_export.h"
26 #ifdef _WIN32
27 #define __PRETTY_FUNCTION__ __FUNCTION__
28 #endif
30 /**
31 * @namespace Debug
32 * @short kdebug with indentation functionality and convenience macros
33 * @author Max Howell <max.howell@methylblue.com>
35 * Usage:
37 * #define DEBUG_PREFIX "Blah"
38 * #include "debug.h"
40 * void function()
41 * {
42 * Debug::Block myBlock( __PRETTY_FUNCTION__ );
44 * debug() << "output1" << endl;
45 * debug() << "output2" << endl;
46 * }
48 * Will output:
50 * app: BEGIN: void function()
51 * app: [Blah] output1
52 * app: [Blah] output2
53 * app: END: void function(): Took 0.1s
55 * @see Block
56 * @see CrashHelper
57 * @see ListStream
60 namespace Debug
62 extern AMAROK_EXPORT QMutex mutex; // defined in app.cpp
64 // we can't use a statically instantiated QCString for the indent, because
65 // static namespaces are unique to each dlopened library. So we piggy back
66 // the QCString on the KApplication instance
68 #define qOApp reinterpret_cast<QObject*>(qApp)
69 class Indent : QObject
71 friend QString &modifieableIndent();
72 Indent() : QObject( qOApp ) { setObjectName( "DEBUG_indent" ); }
73 QString m_string;
76 inline QString &modifieableIndent()
78 QObject* o = qOApp ? qOApp->findChild<QObject*>( "DEBUG_indent" ) : 0;
79 QString &ret = (o ? static_cast<Indent*>( o ) : new Indent)->m_string;
80 return ret;
83 inline QString indent()
85 return modifieableIndent();
88 inline bool debugEnabled()
90 KConfigGroup config = KGlobal::config()->group( "General" );
91 const bool debug = config.readEntry( "Debug Enabled", false );
93 return debug;
96 inline kdbgstream dbgstream()
98 return debugEnabled() ? kdbgstream( QtDebugMsg ) : kDebugDevNull();
101 #undef qApp
103 #ifndef DEBUG_PREFIX
104 #define AMK_PREFIX ""
105 #else
106 #define AMK_PREFIX "[" DEBUG_PREFIX "]"
107 #endif
109 //from kdebug.h
110 enum DebugLevels {
111 KDEBUG_INFO = 0,
112 KDEBUG_WARN = 1,
113 KDEBUG_ERROR = 2,
114 KDEBUG_FATAL = 3
118 static inline kdbgstream debug() { mutex.lock(); QString ind = indent(); mutex.unlock(); return dbgstream() << qPrintable( ind + AMK_PREFIX ); }
119 static inline kdbgstream warning() { mutex.lock(); QString ind = indent(); mutex.unlock(); return dbgstream() << qPrintable( ind + AMK_PREFIX + " [WARNING!]" ); }
120 static inline kdbgstream error() { mutex.lock(); QString ind = indent(); mutex.unlock(); return dbgstream() << qPrintable( ind + AMK_PREFIX + " [ERROR!]" ); }
121 static inline kdbgstream fatal() { mutex.lock(); QString ind = indent(); mutex.unlock(); return dbgstream() << qPrintable( ind + AMK_PREFIX ); }
123 typedef kdbgstream DebugStream;
125 #undef AMK_PREFIX
127 typedef kndbgstream NoDebugStream;
130 using Debug::debug;
131 using Debug::warning;
132 using Debug::error;
133 using Debug::fatal;
134 using Debug::DebugStream;
136 /// Standard function announcer
137 #define DEBUG_FUNC_INFO { Debug::mutex.lock(); kDebug() << Debug::indent() ; Debug::mutex.unlock(); }
139 /// Announce a line
140 #define DEBUG_LINE_INFO { Debug::mutex.lock(); kDebug() << Debug::indent() << "Line: " << __LINE__; Debug::mutex.unlock(); }
142 /// Convenience macro for making a standard Debug::Block
143 #define DEBUG_BLOCK Debug::Block uniquelyNamedStackAllocatedStandardBlock( __PRETTY_FUNCTION__ );
145 /// Use this to remind yourself to finish the implementation of a function
146 #define AMAROK_NOTIMPLEMENTED warning() << "NOT-IMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
148 /// Use this to alert other developers to stop using a function
149 #define AMAROK_DEPRECATED warning() << "DEPRECATED: " << __PRETTY_FUNCTION__ << endl;
152 namespace Debug
155 * @class Debug::Block
156 * @short Use this to label sections of your code
158 * Usage:
160 * void function()
162 * Debug::Block myBlock( "section" );
164 * debug() << "output1" << endl;
165 * debug() << "output2" << endl;
168 * Will output:
170 * app: BEGIN: section
171 * app: [prefix] output1
172 * app: [prefix] output2
173 * app: END: section - Took 0.1s
177 class Block
179 timeval m_start;
180 const char *m_label;
182 public:
183 Block( const char *label )
184 : m_label( label )
186 if( !debugEnabled() ) return;
188 mutex.lock();
189 gettimeofday( &m_start, 0 );
191 kDebug() << "BEGIN:" << label;
192 Debug::modifieableIndent() += " ";
193 mutex.unlock();
196 ~Block()
198 if( !debugEnabled() ) return;
200 mutex.lock();
201 timeval end;
202 gettimeofday( &end, 0 );
204 end.tv_sec -= m_start.tv_sec;
205 if( end.tv_usec < m_start.tv_usec) {
206 // Manually carry a one from the seconds field.
207 end.tv_usec += 1000000;
208 end.tv_sec--;
210 end.tv_usec -= m_start.tv_usec;
212 double duration = double(end.tv_sec) + (double(end.tv_usec) / 1000000.0);
214 Debug::modifieableIndent().truncate( Debug::indent().length() - 2 );
215 kDebug() << "END__:" << m_label
216 << "- Took" << qPrintable( QString::number( duration, 'g', 2 ) + "s" );
217 mutex.unlock();
223 * @name Debug::stamp()
224 * @short To facilitate crash/freeze bugs, by making it easy to mark code that has been processed
226 * Usage:
229 * Debug::stamp();
230 * function1();
231 * Debug::stamp();
232 * function2();
233 * Debug::stamp();
236 * Will output (assuming the crash occurs in function2()
238 * app: Stamp: 1
239 * app: Stamp: 2
243 inline void stamp()
245 static int n = 0;
246 debug() << "| Stamp: " << ++n << endl;
251 #include <QVariant>
253 namespace Debug
256 * @class Debug::List
257 * @short You can pass anything to this and it will output it as a list
259 * debug() << (Debug::List() << anInt << aString << aQStringList << aDouble) << endl;
262 typedef QList<QVariant> List;
265 #endif