1 /*
2 * Copyright (C) 2000-2017 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
4 * Copyright (C) 2006 Jesse Chappell <jesse@essej.net>
5 * Copyright (C) 2007-2011 Carl Hetherington <carl@carlh.net>
6 * Copyright (C) 2013-2015 John Emmas <john@creativepost.co.uk>
7 * Copyright (C) 2013-2016 Tim Mayberry <mojofunk@gmail.com>
8 * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
9 * Copyright (C) 2015 GZharun <grygoriiz@wavesglobal.com>
10 * Copyright (C) 2016-2017 Julien "_FrnchFrgg_" RIVAUD <frnchfrgg@free.fr>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 */
26
27 #include <algorithm>
28 #include <cmath>
29 #include <vector>
30
31 #include <unistd.h>
32 #include <locale.h>
33 #include <errno.h>
34
35 #include <glibmm.h>
36 #include <glibmm/threads.h>
37
38 #include "pbd/xml++.h"
39 #include "pbd/replace_all.h"
40 #include "pbd/unknown_type.h"
41 #include "pbd/enumwriter.h"
42 #include "pbd/locale_guard.h"
43 #include "pbd/types_convert.h"
44
45 #include "ardour/audioengine.h"
46 #include "ardour/buffer.h"
47 #include "ardour/buffer_set.h"
48 #include "ardour/debug.h"
49 #include "ardour/io.h"
50 #include "ardour/port.h"
51 #include "ardour/profile.h"
52 #include "ardour/route.h"
53 #include "ardour/session.h"
54 #include "ardour/types_convert.h"
55 #include "ardour/user_bundle.h"
56
57 #include "pbd/i18n.h"
58
59 #define BLOCK_PROCESS_CALLBACK() Glib::Threads::Mutex::Lock em (AudioEngine::instance()->process_lock())
60
61 using namespace std;
62 using namespace ARDOUR;
63 using namespace PBD;
64
65 const string IO::state_node_name = "IO";
66 bool IO::connecting_legal = false;
67 PBD::Signal0<int> IO::ConnectingLegal;
68 PBD::Signal1<void,ChanCount> IO::PortCountChanged;
69
70 /** @param default_type The type of port that will be created by ensure_io
71 * and friends if no type is explicitly requested (to avoid breakage).
72 */
IO(Session & s,const string & name,Direction dir,DataType default_type,bool sendish)73 IO::IO (Session& s, const string& name, Direction dir, DataType default_type, bool sendish)
74 : SessionObject (s, name)
75 , _direction (dir)
76 , _default_type (default_type)
77 , _sendish (sendish)
78 {
79 _active = true;
80 pending_state_node = 0;
81 setup_bundle ();
82 }
83
IO(Session & s,const XMLNode & node,DataType dt,bool sendish)84 IO::IO (Session& s, const XMLNode& node, DataType dt, bool sendish)
85 : SessionObject(s, "unnamed io")
86 , _direction (Input)
87 , _default_type (dt)
88 , _sendish (sendish)
89 {
90 _active = true;
91 pending_state_node = 0;
92
93 set_state (node, Stateful::loading_state_version);
94 setup_bundle ();
95 }
96
~IO()97 IO::~IO ()
98 {
99 Glib::Threads::Mutex::Lock lm (io_lock);
100
101 DEBUG_TRACE (DEBUG::Ports, string_compose ("IO %1 unregisters %2 ports\n", name(), _ports.num_ports()));
102
103 BLOCK_PROCESS_CALLBACK ();
104
105 for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
106 _session.engine().unregister_port (*i);
107 }
108 delete pending_state_node; pending_state_node = 0;
109 }
110
111 void
connection_change(boost::shared_ptr<Port> a,boost::shared_ptr<Port> b)112 IO::connection_change (boost::shared_ptr<Port> a, boost::shared_ptr<Port> b)
113 {
114 if (_session.deletion_in_progress ()) {
115 return;
116 }
117 /* this could be called from within our own ::disconnect() method(s)
118 or from somewhere that operates directly on a port. so, we don't
119 know for sure if we can take this lock or not. if we fail,
120 we assume that its safely locked by our own ::disconnect().
121 */
122
123 Glib::Threads::Mutex::Lock tm (io_lock, Glib::Threads::TRY_LOCK);
124
125 if (tm.locked()) {
126 /* we took the lock, so we cannot be here from inside
127 * ::disconnect()
128 */
129 if (_ports.contains (a) || _ports.contains (b)) {
130 changed (IOChange (IOChange::ConnectionsChanged), this); /* EMIT SIGNAL */
131 }
132 } else {
133 /* we didn't get the lock, so assume that we're inside
134 * ::disconnect(), and it will call changed() appropriately.
135 */
136 }
137 }
138
139 void
silence(samplecnt_t nframes)140 IO::silence (samplecnt_t nframes)
141 {
142 /* io_lock, not taken: function must be called from Session::process() calltree */
143
144 for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
145 if (i->port_handle ()) {
146 i->get_buffer(nframes).silence (nframes);
147 }
148 }
149 }
150
151 int
disconnect(boost::shared_ptr<Port> our_port,string other_port,void * src)152 IO::disconnect (boost::shared_ptr<Port> our_port, string other_port, void* src)
153 {
154 if (other_port.length() == 0 || our_port == 0) {
155 return 0;
156 }
157
158 {
159 Glib::Threads::Mutex::Lock lm (io_lock);
160
161 /* check that our_port is really one of ours */
162
163 if ( ! _ports.contains(our_port)) {
164 return -1;
165 }
166
167 /* disconnect it from the source */
168
169 DEBUG_TRACE (DEBUG::PortConnectIO,
170 string_compose("IO::disconnect %1 from %2\n", our_port->name(), other_port));
171
172 if (our_port->disconnect (other_port)) {
173 error << string_compose(_("IO: cannot disconnect port %1 from %2"), our_port->name(), other_port) << endmsg;
174 return -1;
175 }
176 }
177
178 changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
179
180 _session.set_dirty ();
181
182 return 0;
183 }
184
185 int
connect(boost::shared_ptr<Port> our_port,string other_port,void * src)186 IO::connect (boost::shared_ptr<Port> our_port, string other_port, void* src)
187 {
188 if (other_port.length() == 0 || our_port == 0) {
189 return 0;
190 }
191
192 {
193 Glib::Threads::Mutex::Lock lm (io_lock);
194
195 /* check that our_port is really one of ours */
196
197 if ( ! _ports.contains(our_port) ) {
198 return -1;
199 }
200
201 /* connect it to the source */
202
203 DEBUG_TRACE (DEBUG::PortConnectIO,
204 string_compose("IO::connect %1 to %2\n", our_port->name(), other_port));
205
206 if (our_port->connect (other_port)) {
207 return -1;
208 }
209 }
210 changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
211 _session.set_dirty ();
212 return 0;
213 }
214
215 bool
can_add_port(DataType type) const216 IO::can_add_port (DataType type) const
217 {
218 switch (type) {
219 case DataType::NIL:
220 return false;
221 case DataType::AUDIO:
222 return true;
223 case DataType::MIDI:
224 return _ports.count ().n_midi() < 1;
225 }
226 abort(); /*NOTREACHED*/
227 return false;
228 }
229
230 int
remove_port(boost::shared_ptr<Port> port,void * src)231 IO::remove_port (boost::shared_ptr<Port> port, void* src)
232 {
233 ChanCount before = _ports.count ();
234 ChanCount after = before;
235 after.set (port->type(), after.get (port->type()) - 1);
236
237 boost::optional<bool> const r = PortCountChanging (after); /* EMIT SIGNAL */
238 if (r.value_or (false)) {
239 return -1;
240 }
241
242 IOChange change;
243
244 {
245 BLOCK_PROCESS_CALLBACK ();
246
247 {
248 Glib::Threads::Mutex::Lock lm (io_lock);
249
250 if (_ports.remove(port)) {
251 change.type = IOChange::Type (change.type | IOChange::ConfigurationChanged);
252 change.before = before;
253 change.after = _ports.count ();
254
255 if (port->connected()) {
256 change.type = IOChange::Type (change.type | IOChange::ConnectionsChanged);
257 }
258
259 _session.engine().unregister_port (port);
260 }
261 }
262
263 PortCountChanged (n_ports()); /* EMIT SIGNAL */
264
265 if (change.type != IOChange::NoChange) {
266 changed (change, src);
267 _buffers.attach_buffers (_ports);
268 }
269 }
270
271 if (change.type & IOChange::ConfigurationChanged) {
272 setup_bundle ();
273 }
274
275 if (change.type == IOChange::NoChange) {
276 return -1;
277 }
278
279 _session.set_dirty ();
280
281 return 0;
282 }
283
284 /** Add a port.
285 *
286 * @param destination Name of port to connect new port to.
287 * @param src Source for emitted ConfigurationChanged signal.
288 * @param type Data type of port. Default value (NIL) will use this IO's default type.
289 */
290 int
add_port(string destination,void * src,DataType type)291 IO::add_port (string destination, void* src, DataType type)
292 {
293 boost::shared_ptr<Port> our_port;
294
295 if (type == DataType::NIL) {
296 type = _default_type;
297 }
298
299 if (!can_add_port (type)) {
300 return -1;
301 }
302
303 ChanCount before = _ports.count ();
304 ChanCount after = before;
305 after.set (type, after.get (type) + 1);
306
307 bool const r = PortCountChanging (after); /* EMIT SIGNAL */
308 if (r) {
309 return -1;
310 }
311
312 IOChange change;
313
314 {
315 BLOCK_PROCESS_CALLBACK ();
316
317
318 {
319 Glib::Threads::Mutex::Lock lm (io_lock);
320
321 /* Create a new port */
322
323 string portname = build_legal_port_name (type);
324
325 if (_direction == Input) {
326 if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
327 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
328 return -1;
329 }
330 } else {
331 if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
332 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
333 return -1;
334 }
335 }
336
337 change.before = _ports.count ();
338 _ports.add (our_port);
339 }
340
341 PortCountChanged (n_ports()); /* EMIT SIGNAL */
342 change.type = IOChange::ConfigurationChanged;
343 change.after = _ports.count ();
344 changed (change, src); /* EMIT SIGNAL */
345 _buffers.attach_buffers (_ports);
346 }
347
348 if (!destination.empty()) {
349 if (our_port->connect (destination)) {
350 return -1;
351 }
352 }
353
354 apply_pretty_name ();
355 setup_bundle ();
356 _session.set_dirty ();
357
358 return 0;
359 }
360
361 int
disconnect(void * src)362 IO::disconnect (void* src)
363 {
364 {
365 Glib::Threads::Mutex::Lock lm (io_lock);
366
367 for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
368 i->disconnect_all ();
369 }
370 }
371
372 changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
373
374 return 0;
375 }
376
377 /** Caller must hold process lock */
378 int
ensure_ports_locked(ChanCount count,bool clear,bool & changed)379 IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed)
380 {
381 #ifndef PLATFORM_WINDOWS
382 assert (!AudioEngine::instance()->process_lock().trylock());
383 #endif
384
385 boost::shared_ptr<Port> port;
386 vector<boost::shared_ptr<Port> > deleted_ports;
387
388 changed = false;
389
390 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
391
392 const size_t n = count.get(*t);
393
394 /* remove unused ports */
395 for (size_t i = n_ports().get(*t); i > n; --i) {
396 port = _ports.port(*t, i-1);
397
398 assert(port);
399 _ports.remove(port);
400
401 /* hold a reference to the port so that we can ensure
402 * that this thread, and not a JACK notification thread,
403 * holds the final reference.
404 */
405
406 deleted_ports.push_back (port);
407 _session.engine().unregister_port (port);
408
409 changed = true;
410 }
411
412 /* this will drop the final reference to the deleted ports,
413 * which will in turn call their destructors, which will in
414 * turn call the backend to unregister them.
415 *
416 * There will no connect/disconnect or register/unregister
417 * callbacks from the backend until we get here, because
418 * they are driven by the Port destructor. The destructor
419 * will not execute until we drop the final reference,
420 * which all happens right .... here.
421 */
422 deleted_ports.clear ();
423
424 /* create any necessary new ports */
425 while (n_ports().get(*t) < n) {
426
427 string portname = build_legal_port_name (*t);
428
429 try {
430
431 if (_direction == Input) {
432 if ((port = _session.engine().register_input_port (*t, portname)) == 0) {
433 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
434 return -1;
435 }
436 } else {
437 if ((port = _session.engine().register_output_port (*t, portname)) == 0) {
438 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
439 return -1;
440 }
441 }
442 }
443
444 catch (AudioEngine::PortRegistrationFailure& err) {
445 /* pass it on */
446 throw;
447 }
448
449 _ports.add (port);
450 changed = true;
451 }
452 }
453
454 if (changed) {
455 PortCountChanged (n_ports()); /* EMIT SIGNAL */
456 _session.set_dirty ();
457 }
458
459 if (clear) {
460 /* disconnect all existing ports so that we get a fresh start */
461 for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
462 i->disconnect_all ();
463 }
464 }
465
466 return 0;
467 }
468
469 /** Caller must hold process lock */
470 int
ensure_ports(ChanCount count,bool clear,void * src)471 IO::ensure_ports (ChanCount count, bool clear, void* src)
472 {
473 #ifndef PLATFORM_WINDOWS
474 assert (!AudioEngine::instance()->process_lock().trylock());
475 #endif
476
477 bool changed = false;
478
479 if (count == n_ports() && !clear) {
480 return 0;
481 }
482
483 IOChange change;
484
485 change.before = _ports.count ();
486
487 {
488 Glib::Threads::Mutex::Lock im (io_lock);
489 if (ensure_ports_locked (count, clear, changed)) {
490 return -1;
491 }
492 }
493
494 if (changed) {
495 change.after = _ports.count ();
496 change.type = IOChange::ConfigurationChanged;
497 this->changed (change, src); /* EMIT SIGNAL */
498 _buffers.attach_buffers (_ports);
499 setup_bundle ();
500 _session.set_dirty ();
501 }
502
503 return 0;
504 }
505
506 void
reestablish_port_subscriptions()507 IO::reestablish_port_subscriptions ()
508 {
509 _port_connections.drop_connections ();
510 for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
511 i->ConnectedOrDisconnected.connect_same_thread (*this, boost::bind (&IO::connection_change, this, _1, _2));
512 }
513 }
514
515 /** Caller must hold process lock */
516 int
ensure_io(ChanCount count,bool clear,void * src)517 IO::ensure_io (ChanCount count, bool clear, void* src)
518 {
519 #ifndef PLATFORM_WINDOWS
520 assert (!AudioEngine::instance()->process_lock().trylock());
521 #endif
522
523 return ensure_ports (count, clear, src);
524 }
525
526 XMLNode&
get_state()527 IO::get_state ()
528 {
529 return state ();
530 }
531
532 XMLNode&
state()533 IO::state ()
534 {
535 XMLNode* node = new XMLNode (state_node_name);
536 int n;
537 Glib::Threads::Mutex::Lock lm (io_lock);
538
539 node->set_property ("name", name());
540 node->set_property ("id", id ());
541 node->set_property ("direction", _direction);
542 node->set_property ("default-type", _default_type);
543
544 if (!_pretty_name_prefix.empty ()) {
545 node->set_property("pretty-name", _pretty_name_prefix);
546 }
547
548 for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
549
550 vector<string> connections;
551
552 XMLNode* pnode = new XMLNode (X_("Port"));
553 pnode->set_property (X_("type"), i->type());
554 pnode->set_property (X_("name"), i->name());
555
556 if (i->get_connections (connections)) {
557 vector<string>::const_iterator ci;
558 std::sort (connections.begin(), connections.end());
559
560 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
561
562 /* if its a connection to our own port,
563 return only the port name, not the
564 whole thing. this allows connections
565 to be re-established even when our
566 client name is different.
567 */
568
569 XMLNode* cnode = new XMLNode (X_("Connection"));
570
571 cnode->set_property (X_("other"), _session.engine().make_port_name_relative (*ci));
572 pnode->add_child_nocopy (*cnode);
573 }
574 }
575
576 node->add_child_nocopy (*pnode);
577 }
578
579 return *node;
580 }
581
582 int
set_state(const XMLNode & node,int version)583 IO::set_state (const XMLNode& node, int version)
584 {
585 /* callers for version < 3000 need to call set_state_2X directly, as A3 IOs
586 * are input OR output, not both, so the direction needs to be specified
587 * by the caller.
588 */
589 assert (version >= 3000);
590
591 /* force use of non-localized representation of decimal point,
592 since we use it a lot in XML files and so forth.
593 */
594
595 if (node.name() != state_node_name) {
596 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
597 return -1;
598 }
599
600 bool ignore_name = node.property ("ignore-name");
601 std::string name;
602 if (node.get_property ("name", name) && !ignore_name) {
603 set_name (name);
604 }
605
606 if (node.get_property (X_("default-type"), _default_type)) {
607 assert(_default_type != DataType::NIL);
608 }
609
610 set_id (node);
611
612 node.get_property ("direction", _direction);
613
614 if (create_ports (node, version)) {
615 return -1;
616 }
617 if (_sendish && _direction == Output) {
618 /* ignore <Port name="..."> from XML for sends, but use the names
619 * ::ensure_ports_locked() creates port using ::build_legal_port_name()
620 * This is needed to properly restore connections when creating
621 * external sends from templates because the IO name changes.
622 */
623 PortSet::iterator i = _ports.begin();
624 XMLNodeConstIterator x = node.children().begin();
625 for (; i != _ports.end() && x != node.children().end(); ++i, ++x) {
626 if ((*x)->name() == "Port") {
627 (*x)->remove_property (X_("name"));
628 (*x)->set_property (X_("name"), i->name());
629 }
630 }
631 }
632
633 // after create_ports, updates names
634 if (node.get_property ("pretty-name", name)) {
635 set_pretty_name (name);
636 }
637
638 if (connecting_legal) {
639
640 if (make_connections (node, version, false)) {
641 return -1;
642 }
643
644 } else {
645
646 delete pending_state_node;
647 pending_state_node = new XMLNode (node);
648 pending_state_node_version = version;
649 pending_state_node_in = false;
650 ConnectingLegal.connect_same_thread (connection_legal_c, boost::bind (&IO::connecting_became_legal, this));
651 }
652
653 return 0;
654 }
655
656 int
set_state_2X(const XMLNode & node,int version,bool in)657 IO::set_state_2X (const XMLNode& node, int version, bool in)
658 {
659 XMLProperty const * prop;
660 LocaleGuard lg;
661
662 /* force use of non-localized representation of decimal point,
663 since we use it a lot in XML files and so forth.
664 */
665
666 if (node.name() != state_node_name) {
667 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
668 return -1;
669 }
670
671 if ((prop = node.property ("name")) != 0) {
672 set_name (prop->value());
673 }
674
675 if ((prop = node.property (X_("default-type"))) != 0) {
676 _default_type = DataType(prop->value());
677 assert(_default_type != DataType::NIL);
678 }
679
680 set_id (node);
681
682 _direction = in ? Input : Output;
683
684 if (create_ports (node, version)) {
685 return -1;
686 }
687
688 if (connecting_legal) {
689
690 if (make_connections_2X (node, version, in)) {
691 return -1;
692 }
693
694 } else {
695
696 delete pending_state_node;
697 pending_state_node = new XMLNode (node);
698 pending_state_node_version = version;
699 pending_state_node_in = in;
700 ConnectingLegal.connect_same_thread (connection_legal_c, boost::bind (&IO::connecting_became_legal, this));
701 }
702
703 return 0;
704 }
705
706 int
connecting_became_legal()707 IO::connecting_became_legal ()
708 {
709 int ret = 0;
710
711 assert (pending_state_node);
712
713 connection_legal_c.disconnect ();
714
715 ret = make_connections (*pending_state_node, pending_state_node_version, pending_state_node_in);
716
717 delete pending_state_node;
718 pending_state_node = 0;
719
720 return ret;
721 }
722
723 boost::shared_ptr<Bundle>
find_possible_bundle(const string & desired_name)724 IO::find_possible_bundle (const string &desired_name)
725 {
726 static const string digits = "0123456789";
727 const string &default_name = (_direction == Input ? _("in") : _("out"));
728 const string &bundle_type_name = (_direction == Input ? _("input") : _("output"));
729
730 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
731
732 if (!c) {
733 int bundle_number, mask;
734 string possible_name;
735 bool stereo = false;
736 string::size_type last_non_digit_pos;
737 std::string bundle_number_str;
738
739 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
740 << endmsg;
741
742 // find numeric suffix of desired name
743 bundle_number = 0;
744
745 last_non_digit_pos = desired_name.find_last_not_of(digits);
746
747 if (last_non_digit_pos != string::npos) {
748 bundle_number_str = desired_name.substr(last_non_digit_pos);
749 bundle_number = string_to<int32_t>(bundle_number_str);
750 }
751
752 // see if it's a stereo connection e.g. "in 3+4"
753
754 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
755 string::size_type left_last_non_digit_pos;
756
757 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
758
759 if (left_last_non_digit_pos != string::npos) {
760 int left_bundle_number = 0;
761 bundle_number_str = desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
762 left_bundle_number = string_to<int32_t>(bundle_number_str);
763
764 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
765 bundle_number--;
766 stereo = true;
767 }
768 }
769 }
770
771 // make 0-based
772 if (bundle_number)
773 bundle_number--;
774
775 // find highest set bit
776 mask = 1;
777 while ((mask <= bundle_number) && (mask <<= 1)) {}
778
779 // "wrap" bundle number into largest possible power of 2
780 // that works...
781
782 while (mask) {
783
784 if (bundle_number & mask) {
785 bundle_number &= ~mask;
786
787 std::string possible_name = default_name + " " + to_string(bundle_number + 1);
788
789 if (stereo) {
790 possible_name += "+" + to_string(bundle_number + 2);
791 }
792
793 if ((c = _session.bundle_by_name (possible_name)) != 0) {
794 break;
795 }
796 }
797 mask >>= 1;
798 }
799 if (c) {
800 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
801 << endmsg;
802 } else {
803 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
804 << endmsg;
805 }
806
807 }
808
809 return c;
810
811 }
812
813 int
get_port_counts_2X(XMLNode const & node,int,ChanCount & n,boost::shared_ptr<Bundle> &)814 IO::get_port_counts_2X (XMLNode const & node, int /*version*/, ChanCount& n, boost::shared_ptr<Bundle>& /*c*/)
815 {
816 XMLProperty const * prop;
817 XMLNodeList children = node.children ();
818
819 uint32_t n_audio = 0;
820
821 for (XMLNodeIterator i = children.begin(); i != children.end(); ++i) {
822
823 if ((prop = node.property ("inputs")) != 0 && _direction == Input) {
824 n_audio = count (prop->value().begin(), prop->value().end(), '{');
825 } else if ((prop = node.property ("input-connection")) != 0 && _direction == Input) {
826 n_audio = 1;
827 } else if ((prop = node.property ("outputs")) != 0 && _direction == Output) {
828 n_audio = count (prop->value().begin(), prop->value().end(), '{');
829 } else if ((prop = node.property ("output-connection")) != 0 && _direction == Output) {
830 n_audio = 2;
831 }
832 }
833
834 ChanCount cnt;
835 cnt.set_audio (n_audio);
836 n = ChanCount::max (n, cnt);
837
838 return 0;
839 }
840
841 int
get_port_counts(const XMLNode & node,int version,ChanCount & n,boost::shared_ptr<Bundle> & c)842 IO::get_port_counts (const XMLNode& node, int version, ChanCount& n, boost::shared_ptr<Bundle>& c)
843 {
844 if (version < 3000) {
845 return get_port_counts_2X (node, version, n, c);
846 }
847
848 XMLProperty const * prop;
849 XMLNodeConstIterator iter;
850 uint32_t n_audio = 0;
851 uint32_t n_midi = 0;
852 ChanCount cnt;
853
854 n = n_ports();
855
856 if ((prop = node.property ("connection")) != 0) {
857
858 if ((c = find_possible_bundle (prop->value())) != 0) {
859 n = ChanCount::max (n, c->nchannels());
860 }
861 return 0;
862 }
863
864 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
865
866 if ((*iter)->name() == X_("Bundle")) {
867 prop = (*iter)->property ("name");
868 if ((c = find_possible_bundle (prop->value())) != 0) {
869 n = ChanCount::max (n, c->nchannels());
870 return 0;
871 } else {
872 return -1;
873 }
874 }
875
876 if ((*iter)->name() == X_("Port")) {
877 prop = (*iter)->property (X_("type"));
878
879 if (!prop) {
880 continue;
881 }
882
883 if (prop->value() == X_("audio")) {
884 cnt.set_audio (++n_audio);
885 } else if (prop->value() == X_("midi")) {
886 cnt.set_midi (++n_midi);
887 }
888 }
889 }
890
891 n = ChanCount::max (n, cnt);
892 return 0;
893 }
894
895 int
create_ports(const XMLNode & node,int version)896 IO::create_ports (const XMLNode& node, int version)
897 {
898 ChanCount n;
899 boost::shared_ptr<Bundle> c;
900
901 get_port_counts (node, version, n, c);
902
903 {
904 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
905
906 if (ensure_ports (n, true, this)) {
907 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
908 return -1;
909 }
910 }
911
912 /* XXX use c */
913
914 return 0;
915 }
916
917 int
make_connections(const XMLNode & node,int version,bool in)918 IO::make_connections (const XMLNode& node, int version, bool in)
919 {
920 if (version < 3000) {
921 return make_connections_2X (node, version, in);
922 }
923
924 XMLProperty const * prop;
925
926 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
927
928 if ((*i)->name() == "Bundle") {
929 XMLProperty const * prop = (*i)->property ("name");
930 if (prop) {
931 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value());
932 if (b) {
933 connect_ports_to_bundle (b, true, this);
934 }
935 }
936
937 return 0;
938 }
939
940 if ((*i)->name() == "Port") {
941
942 prop = (*i)->property (X_("name"));
943
944 if (!prop) {
945 continue;
946 }
947
948 boost::shared_ptr<Port> p = port_by_name (prop->value());
949
950 if (p) {
951 for (XMLNodeConstIterator c = (*i)->children().begin(); c != (*i)->children().end(); ++c) {
952
953 XMLNode* cnode = (*c);
954
955 if (cnode->name() != X_("Connection")) {
956 continue;
957 }
958
959 if ((prop = cnode->property (X_("other"))) == 0) {
960 continue;
961 }
962
963 if (prop) {
964 connect (p, prop->value(), this);
965 }
966 }
967 }
968 }
969 }
970
971 return 0;
972 }
973
974 void
prepare_for_reset(XMLNode & node,const std::string & name)975 IO::prepare_for_reset (XMLNode& node, const std::string& name)
976 {
977 /* reset name */
978 node.set_property ("name", name);
979
980 /* now find connections and reset the name of the port
981 in one so that when we re-use it it will match
982 the name of the thing we're applying it to.
983 */
984
985 XMLProperty * prop;
986 XMLNodeList children = node.children();
987
988 for (XMLNodeIterator i = children.begin(); i != children.end(); ++i) {
989
990 if ((*i)->name() == "Port") {
991
992 prop = (*i)->property (X_("name"));
993
994 if (prop) {
995 string new_name;
996 string old = prop->value();
997 string::size_type slash = old.find ('/');
998
999 if (slash != string::npos) {
1000 /* port name is of form: <IO-name>/<port-name> */
1001
1002 new_name = name;
1003 new_name += old.substr (old.find ('/'));
1004
1005 prop->set_value (new_name);
1006 }
1007 }
1008 }
1009 }
1010 }
1011
1012
1013 int
make_connections_2X(const XMLNode & node,int,bool in)1014 IO::make_connections_2X (const XMLNode& node, int /*version*/, bool in)
1015 {
1016 XMLProperty const * prop;
1017
1018 /* XXX: bundles ("connections" as was) */
1019
1020 if ((prop = node.property ("inputs")) != 0 && in) {
1021
1022 string::size_type ostart = 0;
1023 string::size_type start = 0;
1024 string::size_type end = 0;
1025 int i = 0;
1026 int n;
1027 vector<string> ports;
1028
1029 string const str = prop->value ();
1030
1031 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1032 start += 1;
1033
1034 if ((end = str.find_first_of ('}', start)) == string::npos) {
1035 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1036 return -1;
1037 }
1038
1039 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1040 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1041
1042 return -1;
1043
1044 } else if (n > 0) {
1045
1046
1047 for (int x = 0; x < n; ++x) {
1048 /* XXX: this is a bit of a hack; need to check if it's always valid */
1049 string::size_type const p = ports[x].find ("/out");
1050 if (p != string::npos) {
1051 ports[x].replace (p, 4, "/audio_out");
1052 }
1053 if (NULL != nth(i).get())
1054 nth(i)->connect (ports[x]);
1055 }
1056 }
1057
1058 ostart = end+1;
1059 i++;
1060 }
1061
1062 }
1063
1064 if ((prop = node.property ("outputs")) != 0 && !in) {
1065
1066 string::size_type ostart = 0;
1067 string::size_type start = 0;
1068 string::size_type end = 0;
1069 int i = 0;
1070 int n;
1071 vector<string> ports;
1072
1073 string const str = prop->value ();
1074
1075 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1076 start += 1;
1077
1078 if ((end = str.find_first_of ('}', start)) == string::npos) {
1079 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1080 return -1;
1081 }
1082
1083 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1084 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1085
1086 return -1;
1087
1088 } else if (n > 0) {
1089
1090 for (int x = 0; x < n; ++x) {
1091 /* XXX: this is a bit of a hack; need to check if it's always valid */
1092 string::size_type const p = ports[x].find ("/in");
1093 if (p != string::npos) {
1094 ports[x].replace (p, 3, "/audio_in");
1095 }
1096 if (NULL != nth(i).get())
1097 nth(i)->connect (ports[x]);
1098 }
1099 }
1100
1101 ostart = end+1;
1102 i++;
1103 }
1104 }
1105
1106 return 0;
1107 }
1108
1109 int
set_ports(const string & str)1110 IO::set_ports (const string& str)
1111 {
1112 vector<string> ports;
1113 int n;
1114 uint32_t nports;
1115
1116 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1117 return 0;
1118 }
1119
1120 {
1121 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
1122
1123 // FIXME: audio-only
1124 if (ensure_ports (ChanCount(DataType::AUDIO, nports), true, this)) {
1125 return -1;
1126 }
1127 }
1128
1129 string::size_type start = 0;
1130 string::size_type end = 0;
1131 string::size_type ostart = 0;
1132 for (int i = 0; (start = str.find_first_of ('{', ostart)) != string::npos; ++i) {
1133 start += 1;
1134
1135 if ((end = str.find_first_of ('}', start)) == string::npos) {
1136 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1137 return -1;
1138 }
1139
1140 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1141 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1142
1143 return -1;
1144
1145 } else if (n > 0) {
1146
1147 for (int x = 0; x < n; ++x) {
1148 connect (nth (i), ports[x], this);
1149 }
1150 }
1151
1152 ostart = end+1;
1153 }
1154
1155 return 0;
1156 }
1157
1158 int
parse_io_string(const string & str,vector<string> & ports)1159 IO::parse_io_string (const string& str, vector<string>& ports)
1160 {
1161 string::size_type pos, opos;
1162
1163 if (str.length() == 0) {
1164 return 0;
1165 }
1166
1167 opos = 0;
1168
1169 ports.clear ();
1170
1171 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1172 ports.push_back (str.substr (opos, pos - opos));
1173 opos = pos + 1;
1174 }
1175
1176 if (opos < str.length()) {
1177 ports.push_back (str.substr(opos));
1178 }
1179
1180 return ports.size();
1181 }
1182
1183 int
parse_gain_string(const string & str,vector<string> & ports)1184 IO::parse_gain_string (const string& str, vector<string>& ports)
1185 {
1186 string::size_type pos, opos;
1187
1188 opos = 0;
1189 ports.clear ();
1190
1191 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1192 ports.push_back (str.substr (opos, pos - opos));
1193 opos = pos + 1;
1194 }
1195
1196 if (opos < str.length()) {
1197 ports.push_back (str.substr(opos));
1198 }
1199
1200 return ports.size();
1201 }
1202
1203 bool
set_name(const string & requested_name)1204 IO::set_name (const string& requested_name)
1205 {
1206 string name = requested_name;
1207
1208 if (_name == name) {
1209 return true;
1210 }
1211
1212 /* replace all colons in the name. i wish we didn't have to do this */
1213
1214 replace_all (name, ":", "-");
1215
1216 for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
1217 string current_name = i->name();
1218 current_name.replace (current_name.find (_name), _name.val().length(), name);
1219 i->set_name (current_name);
1220 }
1221
1222 bool const r = SessionObject::set_name (name);
1223
1224 setup_bundle ();
1225
1226 return r;
1227 }
1228
1229 void
set_pretty_name(const std::string & str)1230 IO::set_pretty_name (const std::string& str)
1231 {
1232 if (_pretty_name_prefix == str) {
1233 return;
1234 }
1235 _pretty_name_prefix = str;
1236 apply_pretty_name ();
1237 }
1238
1239 void
apply_pretty_name()1240 IO::apply_pretty_name ()
1241 {
1242 uint32_t pn = 1;
1243 if (_pretty_name_prefix.empty ()) {
1244 return;
1245 }
1246 for (PortSet::iterator i = _ports.begin (); i != _ports.end(); ++i, ++pn) {
1247 (*i)->set_pretty_name (string_compose (("%1/%2 %3"),
1248 _pretty_name_prefix,
1249 _direction == Output ? _("Out") : _("In"),
1250 pn));
1251 }
1252 }
1253
1254 void
set_private_port_latencies(samplecnt_t value,bool playback)1255 IO::set_private_port_latencies (samplecnt_t value, bool playback)
1256 {
1257 LatencyRange lat;
1258 lat.min = lat.max = value;
1259 for (PortSet::iterator i = _ports.begin (); i != _ports.end(); ++i) {
1260 i->set_private_latency_range (lat, playback);
1261 }
1262 }
1263
1264 void
set_public_port_latencies(samplecnt_t value,bool playback) const1265 IO::set_public_port_latencies (samplecnt_t value, bool playback) const
1266 {
1267 LatencyRange lat;
1268 lat.min = lat.max = value;
1269 for (PortSet::const_iterator i = _ports.begin (); i != _ports.end(); ++i) {
1270 i->set_public_latency_range (lat, playback);
1271 }
1272 }
1273
1274 samplecnt_t
latency() const1275 IO::latency () const
1276 {
1277 samplecnt_t max_latency = 0;
1278
1279 /* io lock not taken - must be protected by other means */
1280
1281 for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
1282 samplecnt_t latency;
1283 if ((latency = i->private_latency_range (_direction == Output).max) > max_latency) {
1284 DEBUG_TRACE (DEBUG::LatencyIO, string_compose ("port %1 has %2 latency of %3 - use\n",
1285 name(),
1286 ((_direction == Output) ? "PLAYBACK" : "CAPTURE"),
1287 latency));
1288 max_latency = latency;
1289 }
1290 }
1291
1292 DEBUG_TRACE (DEBUG::LatencyIO, string_compose ("%1: max %4 latency from %2 ports = %3\n",
1293 name(), _ports.num_ports(), max_latency,
1294 ((_direction == Output) ? "PLAYBACK" : "CAPTURE")));
1295 return max_latency;
1296 }
1297
1298 #if 0 // not used, but may some day be handy for debugging
1299 samplecnt_t
1300 IO::public_latency () const
1301 {
1302 samplecnt_t max_latency = 0;
1303
1304 /* io lock not taken - must be protected by other means */
1305
1306 for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
1307 samplecnt_t latency;
1308 if ((latency = i->public_latency_range (_direction == Output).max) > max_latency) {
1309 DEBUG_TRACE (DEBUG::LatencyIO, string_compose ("port %1 has %2 latency of %3 - use\n",
1310 name(),
1311 ((_direction == Output) ? "PLAYBACK" : "CAPTURE"),
1312 latency));
1313 max_latency = latency;
1314 }
1315 }
1316
1317 DEBUG_TRACE (DEBUG::LatencyIO, string_compose ("%1: max %4 public latency from %2 ports = %3\n",
1318 name(), _ports.num_ports(), max_latency,
1319 ((_direction == Output) ? "PLAYBACK" : "CAPTURE")));
1320 return max_latency;
1321 }
1322 #endif
1323
1324 samplecnt_t
connected_latency(bool for_playback) const1325 IO::connected_latency (bool for_playback) const
1326 {
1327 /* io lock not taken - must be protected by other means */
1328 samplecnt_t max_latency = 0;
1329 bool connected = false;
1330
1331 /* if output is not connected to anything, use private latency */
1332 for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
1333 if (i->connected()) {
1334 connected = true;
1335 max_latency = 0;
1336 break;
1337 }
1338 samplecnt_t latency;
1339 if ((latency = i->private_latency_range (for_playback).max) > max_latency) {
1340 max_latency = latency;
1341 }
1342 }
1343 if (connected) {
1344 for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
1345 LatencyRange lr;
1346 i->get_connected_latency_range (lr, for_playback);
1347 if (lr.max > max_latency) {
1348 max_latency = lr.max;
1349 }
1350 }
1351 }
1352 return max_latency;
1353 }
1354
1355 int
connect_ports_to_bundle(boost::shared_ptr<Bundle> c,bool exclusive,void * src)1356 IO::connect_ports_to_bundle (boost::shared_ptr<Bundle> c, bool exclusive, void* src) {
1357 return connect_ports_to_bundle(c, exclusive, false, src);
1358 }
1359
1360 int
connect_ports_to_bundle(boost::shared_ptr<Bundle> c,bool exclusive,bool allow_partial,void * src)1361 IO::connect_ports_to_bundle (boost::shared_ptr<Bundle> c, bool exclusive,
1362 bool allow_partial, void* src)
1363 {
1364 BLOCK_PROCESS_CALLBACK ();
1365
1366 {
1367 Glib::Threads::Mutex::Lock lm2 (io_lock);
1368
1369 if (exclusive) {
1370 for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
1371 i->disconnect_all ();
1372 }
1373 }
1374
1375 c->connect (_bundle, _session.engine(), allow_partial);
1376
1377 }
1378
1379 changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
1380 return 0;
1381 }
1382
1383 int
disconnect_ports_from_bundle(boost::shared_ptr<Bundle> c,void * src)1384 IO::disconnect_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
1385 {
1386 BLOCK_PROCESS_CALLBACK ();
1387
1388 {
1389 Glib::Threads::Mutex::Lock lm2 (io_lock);
1390
1391 c->disconnect (_bundle, _session.engine());
1392
1393 /* If this is a UserBundle, make a note of what we've done */
1394
1395 }
1396
1397 changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
1398 return 0;
1399 }
1400
1401
1402 int
disable_connecting()1403 IO::disable_connecting ()
1404 {
1405 connecting_legal = false;
1406 return 0;
1407 }
1408
1409 int
enable_connecting()1410 IO::enable_connecting ()
1411 {
1412 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
1413 connecting_legal = true;
1414 boost::optional<int> r = ConnectingLegal ();
1415 return r.value_or (0);
1416 }
1417
1418 void
bundle_changed(Bundle::Change)1419 IO::bundle_changed (Bundle::Change /*c*/)
1420 {
1421 }
1422
1423
1424 string
build_legal_port_name(DataType type)1425 IO::build_legal_port_name (DataType type)
1426 {
1427 const int name_size = AudioEngine::instance()->port_name_size();
1428 int limit;
1429 string suffix;
1430
1431 if (type == DataType::AUDIO) {
1432 suffix = X_("audio");
1433 } else if (type == DataType::MIDI) {
1434 suffix = X_("midi");
1435 } else {
1436 throw unknown_type();
1437 }
1438
1439 /* note that if "in" or "out" are translated it will break a session
1440 across locale switches because a port's connection list will
1441 show (old) translated names, but the current port name will
1442 use the (new) translated name.
1443 */
1444
1445 if (_sendish) {
1446 if (_direction == Input) {
1447 suffix += X_("_return");
1448 } else {
1449 suffix += X_("_send");
1450 }
1451 } else {
1452 if (_direction == Input) {
1453 suffix += X_("_in");
1454 } else {
1455 suffix += X_("_out");
1456 }
1457 }
1458
1459 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
1460
1461 limit = name_size - AudioEngine::instance()->my_name().length() - (suffix.length() + 5);
1462
1463 std::vector<char> buf1(name_size+1);
1464 std::vector<char> buf2(name_size+1);
1465
1466 /* colons are illegal in port names, so fix that */
1467
1468 string nom = _name.val();
1469 replace_all (nom, ":", ";");
1470
1471 snprintf (&buf1[0], name_size+1, ("%.*s/%s"), limit, nom.c_str(), suffix.c_str());
1472
1473 int port_number = find_port_hole (&buf1[0]);
1474 snprintf (&buf2[0], name_size+1, "%s %d", &buf1[0], port_number);
1475
1476 return string (&buf2[0]);
1477 }
1478
1479 int32_t
find_port_hole(const char * base)1480 IO::find_port_hole (const char* base)
1481 {
1482 /* CALLER MUST HOLD IO LOCK */
1483
1484 uint32_t n;
1485
1486 if (_ports.empty()) {
1487 return 1;
1488 }
1489
1490 /* we only allow up to 4 characters for the port number
1491 */
1492
1493 for (n = 1; n < 9999; ++n) {
1494 std::vector<char> buf (AudioEngine::instance()->port_name_size());
1495 PortSet::iterator i = _ports.begin();
1496
1497 snprintf (&buf[0], buf.size()+1, _("%s %u"), base, n);
1498
1499 for ( ; i != _ports.end(); ++i) {
1500 if (string(i->name()) == string(&buf[0])) {
1501 break;
1502 }
1503 }
1504
1505 if (i == _ports.end()) {
1506 break;
1507 }
1508 }
1509 return n;
1510 }
1511
1512
1513 boost::shared_ptr<AudioPort>
audio(uint32_t n) const1514 IO::audio(uint32_t n) const
1515 {
1516 return _ports.nth_audio_port (n);
1517
1518 }
1519
1520 boost::shared_ptr<MidiPort>
midi(uint32_t n) const1521 IO::midi(uint32_t n) const
1522 {
1523 return _ports.nth_midi_port (n);
1524 }
1525
1526 /**
1527 * Setup a bundle that describe our inputs or outputs. Also creates the bundle if necessary.
1528 */
1529 void
setup_bundle()1530 IO::setup_bundle ()
1531 {
1532 char buf[32];
1533
1534 if (!_bundle) {
1535 _bundle.reset (new Bundle (_direction == Input));
1536 }
1537
1538 _bundle->suspend_signals ();
1539
1540 _bundle->remove_channels ();
1541
1542 if (_direction == Input) {
1543 snprintf(buf, sizeof (buf), _("%s in"), _name.val().c_str());
1544 } else {
1545 snprintf(buf, sizeof (buf), _("%s out"), _name.val().c_str());
1546 }
1547 _bundle->set_name (buf);
1548
1549 int c = 0;
1550 for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
1551
1552 uint32_t const N = _ports.count().get (*i);
1553 for (uint32_t j = 0; j < N; ++j) {
1554 _bundle->add_channel (bundle_channel_name (j, N, *i), *i);
1555 _bundle->set_port (c, _session.engine().make_port_name_non_relative (_ports.port(*i, j)->name()));
1556 ++c;
1557 }
1558
1559 }
1560
1561 reestablish_port_subscriptions ();
1562
1563 _bundle->resume_signals ();
1564 }
1565
1566 /** @return Bundles connected to our ports */
1567 BundleList
bundles_connected()1568 IO::bundles_connected ()
1569 {
1570 BundleList bundles;
1571
1572 /* Session bundles */
1573 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
1574 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
1575 if ((*i)->connected_to (_bundle, _session.engine())) {
1576 bundles.push_back (*i);
1577 }
1578 }
1579
1580 /* Route bundles */
1581
1582 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
1583
1584 if (_direction == Input) {
1585 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1586 if ((*i)->output()->bundle()->connected_to (_bundle, _session.engine())) {
1587 bundles.push_back ((*i)->output()->bundle());
1588 }
1589 }
1590 } else {
1591 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1592 if ((*i)->input()->bundle()->connected_to (_bundle, _session.engine())) {
1593 bundles.push_back ((*i)->input()->bundle());
1594 }
1595 }
1596 }
1597
1598 return bundles;
1599 }
1600
1601
UserBundleInfo(IO * io,boost::shared_ptr<UserBundle> b)1602 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
1603 {
1604 bundle = b;
1605 b->Changed.connect_same_thread (changed, boost::bind (&IO::bundle_changed, io, _1));
1606 }
1607
1608 std::string
bundle_channel_name(uint32_t c,uint32_t n,DataType t) const1609 IO::bundle_channel_name (uint32_t c, uint32_t n, DataType t) const
1610 {
1611 char buf[32];
1612
1613 if (t == DataType::AUDIO) {
1614
1615 switch (n) {
1616 case 1:
1617 return _("mono");
1618 case 2:
1619 return c == 0 ? _("L") : _("R");
1620 default:
1621 snprintf (buf, sizeof(buf), "%d", (c + 1));
1622 return buf;
1623 }
1624
1625 } else {
1626
1627 snprintf (buf, sizeof(buf), "%d", (c + 1));
1628 return buf;
1629
1630 }
1631
1632 return "";
1633 }
1634
1635 string
name_from_state(const XMLNode & node)1636 IO::name_from_state (const XMLNode& node)
1637 {
1638 XMLProperty const * prop;
1639
1640 if ((prop = node.property ("name")) != 0) {
1641 return prop->value();
1642 }
1643
1644 return string();
1645 }
1646
1647 void
set_name_in_state(XMLNode & node,const string & new_name)1648 IO::set_name_in_state (XMLNode& node, const string& new_name)
1649 {
1650 node.set_property (X_("name"), new_name);
1651 XMLNodeList children = node.children ();
1652 for (XMLNodeIterator i = children.begin(); i != children.end(); ++i) {
1653 if ((*i)->name() == X_("Port")) {
1654 string const old_name = (*i)->property(X_("name"))->value();
1655 string const old_name_second_part = old_name.substr (old_name.find_first_of ("/") + 1);
1656 (*i)->set_property (X_("name"), string_compose ("%1/%2", new_name, old_name_second_part));
1657 }
1658 }
1659 }
1660
1661 bool
connected() const1662 IO::connected () const
1663 {
1664 /* do we have any connections at all? */
1665
1666 for (PortSet::const_iterator p = _ports.begin(); p != _ports.end(); ++p) {
1667 if (p->connected()) {
1668 return true;
1669 }
1670 }
1671
1672 return false;
1673 }
1674
1675 bool
connected_to(boost::shared_ptr<const IO> other) const1676 IO::connected_to (boost::shared_ptr<const IO> other) const
1677 {
1678 if (!other) {
1679 return connected ();
1680 }
1681
1682 assert (_direction != other->direction());
1683
1684 uint32_t i, j;
1685 uint32_t no = n_ports().n_total();
1686 uint32_t ni = other->n_ports ().n_total();
1687
1688 for (i = 0; i < no; ++i) {
1689 for (j = 0; j < ni; ++j) {
1690 if ((NULL != nth(i).get()) && (NULL != other->nth(j).get())) {
1691 if (nth(i)->connected_to (other->nth(j)->name())) {
1692 return true;
1693 }
1694 }
1695 }
1696 }
1697
1698 return false;
1699 }
1700
1701 bool
connected_to(const string & str) const1702 IO::connected_to (const string& str) const
1703 {
1704 for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
1705 if (i->connected_to (str)) {
1706 return true;
1707 }
1708 }
1709
1710 return false;
1711 }
1712
1713 void
collect_input(BufferSet & bufs,pframes_t nframes,ChanCount offset)1714 IO::collect_input (BufferSet& bufs, pframes_t nframes, ChanCount offset)
1715 {
1716 assert(bufs.available() >= _ports.count());
1717
1718 if (_ports.count() == ChanCount::ZERO) {
1719 return;
1720 }
1721
1722 bufs.set_count (_ports.count());
1723
1724 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1725 PortSet::iterator i = _ports.begin(*t);
1726 BufferSet::iterator b = bufs.begin(*t);
1727
1728 for (uint32_t off = 0; off < offset.get(*t); ++off, ++b) {
1729 if (b == bufs.end(*t)) {
1730 continue;
1731 }
1732 }
1733
1734 for ( ; i != _ports.end(*t); ++i, ++b) {
1735 const Buffer& bb (i->get_buffer (nframes));
1736 b->read_from (bb, nframes);
1737 }
1738 }
1739 }
1740
1741 void
copy_to_outputs(BufferSet & bufs,DataType type,pframes_t nframes,samplecnt_t offset)1742 IO::copy_to_outputs (BufferSet& bufs, DataType type, pframes_t nframes, samplecnt_t offset)
1743 {
1744 PortSet::iterator o = _ports.begin(type);
1745 BufferSet::iterator i = bufs.begin(type);
1746 BufferSet::iterator prev = i;
1747
1748 assert(i != bufs.end(type)); // or second loop will crash
1749
1750 // Copy any buffers 1:1 to outputs
1751
1752 while (i != bufs.end(type) && o != _ports.end (type)) {
1753 Buffer& port_buffer (o->get_buffer (nframes));
1754 port_buffer.read_from (*i, nframes, offset);
1755 prev = i;
1756 ++i;
1757 ++o;
1758 }
1759
1760 // Copy last buffer to any extra outputs
1761
1762 while (o != _ports.end(type)) {
1763 Buffer& port_buffer (o->get_buffer (nframes));
1764 port_buffer.read_from (*prev, nframes, offset);
1765 ++o;
1766 }
1767 }
1768
1769 boost::shared_ptr<Port>
port_by_name(const std::string & str) const1770 IO::port_by_name (const std::string& str) const
1771 {
1772 /* to be called only from ::set_state() - no locking */
1773
1774 for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
1775
1776 if (i->name() == str) {
1777 return boost::const_pointer_cast<Port> (*i);
1778 }
1779 }
1780
1781 return boost::shared_ptr<Port> ();
1782 }
1783
1784 bool
physically_connected() const1785 IO::physically_connected () const
1786 {
1787 for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
1788 if (i->physically_connected()) {
1789 return true;
1790 }
1791 }
1792
1793 return false;
1794 }
1795
1796 bool
has_port(boost::shared_ptr<Port> p) const1797 IO::has_port (boost::shared_ptr<Port> p) const
1798 {
1799 Glib::Threads::Mutex::Lock lm (io_lock);
1800 return _ports.contains (p);
1801 }
1802