fix math bug with numthreads computation
[ardour2.git] / gtk2_ardour / midi_tracer.cc
bloba9f38b52ff5a82c8841b4df9011a275face6e4a1
1 #define __STDC_FORMAT_MACROS 1
2 #include <stdint.h>
4 #include <sstream>
5 #include <sys/time.h>
6 #include <time.h>
8 #include "midi++/parser.h"
10 #include "midi_tracer.h"
11 #include "gui_thread.h"
12 #include "i18n.h"
14 using namespace Gtk;
15 using namespace std;
16 using namespace MIDI;
17 using namespace Glib;
19 MidiTracer::MidiTracer (const std::string& name, Parser& p)
20 : ArdourDialog (string_compose (_("MIDI Trace %1"), name))
21 , parser (p)
22 , line_count_adjustment (200, 1, 2000, 1, 10)
23 , line_count_spinner (line_count_adjustment)
24 , line_count_label (_("Store this many lines: "))
25 , autoscroll (true)
26 , show_hex (true)
27 , collect (true)
28 , update_queued (false)
29 , fifo (1024)
30 , buffer_pool ("miditracer", buffer_size, 1024) // 1024 256 byte buffers
31 , autoscroll_button (_("Auto-Scroll"))
32 , base_button (_("Decimal"))
33 , collect_button (_("Enabled"))
35 scroller.add (text);
36 get_vbox()->set_border_width (12);
37 get_vbox()->pack_start (scroller, true, true);
39 text.show ();
40 text.set_name ("MidiTracerTextView");
41 scroller.show ();
42 scroller.set_size_request (400, 400);
44 collect_button.set_active (true);
45 base_button.set_active (false);
46 autoscroll_button.set_active (true);
48 line_count_box.set_spacing (6);
49 line_count_box.pack_start (line_count_label, false, false);
50 line_count_box.pack_start (line_count_spinner, false, false);
52 line_count_spinner.show ();
53 line_count_label.show ();
54 line_count_box.show ();
56 get_action_area()->add (line_count_box);
58 HBox* bbox = manage (new HBox);
59 bbox->add (base_button);
60 bbox->add (collect_button);
61 bbox->add (autoscroll_button);
62 bbox->show ();
64 get_action_area()->add (*bbox);
66 base_button.signal_toggled().connect (sigc::mem_fun (*this, &MidiTracer::base_toggle));
67 collect_button.signal_toggled().connect (sigc::mem_fun (*this, &MidiTracer::collect_toggle));
68 autoscroll_button.signal_toggled().connect (sigc::mem_fun (*this, &MidiTracer::autoscroll_toggle));
70 base_button.show ();
71 collect_button.show ();
72 autoscroll_button.show ();
74 connect ();
78 MidiTracer::~MidiTracer()
82 void
83 MidiTracer::connect ()
85 disconnect ();
86 parser.any.connect_same_thread (connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3));
89 void
90 MidiTracer::disconnect ()
92 connection.disconnect ();
95 void
96 MidiTracer::tracer (Parser&, byte* msg, size_t len)
98 stringstream ss;
99 struct timeval tv;
100 char* buf;
101 struct tm now;
102 size_t bufsize;
103 size_t s;
105 gettimeofday (&tv, 0);
106 localtime_r (&tv.tv_sec, &now);
108 buf = (char *) buffer_pool.alloc ();
109 bufsize = buffer_size;
111 s = strftime (buf, bufsize, "%H:%M:%S", &now);
112 bufsize -= s;
113 s += snprintf (&buf[s], bufsize, ".%06" PRId64, (int64_t) tv.tv_usec);
114 bufsize -= s;
116 switch ((eventType) msg[0]&0xf0) {
117 case off:
118 if (show_hex) {
119 s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x %02x\n", "NoteOff", (msg[0]&0xf)+1, (int) msg[1], (int) msg[2]);
120 } else {
121 s += snprintf (&buf[s], bufsize, "%16s chn %2d %-3d %-3d\n", "NoteOff", (msg[0]&0xf)+1, (int) msg[1], (int) msg[2]);
123 break;
125 case on:
126 if (show_hex) {
127 s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x %02x\n", "NoteOn", (msg[0]&0xf)+1, (int) msg[1], (int) msg[2]);
128 } else {
129 s += snprintf (&buf[s], bufsize, "%16s chn %2d %-3d %-3d\n", "NoteOn", (msg[0]&0xf)+1, (int) msg[1], (int) msg[2]);
131 break;
133 case polypress:
134 if (show_hex) {
135 s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x\n", "PolyPressure", (msg[0]&0xf)+1, (int) msg[1]);
136 } else {
137 s += snprintf (&buf[s], bufsize, "%16s chn %2d %-3d\n", "PolyPressure", (msg[0]&0xf)+1, (int) msg[1]);
139 break;
141 case MIDI::controller:
142 if (show_hex) {
143 s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x %02x\n", "Controller", (msg[0]&0xf)+1, (int) msg[1], (int) msg[2]);
144 } else {
145 s += snprintf (&buf[s], bufsize, "%16s chn %2d %2d %-3d\n", "Controller", (msg[0]&0xf)+1, (int) msg[1], (int) msg[2]);
147 break;
149 case program:
150 if (show_hex) {
151 s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x\n", "Program Change", (msg[0]&0xf)+1, (int) msg[1]);
152 } else {
153 s += snprintf (&buf[s], bufsize, "%16s chn %2d %-3d\n", "Program Change", (msg[0]&0xf)+1, (int) msg[1]);
155 break;
157 case chanpress:
158 if (show_hex) {
159 s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x/%-3d\n", "Channel Pressure", (msg[0]&0xf)+1, (int) msg[1], (int) msg[1]);
160 } else {
161 s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x/%-3d\n", "Channel Pressure", (msg[0]&0xf)+1, (int) msg[1], (int) msg[1]);
163 break;
165 case MIDI::pitchbend:
166 if (show_hex) {
167 s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x\n", "Pitch Bend", (msg[0]&0xf)+1, (int) msg[1]);
168 } else {
169 s += snprintf (&buf[s], bufsize, "%16s chn %2d %-3d\n", "Pitch Bend", (msg[0]&0xf)+1, (int) msg[1]);
171 break;
173 case MIDI::sysex:
174 if (len == 1) {
175 switch (msg[0]) {
176 case 0xf8:
177 s += snprintf (&buf[s], bufsize, "%16s\n", "Clock");
178 break;
179 case 0xfa:
180 s += snprintf (&buf[s], bufsize, "%16s\n", "Start");
181 break;
182 case 0xfb:
183 s += snprintf (&buf[s], bufsize, "%16s\n", "Continue");
184 break;
185 case 0xfc:
186 s += snprintf (&buf[s], bufsize, "%16s\n", "Stop");
187 break;
188 case 0xfe:
189 s += snprintf (&buf[s], bufsize, "%16s\n", "Active Sense");
190 break;
191 case 0xff:
192 s += snprintf (&buf[s], bufsize, "%16s\n", "Reset");
193 break;
194 default:
195 s += snprintf (&buf[s], bufsize, "%16s %02x\n", "Sysex", (int) msg[1]);
196 break;
199 } else {
201 s += snprintf (&buf[s], bufsize, "%16s (%d) = [", "Sysex", (int) len);
202 bufsize -= s;
204 for (unsigned int i = 0; i < len && bufsize > 3; ++i) {
205 if (i > 0) {
206 s += snprintf (&buf[s], bufsize, " %02x", msg[i]);
207 } else {
208 s += snprintf (&buf[s], bufsize, "%02x", msg[i]);
210 bufsize -= s;
212 s += snprintf (&buf[s], bufsize, "]\n");
214 break;
216 case MIDI::song:
217 s += snprintf (&buf[s], bufsize, "%16s\n", "Song");
218 break;
220 case MIDI::tune:
221 s += snprintf (&buf[s], bufsize, "%16s\n", "Tune");
222 break;
224 case MIDI::eox:
225 s += snprintf (&buf[s], bufsize, "%16s\n", "EOX");
226 break;
228 case MIDI::timing:
229 s += snprintf (&buf[s], bufsize, "%16s\n", "Timing");
230 break;
232 case MIDI::start:
233 s += snprintf (&buf[s], bufsize, "%16s\n", "Start");
234 break;
236 case MIDI::stop:
237 s += snprintf (&buf[s], bufsize, "%16s\n", "Stop");
238 break;
240 case MIDI::contineu:
241 s += snprintf (&buf[s], bufsize, "%16s\n", "Continue");
242 break;
244 case active:
245 s += snprintf (&buf[s], bufsize, "%16s\n", "Active Sense");
246 break;
248 default:
249 s += snprintf (&buf[s], bufsize, "%16s\n", "Unknown");
250 break;
253 // If you want to append more to the line, uncomment this first
254 // bufsize -= s;
256 fifo.write (&buf, 1);
258 if (!update_queued) {
259 gui_context()->call_slot (invalidator (*this), boost::bind (&MidiTracer::update, this));
260 update_queued = true;
264 void
265 MidiTracer::update ()
267 bool updated = false;
268 update_queued = false;
270 RefPtr<TextBuffer> buf (text.get_buffer());
272 int excess = buf->get_line_count() - line_count_adjustment.get_value();
274 if (excess > 0) {
275 buf->erase (buf->begin(), buf->get_iter_at_line (excess));
278 char *str;
280 while (fifo.read (&str, 1)) {
281 buf->insert (buf->end(), string (str));
282 buffer_pool.release (str);
283 updated = true;
286 if (updated && autoscroll) {
287 scroller.get_vadjustment()->set_value (scroller.get_vadjustment()->get_upper());
291 void
292 MidiTracer::base_toggle ()
294 show_hex = !base_button.get_active();
297 void
298 MidiTracer::collect_toggle ()
300 if (collect_button.get_active ()) {
301 connect ();
302 } else {
303 disconnect ();
307 void
308 MidiTracer::autoscroll_toggle ()
310 autoscroll = autoscroll_button.get_active ();