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.
20 #include "pbd/error.h"
22 #include "ardour/async_midi_port.h"
23 #include "ardour/audio_backend.h"
24 #include "ardour/audio_port.h"
25 #include "ardour/debug.h"
26 #include "ardour/midi_port.h"
27 #include "ardour/midiport_manager.h"
28 #include "ardour/port_manager.h"
32 using namespace ARDOUR;
37 PortManager::PortManager ()
39 , _port_remove_in_progress (false)
44 PortManager::remove_all_ports ()
46 /* make sure that JACK callbacks that will be invoked as we cleanup
47 * ports know that they have nothing to do.
50 _port_remove_in_progress = true;
52 /* process lock MUST be held by caller
56 RCUWriter<Ports> writer (ports);
57 boost::shared_ptr<Ports> ps = writer.get_copy ();
61 /* clear dead wood list in RCU */
65 _port_remove_in_progress = false;
70 PortManager::make_port_name_relative (const string& portname) const
76 string::size_type len;
78 string self = _backend->my_name();
80 len = portname.length();
82 for (n = 0; n < len; ++n) {
83 if (portname[n] == ':') {
88 if ((n != len) && (portname.substr (0, n) == self)) {
89 return portname.substr (n+1);
96 PortManager::make_port_name_non_relative (const string& portname) const
100 if (portname.find_first_of (':') != string::npos) {
104 str = _backend->my_name();
112 PortManager::get_pretty_name_by_name(const std::string& portname) const
114 PortEngine::PortHandle ph = _backend->get_port_by_name (portname);
118 if (0 == _backend->get_port_property (ph,
119 "http://jackaudio.org/metadata/pretty-name",
129 PortManager::port_is_mine (const string& portname) const
135 string self = _backend->my_name();
137 if (portname.find_first_of (':') != string::npos) {
138 if (portname.substr (0, self.length ()) != self) {
147 PortManager::port_is_physical (const std::string& portname) const
153 PortEngine::PortHandle ph = _backend->get_port_by_name (portname);
158 return _backend->port_is_physical (ph);
162 PortManager::get_physical_outputs (DataType type, std::vector<std::string>& s)
167 _backend->get_physical_outputs (type, s);
171 PortManager::get_physical_inputs (DataType type, std::vector<std::string>& s)
177 _backend->get_physical_inputs (type, s);
181 PortManager::n_physical_outputs () const
184 return ChanCount::ZERO;
187 return _backend->n_physical_outputs ();
191 PortManager::n_physical_inputs () const
194 return ChanCount::ZERO;
196 return _backend->n_physical_inputs ();
199 /** @param name Full or short name of port
200 * @return Corresponding Port or 0.
203 boost::shared_ptr<Port>
204 PortManager::get_port_by_name (const string& portname)
207 return boost::shared_ptr<Port>();
210 if (!port_is_mine (portname)) {
211 /* not an ardour port */
212 return boost::shared_ptr<Port> ();
215 boost::shared_ptr<Ports> pr = ports.reader();
216 std::string rel = make_port_name_relative (portname);
217 Ports::iterator x = pr->find (rel);
219 if (x != pr->end()) {
220 /* its possible that the port was renamed by some 3rd party and
221 we don't know about it. check for this (the check is quick
222 and cheap), and if so, rename the port (which will alter
223 the port map as a side effect).
225 const std::string check = make_port_name_relative (_backend->get_port_name (x->second->port_handle()));
227 x->second->set_name (check);
232 return boost::shared_ptr<Port> ();
236 PortManager::port_renamed (const std::string& old_relative_name, const std::string& new_relative_name)
238 RCUWriter<Ports> writer (ports);
239 boost::shared_ptr<Ports> p = writer.get_copy();
240 Ports::iterator x = p->find (old_relative_name);
243 boost::shared_ptr<Port> port = x->second;
245 p->insert (make_pair (new_relative_name, port));
250 PortManager::get_ports (DataType type, PortList& pl)
252 boost::shared_ptr<Ports> plist = ports.reader();
253 for (Ports::iterator p = plist->begin(); p != plist->end(); ++p) {
254 if (p->second->type() == type) {
255 pl.push_back (p->second);
262 PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
270 return _backend->get_ports (port_name_pattern, type, flags, s);
274 PortManager::port_registration_failure (const std::string& portname)
280 string full_portname = _backend->my_name();
281 full_portname += ':';
282 full_portname += portname;
285 PortEngine::PortHandle p = _backend->get_port_by_name (full_portname);
289 reason = string_compose (_("a port with the name \"%1\" already exists: check for duplicated track/bus names"), portname);
291 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);
294 throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
297 boost::shared_ptr<Port>
298 PortManager::register_port (DataType dtype, const string& portname, bool input, bool async)
300 boost::shared_ptr<Port> newport;
303 if (dtype == DataType::AUDIO) {
304 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering AUDIO port %1, input %2\n",
306 newport.reset (new AudioPort (portname, (input ? IsInput : IsOutput)));
307 } else if (dtype == DataType::MIDI) {
309 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering ASYNC MIDI port %1, input %2\n",
311 newport.reset (new AsyncMIDIPort (portname, (input ? IsInput : IsOutput)));
313 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering MIDI port %1, input %2\n",
315 newport.reset (new MidiPort (portname, (input ? IsInput : IsOutput)));
318 throw PortRegistrationFailure("unable to create port (unknown type)");
321 RCUWriter<Ports> writer (ports);
322 boost::shared_ptr<Ports> ps = writer.get_copy ();
323 ps->insert (make_pair (make_port_name_relative (portname), newport));
325 /* writer goes out of scope, forces update */
329 catch (PortRegistrationFailure& err) {
331 } catch (std::exception& e) {
332 throw PortRegistrationFailure(string_compose(
333 _("unable to create port: %1"), e.what()).c_str());
335 throw PortRegistrationFailure("unable to create port (unknown error)");
338 DEBUG_TRACE (DEBUG::Ports, string_compose ("\t%2 port registration success, ports now = %1\n", ports.reader()->size(), this));
342 boost::shared_ptr<Port>
343 PortManager::register_input_port (DataType type, const string& portname, bool async)
345 return register_port (type, portname, true, async);
348 boost::shared_ptr<Port>
349 PortManager::register_output_port (DataType type, const string& portname, bool async)
351 return register_port (type, portname, false, async);
355 PortManager::unregister_port (boost::shared_ptr<Port> port)
357 /* caller must hold process lock */
360 RCUWriter<Ports> writer (ports);
361 boost::shared_ptr<Ports> ps = writer.get_copy ();
362 Ports::iterator x = ps->find (make_port_name_relative (port->name()));
364 if (x != ps->end()) {
368 /* writer goes out of scope, forces update */
377 PortManager::connected (const string& port_name)
383 PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
389 return _backend->connected (handle);
393 PortManager::connect (const string& source, const string& destination)
397 string s = make_port_name_non_relative (source);
398 string d = make_port_name_non_relative (destination);
400 boost::shared_ptr<Port> src = get_port_by_name (s);
401 boost::shared_ptr<Port> dst = get_port_by_name (d);
404 ret = src->connect (d);
406 ret = dst->connect (s);
408 /* neither port is known to us ...hand-off to the PortEngine
411 ret = _backend->connect (s, d);
418 /* already exists - no error, no warning */
419 } else if (ret < 0) {
420 error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
421 source, s, destination, d)
429 PortManager::disconnect (const string& source, const string& destination)
433 string s = make_port_name_non_relative (source);
434 string d = make_port_name_non_relative (destination);
436 boost::shared_ptr<Port> src = get_port_by_name (s);
437 boost::shared_ptr<Port> dst = get_port_by_name (d);
440 ret = src->disconnect (d);
442 ret = dst->disconnect (s);
444 /* neither port is known to us ...hand-off to the PortEngine
447 ret = _backend->disconnect (s, d);
456 PortManager::disconnect (boost::shared_ptr<Port> port)
458 return port->disconnect_all ();
462 PortManager::reestablish_ports ()
466 boost::shared_ptr<Ports> p = ports.reader ();
468 DEBUG_TRACE (DEBUG::Ports, string_compose ("reestablish %1 ports\n", p->size()));
470 for (i = p->begin(); i != p->end(); ++i) {
471 if (i->second->reestablish ()) {
472 error << string_compose (_("Re-establising port %1 failed"), i->second->name()) << endmsg;
473 std::cerr << string_compose (_("Re-establising port %1 failed"), i->second->name()) << std::endl;
488 PortManager::reconnect_ports ()
490 boost::shared_ptr<Ports> p = ports.reader ();
492 if (!Profile->get_trx()) {
493 /* re-establish connections */
495 DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size()));
497 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
498 i->second->reconnect ();
506 PortManager::connect_callback (const string& a, const string& b, bool conn)
508 boost::shared_ptr<Port> port_a;
509 boost::shared_ptr<Port> port_b;
511 boost::shared_ptr<Ports> pr = ports.reader ();
513 x = pr->find (make_port_name_relative (a));
514 if (x != pr->end()) {
518 x = pr->find (make_port_name_relative (b));
519 if (x != pr->end()) {
523 PortConnectedOrDisconnected (
531 PortManager::registration_callback ()
533 if (!_port_remove_in_progress) {
534 PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
539 PortManager::can_request_input_monitoring () const
545 return _backend->can_monitor_input ();
549 PortManager::request_input_monitoring (const string& name, bool yn) const
555 PortEngine::PortHandle ph = _backend->get_port_by_name (name);
558 _backend->request_input_monitoring (ph, yn);
563 PortManager::ensure_input_monitoring (const string& name, bool yn) const
569 PortEngine::PortHandle ph = _backend->get_port_by_name (name);
572 _backend->ensure_input_monitoring (ph, yn);
577 PortManager::port_name_size() const
583 return _backend->port_name_size ();
587 PortManager::my_name() const
593 return _backend->my_name();
597 PortManager::graph_order_callback ()
599 if (!_port_remove_in_progress) {
600 GraphReordered(); /* EMIT SIGNAL */
607 PortManager::cycle_start (pframes_t nframes)
609 Port::set_global_port_buffer_offset (0);
610 Port::set_cycle_framecnt (nframes);
612 _cycle_ports = ports.reader ();
614 for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
615 p->second->cycle_start (nframes);
620 PortManager::cycle_end (pframes_t nframes)
622 for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
623 p->second->cycle_end (nframes);
626 for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
627 p->second->flush_buffers (nframes);
630 _cycle_ports.reset ();
636 PortManager::silence (pframes_t nframes)
638 for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
639 if (i->second->sends_output()) {
640 i->second->get_buffer(nframes).silence(nframes);
646 PortManager::silence_outputs (pframes_t nframes)
648 std::vector<std::string> port_names;
649 if (get_ports("", DataType::AUDIO, IsOutput, port_names)) {
650 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
651 if (!port_is_mine(*p)) {
654 PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
658 void *buf = _backend->get_buffer(ph, nframes);
662 memset (buf, 0, sizeof(float) * nframes);
666 if (get_ports("", DataType::MIDI, IsOutput, port_names)) {
667 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
668 if (!port_is_mine(*p)) {
671 PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
675 void *buf = _backend->get_buffer(ph, nframes);
679 _backend->midi_clear (buf);
685 PortManager::check_monitoring ()
687 for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
691 if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
692 i->second->set_last_monitor (x);
693 /* XXX I think this is dangerous, due to
694 a likely mutex in the signal handlers ...
696 i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
702 PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
704 for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
706 if (i->second->sends_output()) {
708 boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
710 Sample* s = ap->engine_get_whole_audio_buffer ();
711 gain_t g = base_gain;
713 for (pframes_t n = 0; n < nframes; ++n) {
723 PortManager::port_engine()