ardour
meter_strip.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013 Paul Davis
3  Author: Robin Gareus
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 
20 #include <list>
21 
22 #include <sigc++/bind.h>
23 
24 #include "ardour/session.h"
25 #include "ardour/route.h"
26 #include "ardour/route_group.h"
27 #include "ardour/meter.h"
28 
29 #include "ardour/audio_track.h"
30 #include "ardour/midi_track.h"
31 
32 #include <gtkmm2ext/gtk_ui.h>
33 #include <gtkmm2ext/keyboard.h>
34 #include <gtkmm2ext/utils.h>
35 #include <gtkmm2ext/rgb_macros.h>
36 
37 #include "ardour_ui.h"
38 #include "global_signals.h"
39 #include "logmeter.h"
40 #include "gui_thread.h"
41 #include "ardour_window.h"
42 #include "utils.h"
43 
44 #include "meterbridge.h"
45 #include "meter_strip.h"
46 #include "meter_patterns.h"
47 
48 #include "i18n.h"
49 
50 using namespace ARDOUR;
51 using namespace ARDOUR_UI_UTILS;
52 using namespace PBD;
53 using namespace Gtk;
54 using namespace Gtkmm2ext;
55 using namespace std;
56 using namespace ArdourMeter;
57 
58 PBD::Signal1<void,MeterStrip*> MeterStrip::CatchDeletion;
59 PBD::Signal0<void> MeterStrip::MetricChanged;
60 PBD::Signal0<void> MeterStrip::ConfigurationChanged;
61 
62 #define PX_SCALE(pxmin, dflt) rint(std::max((double)pxmin, (double)dflt * ARDOUR_UI::ui_scale))
63 
64 MeterStrip::MeterStrip (int metricmode, MeterType mt)
65  : AxisView(0)
66  , RouteUI(0)
67 {
68  level_meter = 0;
69  _strip_type = 0;
70  _tick_bar = 0;
71  _metricmode = -1;
73 
74  mtr_vbox.set_spacing (PX_SCALE(2, 2));
75  nfo_vbox.set_spacing (PX_SCALE(2, 2));
76  peakbx.set_size_request (-1, PX_SCALE(14, 14));
77  namebx.set_size_request (PX_SCALE(16, 18), PX_SCALE(32, 52));
78  spacer.set_size_request (-1,0);
79 
80  set_metric_mode(metricmode, mt);
81 
82  meter_metric_area.set_size_request (PX_SCALE(25, 25), 10);
83  meter_metric_area.signal_expose_event().connect (
84  sigc::mem_fun(*this, &MeterStrip::meter_metrics_expose));
85  RedrawMetrics.connect (sigc::mem_fun(*this, &MeterStrip::redraw_metrics));
86 
87  meterbox.pack_start(meter_metric_area, true, false);
88 
89  mtr_vbox.pack_start (peakbx, false, false);
90  mtr_vbox.pack_start (meterbox, true, true);
91  mtr_vbox.pack_start (spacer, false, false);
93 
94  mtr_hsep.set_size_request (-1, 1);
95  mtr_hsep.set_name("BlackSeparator");
96 
97  nfo_vbox.pack_start (mtr_hsep, false, false);
98  nfo_vbox.pack_start (btnbox, false, false);
99  nfo_vbox.pack_start (namebx, false, false);
100 
101  pack_start (mtr_container, true, true);
102  pack_start (nfo_vbox, false, false);
103 
104  peakbx.show();
105  btnbox.show();
106  meter_metric_area.show();
107  meterbox.show();
108  spacer.show();
109  mtr_vbox.show();
110  mtr_container.show();
111  mtr_hsep.show();
112  nfo_vbox.show();
113 
114  UI::instance()->theme_changed.connect (sigc::mem_fun(*this, &MeterStrip::on_theme_changed));
115  ColorsChanged.connect (sigc::mem_fun (*this, &MeterStrip::on_theme_changed));
116  DPIReset.connect (sigc::mem_fun (*this, &MeterStrip::on_theme_changed));
117 }
118 
120  : AxisView(sess)
121  , RouteUI(0)
122  , _route(rt)
123  , peak_display()
124 {
125  mtr_vbox.set_spacing (PX_SCALE(2, 2));
126  nfo_vbox.set_spacing (PX_SCALE(2, 2));
127  SessionHandlePtr::set_session (sess);
128  RouteUI::init ();
129  RouteUI::set_route (rt);
130 
131  _has_midi = false;
132  _tick_bar = 0;
133  _metricmode = -1;
135 
136  // note: level_meter->setup_meters() does the scaling
137  int meter_width = 6;
138  if (_route->shared_peak_meter()->input_streams().n_total() == 1) {
139  meter_width = 12;
140  }
141 
142  // level meter + ticks
143  level_meter = new LevelMeterHBox(sess);
147  level_meter->setup_meters (220, meter_width, 6);
148  level_meter->ButtonPress.connect_same_thread (level_meter_connection, boost::bind (&MeterStrip::level_meter_button_press, this, _1));
149  level_meter->MeterTypeChanged.connect_same_thread (level_meter_connection, boost::bind (&MeterStrip::meter_type_changed, this, _1));
150 
151  meter_align.set(0.5, 0.5, 0.0, 1.0);
152  meter_align.add(*level_meter);
153 
154  meterbox.pack_start(meter_ticks1_area, true, false);
155  meterbox.pack_start(meter_align, true, true);
156  meterbox.pack_start(meter_ticks2_area, true, false);
157 
158  // peak display
159  peak_display.set_name ("meterbridge peakindicator");
161  ARDOUR_UI::instance()->set_tip (peak_display, _("Reset Peak"));
163  peak_display.unset_flags (Gtk::CAN_FOCUS);
164  peak_display.set_size_request(PX_SCALE(12, 12), PX_SCALE(8, 8));
165  peak_display.set_corner_radius(2); // ardour-button scales this
166 
167  peak_align.set(0.5, 1.0, 1.0, 0.8);
169  peakbx.pack_start(peak_align, true, true, 2);
170  peakbx.set_size_request(-1, PX_SCALE(14, 14));
171 
172  // add track-name & -number label
173  number_label.set_text("-");
174  number_label.set_size_request(PX_SCALE(18, 18), PX_SCALE(18, 18));
175 
176  name_changed();
177 
178  name_label.set_corner_radius(2); // ardour button scales radius
180  name_label.set_name("meterbridge label");
181  name_label.set_angle(-90.0);
182  name_label.set_text_ellipsize (Pango::ELLIPSIZE_END);
183  name_label.set_layout_ellipsize_width(48 * PANGO_SCALE);
184  name_label.set_size_request(PX_SCALE(18, 18), PX_SCALE(50, 50));
185  name_label.set_alignment(-1.0, .5);
188 
191  number_label.set_name("tracknumber label");
192  number_label.set_angle(-90.0);
193  number_label.set_layout_ellipsize_width(18 * PANGO_SCALE);
194  number_label.set_alignment(.5, .5);
195 
196  namebx.set_size_request(PX_SCALE(18, 18), PX_SCALE(52, 52));
197  namebx.pack_start(namenumberbx, true, false, 0);
198  namenumberbx.pack_start(name_label, true, false, 0);
199  namenumberbx.pack_start(number_label, false, false, 0);
200 
201  mon_in_box.pack_start(*monitor_input_button, true, false);
202  btnbox.pack_start(mon_in_box, false, false, 1);
203  mon_disk_box.pack_start(*monitor_disk_button, true, false);
204  btnbox.pack_start(mon_disk_box, false, false, 1);
205 
206  recbox.pack_start(*rec_enable_button, true, false);
207  btnbox.pack_start(recbox, false, false, 1);
208  mutebox.pack_start(*mute_button, true, false);
209  btnbox.pack_start(mutebox, false, false, 1);
210  solobox.pack_start(*solo_button, true, false);
211  btnbox.pack_start(solobox, false, false, 1);
212 
214  rec_enable_button->set_size_request (PX_SCALE(18, 18), PX_SCALE(18, 18));
215 
217  mute_button->set_size_request (PX_SCALE(18, 18), PX_SCALE(18, 18));
218 
220  solo_button->set_size_request (PX_SCALE(18, 18), PX_SCALE(18, 18));
221 
223  monitor_input_button->set_size_request (PX_SCALE(18, 18), PX_SCALE(18, 18));
224 
226  monitor_disk_button->set_size_request (PX_SCALE(18, 18), PX_SCALE(18, 18));
227 
228  mutebox.set_size_request (PX_SCALE(18, 18), PX_SCALE(18, 18));
229  solobox.set_size_request (PX_SCALE(18, 18), PX_SCALE(18, 18));
230  recbox.set_size_request (PX_SCALE(18, 18), PX_SCALE(18, 18));
231  mon_in_box.set_size_request (PX_SCALE(18, 18), PX_SCALE(18, 18));
232  mon_disk_box.set_size_request (PX_SCALE(18, 18), PX_SCALE(18, 18));
233  spacer.set_size_request(-1,0);
234 
236  update_name_box();
238 
239  mtr_vbox.pack_start (peakbx, false, false);
240  mtr_vbox.pack_start (meterbox, true, true);
241  mtr_vbox.pack_start (spacer, false, false);
242  mtr_container.add(mtr_vbox);
243 
244  mtr_hsep.set_size_request(-1,1);
245  mtr_hsep.set_name("BlackSeparator");
246 
247  nfo_vbox.pack_start (mtr_hsep, false, false);
248  nfo_vbox.pack_start (btnbox, false, false);
249  nfo_vbox.pack_start (namebx, false, false);
250 
251  pack_start (mtr_container, true, true);
252  pack_start (nfo_vbox, false, false);
253 
254  name_label.show();
255  peak_display.show();
256  peakbx.show();
257  meter_ticks1_area.show();
258  meter_ticks2_area.show();
259  meterbox.show();
260  spacer.show();
261  level_meter->show();
262  meter_align.show();
263  peak_align.show();
264  btnbox.show();
265  mtr_vbox.show();
266  mtr_container.show();
267  mtr_hsep.show();
268  nfo_vbox.show();
269  namenumberbx.show();
270 
271  if (boost::dynamic_pointer_cast<Track>(_route)) {
272  monitor_input_button->show();
273  monitor_disk_button->show();
274  } else {
275  monitor_input_button->hide();
276  monitor_disk_button->hide();
277  }
278 
279  _route->shared_peak_meter()->ConfigurationChanged.connect (
281  );
282 
283  ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &MeterStrip::reset_peak_display));
284  ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &MeterStrip::reset_route_peak_display));
285  ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &MeterStrip::reset_group_peak_display));
286  RedrawMetrics.connect (sigc::mem_fun(*this, &MeterStrip::redraw_metrics));
287  SetMeterTypeMulti.connect (sigc::mem_fun(*this, &MeterStrip::set_meter_type_multi));
288 
290 
291  meter_ticks1_area.set_size_request(PX_SCALE(3, 3), -1);
292  meter_ticks2_area.set_size_request(PX_SCALE(3, 3), -1);
293  meter_ticks1_area.signal_expose_event().connect (sigc::mem_fun(*this, &MeterStrip::meter_ticks1_expose));
294  meter_ticks2_area.signal_expose_event().connect (sigc::mem_fun(*this, &MeterStrip::meter_ticks2_expose));
295 
298 
299  peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &MeterStrip::peak_button_release), false);
300  name_label.signal_button_release_event().connect (sigc::mem_fun(*this, &MeterStrip::name_label_button_release), false);
301 
302  UI::instance()->theme_changed.connect (sigc::mem_fun(*this, &MeterStrip::on_theme_changed));
303  ColorsChanged.connect (sigc::mem_fun (*this, &MeterStrip::on_theme_changed));
304  DPIReset.connect (sigc::mem_fun (*this, &MeterStrip::on_theme_changed));
305  Config->ParameterChanged.connect (*this, invalidator (*this), ui_bind (&MeterStrip::parameter_changed, this, _1), gui_context());
306  sess->config.ParameterChanged.connect (*this, invalidator (*this), ui_bind (&MeterStrip::parameter_changed, this, _1), gui_context());
307 
308  if (_route->is_master()) {
309  _strip_type = 4;
310  }
311  else if (boost::dynamic_pointer_cast<AudioTrack>(_route) == 0
313  /* non-master bus */
314  _strip_type = 3;
315  }
316  else if (boost::dynamic_pointer_cast<MidiTrack>(_route)) {
317  _strip_type = 2;
318  }
319  else {
320  _strip_type = 1;
321  }
322 }
323 
325 {
326  if (level_meter) {
327  delete level_meter;
328  CatchDeletion (this);
329  }
330 }
331 
332 void
334 {
335  delete this;
336 }
337 
338 void
340 {
341  SessionHandlePtr::set_session (s);
342  if (!s) return;
343  s->config.ParameterChanged.connect (*this, invalidator (*this), ui_bind (&MeterStrip::parameter_changed, this, _1), gui_context());
345  update_name_box();
346 }
347 
348 void
350 {
352 }
353 
354 std::string
356 {
357  if (_route) {
358  return string_compose ("mtrs %1", _route->id().to_s());
359  } else {
360  return string ();
361  }
362 }
363 
364 void
366 {
367  mute_button->set_text (S_("Mute|M"));
368 
369  if (_route && _route->solo_safe()) {
371  } else {
373  }
374  if (!Config->get_solo_control_is_listen_control()) {
375  solo_button->set_text (S_("Solo|S"));
376  } else {
377  switch (Config->get_listen_position()) {
378  case AfterFaderListen:
379  solo_button->set_text (S_("AfterFader|A"));
380  break;
381  case PreFaderListen:
382  solo_button->set_text (S_("PreFader|P"));
383  break;
384  }
385  }
386 
387  monitor_input_button->set_text (S_("MonitorInput|I"));
388  monitor_disk_button->set_text (S_("MonitorDisk|D"));
389 }
390 
391 void
393 {
394  if (!what_changed.contains (ARDOUR::Properties::name)) {
395  return;
396  }
397  ENSURE_GUI_THREAD (*this, &MeterStrip::strip_name_changed, what_changed);
398  name_changed();
400  if (level_meter) {
402  }
403 }
404 
405 void
407 {
409 }
410 
411 
412 void
414 {
415  float mpeak = level_meter->update_meters();
416  if (mpeak > max_peak) {
417  max_peak = mpeak;
418  if (mpeak >= ARDOUR_UI::config()->get_meter_peak()) {
420  }
421  }
422 }
423 
424 void
426 {
427  if (level_meter && _route) {
428  int meter_width = 6;
429  if (_route->shared_peak_meter()->input_streams().n_total() == 1) {
430  meter_width = 12;
431  }
432  level_meter->setup_meters (220, meter_width, 6);
433  }
434 }
435 
436 void
438 {
439  int type = 0;
440  _types.clear ();
441  bool old_has_midi = _has_midi;
442 
443  for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
444  if (c.get (*i) > 0) {
445  _types.push_back (*i);
446  type |= 1 << (*i);
447  }
448  }
449 
450  if (boost::dynamic_pointer_cast<AudioTrack>(_route) == 0
451  && boost::dynamic_pointer_cast<MidiTrack>(_route) == 0
452  ) {
453  meter_ticks1_area.set_name ("MyAudioBusMetricsLeft");
454  meter_ticks2_area.set_name ("MyAudioBusMetricsRight");
455  _has_midi = false;
456  }
457  else if (type == (1 << DataType::AUDIO)) {
458  meter_ticks1_area.set_name ("MyAudioTrackMetricsLeft");
459  meter_ticks2_area.set_name ("MyAudioTrackMetricsRight");
460  _has_midi = false;
461  }
462  else if (type == (1 << DataType::MIDI)) {
463  meter_ticks1_area.set_name ("MidiTrackMetricsLeft");
464  meter_ticks2_area.set_name ("MidiTrackMetricsRight");
465  _has_midi = true;
466  } else {
467  meter_ticks1_area.set_name ("AudioMidiTrackMetricsLeft");
468  meter_ticks2_area.set_name ("AudioMidiTrackMetricsRight");
469  _has_midi = true;
470  }
472 
474  if (old_has_midi != _has_midi) MetricChanged();
475  else ConfigurationChanged();
476 }
477 
478 void
480 {
481  std::string n;
482  _tick_bar = m;
483  if (_tick_bar & 1) {
484  n = meter_ticks1_area.get_name();
485  if (n.substr(0,3) != "Bar") {
486  meter_ticks1_area.set_name("Bar" + n);
487  }
488  } else {
489  n = meter_ticks1_area.get_name();
490  if (n.substr(0,3) == "Bar") {
491  meter_ticks1_area.set_name(n.substr(3,-1));
492  }
493  }
494  if (_tick_bar & 2) {
495  n = meter_ticks2_area.get_name();
496  if (n.substr(0,3) != "Bar") {
497  meter_ticks2_area.set_name("Bar" + n);
498  }
499  } else {
500  n = meter_ticks2_area.get_name();
501  if (n.substr(0,3) == "Bar") {
502  meter_ticks2_area.set_name(n.substr(3,-1));
503  }
504  }
505 }
506 
507 void
508 MeterStrip::on_size_request (Gtk::Requisition* r)
509 {
510  VBox::on_size_request(r);
511 }
512 
513 void
514 MeterStrip::on_size_allocate (Gtk::Allocation& a)
515 {
516  const int wh = a.get_height();
517  int nh;
518  int mh = 0;
519  if (_session) {
520  mh = _session->config.get_meterbridge_label_height();
521  }
522  switch (mh) {
523  default:
524  case 0:
525  nh = ceilf(wh * .12f);
526  if (nh < 52) nh = 52;
527  if (nh > 148) nh = 148;
528  break;
529  case 1:
530  nh = 52;
531  break;
532  case 2:
533  nh = 88;
534  break;
535  case 3:
536  nh = 106;
537  break;
538  case 4:
539  nh = 148;
540  break;
541  }
542  int tnh = 0;
543  if (_session && _session->config.get_track_name_number()) {
544  // NB numbers are rotated 90deg. on the meterbridge
545  tnh = 4 + std::max(2u, _session->track_number_decimals()) * 8; // TODO 8 = max_with_of_digit_0_to_9()
546  }
547 
548  nh *= ARDOUR_UI::ui_scale;
549  tnh *= ARDOUR_UI::ui_scale;
550 
551  int prev_height, ignored;
552  bool need_relayout = false;
553 
554  namebx.get_size_request (ignored, prev_height);
555  namebx.set_size_request (PX_SCALE(18, 18), nh + tnh);
556 
557  if (prev_height != nh + tnh) {
558  need_relayout = true;
559  }
560 
561  namenumberbx.get_size_request (ignored, prev_height);
562  namenumberbx.set_size_request (PX_SCALE(18, 18), nh + tnh);
563 
564  if (prev_height != nh + tnh) {
565  need_relayout = true;
566  }
567 
568  if (_route) {
569  int nlh = nh + (_route->is_master() ? tnh : -1);
570  name_label.get_size_request(ignored, prev_height);
571  name_label.set_size_request (PX_SCALE(18, 18), nlh);
572  name_label.set_layout_ellipsize_width ((nh - 4 + (_route->is_master() ? tnh : 0)) * PANGO_SCALE); // XXX
573  if (prev_height != nlh) {
574  need_relayout = true;
575  }
576  }
577 
578  VBox::on_size_allocate(a);
579 
580  if (need_relayout) {
581  queue_resize();
582  MetricChanged(); // force re-layout, parent on_scroll(), queue_resize()
583  }
584 }
585 
586 gint
588 {
589  if (_route) {
591  } else {
593  }
594 }
595 
596 void
598 {
599  if (metric_type == mt && _metricmode == metricmode) {
600  return;
601  }
602  metric_type = mt;
603  _metricmode = metricmode;
604 
605  _types.clear ();
606  switch(metricmode) {
607  case 0:
608  meter_metric_area.set_name ("MidiTrackMetricsLeft");
609  _types.push_back (DataType::MIDI);
610  break;
611  case 1:
612  meter_metric_area.set_name ("AudioTrackMetricsLeft");
613  _types.push_back (DataType::AUDIO);
614  break;
615  case 2:
616  meter_metric_area.set_name ("MidiTrackMetricsRight");
617  _types.push_back (DataType::MIDI);
618  break;
619  case 3:
620  default:
621  meter_metric_area.set_name ("AudioTrackMetricsRight");
622  _types.push_back (DataType::AUDIO);
623  break;
624  }
625  update_background (mt);
626  meter_metric_area.queue_draw ();
627 }
628 
629 void
631 {
632  switch(type) {
633  case MeterIEC1DIN:
634  case MeterIEC1NOR:
635  case MeterIEC2BBC:
636  case MeterIEC2EBU:
637  case MeterK12:
638  case MeterK14:
639  case MeterK20:
640  mtr_container.set_name ("meterstripPPM");
641  break;
642  case MeterVU:
643  mtr_container.set_name ("meterstripVU");
644  break;
645  default:
646  mtr_container.set_name ("meterstripDPM");
647  }
648 }
649 
650 MeterType
652 {
653  assert((!_route && _strip_type == 0) || (_route && _strip_type != 0));
654  if (!_route) return metric_type;
655  return _route->meter_type();
656 }
657 
658 gint
660 {
661  assert(_route);
663 }
664 
665 gint
667 {
668  assert(_route);
670 }
671 
672 void
674 {
675  if (_route && _route.get() == route) {
677  }
678 }
679 
680 void
682 {
683  if (_route && group == _route->route_group()) {
685  }
686 }
687 
688 void
690 {
691  _route->shared_peak_meter()->reset_max();
693  max_peak = -INFINITY;
695 }
696 
697 bool
699 {
700  if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) {
702  } else if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
703  if (_route) {
705  }
706  } else {
708  }
709  return false;
710 }
711 
712 void
714 {
715  meter_metric_area.queue_draw();
716  meter_ticks1_area.queue_draw();
717  meter_ticks2_area.queue_draw();
718 }
719 
720 void
722 {
723  if (!_session) return;
724  int height = 0;
725  if (_session->config.get_show_mute_on_meterbridge()) {
726  height += PX_SCALE(18, 18) + PX_SCALE(2, 2);
727  mutebox.show();
728  } else {
729  mutebox.hide();
730  }
731  if (_session->config.get_show_solo_on_meterbridge()) {
732  height += PX_SCALE(18, 18) + PX_SCALE(2, 2);
733  solobox.show();
734  } else {
735  solobox.hide();
736  }
737  if (_session->config.get_show_rec_on_meterbridge()) {
738  height += PX_SCALE(18, 18) + PX_SCALE(2, 2);
739  recbox.show();
740  } else {
741  recbox.hide();
742  }
743  if (_session->config.get_show_monitor_on_meterbridge()) {
744  height += PX_SCALE(18, 18) + PX_SCALE(2, 2);
745  height += PX_SCALE(18, 18) + PX_SCALE(2, 2);
746  mon_in_box.show();
747  mon_disk_box.show();
748  } else {
749  mon_in_box.hide();
750  mon_disk_box.hide();
751  }
752  btnbox.set_size_request(PX_SCALE(18, 18), height);
753  check_resize();
754 }
755 
756 void
758 {
759  if (!_session) return;
760  if (_session->config.get_show_name_on_meterbridge()) {
761  namebx.show();
762  } else {
763  namebx.hide();
764  }
765 }
766 
767 void
768 MeterStrip::parameter_changed (std::string const & p)
769 {
770  if (p == "meter-peak") {
771  max_peak = -INFINITY;
772  }
773  else if (p == "show-rec-on-meterbridge") {
775  }
776  else if (p == "show-mute-on-meterbridge") {
778  }
779  else if (p == "show-solo-on-meterbridge") {
781  }
782  else if (p == "show-name-on-meterbridge") {
783  update_name_box();
784  }
785  else if (p == "show-monitor-on-meterbridge") {
787  }
788  else if (p == "meterbridge-label-height") {
789  queue_resize();
790  }
791  else if (p == "track-name-number") {
792  name_changed();
793  queue_resize();
794  }
795 }
796 
797 void
799  if (!_route) {
800  return;
801  }
803  if (_session && _session->config.get_track_name_number()) {
804  const int64_t track_number = _route->track_number ();
805  if (track_number == 0) {
806  number_label.set_text("-");
807  number_label.hide();
808  } else {
809  number_label.set_text (PBD::to_string (abs(_route->track_number ()), std::dec));
810  number_label.show();
811  }
812  const int tnh = 4 + std::max(2u, _session->track_number_decimals()) * 8; // TODO 8 = max_width_of_digit_0_to_9()
813  // NB numbers are rotated 90deg. on the meterbridge -> use height
814  number_label.set_size_request(PX_SCALE(18, 18), tnh * ARDOUR_UI::ui_scale);
815  } else {
816  number_label.hide();
817  }
818 }
819 
820 bool
822 {
823  if (ev->button == 3) {
824  if (_route && _route->shared_peak_meter()->input_streams ().n_audio() > 0) {
826  }
827  return true;
828  }
829 
830  return false;
831 }
832 
833 void
835 {
836  using namespace Gtk::Menu_Helpers;
837 
838  Gtk::Menu* m = manage (new Menu);
839  MenuList& items = m->items ();
840 
841  RadioMenuItem::Group group;
842 
855 
856  MeterType cmt = _route->meter_type();
857  const std::string cmn = ArdourMeter::meter_type_string(cmt);
858 
859  items.push_back (SeparatorElem());
860  items.push_back (MenuElem (string_compose(_("Change all in Group to %1"), cmn),
861  sigc::bind (SetMeterTypeMulti, -1, _route->route_group(), cmt)));
862  items.push_back (MenuElem (string_compose(_("Change all to %1"), cmn),
863  sigc::bind (SetMeterTypeMulti, 0, _route->route_group(), cmt)));
864  items.push_back (MenuElem (string_compose(_("Change same track-type to %1"), cmn),
865  sigc::bind (SetMeterTypeMulti, _strip_type, _route->route_group(), cmt)));
866 
867  m->popup (ev->button, ev->time);
868  _suspend_menu_callbacks = false;
869 }
870 
871 bool
873 {
874  if (!_session) return true;
875  if (!_session->config.get_show_name_on_meterbridge()) return true;
876 
877  if (ev->button == 3) {
879  return true;
880  }
881 
882  return false;
883 }
884 
885 void
887 {
888  using namespace Gtk::Menu_Helpers;
889 
890  Gtk::Menu* m = manage (new Menu);
891  MenuList& items = m->items ();
892 
893  RadioMenuItem::Group group;
894 
896  add_label_height_item (items, group, _("Variable height"), 0);
897  add_label_height_item (items, group, _("Short"), 1);
898  add_label_height_item (items, group, _("Tall"), 2);
899  add_label_height_item (items, group, _("Grande"), 3);
900  add_label_height_item (items, group, _("Venti"), 4);
901 
902  m->popup (ev->button, ev->time);
903  _suspend_menu_callbacks = false;
904 }
905 
906 void
907 MeterStrip::add_label_height_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, uint32_t h)
908 {
909  using namespace Menu_Helpers;
910 
911  items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (*this, &MeterStrip::set_label_height), h)));
912  RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
913  i->set_active (_session && _session->config.get_meterbridge_label_height() == h);
914 }
915 
916 void
917 MeterStrip::add_level_meter_type_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, MeterType type)
918 {
919  using namespace Menu_Helpers;
920 
921  items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (*this, &MeterStrip::set_meter_type), type)));
922  RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
923  i->set_active (_route->meter_type() == type);
924 }
925 
926 void
928 {
929  if (_suspend_menu_callbacks) return;
930  if (_route->meter_type() == type) return;
931 
932  level_meter->set_type (type);
933 }
934 
935 void
937 {
938  if (_suspend_menu_callbacks) return;
939  _session->config.set_meterbridge_label_height(h);
940 }
941 
942 void
944 {
945  if (_route->meter_type() != type) {
946  _route->set_meter_type(type);
947  }
948  update_background (type);
949  MetricChanged();
950 }
951 
952 void
954 {
955  switch (what) {
956  case -1:
957  if (_route && group == _route->route_group()) {
958  level_meter->set_type (type);
959  }
960  break;
961  case 0:
962  level_meter->set_type (type);
963  default:
964  if (what == _strip_type) {
965  level_meter->set_type (type);
966  }
967  break;
968  }
969 }
LevelMeterHBox * level_meter
Definition: meter_strip.h:131
Gdk::Color color() const
Definition: route_ui.cc:2138
void update_name_box()
Definition: meter_strip.cc:757
std::string to_string(T t, std::ios_base &(*f)(std::ios_base &))
Definition: convert.h:53
bool _has_midi
Definition: meter_strip.h:126
void redraw_metrics()
Definition: meter_strip.cc:713
void set_session(ARDOUR::Session *s)
Definition: meter_strip.cc:339
virtual void set_meter(ARDOUR::PeakMeter *meter)
Definition: level_meter.cc:77
#define ui_bind(f,...)
Definition: gui_thread.h:37
PBD::Signal0< void > DropReferences
Definition: destructible.h:34
ArdourButton name_label
Definition: meter_strip.h:104
Gtk::Alignment meter_align
Definition: meter_strip.h:116
PBD::Signal1< void, const PropertyChange & > PropertyChanged
Definition: stateful.h:87
void fast_update()
Definition: meter_strip.cc:413
static PBD::Signal0< void > ConfigurationChanged
Definition: meter_strip.h:59
Gtk::VBox namenumberbx
Definition: meter_strip.h:103
sigc::signal< void > DPIReset
Definition: utils.cc:68
void on_size_request(Gtk::Requisition *)
Definition: meter_strip.cc:508
void clear_meters(bool reset_highlight=true)
Definition: level_meter.cc:496
void self_delete()
Definition: meter_strip.cc:333
Definition: ardour_ui.h:130
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
static ARDOUR_UI * instance()
Definition: ardour_ui.h:187
LIBARDOUR_API PBD::PropertyDescriptor< std::string > name
void set_type(ARDOUR::MeterType)
Definition: level_meter.cc:472
void set_meter_type(ARDOUR::MeterType mode)
Definition: meter_strip.cc:927
void set_meter_type(MeterType t)
Definition: route.h:189
bool solo_safe() const
Definition: route.cc:804
void reset_group_peak_display(ARDOUR::RouteGroup *)
Definition: meter_strip.cc:681
bool level_meter_button_press(GdkEventButton *ev)
Definition: meter_strip.cc:821
void meter_configuration_changed(ARDOUR::ChanCount)
Definition: meter_strip.cc:437
bool name_label_button_release(GdkEventButton *ev)
Definition: meter_strip.cc:872
tuple f
Definition: signals.py:35
virtual void set_route(boost::shared_ptr< ARDOUR::Route >)
Definition: route_ui.cc:226
Definition: Beats.hpp:239
static PBD::Signal1< void, MeterStrip * > CatchDeletion
Definition: meter_strip.h:57
void popup_level_meter_menu(GdkEventButton *ev)
Definition: meter_strip.cc:834
void set_button_names()
Definition: meter_strip.cc:365
Gtk::DrawingArea meter_ticks1_area
Definition: meter_strip.h:107
SessionConfiguration config
Definition: session.h:866
boost::shared_ptr< PeakMeter > shared_peak_meter() const
Definition: route.h:198
void on_size_allocate(Gtk::Allocation &)
Definition: meter_strip.cc:514
void meter_type_changed(ARDOUR::MeterType)
Definition: meter_strip.cc:943
MeterStrip(ARDOUR::Session *, boost::shared_ptr< ARDOUR::Route >)
Definition: meter_strip.cc:119
float update_meters()
Definition: level_meter.cc:127
#define ENSURE_GUI_THREAD(obj, method,...)
Definition: gui_thread.h:34
#define invalidator(x)
Definition: gui_thread.h:40
Gtk::HBox mon_in_box
Definition: meter_strip.h:113
void set_elements(Element)
Gtk::HBox peakbx
Definition: meter_strip.h:118
void strip_property_changed(const PBD::PropertyChange &)
Definition: meter_strip.cc:392
Gtk::HBox solobox
Definition: meter_strip.h:111
void reset_peak_display()
Definition: meter_strip.cc:689
sigc::signal< void, ARDOUR::Route * > ResetRoutePeakDisplays
PBD::ScopedConnectionList level_meter_connection
Definition: meter_strip.h:78
void setup_meters(int len=0, int width=3, int thin=2)
Definition: level_meter.cc:237
void popup_name_label_menu(GdkEventButton *ev)
Definition: meter_strip.cc:886
void reset_route_peak_display(ARDOUR::Route *)
Definition: meter_strip.cc:673
#define _(Text)
Definition: i18n.h:11
Gtk::VBox mtr_vbox
Definition: meter_strip.h:96
const std::string meter_type_string(ARDOUR::MeterType)
ArdourButton * rec_enable_button
Definition: route_ui.h:102
Gtk::DrawingArea meter_metric_area
Definition: meter_strip.h:106
int64_t track_number() const
Definition: route.h:302
void name_changed()
Definition: meter_strip.cc:798
uint32_t gdk_color_to_rgba(Gdk::Color const &)
Definition: utils.cc:285
ArdourButton * solo_button
Definition: route_ui.h:101
PBD::Signal1< bool, GdkEventButton * > ButtonPress
Definition: level_meter.h:73
void blink_rec_display(bool onoff)
Definition: meter_strip.cc:349
Gtk::EventBox mtr_container
Definition: meter_strip.h:98
ExplicitActive
Definition: widget_state.h:13
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
static float minus_infinity(void)
Definition: fastlog.h:44
ARDOUR::MeterType meter_type()
Definition: meter_strip.cc:651
virtual void blink_rec_display(bool onoff)
Definition: route_ui.cc:1252
Gtk::HBox recbox
Definition: meter_strip.h:112
Gtkmm2ext::VisualState visual_state() const
Definition: cairo_widget.h:41
void set_metric_mode(int, ARDOUR::MeterType)
Definition: meter_strip.cc:597
MeterType
Definition: types.h:182
ArdourButton * monitor_input_button
Definition: route_ui.h:104
#define PX_SCALE(pxmin, dflt)
Definition: meter_strip.cc:62
Definition: amp.h:29
void set_fixed_colors(const uint32_t active_color, const uint32_t inactive_color)
const PBD::ID & id() const
Definition: stateful.h:68
std::string to_s() const
Definition: id.cc:78
gint meter_expose_metrics(GdkEventExpose *ev, ARDOUR::MeterType type, std::vector< ARDOUR::DataType > types, Gtk::DrawingArea *mma)
Gtk::HBox mutebox
Definition: meter_strip.h:110
void set_visual_state(Gtkmm2ext::VisualState)
Gtk::HBox spacer
Definition: meter_strip.h:101
#define gui_context()
Definition: gui_thread.h:36
Gtk::Alignment peak_align
Definition: meter_strip.h:117
float max_peak
Definition: meter_strip.h:125
static PBD::Signal0< void > MetricChanged
Definition: meter_strip.h:58
void update_background(ARDOUR::MeterType)
Definition: meter_strip.cc:630
gint meter_ticks2_expose(GdkEventExpose *)
Definition: meter_strip.cc:666
sigc::signal< void, int, ARDOUR::RouteGroup *, ARDOUR::MeterType > SetMeterTypeMulti
std::string name() const
Definition: route_ui.cc:1774
void set_active_state(Gtkmm2ext::ActiveState)
void add_label_height_item(Gtk::Menu_Helpers::MenuList &, Gtk::RadioMenuItem::Group &, std::string const &, uint32_t)
Definition: meter_strip.cc:907
std::string state_id() const
Definition: meter_strip.cc:355
void set_layout_ellipsize_width(int w)
PBD::ScopedConnectionList meter_route_connections
Definition: meter_strip.h:77
sigc::signal< void > ResetAllPeakDisplays
T * get() const
Definition: shared_ptr.hpp:268
PBD::Signal1< void, std::string > ParameterChanged
Definition: configuration.h:44
void add_level_meter_type_item(Gtk::Menu_Helpers::MenuList &, Gtk::RadioMenuItem::Group &, std::string const &, ARDOUR::MeterType)
Definition: meter_strip.cc:917
void set_tip(Gtk::Widget &w, const gchar *tip)
void set_angle(const double)
void route_color_changed()
Definition: meter_strip.cc:406
Gtk::HBox mon_disk_box
Definition: meter_strip.h:114
Insensitive
Definition: widget_state.h:23
void set_text_ellipsize(Pango::EllipsizeMode)
boost::shared_ptr< ARDOUR::Route > route()
Definition: meter_strip.h:55
uint32_t get(DataType t) const
Definition: chan_count.h:59
Gtk::HBox namebx
Definition: meter_strip.h:102
boost::shared_ptr< ARDOUR::Route > _route
Definition: meter_strip.h:76
Gtk::DrawingArea meter_ticks2_area
Definition: meter_strip.h:108
bool _suspend_menu_callbacks
Definition: meter_strip.h:148
Gtk::VBox btnbox
Definition: meter_strip.h:119
bool is_master() const
Definition: route.h:111
ArdourButton * mute_button
Definition: route_ui.h:100
gint meter_metrics_expose(GdkEventExpose *)
Definition: meter_strip.cc:587
RouteGroup * route_group() const
std::string name() const
static UIConfiguration * config()
Definition: ardour_ui.h:188
void set_text(const std::string &)
uint32_t track_number_decimals() const
Definition: session.h:268
MeterType meter_type() const
Definition: route.h:190
bool peak_button_release(GdkEventButton *)
Definition: meter_strip.cc:698
void set_meter_type_multi(int, ARDOUR::RouteGroup *, ARDOUR::MeterType)
Definition: meter_strip.cc:953
sigc::signal< void > ColorsChanged
sigc::signal< void, ARDOUR::RouteGroup * > ResetGroupPeakDisplays
Definition: debug.h:30
Gtk::HSeparator mtr_hsep
Definition: meter_strip.h:99
Gtk::VBox nfo_vbox
Definition: meter_strip.h:97
void set_tick_bar(int)
Definition: meter_strip.cc:479
#define S_(Text)
Definition: i18n.h:18
bool contains(PropertyDescriptor< T > p) const
void parameter_changed(std::string const &p)
Definition: meter_strip.cc:768
std::vector< ARDOUR::DataType > _types
Definition: meter_strip.h:122
void set_alignment(const float, const float)
Off
Definition: widget_state.h:13
gint meter_ticks1_expose(GdkEventExpose *)
Definition: meter_strip.cc:659
static float ui_scale
Definition: ardour_ui.h:189
int _strip_type
Definition: meter_strip.h:128
void set_label_height(uint32_t)
Definition: meter_strip.cc:936
int _metricmode
Definition: meter_strip.h:129
void update_button_box()
Definition: meter_strip.cc:721
ArdourButton peak_display
Definition: meter_strip.h:120
Gtk::HBox meterbox
Definition: meter_strip.h:100
ARDOUR::Session * _session
ARDOUR::MeterType metric_type
Definition: meter_strip.h:123
ArdourButton number_label
Definition: meter_strip.h:105
void set_corner_radius(float)
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
PBD::Signal1< void, ARDOUR::MeterType > MeterTypeChanged
Definition: level_meter.h:75
gint meter_expose_ticks(GdkEventExpose *ev, ARDOUR::MeterType type, std::vector< ARDOUR::DataType > types, Gtk::DrawingArea *mta)
ArdourButton * monitor_disk_button
Definition: route_ui.h:105
void on_theme_changed()
Definition: meter_strip.cc:425
sigc::signal< void > RedrawMetrics
void init()
Definition: route_ui.cc:111