2 Copyright (C) 2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <io.h> // Microsoft's nearest equivalent to <unistd.h>
22 #include <ardourext/misc.h>
27 #include "pbd/convert.h"
28 #include "pbd/error.h"
30 #include "ardour/async_midi_port.h"
31 #include "ardour/audio_backend.h"
32 #include "ardour/audio_port.h"
33 #include "ardour/debug.h"
34 #include "ardour/midi_port.h"
35 #include "ardour/midiport_manager.h"
36 #include "ardour/port_manager.h"
37 #include "ardour/profile.h"
38 #include "ardour/session.h"
42 using namespace ARDOUR;
47 PortManager::PortManager ()
49 , _port_remove_in_progress (false)
50 , _port_deletions_pending (8192) /* ick, arbitrary sizing */
55 PortManager::clear_pending_port_deletions ()
59 DEBUG_TRACE (DEBUG::Ports, string_compose ("pending port deletions: %1\n", _port_deletions_pending.read_space()));
61 while (_port_deletions_pending.read (&p, 1) == 1) {
67 PortManager::remove_all_ports ()
69 /* make sure that JACK callbacks that will be invoked as we cleanup
70 * ports know that they have nothing to do.
73 _port_remove_in_progress = true;
75 /* process lock MUST be held by caller
79 RCUWriter<Ports> writer (ports);
80 boost::shared_ptr<Ports> ps = writer.get_copy ();
84 /* clear dead wood list in RCU */
88 /* clear out pending port deletion list. we know this is safe because
89 * the auto connect thread in Session is already dead when this is
90 * done. It doesn't use shared_ptr<Port> anyway.
93 _port_deletions_pending.reset ();
95 _port_remove_in_progress = false;
100 PortManager::make_port_name_relative (const string& portname) const
106 string::size_type colon = portname.find (':');
108 if (colon == string::npos) {
112 if (portname.substr (0, colon) == _backend->my_name()) {
113 return portname.substr (colon+1);
120 PortManager::make_port_name_non_relative (const string& portname) const
124 if (portname.find_first_of (':') != string::npos) {
128 str = _backend->my_name();
136 PortManager::get_pretty_name_by_name(const std::string& portname) const
138 PortEngine::PortHandle ph = _backend->get_port_by_name (portname);
142 if (0 == _backend->get_port_property (ph,
143 "http://jackaudio.org/metadata/pretty-name",
153 PortManager::port_is_mine (const string& portname) const
159 string self = _backend->my_name();
161 if (portname.find_first_of (':') != string::npos) {
162 if (portname.substr (0, self.length ()) != self) {
171 PortManager::port_is_physical (const std::string& portname) const
177 PortEngine::PortHandle ph = _backend->get_port_by_name (portname);
182 return _backend->port_is_physical (ph);
186 PortManager::get_physical_outputs (DataType type, std::vector<std::string>& s)
192 _backend->get_physical_outputs (type, s);
196 PortManager::get_physical_inputs (DataType type, std::vector<std::string>& s)
203 _backend->get_physical_inputs (type, s);
207 PortManager::n_physical_outputs () const
210 return ChanCount::ZERO;
213 return _backend->n_physical_outputs ();
217 PortManager::n_physical_inputs () const
220 return ChanCount::ZERO;
222 return _backend->n_physical_inputs ();
225 /** @param name Full or short name of port
226 * @return Corresponding Port or 0.
229 boost::shared_ptr<Port>
230 PortManager::get_port_by_name (const string& portname)
233 return boost::shared_ptr<Port>();
236 if (!port_is_mine (portname)) {
237 /* not an ardour port */
238 return boost::shared_ptr<Port> ();
241 boost::shared_ptr<Ports> pr = ports.reader();
242 std::string rel = make_port_name_relative (portname);
243 Ports::iterator x = pr->find (rel);
245 if (x != pr->end()) {
246 /* its possible that the port was renamed by some 3rd party and
247 we don't know about it. check for this (the check is quick
248 and cheap), and if so, rename the port (which will alter
249 the port map as a side effect).
251 const std::string check = make_port_name_relative (_backend->get_port_name (x->second->port_handle()));
253 x->second->set_name (check);
258 return boost::shared_ptr<Port> ();
262 PortManager::port_renamed (const std::string& old_relative_name, const std::string& new_relative_name)
264 RCUWriter<Ports> writer (ports);
265 boost::shared_ptr<Ports> p = writer.get_copy();
266 Ports::iterator x = p->find (old_relative_name);
269 boost::shared_ptr<Port> port = x->second;
271 p->insert (make_pair (new_relative_name, port));
276 PortManager::get_ports (DataType type, PortList& pl)
278 boost::shared_ptr<Ports> plist = ports.reader();
279 for (Ports::iterator p = plist->begin(); p != plist->end(); ++p) {
280 if (p->second->type() == type) {
281 pl.push_back (p->second);
288 PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
296 return _backend->get_ports (port_name_pattern, type, flags, s);
300 PortManager::port_registration_failure (const std::string& portname)
306 string full_portname = _backend->my_name();
307 full_portname += ':';
308 full_portname += portname;
311 PortEngine::PortHandle p = _backend->get_port_by_name (full_portname);
315 reason = string_compose (_("a port with the name \"%1\" already exists: check for duplicated track/bus names"), portname);
317 reason = string_compose (_("No more ports are available. You will need to stop %1 and restart with more ports if you need this many tracks."), PROGRAM_NAME);
320 throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
325 void operator() (Port* p) {
326 AudioEngine::instance()->add_pending_port_deletion (p);
330 boost::shared_ptr<Port>
331 PortManager::register_port (DataType dtype, const string& portname, bool input, bool async, PortFlags flags)
333 boost::shared_ptr<Port> newport;
335 /* limit the possible flags that can be set */
337 flags = PortFlags (flags & (Hidden|Shadow|IsTerminal));
340 if (dtype == DataType::AUDIO) {
341 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering AUDIO port %1, input %2\n",
343 newport.reset (new AudioPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)),
345 } else if (dtype == DataType::MIDI) {
347 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering ASYNC MIDI port %1, input %2\n",
349 newport.reset (new AsyncMIDIPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)),
352 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering MIDI port %1, input %2\n",
354 newport.reset (new MidiPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)),
358 throw PortRegistrationFailure("unable to create port (unknown type)");
361 RCUWriter<Ports> writer (ports);
362 boost::shared_ptr<Ports> ps = writer.get_copy ();
363 ps->insert (make_pair (make_port_name_relative (portname), newport));
365 /* writer goes out of scope, forces update */
369 catch (PortRegistrationFailure& err) {
371 } catch (std::exception& e) {
372 throw PortRegistrationFailure(string_compose(
373 _("unable to create port: %1"), e.what()).c_str());
375 throw PortRegistrationFailure("unable to create port (unknown error)");
378 DEBUG_TRACE (DEBUG::Ports, string_compose ("\t%2 port registration success, ports now = %1\n", ports.reader()->size(), this));
382 boost::shared_ptr<Port>
383 PortManager::register_input_port (DataType type, const string& portname, bool async, PortFlags extra_flags)
385 return register_port (type, portname, true, async, extra_flags);
388 boost::shared_ptr<Port>
389 PortManager::register_output_port (DataType type, const string& portname, bool async, PortFlags extra_flags)
391 return register_port (type, portname, false, async, extra_flags);
395 PortManager::unregister_port (boost::shared_ptr<Port> port)
397 /* This is a little subtle. We do not call the backend's port
398 * unregistration code from here. That is left for the Port
399 * destructor. We are trying to drop references to the Port object
400 * here, so that its destructor will run and it will unregister itself.
403 /* caller must hold process lock */
406 RCUWriter<Ports> writer (ports);
407 boost::shared_ptr<Ports> ps = writer.get_copy ();
408 Ports::iterator x = ps->find (make_port_name_relative (port->name()));
410 if (x != ps->end()) {
411 DEBUG_TRACE (DEBUG::Ports, string_compose ("removing %1 from port map (uc=%2)\n", port->name(), port.use_count()));
415 /* writer goes out of scope, forces update */
424 PortManager::connected (const string& port_name)
430 PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
436 return _backend->connected (handle);
440 PortManager::physically_connected (const string& port_name)
446 PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
452 return _backend->physically_connected (handle);
456 PortManager::get_connections (const string& port_name, std::vector<std::string>& s)
463 PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
470 return _backend->get_connections (handle, s);
474 PortManager::connect (const string& source, const string& destination)
478 string s = make_port_name_non_relative (source);
479 string d = make_port_name_non_relative (destination);
481 boost::shared_ptr<Port> src = get_port_by_name (s);
482 boost::shared_ptr<Port> dst = get_port_by_name (d);
485 ret = src->connect (d);
487 ret = dst->connect (s);
489 /* neither port is known to us ...hand-off to the PortEngine
492 ret = _backend->connect (s, d);
499 /* already exists - no error, no warning */
500 } else if (ret < 0) {
501 error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
502 source, s, destination, d)
510 PortManager::disconnect (const string& source, const string& destination)
514 string s = make_port_name_non_relative (source);
515 string d = make_port_name_non_relative (destination);
517 boost::shared_ptr<Port> src = get_port_by_name (s);
518 boost::shared_ptr<Port> dst = get_port_by_name (d);
521 ret = src->disconnect (d);
523 ret = dst->disconnect (s);
525 /* neither port is known to us ...hand-off to the PortEngine
528 ret = _backend->disconnect (s, d);
537 PortManager::disconnect (boost::shared_ptr<Port> port)
539 return port->disconnect_all ();
543 PortManager::reestablish_ports ()
547 boost::shared_ptr<Ports> p = ports.reader ();
549 DEBUG_TRACE (DEBUG::Ports, string_compose ("reestablish %1 ports\n", p->size()));
551 for (i = p->begin(); i != p->end(); ++i) {
552 if (i->second->reestablish ()) {
553 error << string_compose (_("Re-establising port %1 failed"), i->second->name()) << endmsg;
554 std::cerr << string_compose (_("Re-establising port %1 failed"), i->second->name()) << std::endl;
569 PortManager::reconnect_ports ()
571 boost::shared_ptr<Ports> p = ports.reader ();
573 if (!Profile->get_trx()) {
574 /* re-establish connections */
576 DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size()));
578 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
579 i->second->reconnect ();
587 PortManager::connect_callback (const string& a, const string& b, bool conn)
589 boost::shared_ptr<Port> port_a;
590 boost::shared_ptr<Port> port_b;
592 boost::shared_ptr<Ports> pr = ports.reader ();
594 x = pr->find (make_port_name_relative (a));
595 if (x != pr->end()) {
599 x = pr->find (make_port_name_relative (b));
600 if (x != pr->end()) {
604 PortConnectedOrDisconnected (
612 PortManager::registration_callback ()
614 if (!_port_remove_in_progress) {
615 PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
620 PortManager::can_request_input_monitoring () const
626 return _backend->can_monitor_input ();
630 PortManager::request_input_monitoring (const string& name, bool yn) const
636 PortEngine::PortHandle ph = _backend->get_port_by_name (name);
639 _backend->request_input_monitoring (ph, yn);
644 PortManager::ensure_input_monitoring (const string& name, bool yn) const
650 PortEngine::PortHandle ph = _backend->get_port_by_name (name);
653 _backend->ensure_input_monitoring (ph, yn);
658 PortManager::port_name_size() const
664 return _backend->port_name_size ();
668 PortManager::my_name() const
674 return _backend->my_name();
678 PortManager::graph_order_callback ()
680 if (!_port_remove_in_progress) {
681 GraphReordered(); /* EMIT SIGNAL */
688 PortManager::cycle_start (pframes_t nframes)
690 Port::set_global_port_buffer_offset (0);
691 Port::set_cycle_framecnt (nframes);
693 _cycle_ports = ports.reader ();
695 for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
696 p->second->cycle_start (nframes);
701 PortManager::cycle_end (pframes_t nframes)
703 for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
704 p->second->cycle_end (nframes);
707 for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
708 p->second->flush_buffers (nframes);
711 _cycle_ports.reset ();
717 PortManager::silence (pframes_t nframes, Session *s)
719 for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
720 if (s && i->second == s->mtc_output_port ()) {
723 if (s && i->second == s->midi_clock_output_port ()) {
726 if (s && i->second == s->ltc_output_port ()) {
729 if (boost::dynamic_pointer_cast<AsyncMIDIPort>(i->second)) {
732 if (i->second->sends_output()) {
733 i->second->get_buffer(nframes).silence(nframes);
739 PortManager::silence_outputs (pframes_t nframes)
741 std::vector<std::string> port_names;
742 if (get_ports("", DataType::AUDIO, IsOutput, port_names)) {
743 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
744 if (!port_is_mine(*p)) {
747 PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
751 void *buf = _backend->get_buffer(ph, nframes);
755 memset (buf, 0, sizeof(float) * nframes);
759 if (get_ports("", DataType::MIDI, IsOutput, port_names)) {
760 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
761 if (!port_is_mine(*p)) {
764 PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
768 void *buf = _backend->get_buffer(ph, nframes);
772 _backend->midi_clear (buf);
778 PortManager::check_monitoring ()
780 for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
784 if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
785 i->second->set_last_monitor (x);
786 /* XXX I think this is dangerous, due to
787 a likely mutex in the signal handlers ...
789 i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
795 PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
797 for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
799 if (i->second->sends_output()) {
801 boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
803 Sample* s = ap->engine_get_whole_audio_buffer ();
804 gain_t g = base_gain;
806 for (pframes_t n = 0; n < nframes; ++n) {
816 PortManager::port_engine()
823 PortManager::port_is_control_only (std::string const& name)
825 static regex_t compiled_pattern;
826 static string pattern;
828 if (pattern.empty()) {
830 /* This is a list of regular expressions that match ports
831 * related to physical MIDI devices that we do not want to
832 * expose as normal physical ports.
835 const char * const control_only_ports[] = {
836 X_(".*Ableton Push.*"),
837 X_(".*FaderPort .*"),
841 for (size_t n = 0; n < sizeof (control_only_ports)/sizeof (control_only_ports[0]); ++n) {
845 pattern += control_only_ports[n];
849 regcomp (&compiled_pattern, pattern.c_str(), REG_EXTENDED|REG_NOSUB);
852 return regexec (&compiled_pattern, name.c_str(), 0, 0, 0) == 0;
856 PortManager::get_midi_selection_ports (MidiSelectionPorts& copy) const
858 Glib::Threads::Mutex::Lock lm (midi_selection_ports_mutex);
859 copy = _midi_selection_ports;
863 PortManager::add_to_midi_selection_ports (string const & port)
865 Glib::Threads::Mutex::Lock lm (midi_selection_ports_mutex);
866 if (find (_midi_selection_ports.begin(), _midi_selection_ports.end(), port) == _midi_selection_ports.end()) {
867 _midi_selection_ports.push_back (port);
872 PortManager::remove_from_midi_selection_ports (string const & port)
874 Glib::Threads::Mutex::Lock lm (midi_selection_ports_mutex);
875 MidiSelectionPorts::iterator x = find (_midi_selection_ports.begin(), _midi_selection_ports.end(), port);
876 if (x != _midi_selection_ports.end()) {
877 _midi_selection_ports.erase (x);
882 PortManager::clear_midi_selection_ports ()
884 Glib::Threads::Mutex::Lock lm (midi_selection_ports_mutex);
885 _midi_selection_ports.clear ();