2010-03-01 19:00:00 -05:00
/*
2019-08-02 23:10:55 -04:00
* Copyright ( C ) 2010 - 2012 Carl Hetherington < carl @ carlh . net >
* Copyright ( C ) 2010 - 2016 Paul Davis < paul @ linuxaudiosystems . com >
* Copyright ( C ) 2015 - 2016 Robin Gareus < robin @ gareus . org >
* Copyright ( C ) 2015 Tim Mayberry < mojofunk @ gmail . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
2010-03-01 19:00:00 -05:00
# include <cstring>
2019-11-03 08:15:11 -05:00
# include <cstdio>
2010-03-01 19:00:00 -05:00
# include <cstdlib>
# include <iostream>
# include <map>
2012-01-08 11:38:49 -05:00
# include <vector>
# include <algorithm>
2010-03-01 19:00:00 -05:00
2013-07-11 12:36:16 -04:00
# include <boost/tokenizer.hpp>
2010-03-01 19:00:00 -05:00
# include "pbd/debug.h"
2020-10-13 15:26:26 -04:00
# include "pbd/error.h"
2023-07-06 18:13:51 -04:00
# include "pbd/pthread_utils.h"
2010-03-01 19:00:00 -05:00
2016-07-14 14:44:52 -04:00
# include "pbd/i18n.h"
2010-03-01 19:00:00 -05:00
using namespace std ;
2015-06-12 18:14:09 -04:00
using PBD : : DebugBits ;
2013-03-20 17:18:55 -04:00
2015-06-12 18:14:09 -04:00
static uint64_t _debug_bit = 0 ;
typedef std : : map < const char * , DebugBits > DebugMap ;
2013-03-20 17:18:55 -04:00
namespace PBD {
2013-03-24 15:18:20 -04:00
DebugMap & _debug_bit_map ( )
{
static DebugMap map ;
return map ;
}
2013-03-20 17:18:55 -04:00
}
2010-03-01 19:00:00 -05:00
2015-06-12 18:14:09 -04:00
DebugBits PBD : : DEBUG : : Stateful = PBD : : new_debug_bit ( " stateful " ) ;
DebugBits PBD : : DEBUG : : Properties = PBD : : new_debug_bit ( " properties " ) ;
DebugBits PBD : : DEBUG : : FileManager = PBD : : new_debug_bit ( " filemanager " ) ;
DebugBits PBD : : DEBUG : : Pool = PBD : : new_debug_bit ( " pool " ) ;
DebugBits PBD : : DEBUG : : EventLoop = PBD : : new_debug_bit ( " eventloop " ) ;
DebugBits PBD : : DEBUG : : AbstractUI = PBD : : new_debug_bit ( " abstractui " ) ;
DebugBits PBD : : DEBUG : : FileUtils = PBD : : new_debug_bit ( " fileutils " ) ;
DebugBits PBD : : DEBUG : : Configuration = PBD : : new_debug_bit ( " configuration " ) ;
2015-08-18 23:41:19 -04:00
DebugBits PBD : : DEBUG : : UndoHistory = PBD : : new_debug_bit ( " undohistory " ) ;
2015-09-12 07:41:00 -04:00
DebugBits PBD : : DEBUG : : Timing = PBD : : new_debug_bit ( " timing " ) ;
2015-09-13 22:22:39 -04:00
DebugBits PBD : : DEBUG : : Threads = PBD : : new_debug_bit ( " threads " ) ;
2024-09-27 18:33:27 -04:00
DebugBits PBD : : DEBUG : : ThreadName = PBD : : new_debug_bit ( " threadname " ) ;
2016-05-07 06:15:12 -04:00
DebugBits PBD : : DEBUG : : Locale = PBD : : new_debug_bit ( " locale " ) ;
2015-08-16 08:02:27 -04:00
DebugBits PBD : : DEBUG : : StringConvert = PBD : : new_debug_bit ( " stringconvert " ) ;
2019-10-28 18:52:18 -04:00
DebugBits PBD : : DEBUG : : DebugTimestamps = PBD : : new_debug_bit ( " debugtimestamps " ) ;
2020-10-13 15:26:26 -04:00
DebugBits PBD : : DEBUG : : DebugLogToGUI = PBD : : new_debug_bit ( " debuglogtogui " ) ;
2010-03-01 19:00:00 -05:00
2015-05-13 19:37:15 -04:00
/* These are debug bits that are used by backends. Since these are loaded dynamically,
after command - line parsing , defining them in code that is part of the backend
doesn ' t make them available for command line parsing . Put them here .
This is sort of a hack , because it means that the debug bits aren ' t defined
with the code in which they are relevant . But providing access to debug bits
from dynamically loaded code , for use in command line parsing , is way above the pay grade
of this debug tracing scheme .
*/
DebugBits PBD : : DEBUG : : WavesMIDI = PBD : : new_debug_bit ( " WavesMIDI " ) ;
DebugBits PBD : : DEBUG : : WavesAudio = PBD : : new_debug_bit ( " WavesAudio " ) ;
2015-06-12 18:14:09 -04:00
DebugBits PBD : : debug_bits ;
2010-03-01 19:00:00 -05:00
2015-06-12 18:14:09 -04:00
DebugBits
2010-03-01 19:00:00 -05:00
PBD : : new_debug_bit ( const char * name )
{
2015-10-15 08:59:11 -04:00
DebugBits ret ;
DebugMap : : iterator i = _debug_bit_map ( ) . find ( name ) ;
if ( i ! = _debug_bit_map ( ) . end ( ) ) {
return i - > second ;
}
if ( _debug_bit > = debug_bits . size ( ) ) {
cerr < < " Too many debug bits defined, offender was " < < name < < endl ;
2019-09-17 23:57:26 -04:00
abort ( ) ; /*NOTREACHED*/
2015-10-15 08:59:11 -04:00
}
ret . set ( _debug_bit + + , 1 ) ;
_debug_bit_map ( ) . insert ( make_pair ( name , ret ) ) ;
2010-03-01 19:00:00 -05:00
return ret ;
}
void
2023-07-06 18:13:24 -04:00
PBD : : debug_only_print ( const char * prefix , string str )
2010-03-01 19:00:00 -05:00
{
2024-09-27 18:33:27 -04:00
if ( ( PBD : : debug_bits & DEBUG : : ThreadName ) . any ( ) ) {
2023-08-31 10:55:09 -04:00
printf ( " 0x%lx (%s) " , ( intptr_t ) DEBUG_THREAD_SELF , pthread_name ( ) ) ;
2023-07-06 18:13:51 -04:00
}
2019-10-28 18:52:18 -04:00
if ( ( PBD : : debug_bits & DEBUG : : DebugTimestamps ) . any ( ) ) {
2019-10-30 00:07:18 -04:00
printf ( " %ld %s: %s " , g_get_monotonic_time ( ) , prefix , str . c_str ( ) ) ;
} else {
printf ( " %s: %s " , prefix , str . c_str ( ) ) ;
2019-10-28 18:52:18 -04:00
}
2023-07-06 18:13:24 -04:00
}
void
PBD : : debug_print ( const char * prefix , string str )
{
debug_only_print ( prefix , str ) ;
2020-10-13 15:26:26 -04:00
if ( ( PBD : : debug_bits & DEBUG : : DebugLogToGUI ) . any ( ) ) {
std : : replace ( str . begin ( ) , str . end ( ) , ' \n ' , ' ' ) ;
debug < < prefix < < " : " < < str < < endmsg ;
}
2010-03-01 19:00:00 -05:00
}
int
PBD : : parse_debug_options ( const char * str )
{
2014-04-14 15:26:48 -04:00
string in_str = str ;
2013-07-11 12:36:16 -04:00
typedef boost : : tokenizer < boost : : char_separator < char > > tokenizer ;
boost : : char_separator < char > sep ( " , " ) ;
2014-04-14 15:26:48 -04:00
tokenizer tokens ( in_str , sep ) ;
2010-03-01 19:00:00 -05:00
2013-07-11 12:36:16 -04:00
for ( tokenizer : : iterator tok_iter = tokens . begin ( ) ; tok_iter ! = tokens . end ( ) ; + + tok_iter ) {
if ( * tok_iter = = " list " ) {
2010-03-01 19:00:00 -05:00
list_debug_options ( ) ;
return 1 ;
}
2013-07-11 12:36:16 -04:00
if ( * tok_iter = = " all " ) {
2015-06-12 18:14:09 -04:00
debug_bits . set ( ) ; /* sets all bits */
2010-03-01 19:00:00 -05:00
return 0 ;
}
2015-06-12 18:14:09 -04:00
for ( map < const char * , DebugBits > : : iterator i = _debug_bit_map ( ) . begin ( ) ; i ! = _debug_bit_map ( ) . end ( ) ; + + i ) {
2013-07-11 12:36:16 -04:00
const char * cstr = ( * tok_iter ) . c_str ( ) ;
2024-07-25 07:05:07 -04:00
if ( strncasecmp ( cstr , i - > first , strlen ( cstr ) ) = = 0 ) {
debug_bits | = i - > second ;
cout < < string_compose ( X_ ( " Debug flag '%1' set \n " ) , i - > first ) ;
}
}
2010-03-01 19:00:00 -05:00
}
2015-10-05 10:17:49 -04:00
2010-03-01 19:00:00 -05:00
return 0 ;
}
void
PBD : : list_debug_options ( )
{
2012-01-08 20:59:52 -05:00
cout < < _ ( " The following debug options are available. Separate multiple options with commas. \n Names are case-insensitive and can be abbreviated. " ) < < endl < < endl ;
2015-10-04 14:51:05 -04:00
cout < < ' \t ' < < X_ ( " all " ) < < endl ;
2012-01-08 11:38:49 -05:00
vector < string > options ;
2010-03-01 19:00:00 -05:00
2015-06-12 18:14:09 -04:00
for ( map < const char * , DebugBits > : : iterator i = _debug_bit_map ( ) . begin ( ) ; i ! = _debug_bit_map ( ) . end ( ) ; + + i ) {
2012-01-08 11:38:49 -05:00
options . push_back ( i - > first ) ;
2010-03-01 19:00:00 -05:00
}
2012-01-08 11:38:49 -05:00
sort ( options . begin ( ) , options . end ( ) ) ;
for ( vector < string > : : iterator i = options . begin ( ) ; i ! = options . end ( ) ; + + i ) {
cout < < " \t " < < ( * i ) < < endl ;
}
2010-03-01 19:00:00 -05:00
}