29 #include <glibmm/threads.h>
39 #include "ardour/debug.h"
48 #define BLOCK_PROCESS_CALLBACK() Glib::Threads::Mutex::Lock em (AudioEngine::instance()->process_lock())
55 bool IO::connecting_legal =
false;
56 PBD::Signal0<int> IO::ConnectingLegal;
57 PBD::Signal1<void,ChanCount> IO::PortCountChanged;
65 , _default_type (default_type)
69 Port::PostDisconnect.connect_same_thread (*
this, boost::bind (&IO::disconnect_check,
this, _1, _2));
70 pending_state_node = 0;
131 i->increment_port_buffer_offset (offset);
142 i->get_buffer(nframes).silence (nframes);
152 std::vector<UserBundleInfo*> new_list;
156 uint32_t
const N = (*i)->bundle->nchannels().n_total();
164 for (uint32_t j = 0; j <
N; ++j) {
167 for (uint32_t k = 0; k < pl.size(); ++k) {
168 if (
_ports.
port(j)->connected_to (pl[k]) ==
false) {
180 new_list.push_back (*i);
193 if (other_port.length() == 0 || our_port == 0) {
226 if (other_port.length() == 0 || our_port == 0) {
241 if (our_port->
connect (other_port)) {
258 if (r.get_value_or (
false)) {
322 after.
set (type, after.
get (type) + 1);
365 if (!destination.empty()) {
366 if (our_port->
connect (destination)) {
384 i->disconnect_all ();
399 #ifndef PLATFORM_WINDOWS
409 const size_t n = count.
get(*t);
412 for (
size_t i =
n_ports().
get(*t); i > n; --i) {
423 while (
n_ports().
get(*t) < n) {
461 i->disconnect_all ();
472 #ifndef PLATFORM_WINDOWS
478 if (count ==
n_ports() && !clear) {
509 #ifndef PLATFORM_WINDOWS
528 vector<string>::iterator ci;
534 id().
print (buf,
sizeof (buf));
547 vector<string> connections;
553 if (i->get_connections (connections)) {
555 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
587 assert (version >= 3000);
602 if ((prop = node.
property (
"name")) != 0) {
606 if ((prop = node.
property (
X_(
"default-type"))) != 0) {
613 if ((prop = node.
property (
"direction")) != 0) {
635 if ((prop = node.
property (
"user-latency")) != 0) {
658 if ((prop = node.
property (
"name")) != 0) {
662 if ((prop = node.
property (
X_(
"default-type"))) != 0) {
712 static const string digits =
"0123456789";
714 const string &bundle_type_name = (
_direction ==
Input ?
_(
"input") :
_(
"output"));
719 int bundle_number, mask;
720 string possible_name;
722 string::size_type last_non_digit_pos;
730 last_non_digit_pos = desired_name.find_last_not_of(digits);
732 if (last_non_digit_pos != string::npos) {
734 s << desired_name.substr(last_non_digit_pos);
740 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] ==
'+') {
741 string::size_type left_last_non_digit_pos;
743 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
745 if (left_last_non_digit_pos != string::npos) {
746 int left_bundle_number = 0;
748 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
749 s >> left_bundle_number;
751 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
764 while ((mask <= bundle_number) && (mask <<= 1)) {}
771 if (bundle_number & mask) {
772 bundle_number &= ~mask;
775 s << default_name <<
" " << bundle_number + 1;
778 s <<
"+" << bundle_number + 2;
781 possible_name = s.str();
790 info <<
string_compose (
_(
"Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
809 uint32_t n_audio = 0;
814 n_audio = count (prop->
value().begin(), prop->
value().end(),
'{');
818 n_audio = count (prop->
value().begin(), prop->
value().end(),
'{');
834 if (version < 3000) {
840 uint32_t n_audio = 0;
846 if ((prop = node.
property (
"connection")) != 0) {
854 for (iter = node.
children().begin(); iter != node.
children().end(); ++iter) {
856 if ((*iter)->name() ==
X_(
"Bundle")) {
857 prop = (*iter)->property (
"name");
866 if ((*iter)->name() ==
X_(
"Port")) {
867 prop = (*iter)->property (
X_(
"type"));
873 if (prop->
value() ==
X_(
"audio")) {
875 }
else if (prop->
value() ==
X_(
"midi")) {
910 if (version < 3000) {
918 if ((*i)->name() ==
"Bundle") {
919 XMLProperty const * prop = (*i)->property (
"name");
930 if ((*i)->name() ==
"Port") {
932 prop = (*i)->property (
X_(
"name"));
945 if (cnode->
name() !=
X_(
"Connection")) {
949 if ((prop = cnode->
property (
X_(
"other"))) == 0) {
980 if ((*i)->name() ==
"Port") {
982 prop = (*i)->property (
X_(
"name"));
986 string old = prop->
value();
987 string::size_type slash = old.find (
'/');
989 if (slash != string::npos) {
993 new_name += old.substr (old.find (
'/'));
1010 if ((prop = node.
property (
"inputs")) != 0 && in) {
1012 string::size_type ostart = 0;
1013 string::size_type
start = 0;
1014 string::size_type end = 0;
1017 vector<string>
ports;
1019 string const str = prop->
value ();
1021 while ((start = str.find_first_of (
'{', ostart)) != string::npos) {
1024 if ((end = str.find_first_of (
'}', start)) == string::npos) {
1037 for (
int x = 0; x < n; ++x) {
1039 string::size_type
const p = ports[x].find (
"/out");
1040 if (p != string::npos) {
1041 ports[x].replace (p, 4,
"/audio_out");
1043 if (NULL !=
nth(i).
get())
1044 nth(i)->connect (ports[x]);
1054 if ((prop = node.
property (
"outputs")) != 0 && !in) {
1056 string::size_type ostart = 0;
1057 string::size_type
start = 0;
1058 string::size_type end = 0;
1061 vector<string>
ports;
1063 string const str = prop->
value ();
1065 while ((start = str.find_first_of (
'{', ostart)) != string::npos) {
1068 if ((end = str.find_first_of (
'}', start)) == string::npos) {
1080 for (
int x = 0; x < n; ++x) {
1082 string::size_type
const p = ports[x].find (
"/in");
1083 if (p != string::npos) {
1084 ports[x].replace (p, 3,
"/audio_in");
1086 if (NULL !=
nth(i).
get())
1087 nth(i)->connect (ports[x]);
1102 vector<string>
ports;
1106 if ((nports = count (str.begin(), str.end(),
'{')) == 0) {
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) {
1125 if ((end = str.find_first_of (
'}', start)) == string::npos) {
1137 for (
int x = 0; x < n; ++x) {
1151 string::size_type pos, opos;
1153 if (str.length() == 0) {
1162 while ((pos = str.find_first_of (
',', opos)) != string::npos) {
1163 ports.push_back (str.substr (opos, pos - opos));
1167 if (opos < str.length()) {
1168 ports.push_back (str.substr(opos));
1171 return ports.size();
1177 string::size_type pos, opos;
1182 while ((pos = str.find_first_of (
',', opos)) != string::npos) {
1183 ports.push_back (str.substr (opos, pos - opos));
1187 if (opos < str.length()) {
1188 ports.push_back (str.substr(opos));
1191 return ports.size();
1197 string name = requested_name;
1199 if (
_name == name) {
1208 string current_name = i->name();
1210 i->set_name (current_name);
1231 if ((latency = i->private_latency_range (
_direction ==
Output).max) > max_latency) {
1256 i->disconnect_all ();
1329 return r.get_value_or (0);
1348 suffix =
X_(
"audio");
1350 suffix =
X_(
"midi");
1363 suffix +=
X_(
"_return");
1365 suffix +=
X_(
"_send");
1369 suffix +=
X_(
"_in");
1371 suffix +=
X_(
"_out");
1379 std::vector<char> buf1(name_size+1);
1380 std::vector<char> buf2(name_size+1);
1387 snprintf (&buf1[0], name_size+1, (
"%.*s/%s"), limit, nom.c_str(), suffix.c_str());
1390 snprintf (&buf2[0], name_size+1,
"%s %d", &buf1[0], port_number);
1392 return string (&buf2[0]);
1409 for (n = 1; n < 9999; ++n) {
1413 snprintf (&buf[0], buf.size()+1,
_(
"%s %u"), base, n);
1416 if (
string(i->name()) ==
string(&buf[0])) {
1460 snprintf(buf,
sizeof (buf),
_(
"%s in"),
_name.
val().c_str());
1462 snprintf(buf,
sizeof (buf),
_(
"%s out"),
_name.
val().c_str());
1470 for (uint32_t j = 0; j <
N; ++j) {
1489 bundles.push_back ((*i)->bundle);
1494 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
1496 bundles.push_back (*i);
1505 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1507 bundles.push_back ((*i)->output()->bundle());
1511 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1513 bundles.push_back ((*i)->input()->bundle());
1539 return c == 0 ?
_(
"L") :
_(
"R");
1541 snprintf (buf,
sizeof(buf),
_(
"%d"), (c + 1));
1547 snprintf (buf,
sizeof(buf),
_(
"%d"), (c + 1));
1560 if ((prop = node.
property (
"name")) != 0) {
1561 return prop->
value();
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));
1587 if (p->connected()) {
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())) {
1625 if (i->connected_to (str)) {
1641 if (
n_ports().n_total() == 0) {
1648 proc->
run (
_buffers, start_frame, end_frame, nframes,
true);
1667 for (uint32_t off = 0; off < offset.
get(*t); ++off, ++b) {
1668 if (b == bufs.
end(*t)) {
1673 for ( ; i !=
_ports.
end(*t); ++i, ++b) {
1674 Buffer& bb (i->get_buffer (nframes));
1675 b->read_from (bb, nframes);
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);
1700 Buffer& port_buffer (o->get_buffer (nframes));
1701 port_buffer.
read_from (*prev, nframes, offset);
1713 if (i->name() == str) {
1725 if (i->physically_connected()) {
virtual DataType type() const =0
static int enable_connecting()
int make_connections_2X(const XMLNode &, int, bool)
int get_port_counts(const XMLNode &node, int version, ChanCount &n, boost::shared_ptr< Bundle > &c)
XMLNodeList::iterator XMLNodeIterator
ARDOUR::Session & _session
boost::shared_ptr< MidiPort > nth_midi_port(size_t n) const
uint32_t port_name_size() const
int atoi(const string &s)
void disconnect_check(boost::shared_ptr< ARDOUR::Port >, boost::shared_ptr< ARDOUR::Port >)
LIBARDOUR_API uint64_t Latency
PBD::ScopedConnection changed
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
const std::string & value() const
int connect(std::string const &)
boost::shared_ptr< UserBundle > bundle
static void prepare_for_reset(XMLNode &, const std::string &)
void set_count(const ChanCount &count)
virtual void silence(framecnt_t)
static int parse_gain_string(const std::string &, std::vector< std::string > &chns)
bool pending_state_node_in
const char * to_string() const
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
std::vector< std::string > PortList
void connect(boost::shared_ptr< Bundle >, AudioEngine &)
Direction direction() const
framecnt_t latency() const
const std::string & name() const
UserBundleInfo(IO *, boost::shared_ptr< UserBundle > b)
shared_ptr< T > const_pointer_cast(shared_ptr< U > const &r)
XMLNode & get_state(void)
iterator end(DataType type=DataType::NIL)
void copy_to_outputs(BufferSet &bufs, DataType type, pframes_t nframes, framecnt_t offset)
LIBPBD_API Transmitter error
static PBD::Signal2< void, boost::shared_ptr< Port >, boost::shared_ptr< Port > > PostDisconnect
const XMLNodeList & children(const std::string &str=std::string()) const
static PBD::Signal0< int > ConnectingLegal
static bool connecting_legal
std::string bundle_channel_name(uint32_t, uint32_t, DataType) const
std::ostream & endmsg(std::ostream &ostr)
boost::shared_ptr< Bundle > find_possible_bundle(const std::string &desired_name)
void add(boost::shared_ptr< Port > port)
int add_port(std::string connection, void *src, DataType type=DataType::NIL)
int set_state(const XMLNode &, int version)
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
static AudioEngine * instance()
LIBPBD_API int replace_all(std::string &str, const std::string &target, const std::string &replacement)
XMLNode * pending_state_node
int disconnect_ports_from_bundle(boost::shared_ptr< Bundle >, void *)
int make_connections(const XMLNode &, int, bool)
boost::shared_ptr< AudioPort > audio(uint32_t n) const
std::list< XMLNode * > XMLNodeList
int ensure_ports_locked(ChanCount, bool clear, bool &changed)
int remove_port(boost::shared_ptr< Port >, void *src)
int create_ports(const XMLNode &, int version)
int set_state_2X(const XMLNode &, int, bool)
const ChanCount & n_ports() const
static const char * state_node_name
void collect_input(BufferSet &bufs, pframes_t nframes, ChanCount offset)
int connecting_became_legal()
void process_input(boost::shared_ptr< Processor >, framepos_t start_frame, framepos_t end_frame, pframes_t nframes)
XMLProperty * property(const char *)
std::string make_port_name_relative(const std::string &name) const
#define string_2_enum(str, e)
static int disable_connecting()
virtual XMLNode & state(bool full)
enum ARDOUR::IOChange::Type type
bool has_port(boost::shared_ptr< Port >) const
std::vector< boost::shared_ptr< Bundle > > BundleList
int set_ports(const std::string &str)
iterator begin(DataType type)
std::vector< UserBundleInfo * > _bundles_connected
user bundles connected to our ports
void disconnect(boost::shared_ptr< Bundle >, AudioEngine &)
iterator end(DataType type)
const PBD::ID & id() const
virtual bool set_name(const std::string &str)
void print(char *buf, uint32_t bufsize) const
boost::shared_ptr< BundleList > bundles()
bool set_id(const XMLNode &)
boost::shared_ptr< MidiPort > midi(uint32_t n) const
ChanCount nchannels() const
bool physically_connected() const
static PBD::Signal1< void, ChanCount > PortCountChanged
boost::shared_ptr< RouteList > get_routes() const
#define DEBUG_TRACE(bits, str)
static ChanCount max(const ChanCount &a, const ChanCount &b)
virtual void read_from(const Buffer &src, framecnt_t len, framecnt_t dst_offset=0, framecnt_t src_offset=0)=0
BundleList bundles_connected()
static int loading_state_version
PBD::Property< std::string > _name
void bundle_changed(Bundle::Change)
void get_backend_port_addresses(PortSet &, framecnt_t)
LIBPBD_API Transmitter info
bool remove(boost::shared_ptr< Port > port)
std::string build_legal_port_name(DataType type)
void set_audio(uint32_t a)
int ensure_ports(ChanCount, bool clear, void *src)
void check_bundles_connected()
XMLProperty * add_property(const char *name, const std::string &value)
boost::shared_ptr< Port > nth(uint32_t n) const
PBD::Signal1< void, Change > Changed
Glib::Threads::Mutex io_lock
int32_t find_port_hole(const char *base)
#define BLOCK_PROCESS_CALLBACK()
void add_child_nocopy(XMLNode &)
uint32_t get(DataType t) const
static void set_name_in_state(XMLNode &, const std::string &)
int connect(boost::shared_ptr< Port > our_port, std::string other_port, void *src)
void set_midi(uint32_t m)
PBD::ScopedConnection connection_legal_c
bool contains(boost::shared_ptr< const Port > port) const
void set(DataType t, uint32_t count)
boost::shared_ptr< Port > port(size_t index) const
void increment_port_buffer_offset(pframes_t offset)
PBD::Signal1< bool, ChanCount, BoolCombiner > PortCountChanging
const ChanCount & available() const
static const std::string state_node_name
int get_port_counts_2X(const XMLNode &node, int version, ChanCount &n, boost::shared_ptr< Bundle > &c)
static std::string name_from_state(const XMLNode &)
int ensure_io(ChanCount cnt, bool clear, void *src)
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
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
int connect_ports_to_bundle(boost::shared_ptr< Bundle >, bool exclusive, void *)
int pending_state_node_version
boost::shared_ptr< Bundle > _bundle
a bundle representing our ports
bool connected_to(boost::shared_ptr< const IO >) const
bool set_name(const std::string &str)
static int parse_io_string(const std::string &, std::vector< std::string > &chns)
const std::string & set_value(const std::string &v)
int unregister_port(boost::shared_ptr< Port >)
iterator begin(DataType type=DataType::NIL)
std::string make_port_name_non_relative(const std::string &name) const
static const ChanCount ZERO
int disconnect(std::string const &)
XMLNodeList::const_iterator XMLNodeConstIterator
void attach_buffers(PortSet &ports)
virtual void run(BufferSet &, framepos_t, framepos_t, pframes_t, bool)
const ChanCount & count() const
std::string string_compose(const std::string &fmt, const T1 &o1)