MCP: Fix issue with strip "select" buttons that stayed stuck on.
[ardour.git] / libs / surfaces / push2 / 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 #include "ardour/logmeter.h"
24 #include "ardour/rc_configuration.h"
25
26 #include <gtkmm2ext/utils.h>
27 #include <gtkmm2ext/gui_thread.h>
28
29 #include "pbd/fastlog.h"
30 #include "pbd/i18n.h"
31
32 #include "canvas/box.h"
33 #include "canvas/meter.h"
34
35 #include "level_meter.h"
36 #include "push2.h"
37
38 using namespace ARDOUR;
39 using namespace PBD;
40 using namespace Gtkmm2ext;
41 using namespace std;
42 using namespace ArdourSurface;
43 using namespace ArdourCanvas;
44
45 LevelMeter::LevelMeter (Push2& p, Item* parent, int len, Meter::Orientation o)
46         : Container (parent)
47         , p2 (p)
48         , _meter (0)
49         , _meter_orientation(o)
50         , regular_meter_width (6)
51         , meter_length (len)
52         , thin_meter_width(2)
53         , max_peak (minus_infinity())
54         , meter_type (MeterPeak)
55         , visible_meter_type (MeterType(0))
56         , midi_count (0)
57         , meter_count (0)
58         , max_visible_meters (0)
59 {
60         Config->ParameterChanged.connect (_parameter_connection, invalidator(*this), boost::bind (&LevelMeter::parameter_changed, this, _1), &p2);
61
62         if (_meter_orientation == Meter::Vertical) {
63                 meter_packer = new HBox (this);
64         } else {
65                 meter_packer = new VBox (this);
66         }
67
68         meter_packer->set_collapse_on_hide (true);
69 }
70
71 LevelMeter::~LevelMeter ()
72 {
73         _configuration_connection.disconnect();
74         _meter_type_connection.disconnect();
75         _parameter_connection.disconnect();
76         for (vector<MeterInfo>::iterator i = meters.begin(); i != meters.end(); i++) {
77                 delete (*i).meter;
78         }
79         meters.clear();
80 }
81
82 void
83 LevelMeter::set_meter (PeakMeter* meter)
84 {
85         _configuration_connection.disconnect();
86         _meter_type_connection.disconnect();
87
88         _meter = meter;
89
90         if (_meter) {
91                 _meter->ConfigurationChanged.connect (_configuration_connection, invalidator(*this), boost::bind (&LevelMeter::configuration_changed, this, _1, _2), &p2);
92                 _meter->TypeChanged.connect (_meter_type_connection, invalidator (*this), boost::bind (&LevelMeter::meter_type_changed, this, _1), &p2);
93         }
94
95         setup_meters (meter_length, regular_meter_width, thin_meter_width);
96 }
97
98 static float meter_lineup_cfg(MeterLineUp lul, float offset) {
99         switch (lul) {
100                 case MeteringLineUp24:
101                         return offset + 6.0;
102                 case MeteringLineUp20:
103                         return offset + 2.0;
104                 case MeteringLineUp18:
105                         return offset;
106                 case MeteringLineUp15:
107                         return offset - 3.0;
108                 default:
109                         break;
110         }
111         return offset;
112 }
113
114 static float meter_lineup(float offset) {
115         return meter_lineup_cfg (MeteringLineUp24, offset);
116         //return meter_lineup_cfg (UIConfiguration::instance().get_meter_line_up_level(), offset);
117 }
118
119 static float vu_standard() {
120         return 0;
121 #if 0
122         // note - default meter config is +2dB (france)
123         switch (UIConfiguration::instance().get_meter_vu_standard()) {
124                 default:
125                 case MeteringVUfrench:   // 0VU = -2dBu
126                         return 0;
127                 case MeteringVUamerican: // 0VU =  0dBu
128                         return -2;
129                 case MeteringVUstandard: // 0VU = +4dBu
130                         return -6;
131                 case MeteringVUeight:    // 0VU = +8dBu
132                         return -10;
133         }
134 #endif
135 }
136
137 float
138 LevelMeter::update_meters ()
139 {
140         vector<MeterInfo>::iterator i;
141         uint32_t n;
142
143         if (!_meter) {
144                 return 0.0f;
145         }
146
147         uint32_t nmidi = _meter->input_streams().n_midi();
148
149         for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
150                 if ((*i).packed) {
151                         const float mpeak = _meter->meter_level(n, MeterMaxPeak);
152                         if (mpeak > (*i).max_peak) {
153                                 (*i).max_peak = mpeak;
154                                 //(*i).meter->set_highlight(mpeak >= UIConfiguration::instance().get_meter_peak());
155                                 (*i).meter->set_highlight (mpeak >= 2.0);
156                         }
157                         if (mpeak > max_peak) {
158                                 max_peak = mpeak;
159                         }
160
161                         if (n < nmidi) {
162                                 (*i).meter->set (_meter->meter_level (n, MeterPeak));
163                         } else {
164                                 const float peak = _meter->meter_level (n, meter_type);
165                                 if (meter_type == MeterPeak) {
166                                         (*i).meter->set (log_meter (peak));
167                                 } else if (meter_type == MeterPeak0dB) {
168                                         (*i).meter->set (log_meter0dB (peak));
169                                 } else if (meter_type == MeterIEC1NOR) {
170                                         (*i).meter->set (meter_deflect_nordic (peak + meter_lineup(0)));
171                                 } else if (meter_type == MeterIEC1DIN) {
172                                         // (*i).meter->set (meter_deflect_din (peak + meter_lineup_cfg(UIConfiguration::instance().get_meter_line_up_din(), 3.0)));
173                                 } else if (meter_type == MeterIEC2BBC || meter_type == MeterIEC2EBU) {
174                                         (*i).meter->set (meter_deflect_ppm (peak + meter_lineup(0)));
175                                 } else if (meter_type == MeterVU) {
176                                         (*i).meter->set (meter_deflect_vu (peak + vu_standard() + meter_lineup(0)));
177                                 } else if (meter_type == MeterK12) {
178                                         (*i).meter->set (meter_deflect_k (peak, 12), meter_deflect_k(_meter->meter_level(n, MeterPeak), 12));
179                                 } else if (meter_type == MeterK14) {
180                                         (*i).meter->set (meter_deflect_k (peak, 14), meter_deflect_k(_meter->meter_level(n, MeterPeak), 14));
181                                 } else if (meter_type == MeterK20) {
182                                         (*i).meter->set (meter_deflect_k (peak, 20), meter_deflect_k(_meter->meter_level(n, MeterPeak), 20));
183                                 } else { // RMS
184                                         (*i).meter->set (log_meter (peak), log_meter(_meter->meter_level(n, MeterPeak)));
185                                 }
186                         }
187                 }
188         }
189         return max_peak;
190 }
191
192 void
193 LevelMeter::parameter_changed (string p)
194 {
195         if (p == "meter-hold") {
196                 vector<MeterInfo>::iterator i;
197                 uint32_t n;
198
199                 for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
200                         //(*i).meter->set_hold_count ((uint32_t) floor(UIConfiguration::instance().get_meter_hold()));
201                         (*i).meter->set_hold_count (20);
202                 }
203         }
204         else if (p == "meter-line-up-level") {
205                 setup_meters (meter_length, regular_meter_width, thin_meter_width);
206         }
207         else if (p == "meter-style-led") {
208                 setup_meters (meter_length, regular_meter_width, thin_meter_width);
209         }
210         else if (p == "meter-peak") {
211                 vector<MeterInfo>::iterator i;
212                 uint32_t n;
213
214                 for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
215                         (*i).max_peak = minus_infinity();
216                 }
217         }
218 }
219
220 void
221 LevelMeter::configuration_changed (ChanCount /*in*/, ChanCount /*out*/)
222 {
223         setup_meters (meter_length, regular_meter_width, thin_meter_width);
224 }
225
226 void
227 LevelMeter::meter_type_changed (MeterType t)
228 {
229         meter_type = t;
230         setup_meters (meter_length, regular_meter_width, thin_meter_width);
231 }
232
233 void
234 LevelMeter::hide_all_meters ()
235 {
236         for (vector<MeterInfo>::iterator i = meters.begin(); i != meters.end(); ++i) {
237                 if ((*i).packed) {
238                         meter_packer->remove ((*i).meter);
239                         (*i).packed = false;
240                 }
241         }
242         meter_count = 0;
243 }
244
245 void
246 LevelMeter::set_max_audio_meter_count (uint32_t cnt)
247 {
248         if (cnt == max_visible_meters) {
249                 return;
250         }
251         max_visible_meters = cnt;
252         setup_meters (meter_length, regular_meter_width, thin_meter_width);
253 }
254
255 void
256 LevelMeter::setup_meters (int len, int initial_width, int thin_width)
257 {
258
259         if (!_meter) {
260                 hide_all_meters ();
261                 return; /* do it later or never */
262         }
263
264         uint32_t nmidi = _meter->input_streams().n_midi();
265         uint32_t nmeters = _meter->input_streams().n_total();
266         regular_meter_width = initial_width;
267         thin_meter_width = thin_width;
268         meter_length = len;
269
270         guint16 width;
271
272         if (nmeters == 0) {
273                 hide_all_meters ();
274                 return;
275         }
276
277         if (nmeters <= 2) {
278                 width = regular_meter_width;
279         } else {
280                 width = thin_meter_width;
281         }
282
283         if (   meters.size() > 0
284             && nmidi == midi_count
285             && nmeters == meter_count
286             && meters[0].width == width
287             && meters[0].length == len
288             && meter_type == visible_meter_type) {
289                 return;
290         }
291
292 #if 0
293         printf("Meter redraw: %s %s %s %s %s %s\n",
294                         (meters.size() > 0) ? "yes" : "no",
295                         (meters.size() > 0 &&  meters[0].width == width) ? "yes" : "no",
296                         (meters.size() > 0 &&  meters[0].length == len) ? "yes" : "no",
297                         (nmeters == meter_count) ? "yes" : "no",
298                         (meter_type == visible_meter_type) ? "yes" : "no",
299                         !color_changed ? "yes" : "no"
300                         );
301 #endif
302
303         hide_all_meters ();
304         while (meters.size() < nmeters) {
305                 meters.push_back (MeterInfo());
306         }
307
308         //cerr << "LevelMeter::setup_meters() called color_changed = " << color_changed << " colors: " << endl;//DEBUG
309
310         for (int32_t n = nmeters-1; nmeters && n >= 0 ; --n) {
311 #if 0
312                 uint32_t c[10];
313                 uint32_t b[4];
314                 float stp[4];
315                 int styleflags = UIConfiguration::instance().get_meter_style_led() ? 3 : 1;
316                 b[0] = UIConfiguration::instance().color ("meter background bottom");
317                 b[1] = UIConfiguration::instance().color ("meter background top");
318                 b[2] = 0x991122ff; // red highlight gradient Bot
319                 b[3] = 0x551111ff; // red highlight gradient Top
320                 if ((uint32_t) n < nmidi) {
321                         c[0] = UIConfiguration::instance().color ("midi meter color0");
322                         c[1] = UIConfiguration::instance().color ("midi meter color1");
323                         c[2] = UIConfiguration::instance().color ("midi meter color2");
324                         c[3] = UIConfiguration::instance().color ("midi meter color3");
325                         c[4] = UIConfiguration::instance().color ("midi meter color4");
326                         c[5] = UIConfiguration::instance().color ("midi meter color5");
327                         c[6] = UIConfiguration::instance().color ("midi meter color6");
328                         c[7] = UIConfiguration::instance().color ("midi meter color7");
329                         c[8] = UIConfiguration::instance().color ("midi meter color8");
330                         c[9] = UIConfiguration::instance().color ("midi meter color9");
331                         stp[0] = 115.0 *  32.0 / 128.0;
332                         stp[1] = 115.0 *  64.0 / 128.0;
333                         stp[2] = 115.0 * 100.0 / 128.0;
334                         stp[3] = 115.0 * 112.0 / 128.0;
335                 } else {
336                         c[0] = UIConfiguration::instance().color ("meter color0");
337                         c[1] = UIConfiguration::instance().color ("meter color1");
338                         c[2] = UIConfiguration::instance().color ("meter color2");
339                         c[3] = UIConfiguration::instance().color ("meter color3");
340                         c[4] = UIConfiguration::instance().color ("meter color4");
341                         c[5] = UIConfiguration::instance().color ("meter color5");
342                         c[6] = UIConfiguration::instance().color ("meter color6");
343                         c[7] = UIConfiguration::instance().color ("meter color7");
344                         c[8] = UIConfiguration::instance().color ("meter color8");
345                         c[9] = UIConfiguration::instance().color ("meter color9");
346
347                         switch (meter_type) {
348                                 case MeterK20:
349                                         stp[0] = 115.0 * meter_deflect_k(-40, 20);  //-20
350                                         stp[1] = 115.0 * meter_deflect_k(-20, 20);  //  0
351                                         stp[2] = 115.0 * meter_deflect_k(-18, 20);  // +2
352                                         stp[3] = 115.0 * meter_deflect_k(-16, 20);  // +4
353                                         c[0] = c[1] = 0x008800ff;
354                                         c[2] = c[3] = 0x00ff00ff;
355                                         c[4] = c[5] = 0xffff00ff;
356                                         c[6] = c[7] = 0xffff00ff;
357                                         c[8] = c[9] = 0xff0000ff;
358                                         break;
359                                 case MeterK14:
360                                         stp[0] = 115.0 * meter_deflect_k(-34, 14);  //-20
361                                         stp[1] = 115.0 * meter_deflect_k(-14, 14);  //  0
362                                         stp[2] = 115.0 * meter_deflect_k(-12, 14);  // +2
363                                         stp[3] = 115.0 * meter_deflect_k(-10, 14);  // +4
364                                         c[0] = c[1] = 0x008800ff;
365                                         c[2] = c[3] = 0x00ff00ff;
366                                         c[4] = c[5] = 0xffff00ff;
367                                         c[6] = c[7] = 0xffff00ff;
368                                         c[8] = c[9] = 0xff0000ff;
369                                         break;
370                                 case MeterK12:
371                                         stp[0] = 115.0 * meter_deflect_k(-32, 12);  //-20
372                                         stp[1] = 115.0 * meter_deflect_k(-12, 12);  //  0
373                                         stp[2] = 115.0 * meter_deflect_k(-10, 12);  // +2
374                                         stp[3] = 115.0 * meter_deflect_k( -8, 12);  // +4
375                                         c[0] = c[1] = 0x008800ff;
376                                         c[2] = c[3] = 0x00ff00ff;
377                                         c[4] = c[5] = 0xffff00ff;
378                                         c[6] = c[7] = 0xffff00ff;
379                                         c[8] = c[9] = 0xff0000ff;
380                                         break;
381                                 case MeterIEC2BBC:
382                                         c[0] = c[1] = c[2] = c[3] = c[4] = c[5] = c[6] = c[7] = c[8] = c[9] =
383                                                 UIConfiguration::instance().color ("meter color BBC");
384                                         stp[0] = stp[1] = stp[2] = stp[3] = 115.0;
385                                         break;
386                                 case MeterIEC2EBU:
387                                         stp[0] = 115.0 * meter_deflect_ppm(-24); // ignored
388                                         stp[1] = 115.0 * meter_deflect_ppm(-18);
389                                         stp[2] = 115.0 * meter_deflect_ppm( -9);
390                                         stp[3] = 115.0 * meter_deflect_ppm(  0); // ignored
391                                         c[3] = c[2] = c[1];
392                                         c[6] = c[7] = c[8] = c[9];
393                                         break;
394                                 case MeterIEC1NOR:
395                                         stp[0] = 115.0 * meter_deflect_nordic(-30); // ignored
396                                         stp[1] = 115.0 * meter_deflect_nordic(-18);
397                                         stp[2] = 115.0 * meter_deflect_nordic(-12);
398                                         stp[3] = 115.0 * meter_deflect_nordic( -9); // ignored
399                                         c[0] = c[1] = c[2]; // bright-green
400                                         c[6] = c[7] = c[8] = c[9];
401                                         break;
402                                 case MeterIEC1DIN:
403                                         stp[0] = 115.0 * meter_deflect_din(-29); // ignored
404                                         stp[1] = 115.0 * meter_deflect_din(-18);
405                                         stp[2] = 115.0 * meter_deflect_din(-15); // ignored
406                                         stp[3] = 115.0 * meter_deflect_din( -9);
407                                         c[0] = c[2] = c[3] = c[1];
408                                         c[4] = c[6];
409                                         c[5] = c[7];
410                                         break;
411                                 case MeterVU:
412                                         stp[0] = 115.0 * meter_deflect_vu(-26); // -6
413                                         stp[1] = 115.0 * meter_deflect_vu(-23); // -3
414                                         stp[2] = 115.0 * meter_deflect_vu(-20); // 0
415                                         stp[3] = 115.0 * meter_deflect_vu(-18); // +2
416                                         c[0] = c[2] = c[3] = c[4] = c[5] = c[1];
417                                         c[7] = c[8] = c[9] = c[6];
418                                         break;
419                                 case MeterPeak0dB:
420                                          stp[1] =  89.125; // 115.0 * log_meter0dB(-9);
421                                          stp[2] = 106.375; // 115.0 * log_meter0dB(-3);
422                                          stp[3] = 115.0;   // 115.0 * log_meter0dB(0);
423                                         switch (UIConfiguration::instance().get_meter_line_up_level()) {
424                                         case MeteringLineUp24:
425                                                 stp[0] = 115.0 * log_meter0dB(-24);
426                                                 break;
427                                         case MeteringLineUp20:
428                                                 stp[0] = 115.0 * log_meter0dB(-20);
429                                                 break;
430                                         default:
431                                         case MeteringLineUp18:
432                                                 stp[0] = 115.0 * log_meter0dB(-18);
433                                                 break;
434                                         case MeteringLineUp15:
435                                                 stp[0] = 115.0 * log_meter0dB(-15);
436                                         }
437                                         break;
438                                 default: // PEAK, RMS
439                                         stp[1] = 77.5;  // 115 * log_meter(-9)
440                                         stp[2] = 92.5;  // 115 * log_meter(-3)
441                                         stp[3] = 100.0; // 115 * log_meter(0)
442                                         switch (UIConfiguration::instance().get_meter_line_up_level()) {
443                                         case MeteringLineUp24:
444                                                 stp[0] = 42.0;
445                                                 break;
446                                         case MeteringLineUp20:
447                                                 stp[0] = 50.0;
448                                                 break;
449                                         default:
450                                         case MeteringLineUp18:
451                                                 stp[0] = 55.0;
452                                                 break;
453                                         case MeteringLineUp15:
454                                                 stp[0] = 62.5;
455                                                 break;
456                                 }
457                         }
458                 }
459
460 #endif
461                 if (meters[n].width != width || meters[n].length != len || meter_type != visible_meter_type || nmidi != midi_count) {
462                         bool hl = meters[n].meter ? meters[n].meter->get_highlight() : false;
463                         meters[n].packed = false;
464                         delete meters[n].meter;
465                         meters[n].meter = new Meter (this->canvas(), 32, width, _meter_orientation, len);
466                         meters[n].meter->set_highlight(hl);
467                         meters[n].width = width;
468                         meters[n].length = len;
469                 }
470
471                 meter_packer->pack_start (meters[n].meter);
472                 meters[n].packed = true;
473                 if (max_visible_meters == 0 || (uint32_t) n < max_visible_meters + nmidi) {
474                         meters[n].meter->show ();
475                 } else {
476                         meters[n].meter->hide ();
477                 }
478         }
479
480         visible_meter_type = meter_type;
481         midi_count = nmidi;
482         meter_count = nmeters;
483 }
484
485 void
486 LevelMeter::set_type(MeterType t)
487 {
488         meter_type = t;
489         _meter->set_type(t);
490 }
491
492 void LevelMeter::clear_meters (bool reset_highlight)
493 {
494         for (vector<MeterInfo>::iterator i = meters.begin(); i < meters.end(); i++) {
495                 (*i).meter->clear();
496                 (*i).max_peak = minus_infinity();
497                 if (reset_highlight)
498                         (*i).meter->set_highlight(false);
499         }
500         max_peak = minus_infinity();
501 }
502
503 void LevelMeter::hide_meters ()
504 {
505         hide_all_meters();
506 }