File indexing completed on 2024-05-05 04:48:19
0001 /* 0002 Copyright (c) 2003-2005 Max Howell <max.howell@methylblue.com> 0003 Copyright (c) 2007-2009 Mark Kretschmann <kretschmann@kde.org> 0004 Copyright (c) 2010-2011 Kevin Funk <krf@electrostorm.net> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Lesser General Public 0008 License as published by the Free Software Foundation; either 0009 version 2.1 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Lesser General Public License for more details. 0015 0016 You should have received a copy of the GNU Lesser General Public 0017 License along with this library. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #ifndef AMAROK_DEBUG_H 0021 #define AMAROK_DEBUG_H 0022 0023 // We always want debug output available at runtime 0024 #undef QT_NO_DEBUG_OUTPUT 0025 #undef KDE_NO_DEBUG_OUTPUT 0026 0027 #include "core/amarokcore_export.h" 0028 #include <QDebug> 0029 #include <QMutex> 0030 #include <QVariant> 0031 0032 // BEGIN: DEBUG_ASSERT 0033 /** 0034 * Debug helper to write "soft" assertions with escape statements more easily 0035 * If the assertions fails, a warning is printed containing the position 0036 * (file and line number) of the assert and the second parameter is evaluated. 0037 * 0038 * Usage: DEBUG_ASSERT(assertion, statement) 0039 * 0040 * (pseudo code *without* DEBUG_ASSERT) 0041 * \code 0042 * bool someMethod(T* pointer) { 0043 * if (!pointer) 0044 * qWarning() << "Warning pointer is null, aborting"; 0045 * return false; 0046 * (...) 0047 * return someBoolean; 0048 * } 0049 * \endcode 0050 * 0051 * (may be replaced by) 0052 * \code 0053 * bool someMethod(T* pointer) { 0054 * DEBUG_ASSERT(pointer, return false) 0055 * (...) 0056 * return someBoolean; 0057 * } 0058 * \endcode 0059 * 0060 * \author Kevin Funk 0061 * \sa http://qt.gitorious.org/qt-creator/qt-creator/blobs/master/src/libs/utils/qtcassert.h 0062 */ 0063 #define DEBUG_ASSERT(cond, action) \ 0064 if(cond){}else{warning()<< \ 0065 "ASSERTION " #cond " FAILED AT " __FILE__ ":" DEBUG_ASSERT_STRINGIFY(__LINE__);action;} 0066 0067 #define DEBUG_ASSERT_STRINGIFY_INTERNAL(x) #x 0068 #define DEBUG_ASSERT_STRINGIFY(x) DEBUG_ASSERT_STRINGIFY_INTERNAL(x) 0069 // END__: DEBUG_ASSERT 0070 0071 # include <QElapsedTimer> 0072 0073 // Platform specific macros 0074 #ifdef _WIN32 0075 #define __PRETTY_FUNCTION__ __FUNCTION__ 0076 #endif 0077 #ifdef __SUNPRO_CC 0078 #define __PRETTY_FUNCTION__ __FILE__ 0079 #endif 0080 0081 // Debug prefix, override if needed 0082 #ifndef DEBUG_PREFIX 0083 #define AMAROK_PREFIX "" 0084 #else 0085 #define AMAROK_PREFIX "[" DEBUG_PREFIX "]" 0086 #endif 0087 0088 /** 0089 * @namespace Debug 0090 * @short kdebug with indentation functionality and convenience macros 0091 * @author Max Howell <max.howell@methylblue.com> 0092 * 0093 * Usage: 0094 * 0095 * #define DEBUG_PREFIX "Blah" 0096 * #include "debug.h" 0097 * 0098 * void function() 0099 * { 0100 * Debug::Block myBlock( __PRETTY_FUNCTION__ ); 0101 * 0102 * debug() << "output1" << Qt::endl; 0103 * debug() << "output2" << Qt::endl; 0104 * } 0105 * 0106 * Will output: 0107 * 0108 * app: BEGIN: void function() 0109 * app: [Blah] output1 0110 * app: [Blah] output2 0111 * app: END: void function(): Took 0.1s 0112 * 0113 * @see Block 0114 * @see CrashHelper 0115 * @see ListStream 0116 */ 0117 namespace Debug 0118 { 0119 extern AMAROKCORE_EXPORT QMutex mutex; 0120 0121 // from kdebug.h 0122 enum DebugLevel { 0123 KDEBUG_INFO = 0, 0124 KDEBUG_WARN = 1, 0125 KDEBUG_ERROR = 2, 0126 KDEBUG_FATAL = 3 0127 }; 0128 0129 AMAROKCORE_EXPORT QDebug dbgstream( DebugLevel level = KDEBUG_INFO ); 0130 AMAROKCORE_EXPORT bool debugEnabled(); 0131 AMAROKCORE_EXPORT bool debugColorEnabled(); 0132 AMAROKCORE_EXPORT void setDebugEnabled( bool enable ); 0133 AMAROKCORE_EXPORT void setColoredDebug( bool enable ); 0134 AMAROKCORE_EXPORT QString indent(); 0135 0136 static inline QDebug dbgstreamwrapper( DebugLevel level ) { 0137 #ifdef DEBUG_PREFIX 0138 return dbgstream( level ) << AMAROK_PREFIX; 0139 #else 0140 return dbgstream( level ); 0141 #endif 0142 } 0143 0144 static inline QDebug debug() { return dbgstreamwrapper( KDEBUG_INFO ); } 0145 static inline QDebug warning() { return dbgstreamwrapper( KDEBUG_WARN ); } 0146 static inline QDebug error() { return dbgstreamwrapper( KDEBUG_ERROR ); } 0147 static inline QDebug fatal() { return dbgstreamwrapper( KDEBUG_FATAL ); } 0148 0149 AMAROKCORE_EXPORT void perfLog( const QString &message, const QString &func ); 0150 } 0151 0152 using Debug::debug; 0153 using Debug::warning; 0154 using Debug::error; 0155 using Debug::fatal; 0156 0157 /// Standard function announcer 0158 #define DEBUG_FUNC_INFO { Debug::mutex.lock(); qDebug() << Debug::indent() ; Debug::mutex.unlock(); } 0159 0160 /// Announce a line 0161 #define DEBUG_LINE_INFO { Debug::mutex.lock(); qDebug() << Debug::indent() << "Line: " << __LINE__; Debug::mutex.unlock(); } 0162 0163 /// Convenience macro for making a standard Debug::Block 0164 #define DEBUG_BLOCK Debug::Block uniquelyNamedStackAllocatedStandardBlock( __PRETTY_FUNCTION__ ); 0165 0166 /// Use this to remind yourself to finish the implementation of a function 0167 #define AMAROK_NOTIMPLEMENTED warning() << "NOT-IMPLEMENTED:" << __PRETTY_FUNCTION__ << Qt::endl; 0168 0169 /// Use this to alert other developers to stop using a function 0170 #define AMAROK_DEPRECATED warning() << "DEPRECATED:" << __PRETTY_FUNCTION__ << Qt::endl; 0171 0172 /// Performance logging 0173 #define PERF_LOG( msg ) { Debug::perfLog( msg, __PRETTY_FUNCTION__ ); } 0174 0175 class BlockPrivate; 0176 0177 namespace Debug 0178 { 0179 /** 0180 * @class Debug::Block 0181 * @short Use this to label sections of your code 0182 * 0183 * Usage: 0184 * 0185 * void function() 0186 * { 0187 * Debug::Block myBlock( "section" ); 0188 * 0189 * debug() << "output1" << Qt::endl; 0190 * debug() << "output2" << Qt::endl; 0191 * } 0192 * 0193 * Will output: 0194 * 0195 * app: BEGIN: section 0196 * app: [prefix] output1 0197 * app: [prefix] output2 0198 * app: END: section - Took 0.1s 0199 * 0200 */ 0201 class Block 0202 { 0203 public: 0204 AMAROKCORE_EXPORT explicit Block( const char *name ); 0205 AMAROKCORE_EXPORT ~Block(); 0206 0207 private: 0208 QElapsedTimer m_startTime; 0209 0210 const char *m_label; 0211 int m_color; 0212 }; 0213 0214 /** 0215 * @name Debug::stamp() 0216 * @short To facilitate crash/freeze bugs, by making it easy to mark code that has been processed 0217 * 0218 * Usage: 0219 * 0220 * { 0221 * Debug::stamp(); 0222 * function1(); 0223 * Debug::stamp(); 0224 * function2(); 0225 * Debug::stamp(); 0226 * } 0227 * 0228 * Will output (assuming the crash occurs in function2() 0229 * 0230 * app: Stamp: 1 0231 * app: Stamp: 2 0232 * 0233 */ 0234 AMAROKCORE_EXPORT void stamp(); 0235 0236 /** 0237 * @class Debug::List 0238 * @short You can pass anything to this and it will output it as a list 0239 * 0240 * debug() << (Debug::List() << anInt << aString << aQStringList << aDouble) << Qt::endl; 0241 */ 0242 0243 typedef QList<QVariant> List; 0244 } 0245 0246 template<class T> class AmarokSharedPointer; 0247 0248 template<class T> QDebug & 0249 operator<<( QDebug dbg, const AmarokSharedPointer<T> &ptr ) 0250 { 0251 dbg.nospace() << "AmarokSharedPointer(" << *ptr.data() << ")"; 0252 return dbg.space(); 0253 } 0254 0255 #endif