13
0

RecorderUI: Add input port monitoring

This commit is contained in:
Robin Gareus 2021-02-23 13:10:05 +01:00
parent 582c99a156
commit 15361bca55
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 176 additions and 23 deletions

View File

@ -30,9 +30,11 @@
#include "ardour/audio_track.h" #include "ardour/audio_track.h"
#include "ardour/midi_port.h" #include "ardour/midi_port.h"
#include "ardour/midi_track.h" #include "ardour/midi_track.h"
#include "ardour/monitor_return.h"
#include "ardour/profile.h" #include "ardour/profile.h"
#include "ardour/region.h" #include "ardour/region.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/solo_mute_release.h"
#include "gtkmm2ext/gtk_ui.h" #include "gtkmm2ext/gtk_ui.h"
#include "gtkmm2ext/keyboard.h" #include "gtkmm2ext/keyboard.h"
@ -405,12 +407,14 @@ RecorderUI::update_title ()
void void
RecorderUI::update_sensitivity () RecorderUI::update_sensitivity ()
{ {
const bool en = _session ? true : false; const bool en = _session ? true : false;
const bool have_ms = Config->get_use_monitor_bus();
_btn_rec_all.set_sensitive (en); _btn_rec_all.set_sensitive (en);
_btn_rec_none.set_sensitive (en); _btn_rec_none.set_sensitive (en);
for (InputPortMap::const_iterator i = _input_ports.begin (); i != _input_ports.end (); ++i) { for (InputPortMap::const_iterator i = _input_ports.begin (); i != _input_ports.end (); ++i) {
i->second->allow_monitoring (have_ms && en);
i->second->set_sensitive (en); i->second->set_sensitive (en);
if (!en) { if (!en) {
i->second->clear (); i->second->clear ();
@ -426,11 +430,25 @@ RecorderUI::update_recordstate ()
} }
} }
void
RecorderUI::update_monitorstate (std::string pn, bool en)
{
InputPortMap::iterator im = _input_ports.find (pn);
if (im != _input_ports.end()) {
im->second->update_monitorstate (en);
}
}
void void
RecorderUI::parameter_changed (string const& p) RecorderUI::parameter_changed (string const& p)
{ {
if (p == "input-meter-layout") { if (p == "input-meter-layout") {
start_updating (); start_updating ();
} else if (p == "use-monitor-bus") {
bool have_ms = Config->get_use_monitor_bus();
for (InputPortMap::const_iterator i = _input_ports.begin (); i != _input_ports.end (); ++i) {
i->second->allow_monitoring (have_ms);
}
} else if (p == "show-group-tabs") { } else if (p == "show-group-tabs") {
bool const s = _session ? _session->config.get_show_group_tabs () : true; bool const s = _session ? _session->config.get_show_group_tabs () : true;
if (s) { if (s) {
@ -497,6 +515,18 @@ RecorderUI::start_updating ()
meter_area_layout (); meter_area_layout ();
_meter_area.queue_resize (); _meter_area.queue_resize ();
MonitorPort& mp (AudioEngine::instance()->monitor_port ());
mp.MonitorInputChanged.connect (_monitor_connection, invalidator (*this), boost::bind (&RecorderUI::update_monitorstate, this, _1, _2), gui_context());
const bool en = _session ? true : false;
const bool have_ms = Config->get_use_monitor_bus();
for (InputPortMap::const_iterator i = _input_ports.begin (); i != _input_ports.end (); ++i) {
i->second->update_monitorstate (mp.monitoring (i->first));
i->second->allow_monitoring (have_ms && en);
i->second->set_sensitive (en);
}
_fast_screen_update_connection.disconnect (); _fast_screen_update_connection.disconnect ();
/* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS */ /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS */
_fast_screen_update_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &RecorderUI::update_meters), 40, GDK_PRIORITY_REDRAW + 10); _fast_screen_update_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &RecorderUI::update_meters), 40, GDK_PRIORITY_REDRAW + 10);
@ -506,6 +536,7 @@ void
RecorderUI::stop_updating () RecorderUI::stop_updating ()
{ {
_fast_screen_update_connection.disconnect (); _fast_screen_update_connection.disconnect ();
_monitor_connection.disconnect ();
container_clear (_meter_table); container_clear (_meter_table);
_input_ports.clear (); _input_ports.clear ();
} }
@ -529,6 +560,7 @@ RecorderUI::add_or_remove_io (DataType dt, vector<string> ports, bool add)
} }
update_io_widget_labels (); update_io_widget_labels ();
update_sensitivity ();
meter_area_layout (); meter_area_layout ();
_meter_area.queue_resize (); _meter_area.queue_resize ();
@ -770,6 +802,9 @@ RecorderUI::set_connections (string const& p)
void void
RecorderUI::add_track (string const& p) RecorderUI::add_track (string const& p)
{ {
if (!_session) {
return;
}
new_track_for_port (_input_ports[p]->data_type (), p); new_track_for_port (_input_ports[p]->data_type (), p);
} }
@ -1067,8 +1102,7 @@ RecorderUI::peak_reset ()
bool RecorderUI::InputPort::_size_groups_initialized = false; bool RecorderUI::InputPort::_size_groups_initialized = false;
Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_name_size_group; Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_name_size_group;
Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_spill_size_group; Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_ctrl_size_group;
Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_button_size_group;
Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_monitor_size_group; Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_monitor_size_group;
RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* parent, bool vertical) RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* parent, bool vertical)
@ -1077,30 +1111,29 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p
, _alignment (0.5, 0.5, 0, 0) , _alignment (0.5, 0.5, 0, 0)
, _frame (vertical ? ArdourWidgets::Frame::Vertical : ArdourWidgets::Frame::Horizontal) , _frame (vertical ? ArdourWidgets::Frame::Vertical : ArdourWidgets::Frame::Horizontal)
, _spill_button ("", ArdourButton::default_elements, true) , _spill_button ("", ArdourButton::default_elements, true)
, _monitor_button (_("PFL"), ArdourButton::default_elements)
, _name_button (name) , _name_button (name)
, _name_label ("", ALIGN_CENTER, ALIGN_CENTER, false) , _name_label ("", ALIGN_CENTER, ALIGN_CENTER, false)
, _add_button ("+") , _add_button ("+")
, _port_name (name) , _port_name (name)
, _solo_release (0)
{ {
if (!_size_groups_initialized) { if (!_size_groups_initialized) {
_size_groups_initialized = true; _size_groups_initialized = true;
_name_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL); _name_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL);
_spill_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL); _ctrl_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL);
_button_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_VERTICAL);
_monitor_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_BOTH); _monitor_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_BOTH);
} }
Box* box_t; Box* box_t;
Box* box_c; Box* box_n;
Box* box_n; Table* ctrls = manage (new Table);
if (vertical) { if (vertical) {
box_t = manage (new VBox); box_t = manage (new VBox);
box_c = manage (new HBox);
box_n = manage (new VBox); box_n = manage (new VBox);
} else { } else {
box_t = manage (new HBox); box_t = manage (new HBox);
box_c = manage (new VBox);
box_n = manage (new VBox); box_n = manage (new VBox);
} }
@ -1108,6 +1141,12 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p
_spill_button.set_sizing_text(_("(none)")); _spill_button.set_sizing_text(_("(none)"));
_spill_button.signal_clicked.connect (sigc::bind (sigc::mem_fun (*parent, &RecorderUI::spill_port), name)); _spill_button.signal_clicked.connect (sigc::bind (sigc::mem_fun (*parent, &RecorderUI::spill_port), name));
_monitor_button.set_name ("solo button");
//_monitor_button.signal_clicked.connect (sigc::bind (sigc::mem_fun (*parent, &RecorderUI::monitor_port), name));
_monitor_button.signal_button_press_event().connect (sigc::mem_fun(*this, &InputPort::monitor_press), false);
_monitor_button.signal_button_release_event().connect (sigc::mem_fun(*this, &InputPort::monitor_release), false);
set_tooltip (_monitor_button, _("Solo/Listen to this input"));
_add_button.set_name ("generic button"); _add_button.set_name ("generic button");
_add_button.set_icon (ArdourIcon::PlusSign); _add_button.set_icon (ArdourIcon::PlusSign);
_add_button.signal_clicked.connect (sigc::bind (sigc::mem_fun (*parent, &RecorderUI::add_track), name)); _add_button.signal_clicked.connect (sigc::bind (sigc::mem_fun (*parent, &RecorderUI::add_track), name));
@ -1122,9 +1161,13 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p
setup_name (); setup_name ();
box_c->set_spacing (2); ctrls->attach (_spill_button, 0, 2, 0, 1, EXPAND|FILL, EXPAND|FILL, 1, 1);
box_c->pack_start (_spill_button, true, true); if (dt == DataType::AUDIO) {
box_c->pack_start (_add_button, true, true); ctrls->attach (_add_button, 0, 1, 1, 2, SHRINK|FILL, EXPAND|FILL, 1, 1);
ctrls->attach (_monitor_button, 1, 2, 1, 2, SHRINK|FILL, EXPAND|FILL, 1, 1);
} else {
ctrls->attach (_add_button, 0, 2, 1, 2, EXPAND|FILL, EXPAND|FILL, 1, 1);
}
box_n->pack_start (_name_button, true, true); box_n->pack_start (_name_button, true, true);
#if 0 // MIXBUS ? #if 0 // MIXBUS ?
@ -1135,12 +1178,12 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p
if (vertical) { if (vertical) {
nh = 64 * UIConfiguration::instance ().get_ui_scale (); nh = 64 * UIConfiguration::instance ().get_ui_scale ();
box_t->pack_start (_monitor, false, false); box_t->pack_start (_monitor, false, false);
box_t->pack_start (*box_c, false, false, 1); box_t->pack_start (*ctrls, false, false, 1);
box_t->pack_start (*box_n, false, false, 1); box_t->pack_start (*box_n, false, false, 1);
_name_label.set_max_width_chars (9); _name_label.set_max_width_chars (9);
} else { } else {
nh = 120 * UIConfiguration::instance ().get_ui_scale (); nh = 120 * UIConfiguration::instance ().get_ui_scale ();
box_t->pack_start (*box_c, false, false, 1); box_t->pack_start (*ctrls, false, false, 1);
box_t->pack_start (*box_n, false, false, 1); box_t->pack_start (*box_n, false, false, 1);
box_t->pack_start (_monitor, false, false); box_t->pack_start (_monitor, false, false);
_name_label.set_max_width_chars (18); _name_label.set_max_width_chars (18);
@ -1150,14 +1193,10 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p
if (!vertical) { if (!vertical) {
/* match width of all name labels */ /* match width of all name labels */
_name_size_group->add_widget (*box_n); _name_size_group->add_widget (*box_n);
/* match width of all spill labels */ /* match width of control boxes */
_spill_size_group->add_widget (*box_c); _ctrl_size_group->add_widget (*ctrls);
} }
/* match height of spill + name buttons */
_button_size_group->add_widget (_spill_button);
_button_size_group->add_widget (_name_button);
/* equal size for all meters + event monitors */ /* equal size for all meters + event monitors */
_monitor_size_group->add_widget (_monitor); _monitor_size_group->add_widget (_monitor);
@ -1181,11 +1220,14 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p
RecorderUI::InputPort::~InputPort () RecorderUI::InputPort::~InputPort ()
{ {
delete _solo_release;
} }
void void
RecorderUI::InputPort::clear () RecorderUI::InputPort::clear ()
{ {
delete _solo_release;
_solo_release = 0;
_monitor.clear (); _monitor.clear ();
} }
@ -1328,6 +1370,106 @@ RecorderUI::InputPort::spilled () const
return _spill_button.get_active (); return _spill_button.get_active ();
} }
void
RecorderUI::InputPort::allow_monitoring (bool en)
{
if (_dt != DataType::AUDIO) {
en = false;
}
if (!en && _monitor_button.get_active ()) {
_monitor_button.set_active (false);
}
_monitor_button.set_sensitive (en);
}
void
RecorderUI::InputPort::update_monitorstate (bool en)
{
if (_dt == DataType::AUDIO) {
_monitor_button.set_active (en);
}
}
bool
RecorderUI::InputPort::monitor_press (GdkEventButton* ev)
{
if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
return true;
}
if (Keyboard::is_context_menu_event (ev)) {
return false;
}
if (ev->button != 1 && !Keyboard::is_button2_event (ev)) {
return false;
}
MonitorPort& mp (AudioEngine::instance()->monitor_port ());
Session* s = AudioEngine::instance()->session ();
assert (s);
if (Keyboard::is_button2_event (ev)) {
/* momentary */
_solo_release = new SoloMuteRelease (mp.monitoring (_port_name));
}
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
/* Primary-Tertiary-click applies change to all */
if (_solo_release) {
s->prepare_momentary_solo (_solo_release);
}
if (!_monitor_button.get_active ()) {
std::vector<std::string> ports;
AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, ports);
std::list<std::string> portlist;
std::copy (ports.begin (), ports.end (), std::back_inserter (portlist));
mp.set_active_monitors (portlist);
} else {
mp.clear_ports (false);
}
} else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) || (!_monitor_button.get_active () && Config->get_exclusive_solo ())) {
/* Primary-Secondary-click: exclusive solo */
if (_solo_release) {
s->prepare_momentary_solo (_solo_release, true);
} else {
/* clear solo state */
s->prepare_momentary_solo (0, true);
}
/* exclusively solo */
if (!_monitor_button.get_active ()) {
mp.add_port (_port_name);
} else {
delete _solo_release;
_solo_release = 0;
}
} else {
if (_solo_release) {
s->prepare_momentary_solo (_solo_release);
}
/* Toggle Port Listen */
if (!_monitor_button.get_active ()) {
mp.add_port (_port_name);
} else {
mp.remove_port (_port_name);
}
}
return false;
}
bool
RecorderUI::InputPort::monitor_release (GdkEventButton* ev)
{
if (_solo_release) {
_solo_release->release (AudioEngine::instance()->session (), false);
delete _solo_release;
_solo_release = 0;
}
return false;
}
string const& string const&
RecorderUI::InputPort::name () const RecorderUI::InputPort::name () const
{ {

View File

@ -46,6 +46,10 @@
#include "input_port_monitor.h" #include "input_port_monitor.h"
namespace ARDOUR {
class SoloMuteRelease;
}
class TrackRecordAxis; class TrackRecordAxis;
class RecorderGroupTabs; class RecorderGroupTabs;
@ -103,6 +107,7 @@ private:
void update_sensitivity (); void update_sensitivity ();
void update_recordstate (); void update_recordstate ();
void update_monitorstate (std::string, bool);
void new_track_for_port (ARDOUR::DataType, std::string const&); void new_track_for_port (ARDOUR::DataType, std::string const&);
static int calc_columns (int child_width, int parent_width); static int calc_columns (int child_width, int parent_width);
@ -143,6 +148,7 @@ private:
sigc::connection _fast_screen_update_connection; sigc::connection _fast_screen_update_connection;
sigc::connection _ruler_width_update_connection; sigc::connection _ruler_width_update_connection;
PBD::ScopedConnectionList _engine_connections; PBD::ScopedConnectionList _engine_connections;
PBD::ScopedConnection _monitor_connection;
class RecRuler : public CairoWidget , public ARDOUR::SessionHandlePtr class RecRuler : public CairoWidget , public ARDOUR::SessionHandlePtr
{ {
@ -178,6 +184,8 @@ private:
void setup_name (); void setup_name ();
bool spill (bool); bool spill (bool);
bool spilled () const; bool spilled () const;
void allow_monitoring (bool);
void update_monitorstate (bool);
void update_rec_stat (); void update_rec_stat ();
ARDOUR::DataType data_type () const; ARDOUR::DataType data_type () const;
@ -198,22 +206,25 @@ private:
private: private:
void rename_port (); void rename_port ();
bool monitor_press (GdkEventButton*);
bool monitor_release (GdkEventButton*);
ARDOUR::DataType _dt; ARDOUR::DataType _dt;
InputPortMonitor _monitor; InputPortMonitor _monitor;
Gtk::Alignment _alignment; Gtk::Alignment _alignment;
ArdourWidgets::Frame _frame; ArdourWidgets::Frame _frame;
ArdourWidgets::ArdourButton _spill_button; ArdourWidgets::ArdourButton _spill_button;
ArdourWidgets::ArdourButton _monitor_button;
ArdourWidgets::ArdourButton _name_button; ArdourWidgets::ArdourButton _name_button;
Gtk::Label _name_label; Gtk::Label _name_label;
ArdourWidgets::ArdourButton _add_button; ArdourWidgets::ArdourButton _add_button;
std::string _port_name; std::string _port_name;
ARDOUR::WeakRouteList _connected_routes; ARDOUR::WeakRouteList _connected_routes;
ARDOUR::SoloMuteRelease* _solo_release;
static bool _size_groups_initialized; static bool _size_groups_initialized;
static Glib::RefPtr<Gtk::SizeGroup> _name_size_group; static Glib::RefPtr<Gtk::SizeGroup> _name_size_group;
static Glib::RefPtr<Gtk::SizeGroup> _spill_size_group; static Glib::RefPtr<Gtk::SizeGroup> _ctrl_size_group;
static Glib::RefPtr<Gtk::SizeGroup> _button_size_group;
static Glib::RefPtr<Gtk::SizeGroup> _monitor_size_group; static Glib::RefPtr<Gtk::SizeGroup> _monitor_size_group;
}; };