af8cd052cde2f594d20bef79308b2739176daa5f
[ardour.git] / libs / pbd / debug.cc
1 /*
2     Copyright (C) 2009 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <cstring>
21 #include <cstdlib>
22 #include <iostream>
23 #include <map>
24 #include <vector>
25 #include <algorithm>
26
27 #include <boost/tokenizer.hpp>
28
29 #include "pbd/debug.h"
30
31 #include "i18n.h"
32
33 using namespace std;
34 using PBD::DebugBits;
35
36 static uint64_t _debug_bit = 0;
37
38 typedef std::map<const char*,DebugBits> DebugMap;
39
40 namespace PBD {
41         DebugMap & _debug_bit_map()
42         {
43                 static DebugMap map;
44                 return map;
45         }
46 }
47
48 DebugBits PBD::DEBUG::Stateful = PBD::new_debug_bit ("stateful");
49 DebugBits PBD::DEBUG::Properties = PBD::new_debug_bit ("properties");
50 DebugBits PBD::DEBUG::FileManager = PBD::new_debug_bit ("filemanager");
51 DebugBits PBD::DEBUG::Pool = PBD::new_debug_bit ("pool");
52 DebugBits PBD::DEBUG::EventLoop = PBD::new_debug_bit ("eventloop");
53 DebugBits PBD::DEBUG::AbstractUI = PBD::new_debug_bit ("abstractui");
54 DebugBits PBD::DEBUG::FileUtils = PBD::new_debug_bit ("fileutils");
55 DebugBits PBD::DEBUG::Configuration = PBD::new_debug_bit ("configuration");
56 DebugBits PBD::DEBUG::UndoHistory = PBD::new_debug_bit ("undohistory");
57 DebugBits PBD::DEBUG::Timing = PBD::new_debug_bit ("timing");
58 DebugBits PBD::DEBUG::Threads = PBD::new_debug_bit ("threads");
59
60 /* These are debug bits that are used by backends. Since these are loaded dynamically,
61    after command-line parsing, defining them in code that is part of the backend
62    doesn't make them available for command line parsing. Put them here.
63
64    This is sort of a hack, because it means that the debug bits aren't defined
65    with the code in which they are relevant. But providing access to debug bits
66    from dynamically loaded code, for use in command line parsing, is way above the pay grade
67    of this debug tracing scheme.
68 */
69 DebugBits PBD::DEBUG::WavesMIDI = PBD::new_debug_bit ("WavesMIDI");
70 DebugBits PBD::DEBUG::WavesAudio = PBD::new_debug_bit ("WavesAudio");
71
72 DebugBits PBD::debug_bits;
73
74 DebugBits
75 PBD::new_debug_bit (const char* name)
76 {
77         DebugBits ret;
78         ret.set (_debug_bit++, 1);
79         _debug_bit_map().insert (make_pair (name, ret));
80         return ret;
81 }
82
83 void
84 PBD::debug_print (const char* prefix, string str)
85 {
86         cout << prefix << ": " << str;
87 }
88
89 int
90 PBD::parse_debug_options (const char* str)
91 {
92         string in_str = str;
93         typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
94         boost::char_separator<char> sep (",");
95         tokenizer tokens (in_str, sep);
96         DebugBits bits;
97
98         for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
99                 if (*tok_iter == "list") {
100                         list_debug_options ();
101                         return 1;
102                 }
103
104                 if (*tok_iter == "all") {
105                         debug_bits.set (); /* sets all bits */
106                         return 0;
107                 }
108
109                 for (map<const char*,DebugBits>::iterator i = _debug_bit_map().begin(); i != _debug_bit_map().end(); ++i) {
110                         const char* cstr = (*tok_iter).c_str();
111
112                         if (strncasecmp (cstr, i->first, strlen (cstr)) == 0) {
113                                 bits |= i->second;
114                                 cout << i->first << " set ... debug bits now set to " << bits << " using " << i->second << endl;
115                         }
116                 }
117         }
118
119         debug_bits = bits;
120
121         return 0;
122 }
123
124 void
125 PBD::list_debug_options ()
126 {
127         cout << _("The following debug options are available. Separate multiple options with commas.\nNames are case-insensitive and can be abbreviated.") << endl << endl;
128         cout << '\t' << X_("all") << endl;
129
130         vector<string> options;
131
132         for (map<const char*,DebugBits>::iterator i = _debug_bit_map().begin(); i != _debug_bit_map().end(); ++i) {
133                 options.push_back (i->first);
134         }
135
136         sort (options.begin(), options.end());
137
138         for (vector<string>::iterator i = options.begin(); i != options.end(); ++i) {
139                 cout << "\t" << (*i) << endl;
140         }
141 }