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