implement new meter types
[ardour.git] / gtk2_ardour / level_meter.cc
1 /*
2   Copyright (C) 2002 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 <limits.h>
21
22 #include "ardour/meter.h"
23
24 #include <gtkmm2ext/utils.h>
25 #include <gtkmm2ext/fastmeter.h>
26 #include <gtkmm2ext/barcontroller.h>
27 #include "midi++/manager.h"
28 #include "pbd/fastlog.h"
29
30 #include "ardour_ui.h"
31 #include "global_signals.h"
32 #include "level_meter.h"
33 #include "utils.h"
34 #include "logmeter.h"
35 #include "gui_thread.h"
36 #include "keyboard.h"
37 #include "public_editor.h"
38
39 #include "i18n.h"
40
41 using namespace ARDOUR;
42 using namespace PBD;
43 using namespace Gtkmm2ext;
44 using namespace Gtk;
45 using namespace std;
46
47 LevelMeter::LevelMeter (Session* s)
48         : _meter (0)
49         , meter_length (0)
50         , thin_meter_width(2)
51 {
52         set_session (s);
53         set_spacing (1);
54         Config->ParameterChanged.connect (_parameter_connection, invalidator (*this), boost::bind (&LevelMeter::parameter_changed, this, _1), gui_context());
55         UI::instance()->theme_changed.connect (sigc::mem_fun(*this, &LevelMeter::on_theme_changed));
56         ColorsChanged.connect (sigc::mem_fun (*this, &LevelMeter::color_handler));
57         max_peak = minus_infinity();
58         meter_type = MeterPeak;
59 }
60
61 void
62 LevelMeter::on_theme_changed()
63 {
64         style_changed = true;
65 }
66
67 LevelMeter::~LevelMeter ()
68 {
69         for (vector<MeterInfo>::iterator i = meters.begin(); i != meters.end(); i++) {
70                 delete (*i).meter;
71         }
72 }
73
74 void
75 LevelMeter::set_meter (PeakMeter* meter)
76 {
77         _configuration_connection.disconnect();
78         _meter_type_connection.disconnect();
79
80         _meter = meter;
81
82         if (_meter) {
83                 _meter->ConfigurationChanged.connect (_configuration_connection, invalidator (*this), boost::bind (&LevelMeter::configuration_changed, this, _1, _2), gui_context());
84                 _meter->TypeChanged.connect (_meter_type_connection, invalidator (*this), boost::bind (&LevelMeter::meter_type_changed, this, _1), gui_context());
85         }
86 }
87
88 float
89 LevelMeter::update_meters ()
90 {
91         vector<MeterInfo>::iterator i;
92         uint32_t n;
93
94         if (!_meter) {
95                 return 0.0f;
96         }
97
98         uint32_t nmidi = _meter->input_streams().n_midi();
99
100         for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
101                 if ((*i).packed) {
102                         const float mpeak = _meter->meter_level(n, MeterMaxPeak);
103                         if (mpeak > (*i).max_peak) {
104                                 (*i).max_peak = mpeak;
105                                 (*i).meter->set_highlight(mpeak > Config->get_meter_peak());
106                         }
107                         if (mpeak > max_peak) {
108                                 max_peak = mpeak;
109                         }
110
111                         if (n < nmidi) {
112                                 (*i).meter->set (_meter->meter_level (n, MeterPeak));
113                         } else {
114                                 const float peak = _meter->meter_level (n, meter_type);
115                                 if (meter_type == MeterPeak) {
116                                         (*i).meter->set (log_meter (peak));
117                                 } else if (meter_type == MeterIEC1NOR) {
118                                         (*i).meter->set (meter_deflect_nordic (peak));
119                                 } else if (meter_type == MeterIEC1DIN) {
120                                         (*i).meter->set (meter_deflect_din (peak));
121                                 } else if (meter_type == MeterIEC2BBC || meter_type == MeterIEC2EBU) {
122                                         (*i).meter->set (meter_deflect_ppm (peak));
123                                 } else if (meter_type == MeterVU) {
124                                         (*i).meter->set (meter_deflect_vu (peak));
125                                 } else if (meter_type == MeterK14) {
126                                         (*i).meter->set (meter_deflect_k (peak, 14), meter_deflect_k(_meter->meter_level(n, MeterPeak), 14));
127                                 } else if (meter_type == MeterK20) {
128                                         (*i).meter->set (meter_deflect_k (peak, 20), meter_deflect_k(_meter->meter_level(n, MeterPeak), 20));
129                                 } else {
130                                         (*i).meter->set (log_meter (peak), log_meter(_meter->meter_level(n, MeterPeak)));
131                                 }
132                         }
133                 }
134         }
135         return max_peak;
136 }
137
138 void
139 LevelMeter::parameter_changed (string p)
140 {
141         ENSURE_GUI_THREAD (*this, &LevelMeter::parameter_changed, p)
142
143         if (p == "meter-hold") {
144                 vector<MeterInfo>::iterator i;
145                 uint32_t n;
146
147                 for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
148                         (*i).meter->set_hold_count ((uint32_t) floor(Config->get_meter_hold()));
149                 }
150         }
151         else if (p == "meter-line-up-level") {
152                 color_changed = true;
153                 setup_meters (meter_length, regular_meter_width, thin_meter_width);
154         }
155         else if (p == "meter-peak") {
156                 vector<MeterInfo>::iterator i;
157                 uint32_t n;
158
159                 for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
160                         (*i).max_peak = minus_infinity();
161                 }
162         }
163 }
164
165 void
166 LevelMeter::configuration_changed (ChanCount /*in*/, ChanCount /*out*/)
167 {
168         color_changed = true;
169         setup_meters (meter_length, regular_meter_width, thin_meter_width);
170 }
171
172 void
173 LevelMeter::meter_type_changed (MeterType t)
174 {
175         meter_type = t;
176         color_changed = true;
177         setup_meters (meter_length, regular_meter_width, thin_meter_width);
178         MeterTypeChanged(t);
179 }
180
181 void
182 LevelMeter::hide_all_meters ()
183 {
184         for (vector<MeterInfo>::iterator i = meters.begin(); i != meters.end(); ++i) {
185                 if ((*i).packed) {
186                         remove (*((*i).meter));
187                         (*i).packed = false;
188                 }
189         }
190 }
191
192 void
193 LevelMeter::setup_meters (int len, int initial_width, int thin_width)
194 {
195         hide_all_meters ();
196
197         if (!_meter) {
198                 return; /* do it later or never */
199         }
200
201         int32_t nmidi = _meter->input_streams().n_midi();
202         uint32_t nmeters = _meter->input_streams().n_total();
203         regular_meter_width = initial_width;
204         thin_meter_width = thin_width;
205         meter_length = len;
206
207         guint16 width;
208
209         if (nmeters == 0) {
210                 return;
211         }
212
213         if (nmeters <= 2) {
214                 width = regular_meter_width;
215         } else {
216                 width = thin_meter_width;
217         }
218
219         while (meters.size() < nmeters) {
220                 meters.push_back (MeterInfo());
221         }
222
223         //cerr << "LevelMeter::setup_meters() called color_changed = " << color_changed << " colors: " << endl;//DEBUG
224
225         for (int32_t n = nmeters-1; nmeters && n >= 0 ; --n) {
226                 uint32_t c[10];
227                 float stp[4];
228                 if (n < nmidi) {
229                         c[0] = ARDOUR_UI::config()->get_canvasvar_MidiMeterColor0();
230                         c[1] = ARDOUR_UI::config()->get_canvasvar_MidiMeterColor1();
231                         c[2] = ARDOUR_UI::config()->get_canvasvar_MidiMeterColor2();
232                         c[3] = ARDOUR_UI::config()->get_canvasvar_MidiMeterColor3();
233                         c[4] = ARDOUR_UI::config()->get_canvasvar_MidiMeterColor4();
234                         c[5] = ARDOUR_UI::config()->get_canvasvar_MidiMeterColor5();
235                         c[6] = ARDOUR_UI::config()->get_canvasvar_MidiMeterColor6();
236                         c[7] = ARDOUR_UI::config()->get_canvasvar_MidiMeterColor7();
237                         c[8] = ARDOUR_UI::config()->get_canvasvar_MidiMeterColor8();
238                         c[9] = ARDOUR_UI::config()->get_canvasvar_MidiMeterColor9();
239                         stp[0] = 115.0 *  32.0 / 128.0;
240                         stp[1] = 115.0 *  64.0 / 128.0;
241                         stp[2] = 115.0 * 100.0 / 128.0;
242                         stp[3] = 115.0 * 112.0 / 128.0;
243                 } else {
244                         c[0] = ARDOUR_UI::config()->get_canvasvar_MeterColor0();
245                         c[1] = ARDOUR_UI::config()->get_canvasvar_MeterColor1();
246                         c[2] = ARDOUR_UI::config()->get_canvasvar_MeterColor2();
247                         c[3] = ARDOUR_UI::config()->get_canvasvar_MeterColor3();
248                         c[4] = ARDOUR_UI::config()->get_canvasvar_MeterColor4();
249                         c[5] = ARDOUR_UI::config()->get_canvasvar_MeterColor5();
250                         c[6] = ARDOUR_UI::config()->get_canvasvar_MeterColor6();
251                         c[7] = ARDOUR_UI::config()->get_canvasvar_MeterColor7();
252                         c[8] = ARDOUR_UI::config()->get_canvasvar_MeterColor8();
253                         c[9] = ARDOUR_UI::config()->get_canvasvar_MeterColor9();
254
255                         switch (meter_type) {
256                                 case MeterK20:
257                                         stp[0] = 115.0 * meter_deflect_k(-40, 20);  //-20
258                                         stp[1] = 115.0 * meter_deflect_k(-20, 20);  //  0
259                                         stp[2] = 115.0 * meter_deflect_k(-18, 20);  // +2
260                                         stp[3] = 115.0 * meter_deflect_k(-16, 20);  // +4
261                                         c[0] = c[1] = 0x008800ff;
262                                         c[2] = c[3] = 0x00ff00ff;
263                                         c[4] = c[5] = 0xffff00ff;
264                                         c[6] = c[7] = 0xffff00ff;
265                                         c[8] = c[9] = 0xff0000ff;
266                                         break;
267                                 case MeterK14:
268                                         stp[0] = 115.0 * meter_deflect_k(-34, 14);  //-20
269                                         stp[1] = 115.0 * meter_deflect_k(-14, 14);  //  0
270                                         stp[2] = 115.0 * meter_deflect_k(-12, 14);  // +2
271                                         stp[3] = 115.0 * meter_deflect_k(-10, 14);  // +4
272                                         c[0] = c[1] = 0x008800ff;
273                                         c[2] = c[3] = 0x00ff00ff;
274                                         c[4] = c[5] = 0xffff00ff;
275                                         c[6] = c[7] = 0xffff00ff;
276                                         c[8] = c[9] = 0xff0000ff;
277                                         break;
278                                 case MeterIEC2EBU:
279                                 case MeterIEC2BBC:
280                                         stp[0] = 115.0 * meter_deflect_ppm(-18);
281                                         stp[1] = 115.0 * meter_deflect_ppm(-14);
282                                         stp[2] = 115.0 * meter_deflect_ppm(-10);
283                                         stp[3] = 115.0 * meter_deflect_ppm( -8);
284                                         break;
285                                 case MeterIEC1NOR:
286                                         stp[0] = 115.0 * meter_deflect_nordic(-18);
287                                         stp[1] = 115.0 * meter_deflect_nordic(-15);
288                                         stp[2] = 115.0 * meter_deflect_nordic(-12);
289                                         stp[3] = 115.0 * meter_deflect_nordic( -9);
290                                         break;
291                                 case MeterIEC1DIN:
292                                         stp[0] = 115.0 * meter_deflect_din(-29);
293                                         stp[1] = 115.0 * meter_deflect_din(-18);
294                                         stp[2] = 115.0 * meter_deflect_din(-15);
295                                         stp[3] = 115.0 * meter_deflect_din( -9);
296                                         break;
297                                 case MeterVU:
298                                         stp[0] = 115.0 * meter_deflect_vu(-26); // -6
299                                         stp[1] = 115.0 * meter_deflect_vu(-23); // -3
300                                         stp[2] = 115.0 * meter_deflect_vu(-20); // 0
301                                         stp[3] = 115.0 * meter_deflect_vu(-18); // +2
302                                         break;
303                                 default: // PEAK, RMS
304                                         stp[1] = 77.5;  // 115 * log_meter(-10)
305                                         stp[2] = 92.5;  // 115 * log_meter(-3)
306                                         stp[3] = 100.0; // 115 * log_meter(0)
307                                 switch (Config->get_meter_line_up_level()) {
308                                         case MeteringLineUp24:
309                                                 stp[0] = 42.0;
310                                                 break;
311                                         case MeteringLineUp20:
312                                                 stp[0] = 50.0;
313                                                 break;
314                                         default:
315                                         case MeteringLineUp18:
316                                                 stp[0] = 55.0;
317                                                 break;
318                                         case MeteringLineUp15:
319                                                 stp[0] = 62.5;
320                                                 break;
321                                 }
322                         }
323                 }
324                 if (meters[n].width != width || meters[n].length != len || color_changed) {
325                         delete meters[n].meter;
326                         meters[n].meter = new FastMeter ((uint32_t) floor (Config->get_meter_hold()), width, FastMeter::Vertical, len,
327                                                          c[0], c[1], c[2], c[3], c[4],
328                                                          c[5], c[6], c[7], c[8], c[9],
329                                                          ARDOUR_UI::config()->get_canvasvar_MeterBackgroundBot(),
330                                                          ARDOUR_UI::config()->get_canvasvar_MeterBackgroundTop(),
331                                                          0x991122ff, 0x551111ff,
332                                                          stp[0], stp[1], stp[2], stp[3]
333                                 );
334                         meters[n].width = width;
335                         meters[n].length = len;
336                         meters[n].meter->add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
337                         meters[n].meter->signal_button_press_event().connect (sigc::mem_fun (*this, &LevelMeter::meter_button_press));
338                         meters[n].meter->signal_button_release_event().connect (sigc::mem_fun (*this, &LevelMeter::meter_button_release));
339                 }
340
341                 pack_end (*meters[n].meter, false, false);
342                 meters[n].meter->show_all ();
343                 meters[n].packed = true;
344         }
345         show();
346         color_changed = false;
347 }
348
349 void
350 LevelMeter::set_type(MeterType t)
351 {
352         meter_type = t;
353         _meter->set_type(t);
354 }
355
356 bool
357 LevelMeter::meter_button_press (GdkEventButton* ev)
358 {
359         return ButtonPress (ev); /* EMIT SIGNAL */
360 }
361
362 bool
363 LevelMeter::meter_button_release (GdkEventButton* ev)
364 {
365         if (ev->button == 1) {
366                 clear_meters (false);
367         }
368
369         return true;
370 }
371
372
373 void LevelMeter::clear_meters (bool reset_highlight)
374 {
375         for (vector<MeterInfo>::iterator i = meters.begin(); i < meters.end(); i++) {
376                 (*i).meter->clear();
377                 (*i).max_peak = minus_infinity();
378                 if (reset_highlight)
379                         (*i).meter->set_highlight(false);
380         }
381         max_peak = minus_infinity();
382 }
383
384 void LevelMeter::hide_meters ()
385 {
386         hide_all_meters();
387 }
388
389 void
390 LevelMeter::color_handler ()
391 {
392         color_changed = true;
393 }
394