1/*
2 Copyright (c) 2003-2005 Max Howell <max.howell@methylblue.com>
3 Copyright (c) 2007-2009 Mark Kretschmann <kretschmann@kde.org>
4 Copyright (c) 2010 Kevin Funk <krf@electrostorm.net>
5 Copyright (c) 2011 Harald Sitter <sitter@kde.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "debug.h"
22#include "debug_p.h"
23
24#include <QtCore/QMutex>
25#include <QtCore/QObject>
26#include <QApplication>
27
28#ifdef Q_OS_UNIX
29# include <unistd.h>
30#endif
31
32// Define Application wide prefix
33#ifndef APP_PREFIX
34#define APP_PREFIX QLatin1String( "PHONON-VLC" )
35#endif
36
37#define DEBUG_INDENT_OBJECTNAME QLatin1String("Debug_Indent_object")
38
39QRecursiveMutex Debug::mutex;
40
41using namespace Debug;
42
43static bool s_debugColorsEnabled = true;
44static DebugLevel s_debugLevel = DEBUG_NONE;
45
46IndentPrivate::IndentPrivate(QObject* parent)
47 : QObject(parent)
48{
49 setObjectName( DEBUG_INDENT_OBJECTNAME );
50}
51
52/**
53 * We can't use a statically instantiated QString for the indent, because
54 * static namespaces are unique to each dlopened library. So we piggy back
55 * the QString on the KApplication instance
56 */
57IndentPrivate* IndentPrivate::instance()
58{
59 QObject* qOApp = reinterpret_cast<QObject*>(qApp);
60 QObject* obj = qOApp ? qOApp->findChild<QObject*>( DEBUG_INDENT_OBJECTNAME ) : 0;
61 return (obj ? static_cast<IndentPrivate*>( obj ) : new IndentPrivate( qApp ));
62}
63
64/*
65 Text color codes (use last digit here)
66 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
67*/
68static int s_colors[] = { 1, 2, 4, 5, 6 }; // no yellow and white for sanity
69static int s_colorIndex = 0;
70
71static QString toString( DebugLevel level )
72{
73 switch( level )
74 {
75 case DEBUG_WARN:
76 return "[WARNING]";
77 case DEBUG_ERROR:
78 return "[ERROR__]";
79 case DEBUG_FATAL:
80 return "[FATAL__]";
81 default:
82 return QString();
83 }
84}
85
86static int toColor( DebugLevel level )
87{
88 switch( level ) {
89 case DEBUG_WARN:
90 return 3; // red
91 case DEBUG_ERROR:
92 case DEBUG_FATAL:
93 return 1; // yellow
94 default:
95 return 0; // default: black
96 }
97}
98
99static QString colorize( const QString &text, int color = s_colorIndex )
100{
101 if( !debugColorEnabled() )
102 return text;
103
104 return QString( "\x1b[00;3%1m%2\x1b[00;39m" ).arg( args: QString::number(s_colors[color]), args: text );
105}
106
107static QString reverseColorize( const QString &text, int color )
108{
109 if( !debugColorEnabled() )
110 return text;
111
112 return QString( "\x1b[07;3%1m%2\x1b[00;39m" ).arg( args: QString::number(color), args: text );
113}
114
115QString Debug::indent()
116{
117 return IndentPrivate::instance()->m_string;
118}
119
120bool Debug::debugEnabled()
121{
122 return s_debugLevel < DEBUG_NONE;
123}
124
125bool Debug::debugColorEnabled()
126{
127 return s_debugColorsEnabled;
128}
129
130DebugLevel Debug::minimumDebugLevel()
131{
132 return s_debugLevel;
133}
134
135void Debug::setColoredDebug( bool enable )
136{
137 s_debugColorsEnabled = enable;
138}
139
140void Debug::setMinimumDebugLevel(DebugLevel level)
141{
142 s_debugLevel = level;
143}
144
145QDebug Debug::dbgstream( DebugLevel level )
146{
147 if ( level < s_debugLevel )
148 return nullDebug();
149
150 mutex.lock();
151 const QString currentIndent = indent();
152 mutex.unlock();
153
154 QString text = QString("%1%2").arg( APP_PREFIX ).arg( a: currentIndent );
155 if ( level > DEBUG_INFO )
156 text.append( s: ' ' + reverseColorize( text: toString(level), color: toColor( level ) ) );
157
158 return QDebug( QtDebugMsg ) << qPrintable( text );
159}
160
161void Debug::perfLog( const QString &message, const QString &func )
162{
163#ifdef Q_OS_UNIX
164 if( !debugEnabled() )
165 return;
166
167 QString str = QString( "MARK: %1: %2 %3" ).arg( qApp->applicationName(), args: func, args: message );
168 access( name: str.toLocal8Bit().data(), F_OK );
169#endif
170}
171
172Block::Block( const char *label )
173 : m_label( label )
174 , m_color( s_colorIndex )
175{
176 if( !debugEnabled() || DEBUG_INFO < s_debugLevel)
177 return;
178
179#if QT_VERSION >= 0x040700
180 m_startTime.start();
181#else
182 m_startTime = QTime::currentTime();
183#endif
184
185 mutex.lock();
186 s_colorIndex = (s_colorIndex + 1) % 5;
187 dbgstream()
188 << qPrintable( colorize( QLatin1String( "BEGIN:" ), m_color ) )
189 << m_label;
190 IndentPrivate::instance()->m_string += QLatin1String(" ");
191 mutex.unlock();
192}
193
194Block::~Block()
195{
196 if( !debugEnabled() || DEBUG_INFO < s_debugLevel)
197 return;
198
199#if QT_VERSION >= 0x040700
200 const double duration = m_startTime.elapsed() / 1000.0;
201#else
202 const double duration = (double)m_startTime.msecsTo( QTime::currentTime() ) / 1000.0;
203#endif
204
205 mutex.lock();
206 IndentPrivate::instance()->m_string.truncate( pos: Debug::indent().length() - 2 );
207 mutex.unlock();
208
209 // Print timing information, and a special message (DELAY) if the method took longer than 5s
210 if( duration < 5.0 )
211 {
212 dbgstream()
213 << qPrintable( colorize( QLatin1String( "END__:" ), m_color ) )
214 << m_label
215 << qPrintable( colorize( QString( "[Took: %3s]")
216 .arg( QString::number(duration, 'g', 2) ), m_color ) );
217 }
218 else
219 {
220 dbgstream()
221 << qPrintable( colorize( QString( "END__:" ), m_color ) )
222 << m_label
223 << qPrintable( reverseColorize( QString( "[DELAY Took (quite long) %3s]")
224 .arg( QString::number(duration, 'g', 2) ), toColor( DEBUG_WARN ) ) );
225 }
226}
227
228void Debug::stamp()
229{
230 static int n = 0;
231 debug() << "| Stamp: " << ++n << Qt::endl;
232}
233

source code of phonon-vlc/src/utils/debug.cpp