diff --git a/gtk2_ardour/recorder_ui.cc b/gtk2_ardour/recorder_ui.cc index d72febbcec..c52d24c4a7 100644 --- a/gtk2_ardour/recorder_ui.cc +++ b/gtk2_ardour/recorder_ui.cc @@ -31,6 +31,7 @@ #include "ardour/audioengine.h" #include "ardour/audio_port.h" #include "ardour/audio_track.h" +#include "ardour/io_plug.h" #include "ardour/midi_port.h" #include "ardour/midi_track.h" #include "ardour/monitor_return.h" @@ -430,6 +431,7 @@ RecorderUI::set_session (Session* s) _session->EndTimeChanged.connect (_session_connections, invalidator (*this), boost::bind (&RecorderUI::gui_extents_changed, this), gui_context()); _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RecorderUI::update_sensitivity, this), gui_context()); _session->UpdateRouteRecordState.connect (_session_connections, invalidator (*this), boost::bind (&RecorderUI::update_recordstate, this), gui_context()); + _session->IOPluginsChanged.connect (_session_connections, invalidator (*this), boost::bind (&RecorderUI::io_plugins_changed, this), gui_context()); /* map_parameters */ parameter_changed ("show-group-tabs"); @@ -556,13 +558,23 @@ RecorderUI::start_updating () PortManager::AudioInputPorts const aip (AudioEngine::instance ()->audio_input_ports ()); PortManager::MIDIInputPorts const mip (AudioEngine::instance ()->midi_input_ports ()); - if (aip.size () + mip.size () == 0) { + size_t iop_audio = 0; + size_t iop_midi = 0; + boost::shared_ptr iop (_session->io_plugs ()); + for (auto& p : *iop) { + PortManager::AudioInputPorts const& aip (p->audio_input_ports ()); + PortManager::MIDIInputPorts const& mip (p->midi_input_ports ()); + iop_audio += aip.size (); + iop_midi += mip.size (); + } + + if (aip.size () + mip.size () + iop_audio + iop_midi == 0) { return; } switch (UIConfiguration::instance ().get_input_meter_layout ()) { case LayoutAutomatic: - if (aip.size () + mip.size () > 16) { + if (aip.size () + mip.size () + iop_audio + iop_midi > 16) { _vertical = true; } else { _vertical = false; @@ -592,6 +604,10 @@ RecorderUI::start_updating () set_connections (i->first); } + for (auto& p : *iop) { + io_plugin_add (p); + } + update_io_widget_labels (); meter_area_layout (); _meter_area.queue_resize (); @@ -620,6 +636,8 @@ RecorderUI::stop_updating () _monitor_connection.disconnect (); container_clear (_meter_table); _input_ports.clear (); + _ioplugins.clear (); + _going_away_connections.drop_connections (); } void @@ -650,6 +668,69 @@ RecorderUI::add_or_remove_io (DataType dt, vector ports, bool add) } } + post_add_remove (spill_changed); +} + +void +RecorderUI::io_plugins_changed () +{ + _fast_screen_update_connection.disconnect (); + boost::shared_ptr iop (_session->io_plugs ()); + for (auto& p : *iop) { + if (_ioplugins.find (p) != _ioplugins.end ()) { + continue; + } + io_plugin_add (p); + } + post_add_remove (false); +} + +void +RecorderUI::io_plugin_add (boost::shared_ptr p) +{ + PortManager::AudioInputPorts const& aip (p->audio_input_ports ()); + PortManager::MIDIInputPorts const& mip (p->midi_input_ports ()); + _ioplugins.insert (p); + p->DropReferences.connect (_going_away_connections, invalidator (*this), boost::bind (&RecorderUI::io_plugin_going_away, this, boost::weak_ptr(p)), gui_context ()); + for (auto i = aip.begin (); i != aip.end (); ++i) { + _input_ports[i->first] = boost::shared_ptr (new InputPort (i->first, DataType::AUDIO, this, _vertical, true)); + set_connections (i->first); + } + for (auto i = mip.begin (); i != mip.end (); ++i) { + _input_ports[i->first] = boost::shared_ptr (new InputPort (i->first, DataType::MIDI, this, _vertical, true)); + set_connections (i->first); + } +} + +void +RecorderUI::io_plugin_going_away (boost::weak_ptr wp) +{ + _fast_screen_update_connection.disconnect (); + bool spill_changed = false; + + boost::shared_ptr p = wp.lock (); + if (!p) { + assert (0); + return; + } + PortManager::AudioInputPorts const& aip (p->audio_input_ports ()); + PortManager::MIDIInputPorts const& mip (p->midi_input_ports ()); + for (auto i = aip.begin (); i != aip.end (); ++i) { + _input_ports.erase (i->first); + spill_changed |= 0 != _spill_port_names.erase (i->first); + } + for (auto i = mip.begin (); i != mip.end (); ++i) { + _input_ports.erase (i->first); + spill_changed |= 0 != _spill_port_names.erase (i->first); + } + + _ioplugins.erase (p); + post_add_remove (spill_changed); +} + +void +RecorderUI::post_add_remove (bool spill_changed) +{ update_io_widget_labels (); update_sensitivity (); meter_area_layout (); @@ -667,8 +748,10 @@ RecorderUI::add_or_remove_io (DataType dt, vector ports, bool add) void RecorderUI::update_io_widget_labels () { - uint32_t n_audio = 0; - uint32_t n_midi = 0; + uint32_t n_audio = 0; + uint32_t n_midi = 0; + uint32_t n_io_audio = 0; + uint32_t n_io_midi = 0; InputPortSet ips; for (InputPortMap::const_iterator i = _input_ports.begin (); i != _input_ports.end (); ++i) { @@ -676,13 +759,24 @@ RecorderUI::update_io_widget_labels () } for (InputPortSet::const_iterator i = ips.begin (); i != ips.end (); ++i) { boost::shared_ptr const& ip = *i; - switch (ip->data_type ()) { - case DataType::AUDIO: - ip->set_frame_label (string_compose (_("Audio Input %1"), ++n_audio)); - break; - case DataType::MIDI: - ip->set_frame_label (string_compose (_("MIDI Input %1"), ++n_midi)); - break; + if (ip->ioplug ()) { + switch (ip->data_type ()) { + case DataType::AUDIO: + ip->set_frame_label (string_compose (_("I/O Plugin Audio %1"), ++n_io_audio)); + break; + case DataType::MIDI: + ip->set_frame_label (string_compose (_("I/O Plugin MIDI %1"), ++n_io_midi)); + break; + } + } else { + switch (ip->data_type ()) { + case DataType::AUDIO: + ip->set_frame_label (string_compose (_("Audio Input %1"), ++n_audio)); + break; + case DataType::MIDI: + ip->set_frame_label (string_compose (_("MIDI Input %1"), ++n_midi)); + break; + } } } } @@ -691,6 +785,7 @@ bool RecorderUI::update_meters () { PortManager::AudioInputPorts const aip (AudioEngine::instance ()->audio_input_ports ()); + boost::shared_ptr iop (_session->io_plugs ()); /* scope data needs to be read continuously */ for (PortManager::AudioInputPorts::const_iterator i = aip.begin (); i != aip.end (); ++i) { @@ -700,6 +795,16 @@ RecorderUI::update_meters () } } + for (auto& p : *iop) { + PortManager::AudioInputPorts const& aip (p->audio_input_ports ()); + for (auto i = aip.begin (); i != aip.end (); ++i) { + InputPortMap::iterator im = _input_ports.find (i->first); + if (im != _input_ports.end()) { + im->second->update (*(i->second.scope)); + } + } + } + if (!contents ().get_mapped ()) { return true; } @@ -720,6 +825,24 @@ RecorderUI::update_meters () } } + for (auto& p : *iop) { + PortManager::AudioInputPorts const& aip (p->audio_input_ports ()); + PortManager::MIDIInputPorts const& mip (p->midi_input_ports ()); + for (auto i = aip.begin (); i != aip.end (); ++i) { + InputPortMap::iterator im = _input_ports.find (i->first); + if (im != _input_ports.end()) { + im->second->update (accurate_coefficient_to_dB (i->second.meter->level), accurate_coefficient_to_dB (i->second.meter->peak)); + } + } + for (PortManager::MIDIInputPorts::const_iterator i = mip.begin (); i != mip.end (); ++i) { + InputPortMap::iterator im = _input_ports.find (i->first); + if (im != _input_ports.end()) { + im->second->update ((float const*)i->second.meter->chn_active); + im->second->update (*(i->second.monitor)); + } + } + } + for (list::const_iterator i = _recorders.begin (); i != _recorders.end (); ++i) { (*i)->fast_update (); } @@ -1215,6 +1338,9 @@ void RecorderUI::peak_reset () { AudioEngine::instance ()->reset_input_meters (); + for (auto& p : _ioplugins) { + p->reset_input_meters (); + } } /* ****************************************************************************/ @@ -1225,7 +1351,7 @@ Glib::RefPtr RecorderUI::InputPort::_name_size_group; Glib::RefPtr RecorderUI::InputPort::_ctrl_size_group; Glib::RefPtr 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, bool ioplug) : _dt (dt) , _monitor (dt, AudioEngine::instance()->sample_rate (), vertical ? InputPortMonitor::Vertical : InputPortMonitor::Horizontal) , _alignment (0.5, 0.5, 0, 0) @@ -1236,6 +1362,7 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p , _name_label ("", ALIGN_CENTER, ALIGN_CENTER, false) , _add_button ("+") , _port_name (name) + , _ioplug (ioplug) , _solo_release (0) { if (!_size_groups_initialized) { @@ -1275,7 +1402,10 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p _name_button.set_corner_radius (2); _name_button.set_name ("generic button"); _name_button.set_text_ellipsize (Pango::ELLIPSIZE_MIDDLE); - _name_button.signal_clicked.connect (sigc::mem_fun (*this, &RecorderUI::InputPort::rename_port)); + + if (!_ioplug) { + _name_button.signal_clicked.connect (sigc::mem_fun (*this, &RecorderUI::InputPort::rename_port)); + } _name_label.set_ellipsize (Pango::ELLIPSIZE_MIDDLE); @@ -1321,7 +1451,11 @@ RecorderUI::InputPort::InputPort (string const& name, DataType dt, RecorderUI* p _monitor_size_group->add_widget (_monitor); Gdk::Color bg; - ARDOUR_UI_UTILS::set_color_from_rgba (bg, UIConfiguration::instance ().color ("neutral:background2")); + if (_ioplug) { + ARDOUR_UI_UTILS::set_color_from_rgba (bg, UIConfiguration::instance ().color ("neutral:background")); + } else { + ARDOUR_UI_UTILS::set_color_from_rgba (bg, UIConfiguration::instance ().color ("neutral:background2")); + } _frame.modify_bg (Gtk::STATE_NORMAL, bg); /* top level packing with border */ @@ -1432,7 +1566,11 @@ RecorderUI::InputPort::setup_name () _name_button.set_text (_port_name); _name_label.set_text (""); } - set_tooltip (_name_button, string_compose (_("Set or edit the custom name for input port '%1'"), _port_name)); + if (_ioplug) { + set_tooltip (_name_button, string_compose (_("I/O Plugin input port '%1'"), _port_name)); + } else { + set_tooltip (_name_button, string_compose (_("Set or edit the custom name for input port '%1'"), _port_name)); + } } void @@ -1493,7 +1631,7 @@ RecorderUI::InputPort::spilled () const void RecorderUI::InputPort::allow_monitoring (bool en) { - if (_dt != DataType::AUDIO) { + if (_dt != DataType::AUDIO || _ioplug) { en = false; } if (!en && _monitor_button.get_active ()) { @@ -1639,8 +1777,8 @@ RecorderUI::RecRuler::set_gui_extents (samplepos_t start, samplepos_t end) void RecorderUI::RecRuler::render (Cairo::RefPtr const& cr, cairo_rectangle_t* r) { - cr->rectangle (r->x, r->y, r->width, r->height); - cr->clip (); + cr->rectangle (r->x, r->y, r->width, r->height); + cr->clip (); if (!_session || _left >= _right) { return; diff --git a/gtk2_ardour/recorder_ui.h b/gtk2_ardour/recorder_ui.h index 4e699559f8..2bd833609d 100644 --- a/gtk2_ardour/recorder_ui.h +++ b/gtk2_ardour/recorder_ui.h @@ -51,6 +51,7 @@ namespace ARDOUR { class SoloMuteRelease; + class IOPlug; } class TrackRecordAxis; @@ -87,6 +88,10 @@ private: void stop_updating (); bool update_meters (); void add_or_remove_io (ARDOUR::DataType, std::vector, bool); + void io_plugins_changed (); + void io_plugin_add (boost::shared_ptr); + void io_plugin_going_away (boost::weak_ptr); + void post_add_remove (bool); void update_io_widget_labels (); void initial_track_display (); @@ -157,11 +162,6 @@ private: std::set _spill_port_names; - 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 { public: @@ -188,7 +188,7 @@ private: class InputPort : public Gtk::EventBox { public: - InputPort (std::string const&, ARDOUR::DataType, RecorderUI*, bool vertical = false); + InputPort (std::string const&, ARDOUR::DataType, RecorderUI*, bool vertical = false, bool ioplug = false); ~InputPort (); void set_frame_label (std::string const&); @@ -201,6 +201,7 @@ private: void update_rec_stat (); ARDOUR::DataType data_type () const; + bool ioplug () const { return _ioplug; } std::string const& name () const; void update (float, float); // FastMeter @@ -210,6 +211,9 @@ private: void clear (); bool operator< (InputPort const& o) const { + if (_ioplug != o._ioplug) { + return !_ioplug; + } if (_dt == o._dt) { return PBD::naturally_less (_port_name.c_str (), o._port_name.c_str ()); } @@ -231,6 +235,7 @@ private: Gtk::Label _name_label; ArdourWidgets::ArdourButton _add_button; std::string _port_name; + bool _ioplug; ARDOUR::WeakRouteList _connected_routes; ARDOUR::SoloMuteRelease* _solo_release; @@ -248,6 +253,7 @@ private: typedef std::map > InputPortMap; typedef std::set, InputPortPtrSort> InputPortSet; + typedef std::set> IOPlugSet; RecRuler _ruler; Gtk::EventBox _space; @@ -258,6 +264,13 @@ private: InputPortMap _input_ports; std::list _recorders; std::list _visible_recorders; + IOPlugSet _ioplugins; + + sigc::connection _fast_screen_update_connection; + sigc::connection _ruler_width_update_connection; + PBD::ScopedConnectionList _engine_connections; + PBD::ScopedConnection _monitor_connection; + PBD::ScopedConnectionList _going_away_connections; public: /* only for RecorderGroupTab */