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/midi_port.h"
#include "ardour/midi_track.h"
#include "ardour/monitor_return.h"
#include "ardour/profile.h"
#include "ardour/region.h"
#include "ardour/session.h"
#include "ardour/solo_mute_release.h"
#include "gtkmm2ext/gtk_ui.h"
#include "gtkmm2ext/keyboard.h"
@ -405,12 +407,14 @@ RecorderUI::update_title ()
void
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_none.set_sensitive (en);
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);
if (!en) {
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
RecorderUI::parameter_changed (string const& p)
{
if (p == "input-meter-layout") {
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") {
bool const s = _session ? _session->config.get_show_group_tabs () : true;
if (s) {
@ -497,6 +515,18 @@ RecorderUI::start_updating ()
meter_area_layout ();
_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 ();
/* 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);
@ -506,6 +536,7 @@ void
RecorderUI::stop_updating ()
{
_fast_screen_update_connection.disconnect ();
_monitor_connection.disconnect ();
container_clear (_meter_table);
_input_ports.clear ();
}
@ -529,6 +560,7 @@ RecorderUI::add_or_remove_io (DataType dt, vector<string> ports, bool add)
}
update_io_widget_labels ();
update_sensitivity ();
meter_area_layout ();
_meter_area.queue_resize ();
@ -770,6 +802,9 @@ RecorderUI::set_connections (string const& p)
void
RecorderUI::add_track (string const& p)
{
if (!_session) {
return;
}
new_track_for_port (_input_ports[p]->data_type (), p);
}
@ -1067,8 +1102,7 @@ RecorderUI::peak_reset ()
bool RecorderUI::InputPort::_size_groups_initialized = false;
Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_name_size_group;
Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_spill_size_group;
Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_button_size_group;
Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_ctrl_size_group;
Glib::RefPtr<Gtk::SizeGroup> RecorderUI::InputPort::_monitor_size_group;
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)
, _frame (vertical ? ArdourWidgets::Frame::Vertical : ArdourWidgets::Frame::Horizontal)
, _spill_button ("", ArdourButton::default_elements, true)
, _monitor_button (_("PFL"), ArdourButton::default_elements)
, _name_button (name)
, _name_label ("", ALIGN_CENTER, ALIGN_CENTER, false)
, _add_button ("+")
, _port_name (name)
, _solo_release (0)
{
if (!_size_groups_initialized) {
_size_groups_initialized = true;
_name_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL);
_spill_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL);
_button_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_VERTICAL);
_ctrl_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL);
_monitor_size_group = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_BOTH);
}
Box* box_t;
Box* box_c;
Box* box_n;
Box* box_t;
Box* box_n;
Table* ctrls = manage (new Table);
if (vertical) {
box_t = manage (new VBox);
box_c = manage (new HBox);
box_n = manage (new VBox);
} else {
box_t = manage (new HBox);
box_c = 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.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_icon (ArdourIcon::PlusSign);
_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 ();
box_c->set_spacing (2);
box_c->pack_start (_spill_button, true, true);
box_c->pack_start (_add_button, true, true);
ctrls->attach (_spill_button, 0, 2, 0, 1, EXPAND|FILL, EXPAND|FILL, 1, 1);
if (dt == DataType::AUDIO) {
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);
#if 0 // MIXBUS ?
@ -1135,12 +1178,12 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p
if (vertical) {
nh = 64 * UIConfiguration::instance ().get_ui_scale ();
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);
_name_label.set_max_width_chars (9);
} else {
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 (_monitor, false, false);
_name_label.set_max_width_chars (18);
@ -1150,14 +1193,10 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p
if (!vertical) {
/* match width of all name labels */
_name_size_group->add_widget (*box_n);
/* match width of all spill labels */
_spill_size_group->add_widget (*box_c);
/* match width of control boxes */
_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 */
_monitor_size_group->add_widget (_monitor);
@ -1181,11 +1220,14 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p
RecorderUI::InputPort::~InputPort ()
{
delete _solo_release;
}
void
RecorderUI::InputPort::clear ()
{
delete _solo_release;
_solo_release = 0;
_monitor.clear ();
}
@ -1328,6 +1370,106 @@ RecorderUI::InputPort::spilled () const
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&
RecorderUI::InputPort::name () const
{

View File

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