Robin Gareus
4050ca5633
Copyright-holder and year information is extracted from git log. git history begins in 2005. So (C) from 1998..2005 is lost. Also some (C) assignment of commits where the committer didn't use --author.
774 lines
19 KiB
C++
774 lines
19 KiB
C++
/*
|
|
* Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
|
|
* Copyright (C) 2014-2017 Tim Mayberry <mojofunk@gmail.com>
|
|
* Copyright (C) 2015-2016 Paul Davis <paul@linuxaudiosystems.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#ifdef WAF_BUILD
|
|
#include "gtk2ardour-config.h"
|
|
#endif
|
|
|
|
#include <map>
|
|
#include <sigc++/bind.h>
|
|
|
|
#include <gtkmm/accelmap.h>
|
|
#include <gtkmm/comboboxtext.h>
|
|
|
|
#include <glibmm/threads.h>
|
|
|
|
#include <gtkmm2ext/gtk_ui.h>
|
|
#include <gtkmm2ext/utils.h>
|
|
#include <gtkmm2ext/window_title.h>
|
|
|
|
#include "ardour/debug.h"
|
|
#include "ardour/midi_track.h"
|
|
#include "ardour/route_group.h"
|
|
#include "ardour/session.h"
|
|
|
|
#include "ardour/audio_track.h"
|
|
#include "ardour/midi_track.h"
|
|
|
|
#include "meterbridge.h"
|
|
|
|
#include "keyboard.h"
|
|
#include "monitor_section.h"
|
|
#include "public_editor.h"
|
|
#include "ardour_ui.h"
|
|
#include "utils.h"
|
|
#include "route_sorter.h"
|
|
#include "actions.h"
|
|
#include "gui_thread.h"
|
|
#include "meter_patterns.h"
|
|
#include "timers.h"
|
|
|
|
#include "pbd/i18n.h"
|
|
|
|
using namespace ARDOUR;
|
|
using namespace ARDOUR_UI_UTILS;
|
|
using namespace PBD;
|
|
using namespace Gtk;
|
|
using namespace Glib;
|
|
using namespace Gtkmm2ext;
|
|
using namespace std;
|
|
using namespace ArdourMeter;
|
|
|
|
using PBD::atoi;
|
|
|
|
Meterbridge* Meterbridge::_instance = 0;
|
|
|
|
Meterbridge*
|
|
Meterbridge::instance ()
|
|
{
|
|
if (!_instance) {
|
|
_instance = new Meterbridge;
|
|
}
|
|
|
|
return _instance;
|
|
}
|
|
|
|
Meterbridge::Meterbridge ()
|
|
: Window (Gtk::WINDOW_TOPLEVEL)
|
|
, VisibilityTracker (*((Gtk::Window*) this))
|
|
, _visible (false)
|
|
, _show_busses (false)
|
|
, metrics_left (1, MeterPeak)
|
|
, metrics_right (2, MeterPeak)
|
|
, cur_max_width (-1)
|
|
{
|
|
set_name ("Meter Bridge");
|
|
|
|
m_width = default_width;
|
|
m_height = default_height;
|
|
m_root_x = 1;
|
|
m_root_y = 1;
|
|
|
|
update_title ();
|
|
|
|
set_wmclass (X_("ardour_mixer"), PROGRAM_NAME);
|
|
|
|
#ifdef __APPLE__
|
|
set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
|
|
#else
|
|
if (UIConfiguration::instance().get_all_floating_windows_are_dialogs()) {
|
|
set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
|
|
} else {
|
|
set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY);
|
|
}
|
|
#endif
|
|
|
|
Gdk::Geometry geom;
|
|
geom.max_width = 1<<16;
|
|
geom.max_height = max_height;
|
|
geom.min_width = 40;
|
|
geom.min_height = -1;
|
|
geom.height_inc = 16;
|
|
geom.width_inc = 1;
|
|
assert(max_height % 16 == 0);
|
|
set_geometry_hints(*((Gtk::Window*) this), geom, Gdk::HINT_MIN_SIZE | Gdk::HINT_MAX_SIZE | Gdk::HINT_RESIZE_INC);
|
|
|
|
set_border_width (0);
|
|
|
|
metrics_vpacker_left.pack_start (metrics_left, true, true);
|
|
metrics_vpacker_left.pack_start (metrics_spacer_left, false, false);
|
|
metrics_spacer_left.set_size_request(-1, 0);
|
|
metrics_spacer_left.set_spacing(0);
|
|
|
|
metrics_vpacker_right.pack_start (metrics_right, true, true);
|
|
metrics_vpacker_right.pack_start (metrics_spacer_right, false, false);
|
|
metrics_spacer_right.set_size_request(-1, 0);
|
|
metrics_spacer_right.set_spacing(0);
|
|
|
|
signal_delete_event().connect (sigc::mem_fun (*this, &Meterbridge::hide_window));
|
|
signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
|
|
MeterStrip::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Meterbridge::remove_strip, this, _1), gui_context());
|
|
MeterStrip::MetricChanged.connect (*this, invalidator (*this), boost::bind(&Meterbridge::sync_order_keys, this), gui_context());
|
|
MeterStrip::ConfigurationChanged.connect (*this, invalidator (*this), boost::bind(&Meterbridge::queue_resize, this), gui_context());
|
|
PresentationInfo::Change.connect (*this, invalidator (*this), boost::bind (&Meterbridge::resync_order, this, _1), gui_context());
|
|
|
|
/* work around ScrolledWindowViewport alignment mess Part one */
|
|
Gtk::HBox * yspc = manage (new Gtk::HBox());
|
|
yspc->set_size_request(-1, 1);
|
|
Gtk::VBox * xspc = manage (new Gtk::VBox());
|
|
xspc->pack_start(meterarea, true, true);
|
|
xspc->pack_start(*yspc, false, false);
|
|
yspc->show();
|
|
xspc->show();
|
|
|
|
meterarea.set_spacing(0);
|
|
scroller.set_shadow_type(Gtk::SHADOW_NONE);
|
|
scroller.set_border_width(0);
|
|
scroller.add (*xspc);
|
|
scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER);
|
|
|
|
global_hpacker.pack_start (metrics_vpacker_left, false, false);
|
|
global_hpacker.pack_start (scroller, true, true);
|
|
global_hpacker.pack_start (metrics_vpacker_right, false, false);
|
|
|
|
global_vpacker.pack_start (global_hpacker, true, true);
|
|
add (global_vpacker);
|
|
|
|
metrics_left.show();
|
|
metrics_right.show();
|
|
|
|
metrics_vpacker_left.show();
|
|
metrics_spacer_left.show();
|
|
metrics_vpacker_right.show();
|
|
metrics_spacer_right.show();
|
|
|
|
meterarea.show();
|
|
global_vpacker.show();
|
|
global_hpacker.show();
|
|
scroller.show();
|
|
|
|
/* the return of the ScrolledWindowViewport mess:
|
|
* remove shadow from scrollWindow's viewport
|
|
* see http://www.mail-archive.com/gtkmm-list@gnome.org/msg03509.html
|
|
*/
|
|
Gtk::Viewport* viewport = (Gtk::Viewport*) scroller.get_child();
|
|
viewport->set_shadow_type(Gtk::SHADOW_NONE);
|
|
viewport->set_border_width(0);
|
|
|
|
UI::instance()->theme_changed.connect (sigc::mem_fun(*this, &Meterbridge::on_theme_changed));
|
|
UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &Meterbridge::on_theme_changed));
|
|
UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &Meterbridge::on_theme_changed));
|
|
}
|
|
|
|
Meterbridge::~Meterbridge ()
|
|
{
|
|
while (_metrics.size() > 0) {
|
|
delete (_metrics.back());
|
|
_metrics.pop_back();
|
|
}
|
|
}
|
|
|
|
void
|
|
Meterbridge::show_window ()
|
|
{
|
|
present();
|
|
if (!_visible) {
|
|
set_window_pos_and_size ();
|
|
}
|
|
_visible = true;
|
|
}
|
|
|
|
/* code duplicated from gtk2_ardour/mixer_ui.cc Mixer_UI::update_title() */
|
|
void
|
|
Meterbridge::update_title ()
|
|
{
|
|
if (_session) {
|
|
string n;
|
|
|
|
if (_session->snap_name() != _session->name()) {
|
|
n = _session->snap_name ();
|
|
} else {
|
|
n = _session->name ();
|
|
}
|
|
|
|
if (_session->dirty ()) {
|
|
n = "*" + n;
|
|
}
|
|
|
|
WindowTitle title (n);
|
|
title += S_("Window|Meterbridge");
|
|
title += Glib::get_application_name ();
|
|
set_title (title.get_string());
|
|
|
|
} else {
|
|
|
|
WindowTitle title (S_("Window|Meterbridge"));
|
|
title += Glib::get_application_name ();
|
|
set_title (title.get_string());
|
|
}
|
|
}
|
|
|
|
void
|
|
Meterbridge::set_window_pos_and_size ()
|
|
{
|
|
resize (m_width, m_height);
|
|
if (m_root_x >= 0 && m_root_y >= 0) {
|
|
move (m_root_x, m_root_y);
|
|
}
|
|
}
|
|
|
|
void
|
|
Meterbridge::get_window_pos_and_size ()
|
|
{
|
|
get_position(m_root_x, m_root_y);
|
|
get_size(m_width, m_height);
|
|
}
|
|
|
|
bool
|
|
Meterbridge::hide_window (GdkEventAny *ev)
|
|
{
|
|
if (!_visible) return 0;
|
|
get_window_pos_and_size();
|
|
_visible = false;
|
|
return just_hide_it(ev, static_cast<Gtk::Window *>(this));
|
|
}
|
|
|
|
bool
|
|
Meterbridge::on_key_press_event (GdkEventKey* ev)
|
|
{
|
|
if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
|
|
return true;
|
|
}
|
|
return relay_key_press (ev, this);
|
|
}
|
|
|
|
bool
|
|
Meterbridge::on_key_release_event (GdkEventKey* ev)
|
|
{
|
|
if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
|
|
return true;
|
|
}
|
|
/* don't forward releases */
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
Meterbridge::on_scroll_event (GdkEventScroll* ev)
|
|
{
|
|
switch (ev->direction) {
|
|
case GDK_SCROLL_LEFT:
|
|
scroll_left ();
|
|
return true;
|
|
case GDK_SCROLL_UP:
|
|
if (ev->state & Keyboard::TertiaryModifier) {
|
|
scroll_left ();
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
case GDK_SCROLL_RIGHT:
|
|
scroll_right ();
|
|
return true;
|
|
|
|
case GDK_SCROLL_DOWN:
|
|
if (ev->state & Keyboard::TertiaryModifier) {
|
|
scroll_right ();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
Meterbridge::scroll_left ()
|
|
{
|
|
if (!scroller.get_hscrollbar()) return;
|
|
Adjustment* adj = scroller.get_hscrollbar()->get_adjustment();
|
|
/* stupid GTK: can't rely on clamping across versions */
|
|
scroller.get_hscrollbar()->set_value (max (adj->get_lower(), adj->get_value() - adj->get_step_increment()));
|
|
}
|
|
|
|
void
|
|
Meterbridge::scroll_right ()
|
|
{
|
|
if (!scroller.get_hscrollbar()) return;
|
|
Adjustment* adj = scroller.get_hscrollbar()->get_adjustment();
|
|
/* stupid GTK: can't rely on clamping across versions */
|
|
scroller.get_hscrollbar()->set_value (min (adj->get_upper(), adj->get_value() + adj->get_step_increment()));
|
|
}
|
|
|
|
void
|
|
Meterbridge::on_size_request (Gtk::Requisition* r)
|
|
{
|
|
meter_clear_pattern_cache(3);
|
|
Gtk::Window::on_size_request(r);
|
|
|
|
Gdk::Geometry geom;
|
|
Gtk::Requisition mr = meterarea.size_request();
|
|
|
|
geom.max_width = mr.width + metrics_left.get_width() + metrics_right.get_width();
|
|
geom.max_width = std::max(50, geom.max_width);
|
|
geom.max_height = max_height;
|
|
|
|
if (cur_max_width != geom.max_width) {
|
|
cur_max_width = geom.max_width;
|
|
/* height resizes are 'heavy' since the metric areas and meter-patterns
|
|
* are re-generated. limit to 16px steps. */
|
|
geom.height_inc = 16;
|
|
geom.width_inc = 1;
|
|
geom.min_width = 40;
|
|
geom.min_height = -1;
|
|
set_geometry_hints(*((Gtk::Window*) this), geom, Gdk::HINT_MIN_SIZE | Gdk::HINT_MAX_SIZE | Gdk::HINT_RESIZE_INC);
|
|
}
|
|
}
|
|
|
|
void
|
|
Meterbridge::on_size_allocate (Gtk::Allocation& a)
|
|
{
|
|
const Gtk::Scrollbar * hsc = scroller.get_hscrollbar();
|
|
|
|
/* switch left/right edge patterns depending on horizontal scroll-position */
|
|
if (scroller.get_hscrollbar_visible() && hsc) {
|
|
if (!scroll_connection.connected()) {
|
|
scroll_connection = scroller.get_hscrollbar()->get_adjustment()->signal_value_changed().connect(sigc::mem_fun (*this, &Meterbridge::on_scroll));
|
|
scroller.get_hscrollbar()->get_adjustment()->signal_changed().connect(sigc::mem_fun (*this, &Meterbridge::on_scroll));
|
|
}
|
|
gint scrollbar_spacing;
|
|
gtk_widget_style_get (GTK_WIDGET (scroller.gobj()),
|
|
"scrollbar-spacing", &scrollbar_spacing, NULL);
|
|
const int h = hsc->get_height() + scrollbar_spacing + 1;
|
|
metrics_spacer_left.set_size_request(-1, h);
|
|
metrics_spacer_right.set_size_request(-1, h);
|
|
} else {
|
|
metrics_spacer_left.set_size_request(-1, 0);
|
|
metrics_spacer_right.set_size_request(-1, 0);
|
|
}
|
|
Gtk::Window::on_size_allocate(a);
|
|
}
|
|
|
|
void
|
|
Meterbridge::on_scroll()
|
|
{
|
|
if (!scroller.get_hscrollbar()) return;
|
|
|
|
Adjustment* adj = scroller.get_hscrollbar()->get_adjustment();
|
|
int leftend = adj->get_value();
|
|
int rightend = scroller.get_width() + leftend;
|
|
|
|
int mm_left = _mm_left;
|
|
int mm_right = _mm_right;
|
|
ARDOUR::MeterType mt_left = _mt_left;
|
|
ARDOUR::MeterType mt_right = _mt_right;
|
|
|
|
for (unsigned int i = 0; i < _metrics.size(); ++i) {
|
|
int sx, dx = 0, dy = 0;
|
|
int mm = _metrics[i]->get_metric_mode();
|
|
sx = (mm & 2) ? _metrics[i]->get_width() : 0;
|
|
|
|
_metrics[i]->translate_coordinates(meterarea, sx, 0, dx, dy);
|
|
|
|
if (dx < leftend && !(mm&2)) {
|
|
mm_left = mm;
|
|
mt_left = _metrics[i]->meter_type();
|
|
}
|
|
if (dx > rightend && (mm&2)) {
|
|
mm_right = mm;
|
|
mt_right = _metrics[i]->meter_type();
|
|
break;
|
|
}
|
|
}
|
|
metrics_left.set_metric_mode(mm_left, mt_left);
|
|
metrics_right.set_metric_mode(mm_right, mt_right);
|
|
}
|
|
|
|
void
|
|
Meterbridge::set_session (Session* s)
|
|
{
|
|
SessionHandlePtr::set_session (s);
|
|
|
|
if (!_session) {
|
|
return;
|
|
}
|
|
|
|
metrics_left.set_session(s);
|
|
metrics_right.set_session(s);
|
|
|
|
XMLNode* node = _session->instant_xml(X_("Meterbridge"));
|
|
if (node) {
|
|
set_state (*node);
|
|
}
|
|
|
|
update_title ();
|
|
_show_busses = _session->config.get_show_busses_on_meterbridge();
|
|
_show_master = _session->config.get_show_master_on_meterbridge();
|
|
_show_midi = _session->config.get_show_midi_on_meterbridge();
|
|
|
|
RouteList copy = _session->get_routelist ();
|
|
copy.sort (Stripable::Sorter (true));
|
|
add_strips (copy);
|
|
|
|
_session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Meterbridge::add_strips, this, _1), gui_context());
|
|
_session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Meterbridge::update_title, this), gui_context());
|
|
_session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Meterbridge::update_title, this), gui_context());
|
|
_session->config.ParameterChanged.connect (*this, invalidator (*this), ui_bind (&Meterbridge::parameter_changed, this, _1), gui_context());
|
|
Config->ParameterChanged.connect (*this, invalidator (*this), ui_bind (&Meterbridge::parameter_changed, this, _1), gui_context());
|
|
|
|
if (_visible) {
|
|
show_window();
|
|
present ();
|
|
}
|
|
start_updating ();
|
|
}
|
|
|
|
void
|
|
Meterbridge::session_going_away ()
|
|
{
|
|
ENSURE_GUI_THREAD (*this, &Meterbridge::session_going_away);
|
|
|
|
for (list<MeterBridgeStrip>::iterator i = strips.begin(); i != strips.end(); ++i) {
|
|
delete ((*i).s);
|
|
}
|
|
|
|
strips.clear ();
|
|
stop_updating ();
|
|
|
|
SessionHandlePtr::session_going_away ();
|
|
|
|
_session = 0;
|
|
update_title ();
|
|
}
|
|
|
|
int
|
|
Meterbridge::set_state (const XMLNode& node)
|
|
{
|
|
XMLNode* geometry;
|
|
|
|
m_width = default_width;
|
|
m_height = default_height;
|
|
m_root_x = 1;
|
|
m_root_y = 1;
|
|
|
|
if ((geometry = find_named_node (node, "geometry")) != 0) {
|
|
geometry->get_property ("x-size", m_width);
|
|
geometry->get_property ("y-size", m_height);
|
|
geometry->get_property ("x-pos", m_root_x);
|
|
geometry->get_property ("y-pos", m_root_y);
|
|
}
|
|
|
|
set_window_pos_and_size ();
|
|
|
|
node.get_property ("show-meterbridge", _visible);
|
|
|
|
return 0;
|
|
}
|
|
|
|
XMLNode&
|
|
Meterbridge::get_state (void)
|
|
{
|
|
XMLNode* node = new XMLNode ("Meterbridge");
|
|
|
|
if (is_realized() && _visible) {
|
|
get_window_pos_and_size ();
|
|
}
|
|
|
|
XMLNode* geometry = new XMLNode ("geometry");
|
|
geometry->set_property(X_("x-size"), m_width);
|
|
geometry->set_property(X_("y-size"), m_height);
|
|
geometry->set_property(X_("x-pos"), m_root_x);
|
|
geometry->set_property(X_("y-pos"), m_root_y);
|
|
node->add_child_nocopy (*geometry);
|
|
|
|
node->set_property ("show-meterbridge", _visible);
|
|
return *node;
|
|
}
|
|
|
|
|
|
gint
|
|
Meterbridge::start_updating ()
|
|
{
|
|
fast_screen_update_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &Meterbridge::fast_update_strips));
|
|
return 0;
|
|
}
|
|
|
|
gint
|
|
Meterbridge::stop_updating ()
|
|
{
|
|
fast_screen_update_connection.disconnect();
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
Meterbridge::fast_update_strips ()
|
|
{
|
|
if (!is_mapped () || !_session) {
|
|
return;
|
|
}
|
|
for (list<MeterBridgeStrip>::iterator i = strips.begin(); i != strips.end(); ++i) {
|
|
if (!(*i).visible) continue;
|
|
(*i).s->fast_update ();
|
|
}
|
|
}
|
|
|
|
void
|
|
Meterbridge::add_strips (RouteList& routes)
|
|
{
|
|
MeterStrip* strip;
|
|
for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
|
|
boost::shared_ptr<Route> route = (*x);
|
|
if (route->is_auditioner()) {
|
|
continue;
|
|
}
|
|
if (route->is_monitor()) {
|
|
continue;
|
|
}
|
|
|
|
strip = new MeterStrip (_session, route);
|
|
strips.push_back (MeterBridgeStrip(strip));
|
|
route->active_changed.connect (*this, invalidator (*this), boost::bind (&Meterbridge::sync_order_keys, this), gui_context ());
|
|
|
|
meterarea.pack_start (*strip, false, false);
|
|
strip->show();
|
|
}
|
|
|
|
resync_order();
|
|
}
|
|
|
|
void
|
|
Meterbridge::remove_strip (MeterStrip* strip)
|
|
{
|
|
if (_session && _session->deletion_in_progress()) {
|
|
return;
|
|
}
|
|
|
|
list<MeterBridgeStrip>::iterator i;
|
|
for (list<MeterBridgeStrip>::iterator i = strips.begin(); i != strips.end(); ++i) {
|
|
if ( (*i).s == strip) {
|
|
strips.erase (i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
resync_order();
|
|
}
|
|
|
|
void
|
|
Meterbridge::sync_order_keys ()
|
|
{
|
|
Glib::Threads::Mutex::Lock lm (_resync_mutex);
|
|
|
|
MeterOrderRouteSorter sorter;
|
|
strips.sort(sorter);
|
|
|
|
int pos = 0;
|
|
int vis = 0;
|
|
MeterStrip * last = 0;
|
|
|
|
unsigned int metrics = 0;
|
|
MeterType lmt = MeterPeak;
|
|
bool have_midi = false;
|
|
metrics_left.set_metric_mode(1, lmt);
|
|
|
|
for (list<MeterBridgeStrip>::iterator i = strips.begin(); i != strips.end(); ++i) {
|
|
|
|
if (! (*i).s->route()->active()) {
|
|
(*i).s->hide();
|
|
(*i).visible = false;
|
|
}
|
|
else if ((*i).s->route()->is_master()) {
|
|
if (_show_master) {
|
|
(*i).s->show();
|
|
(*i).visible = true;
|
|
vis++;
|
|
} else {
|
|
(*i).s->hide();
|
|
(*i).visible = false;
|
|
}
|
|
}
|
|
else if (boost::dynamic_pointer_cast<AudioTrack>((*i).s->route()) == 0
|
|
&& boost::dynamic_pointer_cast<MidiTrack>((*i).s->route()) == 0
|
|
) {
|
|
/* non-master bus */
|
|
if (_show_busses) {
|
|
(*i).s->show();
|
|
(*i).visible = true;
|
|
vis++;
|
|
} else {
|
|
(*i).s->hide();
|
|
(*i).visible = false;
|
|
}
|
|
}
|
|
else if (boost::dynamic_pointer_cast<MidiTrack>((*i).s->route())) {
|
|
if (_show_midi) {
|
|
(*i).s->show();
|
|
(*i).visible = true;
|
|
vis++;
|
|
} else {
|
|
(*i).s->hide();
|
|
(*i).visible = false;
|
|
}
|
|
}
|
|
else {
|
|
(*i).s->show();
|
|
(*i).visible = true;
|
|
vis++;
|
|
}
|
|
|
|
(*i).s->set_tick_bar(0);
|
|
|
|
MeterType nmt = (*i).s->meter_type();
|
|
if (nmt == MeterKrms) nmt = MeterPeak; // identical metrics
|
|
if (vis == 1) {
|
|
(*i).s->set_tick_bar(1);
|
|
}
|
|
|
|
if ((*i).visible && nmt != lmt && vis == 1) {
|
|
lmt = nmt;
|
|
metrics_left.set_metric_mode(1, lmt);
|
|
} else if ((*i).visible && nmt != lmt) {
|
|
|
|
if (last) {
|
|
last->set_tick_bar(last->get_tick_bar() | 2);
|
|
}
|
|
(*i).s->set_tick_bar((*i).s->get_tick_bar() | 1);
|
|
|
|
if (_metrics.size() <= metrics) {
|
|
_metrics.push_back(new MeterStrip(have_midi ? 2 : 3, lmt));
|
|
meterarea.pack_start (*_metrics[metrics], false, false);
|
|
_metrics[metrics]->set_session(_session);
|
|
_metrics[metrics]->show();
|
|
} else {
|
|
_metrics[metrics]->set_metric_mode(have_midi ? 2 : 3, lmt);
|
|
}
|
|
meterarea.reorder_child(*_metrics[metrics], pos++);
|
|
metrics++;
|
|
|
|
lmt = nmt;
|
|
|
|
if (_metrics.size() <= metrics) {
|
|
_metrics.push_back(new MeterStrip(1, lmt));
|
|
meterarea.pack_start (*_metrics[metrics], false, false);
|
|
_metrics[metrics]->set_session(_session);
|
|
_metrics[metrics]->show();
|
|
} else {
|
|
_metrics[metrics]->set_metric_mode(1, lmt);
|
|
}
|
|
meterarea.reorder_child(*_metrics[metrics], pos++);
|
|
metrics++;
|
|
have_midi = false;
|
|
}
|
|
|
|
if ((*i).visible && (*i).s->has_midi()) {
|
|
have_midi = true;
|
|
}
|
|
|
|
meterarea.reorder_child(*((*i).s), pos++);
|
|
if ((*i).visible) {
|
|
last = (*i).s;
|
|
}
|
|
}
|
|
|
|
if (last) {
|
|
last->set_tick_bar(last->get_tick_bar() | 2);
|
|
}
|
|
|
|
metrics_right.set_metric_mode(have_midi ? 2 : 3, lmt);
|
|
|
|
while (_metrics.size() > metrics) {
|
|
meterarea.remove(*_metrics.back());
|
|
delete (_metrics.back());
|
|
_metrics.pop_back();
|
|
}
|
|
|
|
_mm_left = metrics_left.get_metric_mode();
|
|
_mt_left = metrics_left.meter_type();
|
|
_mm_right = metrics_right.get_metric_mode();
|
|
_mt_right = metrics_right.meter_type();
|
|
|
|
on_scroll();
|
|
queue_resize();
|
|
}
|
|
|
|
void
|
|
Meterbridge::resync_order (PropertyChange what_changed)
|
|
{
|
|
if (what_changed.contains (ARDOUR::Properties::order)) {
|
|
sync_order_keys();
|
|
}
|
|
}
|
|
|
|
void
|
|
Meterbridge::parameter_changed (std::string const & p)
|
|
{
|
|
if (p == "show-busses-on-meterbridge") {
|
|
_show_busses = _session->config.get_show_busses_on_meterbridge();
|
|
resync_order();
|
|
}
|
|
else if (p == "show-master-on-meterbridge") {
|
|
_show_master = _session->config.get_show_master_on_meterbridge();
|
|
resync_order();
|
|
}
|
|
else if (p == "show-midi-on-meterbridge") {
|
|
_show_midi = _session->config.get_show_midi_on_meterbridge();
|
|
resync_order();
|
|
}
|
|
else if (p == "meter-line-up-level") {
|
|
meter_clear_pattern_cache();
|
|
}
|
|
else if (p == "show-rec-on-meterbridge") {
|
|
scroller.queue_resize();
|
|
}
|
|
else if (p == "show-mute-on-meterbridge") {
|
|
scroller.queue_resize();
|
|
}
|
|
else if (p == "show-solo-on-meterbridge") {
|
|
scroller.queue_resize();
|
|
}
|
|
else if (p == "show-name-on-meterbridge") {
|
|
scroller.queue_resize();
|
|
}
|
|
else if (p == "meterbridge-label-height") {
|
|
scroller.queue_resize();
|
|
}
|
|
else if (p == "show-monitor-on-meterbridge") {
|
|
scroller.queue_resize();
|
|
}
|
|
else if (p == "track-name-number") {
|
|
scroller.queue_resize();
|
|
}
|
|
}
|
|
|
|
void
|
|
Meterbridge::on_theme_changed ()
|
|
{
|
|
meter_clear_pattern_cache();
|
|
}
|