+ if (!_backend) {
+ return;
+ }
+
+ PortEngine::PortHandle ph = _backend->get_port_by_name (name);
+
+ if (ph) {
+ _backend->ensure_input_monitoring (ph, yn);
+ }
+}
+
+uint32_t
+PortManager::port_name_size() const
+{
+ if (!_backend) {
+ return 0;
+ }
+
+ return _backend->port_name_size ();
+}
+
+string
+PortManager::my_name() const
+{
+ if (!_backend) {
+ return string();
+ }
+
+ return _backend->my_name();
+}
+
+int
+PortManager::graph_order_callback ()
+{
+ if (!_port_remove_in_progress) {
+ GraphReordered(); /* EMIT SIGNAL */
+ }
+
+ return 0;
+}
+
+void
+PortManager::cycle_start (pframes_t nframes)
+{
+ Port::set_global_port_buffer_offset (0);
+ Port::set_cycle_framecnt (nframes);
+
+ _cycle_ports = ports.reader ();
+
+ for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
+ p->second->cycle_start (nframes);
+ }
+}
+
+void
+PortManager::cycle_end (pframes_t nframes)
+{
+ for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
+ p->second->cycle_end (nframes);
+ }
+
+ for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
+ p->second->flush_buffers (nframes);
+ }
+
+ _cycle_ports.reset ();
+
+ /* we are done */
+}
+
+void
+PortManager::silence (pframes_t nframes, Session *s)
+{
+ for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
+ if (s && i->second == s->mtc_output_port ()) {
+ continue;
+ }
+ if (s && i->second == s->midi_clock_output_port ()) {
+ continue;
+ }
+ if (s && i->second == s->ltc_output_port ()) {
+ continue;
+ }
+ if (boost::dynamic_pointer_cast<AsyncMIDIPort>(i->second)) {
+ continue;
+ }
+ if (i->second->sends_output()) {
+ i->second->get_buffer(nframes).silence(nframes);
+ }
+ }
+}
+
+void
+PortManager::silence_outputs (pframes_t nframes)
+{
+ std::vector<std::string> port_names;
+ if (get_ports("", DataType::AUDIO, IsOutput, port_names)) {
+ for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
+ if (!port_is_mine(*p)) {
+ continue;
+ }
+ PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
+ if (!ph) {
+ continue;
+ }
+ void *buf = _backend->get_buffer(ph, nframes);
+ if (!buf) {
+ continue;
+ }
+ memset (buf, 0, sizeof(float) * nframes);
+ }
+ }
+
+ if (get_ports("", DataType::MIDI, IsOutput, port_names)) {
+ for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
+ if (!port_is_mine(*p)) {
+ continue;
+ }
+ PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
+ if (!ph) {
+ continue;
+ }
+ void *buf = _backend->get_buffer(ph, nframes);
+ if (!buf) {
+ continue;
+ }
+ _backend->midi_clear (buf);
+ }
+ }
+}
+
+void
+PortManager::check_monitoring ()
+{
+ for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
+
+ bool x;
+
+ if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
+ i->second->set_last_monitor (x);
+ /* XXX I think this is dangerous, due to
+ a likely mutex in the signal handlers ...
+ */
+ i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
+ }
+ }
+}
+
+void
+PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
+{
+ for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
+
+ if (i->second->sends_output()) {
+
+ boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
+ if (ap) {
+ Sample* s = ap->engine_get_whole_audio_buffer ();
+ gain_t g = base_gain;
+
+ for (pframes_t n = 0; n < nframes; ++n) {
+ *s++ *= g;
+ g -= gain_step;
+ }
+ }
+ }
+ }
+}
+
+PortEngine&
+PortManager::port_engine()
+{
+ assert (_backend);
+ return *_backend;
+}
+
+bool
+PortManager::port_is_control_only (std::string const& name)
+{
+ static regex_t compiled_pattern;
+ static string pattern;
+
+ if (pattern.empty()) {
+
+ /* This is a list of regular expressions that match ports
+ * related to physical MIDI devices that we do not want to
+ * expose as normal physical ports.
+ */
+
+ const char * const control_only_ports[] = {
+ X_(".*Ableton Push.*"),
+ X_(".*FaderPort .*"),
+ X_(".*FaderPort8 .*"),
+ };
+
+ pattern = "(";
+ for (size_t n = 0; n < sizeof (control_only_ports)/sizeof (control_only_ports[0]); ++n) {
+ if (n > 0) {
+ pattern += '|';
+ }
+ pattern += control_only_ports[n];
+ }
+ pattern += ')';
+
+ regcomp (&compiled_pattern, pattern.c_str(), REG_EXTENDED|REG_NOSUB);
+ }
+
+ return regexec (&compiled_pattern, name.c_str(), 0, 0, 0) == 0;
+}
+
+PortManager::MidiPortInformation
+PortManager::midi_port_information (std::string const & name)
+{
+ Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
+
+ fill_midi_port_info_locked ();
+
+ MidiPortInfo::iterator x = midi_port_info.find (name);
+
+ if (x != midi_port_info.end()) {
+ return x->second;
+ }
+
+ return MidiPortInformation ();
+}
+
+void
+PortManager::get_known_midi_ports (vector<string>& copy)
+{
+ Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
+
+ fill_midi_port_info_locked ();
+
+ for (MidiPortInfo::const_iterator x = midi_port_info.begin(); x != midi_port_info.end(); ++x) {
+ copy.push_back (x->first);
+ }
+}
+
+void
+PortManager::get_midi_selection_ports (vector<string>& copy)
+{
+ Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
+
+ fill_midi_port_info_locked ();
+
+ for (MidiPortInfo::const_iterator x = midi_port_info.begin(); x != midi_port_info.end(); ++x) {
+ if (x->second.properties & MidiPortSelection) {
+ copy.push_back (x->first);
+ }
+ }
+}
+
+void
+PortManager::set_midi_port_pretty_name (string const & port, string const & pretty)
+{
+ {
+ Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
+
+ fill_midi_port_info_locked ();
+
+ MidiPortInfo::iterator x = midi_port_info.find (port);
+ if (x == midi_port_info.end()) {
+ return;
+ }
+ x->second.pretty_name = pretty;
+ }
+
+ /* push into back end */
+
+ PortEngine::PortHandle ph = _backend->get_port_by_name (port);