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)
54 PortManager::remove_all_ports ()
56 /* make sure that JACK callbacks that will be invoked as we cleanup
57 * ports know that they have nothing to do.
60 _port_remove_in_progress = true;
62 /* process lock MUST be held by caller
66 RCUWriter<Ports> writer (ports);
67 boost::shared_ptr<Ports> ps = writer.get_copy ();
71 /* clear dead wood list in RCU */
75 _port_remove_in_progress = false;
80 PortManager::make_port_name_relative (const string& portname) const
86 string::size_type colon = portname.find (':');
88 if (colon == string::npos) {
92 if (portname.substr (0, colon) == _backend->my_name()) {
93 return portname.substr (colon+1);
100 PortManager::make_port_name_non_relative (const string& portname) const
104 if (portname.find_first_of (':') != string::npos) {
108 str = _backend->my_name();
116 PortManager::get_pretty_name_by_name(const std::string& portname) const
118 PortEngine::PortHandle ph = _backend->get_port_by_name (portname);
122 if (0 == _backend->get_port_property (ph,
123 "http://jackaudio.org/metadata/pretty-name",
133 PortManager::port_is_mine (const string& portname) const
139 string self = _backend->my_name();
141 if (portname.find_first_of (':') != string::npos) {
142 if (portname.substr (0, self.length ()) != self) {
151 PortManager::port_is_physical (const std::string& portname) const
157 PortEngine::PortHandle ph = _backend->get_port_by_name (portname);
162 return _backend->port_is_physical (ph);
166 PortManager::get_physical_outputs (DataType type, std::vector<std::string>& s)
172 _backend->get_physical_outputs (type, s);
176 PortManager::get_physical_inputs (DataType type, std::vector<std::string>& s)
183 _backend->get_physical_inputs (type, s);
187 PortManager::n_physical_outputs () const
190 return ChanCount::ZERO;
193 return _backend->n_physical_outputs ();
197 PortManager::n_physical_inputs () const
200 return ChanCount::ZERO;
202 return _backend->n_physical_inputs ();
205 /** @param name Full or short name of port
206 * @return Corresponding Port or 0.
209 boost::shared_ptr<Port>
210 PortManager::get_port_by_name (const string& portname)
213 return boost::shared_ptr<Port>();
216 if (!port_is_mine (portname)) {
217 /* not an ardour port */
218 return boost::shared_ptr<Port> ();
221 boost::shared_ptr<Ports> pr = ports.reader();
222 std::string rel = make_port_name_relative (portname);
223 Ports::iterator x = pr->find (rel);
225 if (x != pr->end()) {
226 /* its possible that the port was renamed by some 3rd party and
227 we don't know about it. check for this (the check is quick
228 and cheap), and if so, rename the port (which will alter
229 the port map as a side effect).
231 const std::string check = make_port_name_relative (_backend->get_port_name (x->second->port_handle()));
233 x->second->set_name (check);
238 return boost::shared_ptr<Port> ();
242 PortManager::port_renamed (const std::string& old_relative_name, const std::string& new_relative_name)
244 RCUWriter<Ports> writer (ports);
245 boost::shared_ptr<Ports> p = writer.get_copy();
246 Ports::iterator x = p->find (old_relative_name);
249 boost::shared_ptr<Port> port = x->second;
251 p->insert (make_pair (new_relative_name, port));
256 PortManager::get_ports (DataType type, PortList& pl)
258 boost::shared_ptr<Ports> plist = ports.reader();
259 for (Ports::iterator p = plist->begin(); p != plist->end(); ++p) {
260 if (p->second->type() == type) {
261 pl.push_back (p->second);
268 PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
276 return _backend->get_ports (port_name_pattern, type, flags, s);
280 PortManager::port_registration_failure (const std::string& portname)
286 string full_portname = _backend->my_name();
287 full_portname += ':';
288 full_portname += portname;
291 PortEngine::PortHandle p = _backend->get_port_by_name (full_portname);
295 reason = string_compose (_("a port with the name \"%1\" already exists: check for duplicated track/bus names"), portname);
297 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);
300 throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
303 boost::shared_ptr<Port>
304 PortManager::register_port (DataType dtype, const string& portname, bool input, bool async, PortFlags flags)
306 boost::shared_ptr<Port> newport;
308 /* limit the possible flags that can be set */
310 flags = PortFlags (flags & (Hidden|Shadow|IsTerminal));
313 if (dtype == DataType::AUDIO) {
314 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering AUDIO port %1, input %2\n",
316 newport.reset (new AudioPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)));
317 } else if (dtype == DataType::MIDI) {
319 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering ASYNC MIDI port %1, input %2\n",
321 newport.reset (new AsyncMIDIPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)));
323 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering MIDI port %1, input %2\n",
325 newport.reset (new MidiPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)));
328 throw PortRegistrationFailure("unable to create port (unknown type)");
331 RCUWriter<Ports> writer (ports);
332 boost::shared_ptr<Ports> ps = writer.get_copy ();
333 ps->insert (make_pair (make_port_name_relative (portname), newport));
335 /* writer goes out of scope, forces update */
339 catch (PortRegistrationFailure& err) {
341 } catch (std::exception& e) {
342 throw PortRegistrationFailure(string_compose(
343 _("unable to create port: %1"), e.what()).c_str());
345 throw PortRegistrationFailure("unable to create port (unknown error)");
348 DEBUG_TRACE (DEBUG::Ports, string_compose ("\t%2 port registration success, ports now = %1\n", ports.reader()->size(), this));
352 boost::shared_ptr<Port>
353 PortManager::register_input_port (DataType type, const string& portname, bool async, PortFlags extra_flags)
355 return register_port (type, portname, true, async, extra_flags);
358 boost::shared_ptr<Port>
359 PortManager::register_output_port (DataType type, const string& portname, bool async, PortFlags extra_flags)
361 return register_port (type, portname, false, async, extra_flags);
365 PortManager::unregister_port (boost::shared_ptr<Port> port)
367 /* This is a little subtle. We do not call the backend's port
368 * unregistration code from here. That is left for the Port
369 * destructor. We are trying to drop references to the Port object
370 * here, so that its destructor will run and it will unregister itself.
373 /* caller must hold process lock */
376 RCUWriter<Ports> writer (ports);
377 boost::shared_ptr<Ports> ps = writer.get_copy ();
378 Ports::iterator x = ps->find (make_port_name_relative (port->name()));
380 if (x != ps->end()) {
384 /* writer goes out of scope, forces update */
393 PortManager::connected (const string& port_name)
399 PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
405 return _backend->connected (handle);
409 PortManager::physically_connected (const string& port_name)
415 PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
421 return _backend->physically_connected (handle);
425 PortManager::get_connections (const string& port_name, std::vector<std::string>& s)
432 PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
439 return _backend->get_connections (handle, s);
443 PortManager::connect (const string& source, const string& destination)
447 string s = make_port_name_non_relative (source);
448 string d = make_port_name_non_relative (destination);
450 boost::shared_ptr<Port> src = get_port_by_name (s);
451 boost::shared_ptr<Port> dst = get_port_by_name (d);
454 ret = src->connect (d);
456 ret = dst->connect (s);
458 /* neither port is known to us ...hand-off to the PortEngine
461 ret = _backend->connect (s, d);
468 /* already exists - no error, no warning */
469 } else if (ret < 0) {
470 error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
471 source, s, destination, d)
479 PortManager::disconnect (const string& source, const string& destination)
483 string s = make_port_name_non_relative (source);
484 string d = make_port_name_non_relative (destination);
486 boost::shared_ptr<Port> src = get_port_by_name (s);
487 boost::shared_ptr<Port> dst = get_port_by_name (d);
490 ret = src->disconnect (d);
492 ret = dst->disconnect (s);
494 /* neither port is known to us ...hand-off to the PortEngine
497 ret = _backend->disconnect (s, d);
506 PortManager::disconnect (boost::shared_ptr<Port> port)
508 return port->disconnect_all ();
512 PortManager::reestablish_ports ()
516 boost::shared_ptr<Ports> p = ports.reader ();
518 DEBUG_TRACE (DEBUG::Ports, string_compose ("reestablish %1 ports\n", p->size()));
520 for (i = p->begin(); i != p->end(); ++i) {
521 if (i->second->reestablish ()) {
522 error << string_compose (_("Re-establising port %1 failed"), i->second->name()) << endmsg;
523 std::cerr << string_compose (_("Re-establising port %1 failed"), i->second->name()) << std::endl;
538 PortManager::reconnect_ports ()
540 boost::shared_ptr<Ports> p = ports.reader ();
542 if (!Profile->get_trx()) {
543 /* re-establish connections */
545 DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size()));
547 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
548 i->second->reconnect ();
556 PortManager::connect_callback (const string& a, const string& b, bool conn)
558 boost::shared_ptr<Port> port_a;
559 boost::shared_ptr<Port> port_b;
561 boost::shared_ptr<Ports> pr = ports.reader ();
563 x = pr->find (make_port_name_relative (a));
564 if (x != pr->end()) {
568 x = pr->find (make_port_name_relative (b));
569 if (x != pr->end()) {
573 PortConnectedOrDisconnected (
581 PortManager::registration_callback ()
583 if (!_port_remove_in_progress) {
584 PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
589 PortManager::can_request_input_monitoring () const
595 return _backend->can_monitor_input ();
599 PortManager::request_input_monitoring (const string& name, bool yn) const
605 PortEngine::PortHandle ph = _backend->get_port_by_name (name);
608 _backend->request_input_monitoring (ph, yn);
613 PortManager::ensure_input_monitoring (const string& name, bool yn) const
619 PortEngine::PortHandle ph = _backend->get_port_by_name (name);
622 _backend->ensure_input_monitoring (ph, yn);
627 PortManager::port_name_size() const
633 return _backend->port_name_size ();
637 PortManager::my_name() const
643 return _backend->my_name();
647 PortManager::graph_order_callback ()
649 if (!_port_remove_in_progress) {
650 GraphReordered(); /* EMIT SIGNAL */
657 PortManager::cycle_start (pframes_t nframes)
659 Port::set_global_port_buffer_offset (0);
660 Port::set_cycle_framecnt (nframes);
662 _cycle_ports = ports.reader ();
664 for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
665 p->second->cycle_start (nframes);
670 PortManager::cycle_end (pframes_t nframes)
672 for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
673 p->second->cycle_end (nframes);
676 for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
677 p->second->flush_buffers (nframes);
680 _cycle_ports.reset ();
686 PortManager::silence (pframes_t nframes, Session *s)
688 for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
689 if (s && i->second == s->mtc_output_port ()) {
692 if (s && i->second == s->midi_clock_output_port ()) {
695 if (s && i->second == s->ltc_output_port ()) {
698 if (boost::dynamic_pointer_cast<AsyncMIDIPort>(i->second)) {
701 if (i->second->sends_output()) {
702 i->second->get_buffer(nframes).silence(nframes);
708 PortManager::silence_outputs (pframes_t nframes)
710 std::vector<std::string> port_names;
711 if (get_ports("", DataType::AUDIO, IsOutput, port_names)) {
712 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
713 if (!port_is_mine(*p)) {
716 PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
720 void *buf = _backend->get_buffer(ph, nframes);
724 memset (buf, 0, sizeof(float) * nframes);
728 if (get_ports("", DataType::MIDI, IsOutput, port_names)) {
729 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
730 if (!port_is_mine(*p)) {
733 PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
737 void *buf = _backend->get_buffer(ph, nframes);
741 _backend->midi_clear (buf);
747 PortManager::check_monitoring ()
749 for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
753 if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
754 i->second->set_last_monitor (x);
755 /* XXX I think this is dangerous, due to
756 a likely mutex in the signal handlers ...
758 i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
764 PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
766 for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
768 if (i->second->sends_output()) {
770 boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
772 Sample* s = ap->engine_get_whole_audio_buffer ();
773 gain_t g = base_gain;
775 for (pframes_t n = 0; n < nframes; ++n) {
785 PortManager::port_engine()
792 PortManager::port_is_control_only (std::string const& name)
794 static regex_t compiled_pattern;
795 static string pattern;
797 if (pattern.empty()) {
799 /* This is a list of regular expressions that match ports
800 * related to physical MIDI devices that we do not want to
801 * expose as normal physical ports.
804 const char * const control_only_ports[] = {
805 X_(".*Ableton Push.*"),
806 X_(".*FaderPort .*"),
810 for (size_t n = 0; n < sizeof (control_only_ports)/sizeof (control_only_ports[0]); ++n) {
814 pattern += control_only_ports[n];
818 regcomp (&compiled_pattern, pattern.c_str(), REG_EXTENDED|REG_NOSUB);
821 return regexec (&compiled_pattern, name.c_str(), 0, 0, 0) == 0;