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