mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 19:56:31 +01:00
Use shared_ptr for Port in the AudioEngine; improves thread-safety of the audio engine's port list as a writer cannot destroy a port in one thread while the port list is being iterated in another.
git-svn-id: svn://localhost/ardour2/branches/3.0@10327 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
f65e3f287b
commit
7bdcc127e3
23 changed files with 169 additions and 175 deletions
|
|
@ -218,21 +218,21 @@ PortExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c)
|
||||||
}
|
}
|
||||||
|
|
||||||
Glib::RefPtr<Gtk::ListStore> port_list = r_it->get_value (route_cols.port_list_col);
|
Glib::RefPtr<Gtk::ListStore> port_list = r_it->get_value (route_cols.port_list_col);
|
||||||
std::set<AudioPort *> route_ports;
|
std::set<boost::weak_ptr<AudioPort> > route_ports;
|
||||||
std::set<AudioPort *> intersection;
|
std::set<boost::weak_ptr<AudioPort> > intersection;
|
||||||
std::map<AudioPort *, string> port_labels;
|
std::map<boost::weak_ptr<AudioPort>, string> port_labels;
|
||||||
|
|
||||||
for (Gtk::ListStore::Children::const_iterator p_it = port_list->children().begin(); p_it != port_list->children().end(); ++p_it) {
|
for (Gtk::ListStore::Children::const_iterator p_it = port_list->children().begin(); p_it != port_list->children().end(); ++p_it) {
|
||||||
route_ports.insert ((*p_it)->get_value (route_cols.port_cols.port));
|
route_ports.insert ((*p_it)->get_value (route_cols.port_cols.port));
|
||||||
port_labels.insert (std::pair<AudioPort*, string> ((*p_it)->get_value (route_cols.port_cols.port),
|
port_labels.insert (make_pair ((*p_it)->get_value (route_cols.port_cols.port),
|
||||||
(*p_it)->get_value (route_cols.port_cols.label)));
|
(*p_it)->get_value (route_cols.port_cols.label)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set_intersection (pec->get_ports().begin(), pec->get_ports().end(),
|
std::set_intersection (pec->get_ports().begin(), pec->get_ports().end(),
|
||||||
route_ports.begin(), route_ports.end(),
|
route_ports.begin(), route_ports.end(),
|
||||||
std::insert_iterator<std::set<AudioPort *> > (intersection, intersection.begin()));
|
std::insert_iterator<std::set<boost::weak_ptr<AudioPort> > > (intersection, intersection.begin()));
|
||||||
|
|
||||||
intersection.erase (0); // Remove "none" selection
|
intersection.erase (boost::weak_ptr<AudioPort> ()); // Remove "none" selection
|
||||||
|
|
||||||
if (intersection.empty()) {
|
if (intersection.empty()) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -244,13 +244,13 @@ PortExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c)
|
||||||
/* Set previous channels (if any) to none */
|
/* Set previous channels (if any) to none */
|
||||||
|
|
||||||
for (uint32_t chn = 1; chn < i; ++chn) {
|
for (uint32_t chn = 1; chn < i; ++chn) {
|
||||||
r_it->set_value (route_cols.get_channel (chn).port, (AudioPort *) 0);
|
r_it->set_value (route_cols.get_channel (chn).port, boost::weak_ptr<AudioPort> ());
|
||||||
r_it->set_value (route_cols.get_channel (chn).label, string ("(none)"));
|
r_it->set_value (route_cols.get_channel (chn).label, string ("(none)"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioPort * port = *intersection.begin();
|
boost::weak_ptr<AudioPort> port = *intersection.begin();
|
||||||
std::map<AudioPort *, string>::iterator label_it = port_labels.find (port);
|
std::map<boost::weak_ptr<AudioPort>, string>::iterator label_it = port_labels.find (port);
|
||||||
string label = label_it != port_labels.end() ? label_it->second : "error";
|
string label = label_it != port_labels.end() ? label_it->second : "error";
|
||||||
|
|
||||||
r_it->set_value (route_cols.get_channel (i).port, port);
|
r_it->set_value (route_cols.get_channel (i).port, port);
|
||||||
|
|
@ -294,7 +294,7 @@ PortExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * io)
|
||||||
row = *iter;
|
row = *iter;
|
||||||
|
|
||||||
row[route_cols.port_cols.selected] = false;
|
row[route_cols.port_cols.selected] = false;
|
||||||
row[route_cols.port_cols.port] = 0;
|
row[route_cols.port_cols.port] = boost::weak_ptr<AudioPort> ();
|
||||||
row[route_cols.port_cols.label] = "(none)";
|
row[route_cols.port_cols.label] = "(none)";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -331,7 +331,7 @@ PortExportChannelSelector::ChannelTreeView::set_channel_count (uint32_t channels
|
||||||
for (Gtk::ListStore::Children::iterator it = route_list->children().begin(); it != route_list->children().end(); ++it) {
|
for (Gtk::ListStore::Children::iterator it = route_list->children().begin(); it != route_list->children().end(); ++it) {
|
||||||
std::string label = it->get_value(route_cols.selected) ? "(none)" : "";
|
std::string label = it->get_value(route_cols.selected) ? "(none)" : "";
|
||||||
it->set_value (route_cols.get_channel (n_channels).label, label);
|
it->set_value (route_cols.get_channel (n_channels).label, label);
|
||||||
it->set_value (route_cols.get_channel (n_channels).port, (AudioPort *) 0);
|
it->set_value (route_cols.get_channel (n_channels).port, boost::weak_ptr<AudioPort> ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set column width */
|
/* set column width */
|
||||||
|
|
@ -355,7 +355,6 @@ PortExportChannelSelector::ChannelTreeView::set_channel_count (uint32_t channels
|
||||||
void
|
void
|
||||||
PortExportChannelSelector::ChannelTreeView::update_config ()
|
PortExportChannelSelector::ChannelTreeView::update_config ()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!config) { return; }
|
if (!config) { return; }
|
||||||
|
|
||||||
config->clear_channels();
|
config->clear_channels();
|
||||||
|
|
@ -372,7 +371,8 @@ PortExportChannelSelector::ChannelTreeView::update_config ()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioPort * port = row[route_cols.get_channel (i).port];
|
boost::weak_ptr<AudioPort> weak_port = row[route_cols.get_channel (i).port];
|
||||||
|
boost::shared_ptr<AudioPort> port = weak_port.lock ();
|
||||||
if (port) {
|
if (port) {
|
||||||
pec->add_port (port);
|
pec->add_port (port);
|
||||||
}
|
}
|
||||||
|
|
@ -398,7 +398,7 @@ PortExportChannelSelector::ChannelTreeView::update_toggle_selection (std::string
|
||||||
}
|
}
|
||||||
|
|
||||||
iter->set_value (route_cols.get_channel (i).label, std::string("(none)"));
|
iter->set_value (route_cols.get_channel (i).label, std::string("(none)"));
|
||||||
iter->set_value (route_cols.get_channel (i).port, (AudioPort *) 0);
|
iter->set_value (route_cols.get_channel (i).port, boost::weak_ptr<AudioPort> ());
|
||||||
|
|
||||||
Glib::RefPtr<Gtk::ListStore> port_list = iter->get_value (route_cols.port_list_col);
|
Glib::RefPtr<Gtk::ListStore> port_list = iter->get_value (route_cols.port_list_col);
|
||||||
Gtk::ListStore::Children::iterator port_it;
|
Gtk::ListStore::Children::iterator port_it;
|
||||||
|
|
@ -407,7 +407,7 @@ PortExportChannelSelector::ChannelTreeView::update_toggle_selection (std::string
|
||||||
for (port_it = port_list->children().begin(); port_it != port_list->children().end(); ++port_it) {
|
for (port_it = port_list->children().begin(); port_it != port_list->children().end(); ++port_it) {
|
||||||
if (port_number == i) {
|
if (port_number == i) {
|
||||||
iter->set_value (route_cols.get_channel (i).label, (std::string) (*port_it)->get_value (route_cols.port_cols.label));
|
iter->set_value (route_cols.get_channel (i).label, (std::string) (*port_it)->get_value (route_cols.port_cols.label));
|
||||||
iter->set_value (route_cols.get_channel (i).port, (AudioPort *) (*port_it)->get_value (route_cols.port_cols.port));
|
iter->set_value (route_cols.get_channel (i).port, (*port_it)->get_value (route_cols.port_cols.port));
|
||||||
}
|
}
|
||||||
|
|
||||||
++port_number;
|
++port_number;
|
||||||
|
|
@ -429,7 +429,8 @@ PortExportChannelSelector::ChannelTreeView::update_selection_text (std::string c
|
||||||
for (port_it = port_list->children().begin(); port_it != port_list->children().end(); ++port_it) {
|
for (port_it = port_list->children().begin(); port_it != port_list->children().end(); ++port_it) {
|
||||||
std::string label = port_it->get_value (route_cols.port_cols.label);
|
std::string label = port_it->get_value (route_cols.port_cols.label);
|
||||||
if (label == new_text) {
|
if (label == new_text) {
|
||||||
iter->set_value (route_cols.get_channel (channel).port, (AudioPort *) (*port_it)[route_cols.port_cols.port]);
|
boost::weak_ptr<AudioPort> w = (*port_it)[route_cols.port_cols.port];
|
||||||
|
iter->set_value (route_cols.get_channel (channel).port, w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ class PortExportChannelSelector : public ExportChannelSelector
|
||||||
public:
|
public:
|
||||||
Channel (RouteCols & cols) { cols.add (port); cols.add (label); }
|
Channel (RouteCols & cols) { cols.add (port); cols.add (label); }
|
||||||
|
|
||||||
Gtk::TreeModelColumn<ARDOUR::AudioPort *> port;
|
Gtk::TreeModelColumn<boost::weak_ptr<ARDOUR::AudioPort> > port;
|
||||||
Gtk::TreeModelColumn<std::string> label;
|
Gtk::TreeModelColumn<std::string> label;
|
||||||
};
|
};
|
||||||
std::list<Channel> channels;
|
std::list<Channel> channels;
|
||||||
|
|
@ -147,7 +147,7 @@ class PortExportChannelSelector : public ExportChannelSelector
|
||||||
PortCols () { add(selected); add(port); add(label); }
|
PortCols () { add(selected); add(port); add(label); }
|
||||||
|
|
||||||
Gtk::TreeModelColumn<bool> selected; // not used ATM
|
Gtk::TreeModelColumn<bool> selected; // not used ATM
|
||||||
Gtk::TreeModelColumn<ARDOUR::AudioPort *> port;
|
Gtk::TreeModelColumn<boost::weak_ptr<ARDOUR::AudioPort> > port;
|
||||||
Gtk::TreeModelColumn<std::string> label;
|
Gtk::TreeModelColumn<std::string> label;
|
||||||
};
|
};
|
||||||
PortCols port_cols;
|
PortCols port_cols;
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ GlobalPortMatrix::set_state (BundleChannel c[2], bool s)
|
||||||
for (Bundle::PortList::const_iterator i = in_ports.begin(); i != in_ports.end(); ++i) {
|
for (Bundle::PortList::const_iterator i = in_ports.begin(); i != in_ports.end(); ++i) {
|
||||||
for (Bundle::PortList::const_iterator j = out_ports.begin(); j != out_ports.end(); ++j) {
|
for (Bundle::PortList::const_iterator j = out_ports.begin(); j != out_ports.end(); ++j) {
|
||||||
|
|
||||||
Port* p = _session->engine().get_port_by_name (*i);
|
boost::shared_ptr<Port> p = _session->engine().get_port_by_name (*i);
|
||||||
Port* q = _session->engine().get_port_by_name (*j);
|
boost::shared_ptr<Port> q = _session->engine().get_port_by_name (*j);
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
if (s) {
|
if (s) {
|
||||||
|
|
@ -105,8 +105,8 @@ GlobalPortMatrix::get_state (BundleChannel c[2]) const
|
||||||
for (Bundle::PortList::const_iterator i = in_ports.begin(); i != in_ports.end(); ++i) {
|
for (Bundle::PortList::const_iterator i = in_ports.begin(); i != in_ports.end(); ++i) {
|
||||||
for (Bundle::PortList::const_iterator j = out_ports.begin(); j != out_ports.end(); ++j) {
|
for (Bundle::PortList::const_iterator j = out_ports.begin(); j != out_ports.end(); ++j) {
|
||||||
|
|
||||||
Port* p = _session->engine().get_port_by_name (*i);
|
boost::shared_ptr<Port> p = _session->engine().get_port_by_name (*i);
|
||||||
Port* q = _session->engine().get_port_by_name (*j);
|
boost::shared_ptr<Port> q = _session->engine().get_port_by_name (*j);
|
||||||
|
|
||||||
if (!p && !q) {
|
if (!p && !q) {
|
||||||
/* two non-Ardour ports; things are slightly more involved */
|
/* two non-Ardour ports; things are slightly more involved */
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ IOSelector::set_state (ARDOUR::BundleChannel c[2], bool s)
|
||||||
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
|
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
|
||||||
for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
|
for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
|
||||||
|
|
||||||
Port* f = _session->engine().get_port_by_name (*i);
|
boost::shared_ptr<Port> f = _session->engine().get_port_by_name (*i);
|
||||||
if (!f) {
|
if (!f) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -172,7 +172,7 @@ IOSelector::get_state (ARDOUR::BundleChannel c[2]) const
|
||||||
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
|
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
|
||||||
for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
|
for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
|
||||||
|
|
||||||
Port* f = _session->engine().get_port_by_name (*i);
|
boost::shared_ptr<Port> f = _session->engine().get_port_by_name (*i);
|
||||||
|
|
||||||
/* since we are talking about an IO, our ports should all have an associated Port *,
|
/* since we are talking about an IO, our ports should all have an associated Port *,
|
||||||
so the above call should never fail */
|
so the above call should never fail */
|
||||||
|
|
|
||||||
|
|
@ -993,7 +993,7 @@ MixerStrip::update_io_button (boost::shared_ptr<ARDOUR::Route> route, Width widt
|
||||||
{
|
{
|
||||||
uint32_t io_count;
|
uint32_t io_count;
|
||||||
uint32_t io_index;
|
uint32_t io_index;
|
||||||
Port *port;
|
boost::shared_ptr<Port> port;
|
||||||
vector<string> port_connections;
|
vector<string> port_connections;
|
||||||
|
|
||||||
uint32_t total_connection_count = 0;
|
uint32_t total_connection_count = 0;
|
||||||
|
|
@ -1185,8 +1185,15 @@ MixerStrip::diskstream_changed ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerStrip::port_connected_or_disconnected (Port* a, Port* b)
|
MixerStrip::port_connected_or_disconnected (boost::weak_ptr<Port> wa, boost::weak_ptr<Port> wb)
|
||||||
{
|
{
|
||||||
|
boost::shared_ptr<Port> a = wa.lock ();
|
||||||
|
boost::shared_ptr<Port> b = wb.lock ();
|
||||||
|
|
||||||
|
if (!a || !b) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_route->input()->has_port (a) || _route->input()->has_port (b)) {
|
if (_route->input()->has_port (a) || _route->input()->has_port (b)) {
|
||||||
update_input_display ();
|
update_input_display ();
|
||||||
set_width_enum (_width, this);
|
set_width_enum (_width, this);
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
|
||||||
static int scrollbar_height;
|
static int scrollbar_height;
|
||||||
|
|
||||||
void update_io_button (boost::shared_ptr<ARDOUR::Route> route, Width width, bool input_button);
|
void update_io_button (boost::shared_ptr<ARDOUR::Route> route, Width width, bool input_button);
|
||||||
void port_connected_or_disconnected (ARDOUR::Port *, ARDOUR::Port *);
|
void port_connected_or_disconnected (boost::weak_ptr<ARDOUR::Port>, boost::weak_ptr<ARDOUR::Port>);
|
||||||
|
|
||||||
static std::string meter_point_string (ARDOUR::MeterPoint);
|
static std::string meter_point_string (ARDOUR::MeterPoint);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -700,7 +700,7 @@ PortMatrix::remove_channel (ARDOUR::BundleChannel b)
|
||||||
boost::shared_ptr<IO> io = io_from_bundle (b.bundle);
|
boost::shared_ptr<IO> io = io_from_bundle (b.bundle);
|
||||||
|
|
||||||
if (io) {
|
if (io) {
|
||||||
Port* p = io->nth (b.channel);
|
boost::shared_ptr<Port> p = io->nth (b.channel);
|
||||||
if (p) {
|
if (p) {
|
||||||
int const r = io->remove_port (p, this);
|
int const r = io->remove_port (p, this);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ class ProcessThread;
|
||||||
class AudioEngine : public SessionHandlePtr
|
class AudioEngine : public SessionHandlePtr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::set<Port*> Ports;
|
typedef std::set<boost::shared_ptr<Port> > Ports;
|
||||||
|
|
||||||
AudioEngine (std::string client_name, std::string session_uuid);
|
AudioEngine (std::string client_name, std::string session_uuid);
|
||||||
virtual ~AudioEngine ();
|
virtual ~AudioEngine ();
|
||||||
|
|
@ -161,9 +161,9 @@ public:
|
||||||
virtual const char *what() const throw() { return "could not connect to engine backend"; }
|
virtual const char *what() const throw() { return "could not connect to engine backend"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
Port *register_input_port (DataType, const std::string& portname);
|
boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname);
|
||||||
Port *register_output_port (DataType, const std::string& portname);
|
boost::shared_ptr<Port> register_output_port (DataType, const std::string& portname);
|
||||||
int unregister_port (Port &);
|
int unregister_port (boost::shared_ptr<Port>);
|
||||||
|
|
||||||
bool port_is_physical (const std::string&) const;
|
bool port_is_physical (const std::string&) const;
|
||||||
void ensure_monitor_input (const std::string&, bool) const;
|
void ensure_monitor_input (const std::string&, bool) const;
|
||||||
|
|
@ -172,7 +172,7 @@ public:
|
||||||
|
|
||||||
int connect (const std::string& source, const std::string& destination);
|
int connect (const std::string& source, const std::string& destination);
|
||||||
int disconnect (const std::string& source, const std::string& destination);
|
int disconnect (const std::string& source, const std::string& destination);
|
||||||
int disconnect (Port &);
|
int disconnect (boost::shared_ptr<Port>);
|
||||||
|
|
||||||
const char ** get_ports (const std::string& port_name_pattern, const std::string& type_name_pattern, uint32_t flags);
|
const char ** get_ports (const std::string& port_name_pattern, const std::string& type_name_pattern, uint32_t flags);
|
||||||
|
|
||||||
|
|
@ -184,7 +184,7 @@ public:
|
||||||
void get_physical_outputs (DataType type, std::vector<std::string>&);
|
void get_physical_outputs (DataType type, std::vector<std::string>&);
|
||||||
void get_physical_inputs (DataType type, std::vector<std::string>&);
|
void get_physical_inputs (DataType type, std::vector<std::string>&);
|
||||||
|
|
||||||
Port *get_port_by_name (const std::string &);
|
boost::shared_ptr<Port> get_port_by_name (const std::string &);
|
||||||
|
|
||||||
enum TransportState {
|
enum TransportState {
|
||||||
TransportStopped = JackTransportStopped,
|
TransportStopped = JackTransportStopped,
|
||||||
|
|
@ -247,7 +247,7 @@ _ the regular process() call to session->process() is not made.
|
||||||
* The std::string parameters are the (long) port names.
|
* The std::string parameters are the (long) port names.
|
||||||
* The bool parameter is true if ports were connected, or false for disconnected.
|
* The bool parameter is true if ports were connected, or false for disconnected.
|
||||||
*/
|
*/
|
||||||
PBD::Signal5<void, Port *, std::string, Port *, std::string, bool> PortConnectedOrDisconnected;
|
PBD::Signal5<void, boost::weak_ptr<Port>, std::string, boost::weak_ptr<Port>, std::string, bool> PortConnectedOrDisconnected;
|
||||||
|
|
||||||
std::string make_port_name_relative (std::string) const;
|
std::string make_port_name_relative (std::string) const;
|
||||||
std::string make_port_name_non_relative (std::string) const;
|
std::string make_port_name_non_relative (std::string) const;
|
||||||
|
|
@ -283,7 +283,7 @@ private:
|
||||||
|
|
||||||
SerializedRCUManager<Ports> ports;
|
SerializedRCUManager<Ports> ports;
|
||||||
|
|
||||||
Port* register_port (DataType type, const std::string& portname, bool input);
|
boost::shared_ptr<Port> register_port (DataType type, const std::string& portname, bool input);
|
||||||
|
|
||||||
int process_callback (pframes_t nframes);
|
int process_callback (pframes_t nframes);
|
||||||
void* process_thread ();
|
void* process_thread ();
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ class ExportChannel : public boost::less_than_comparable<ExportChannel>
|
||||||
class PortExportChannel : public ExportChannel
|
class PortExportChannel : public ExportChannel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::set<AudioPort *> PortSet;
|
typedef std::set<boost::weak_ptr<AudioPort> > PortSet;
|
||||||
|
|
||||||
PortExportChannel ();
|
PortExportChannel ();
|
||||||
void set_max_buffer_size(framecnt_t frames);
|
void set_max_buffer_size(framecnt_t frames);
|
||||||
|
|
@ -78,7 +78,7 @@ class PortExportChannel : public ExportChannel
|
||||||
|
|
||||||
bool operator< (ExportChannel const & other) const;
|
bool operator< (ExportChannel const & other) const;
|
||||||
|
|
||||||
void add_port (AudioPort * port) { ports.insert (port); }
|
void add_port (boost::weak_ptr<AudioPort> port) { ports.insert (port); }
|
||||||
PortSet const & get_ports () { return ports; }
|
PortSet const & get_ports () { return ports; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -102,9 +102,9 @@ class IO : public SessionObject, public Latent
|
||||||
boost::shared_ptr<Bundle> bundle () { return _bundle; }
|
boost::shared_ptr<Bundle> bundle () { return _bundle; }
|
||||||
|
|
||||||
int add_port (std::string connection, void *src, DataType type = DataType::NIL);
|
int add_port (std::string connection, void *src, DataType type = DataType::NIL);
|
||||||
int remove_port (Port *, void *src);
|
int remove_port (boost::shared_ptr<Port>, void *src);
|
||||||
int connect (Port *our_port, std::string other_port, void *src);
|
int connect (boost::shared_ptr<Port> our_port, std::string other_port, void *src);
|
||||||
int disconnect (Port *our_port, std::string other_port, void *src);
|
int disconnect (boost::shared_ptr<Port> our_port, std::string other_port, void *src);
|
||||||
int disconnect (void *src);
|
int disconnect (void *src);
|
||||||
bool connected_to (boost::shared_ptr<const IO>) const;
|
bool connected_to (boost::shared_ptr<const IO>) const;
|
||||||
bool connected_to (const std::string&) const;
|
bool connected_to (const std::string&) const;
|
||||||
|
|
@ -117,20 +117,20 @@ class IO : public SessionObject, public Latent
|
||||||
PortSet& ports() { return _ports; }
|
PortSet& ports() { return _ports; }
|
||||||
const PortSet& ports() const { return _ports; }
|
const PortSet& ports() const { return _ports; }
|
||||||
|
|
||||||
bool has_port (Port *) const;
|
bool has_port (boost::shared_ptr<Port>) const;
|
||||||
|
|
||||||
Port *nth (uint32_t n) const {
|
boost::shared_ptr<Port> nth (uint32_t n) const {
|
||||||
if (n < _ports.num_ports()) {
|
if (n < _ports.num_ports()) {
|
||||||
return _ports.port(n);
|
return _ports.port(n);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return boost::shared_ptr<Port> ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Port* port_by_name (const std::string& str) const;
|
boost::shared_ptr<Port> port_by_name (const std::string& str) const;
|
||||||
|
|
||||||
AudioPort* audio(uint32_t n) const;
|
boost::shared_ptr<AudioPort> audio(uint32_t n) const;
|
||||||
MidiPort* midi(uint32_t n) const;
|
boost::shared_ptr<MidiPort> midi(uint32_t n) const;
|
||||||
|
|
||||||
const ChanCount& n_ports () const { return _ports.count(); }
|
const ChanCount& n_ports () const { return _ports.count(); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ class MidiDiskstream : public Diskstream
|
||||||
|
|
||||||
MidiRingBuffer<framepos_t>* _playback_buf;
|
MidiRingBuffer<framepos_t>* _playback_buf;
|
||||||
MidiRingBuffer<framepos_t>* _capture_buf;
|
MidiRingBuffer<framepos_t>* _capture_buf;
|
||||||
MidiPort* _source_port;
|
boost::weak_ptr<MidiPort> _source_port;
|
||||||
boost::shared_ptr<SMFSource> _write_source;
|
boost::shared_ptr<SMFSource> _write_source;
|
||||||
NoteMode _note_mode;
|
NoteMode _note_mode;
|
||||||
volatile gint _frames_written_to_ringbuffer;
|
volatile gint _frames_written_to_ringbuffer;
|
||||||
|
|
|
||||||
|
|
@ -42,20 +42,20 @@ public:
|
||||||
size_t num_ports() const;
|
size_t num_ports() const;
|
||||||
size_t num_ports(DataType type) const { return _ports[type].size(); }
|
size_t num_ports(DataType type) const { return _ports[type].size(); }
|
||||||
|
|
||||||
void add(Port* port);
|
void add (boost::shared_ptr<Port> port);
|
||||||
bool remove(Port* port);
|
bool remove (boost::shared_ptr<Port> port);
|
||||||
|
|
||||||
/** nth port */
|
/** nth port */
|
||||||
Port* port(size_t index) const;
|
boost::shared_ptr<Port> port(size_t index) const;
|
||||||
|
|
||||||
/** nth port of type @a t, or nth port if t = NIL */
|
/** nth port of type @a t, or nth port if t = NIL */
|
||||||
Port* port(DataType t, size_t index) const;
|
boost::shared_ptr<Port> port(DataType t, size_t index) const;
|
||||||
|
|
||||||
AudioPort* nth_audio_port(size_t n) const;
|
boost::shared_ptr<AudioPort> nth_audio_port(size_t n) const;
|
||||||
|
|
||||||
MidiPort* nth_midi_port(size_t n) const;
|
boost::shared_ptr<MidiPort> nth_midi_port(size_t n) const;
|
||||||
|
|
||||||
bool contains(const Port* port) const;
|
bool contains (boost::shared_ptr<const Port> port) const;
|
||||||
|
|
||||||
/** Remove all ports from the PortSet. Ports are not deregistered with
|
/** Remove all ports from the PortSet. Ports are not deregistered with
|
||||||
* the engine, it's the caller's responsibility to not leak here!
|
* the engine, it's the caller's responsibility to not leak here!
|
||||||
|
|
@ -69,8 +69,8 @@ public:
|
||||||
template<typename PS, typename P>
|
template<typename PS, typename P>
|
||||||
class iterator_base {
|
class iterator_base {
|
||||||
public:
|
public:
|
||||||
P& operator*() { return *_set.port(_type, _index); }
|
boost::shared_ptr<P> operator*() { return _set.port(_type, _index); }
|
||||||
P* operator->() { return _set.port(_type, _index); }
|
boost::shared_ptr<P> operator->() { return _set.port(_type, _index); }
|
||||||
iterator_base<PS,P>& operator++() { ++_index; return *this; } // yes, prefix only
|
iterator_base<PS,P>& operator++() { ++_index; return *this; } // yes, prefix only
|
||||||
bool operator==(const iterator_base<PS,P>& other) { return (_index == other._index); }
|
bool operator==(const iterator_base<PS,P>& other) { return (_index == other._index); }
|
||||||
bool operator!=(const iterator_base<PS,P>& other) { return (_index != other._index); }
|
bool operator!=(const iterator_base<PS,P>& other) { return (_index != other._index); }
|
||||||
|
|
@ -109,8 +109,8 @@ public:
|
||||||
|
|
||||||
class audio_iterator {
|
class audio_iterator {
|
||||||
public:
|
public:
|
||||||
AudioPort& operator*() { return *_set.nth_audio_port(_index); }
|
boost::shared_ptr<AudioPort> operator*() { return _set.nth_audio_port(_index); }
|
||||||
AudioPort* operator->() { return _set.nth_audio_port(_index); }
|
boost::shared_ptr<AudioPort> operator->() { return _set.nth_audio_port(_index); }
|
||||||
audio_iterator& operator++() { ++_index; return *this; } // yes, prefix only
|
audio_iterator& operator++() { ++_index; return *this; } // yes, prefix only
|
||||||
bool operator==(const audio_iterator& other) { return (_index == other._index); }
|
bool operator==(const audio_iterator& other) { return (_index == other._index); }
|
||||||
bool operator!=(const audio_iterator& other) { return (_index != other._index); }
|
bool operator!=(const audio_iterator& other) { return (_index != other._index); }
|
||||||
|
|
@ -128,7 +128,7 @@ public:
|
||||||
audio_iterator audio_end() { return audio_iterator(*this, _count.n_audio()); }
|
audio_iterator audio_end() { return audio_iterator(*this, _count.n_audio()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<Port*> PortVec;
|
typedef std::vector<boost::shared_ptr<Port> > PortVec;
|
||||||
|
|
||||||
// Vector of vectors, indexed by DataType::to_index()
|
// Vector of vectors, indexed by DataType::to_index()
|
||||||
std::vector<PortVec> _ports;
|
std::vector<PortVec> _ports;
|
||||||
|
|
|
||||||
|
|
@ -489,7 +489,7 @@ AudioDiskstream::process (framepos_t transport_frame, pframes_t nframes, bool& n
|
||||||
for recording, and use rec_offset
|
for recording, and use rec_offset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AudioPort* const ap = _io->audio (n);
|
boost::shared_ptr<AudioPort> const ap = _io->audio (n);
|
||||||
assert(ap);
|
assert(ap);
|
||||||
assert(rec_nframes <= (framecnt_t) ap->get_audio_buffer(nframes).capacity());
|
assert(rec_nframes <= (framecnt_t) ap->get_audio_buffer(nframes).capacity());
|
||||||
|
|
||||||
|
|
@ -505,7 +505,7 @@ AudioDiskstream::process (framepos_t transport_frame, pframes_t nframes, bool& n
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioPort* const ap = _io->audio (n);
|
boost::shared_ptr<AudioPort> const ap = _io->audio (n);
|
||||||
assert(ap);
|
assert(ap);
|
||||||
|
|
||||||
Sample* buf = ap->get_audio_buffer(nframes).data (rec_offset);
|
Sample* buf = ap->get_audio_buffer(nframes).data (rec_offset);
|
||||||
|
|
|
||||||
|
|
@ -382,8 +382,8 @@ AudioEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int co
|
||||||
jack_port_t* jack_port_a = jack_port_by_id (_priv_jack, id_a);
|
jack_port_t* jack_port_a = jack_port_by_id (_priv_jack, id_a);
|
||||||
jack_port_t* jack_port_b = jack_port_by_id (_priv_jack, id_b);
|
jack_port_t* jack_port_b = jack_port_by_id (_priv_jack, id_b);
|
||||||
|
|
||||||
Port* port_a = 0;
|
boost::shared_ptr<Port> port_a;
|
||||||
Port* port_b = 0;
|
boost::shared_ptr<Port> port_b;
|
||||||
|
|
||||||
boost::shared_ptr<Ports> pr = ae->ports.reader ();
|
boost::shared_ptr<Ports> pr = ae->ports.reader ();
|
||||||
Ports::iterator i = pr->begin ();
|
Ports::iterator i = pr->begin ();
|
||||||
|
|
@ -530,15 +530,14 @@ AudioEngine::process_callback (pframes_t nframes)
|
||||||
|
|
||||||
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
||||||
|
|
||||||
Port *port = (*i);
|
|
||||||
bool x;
|
bool x;
|
||||||
|
|
||||||
if (port->last_monitor() != (x = port->monitoring_input ())) {
|
if ((*i)->last_monitor() != (x = (*i)->monitoring_input ())) {
|
||||||
port->set_last_monitor (x);
|
(*i)->set_last_monitor (x);
|
||||||
/* XXX I think this is dangerous, due to
|
/* XXX I think this is dangerous, due to
|
||||||
a likely mutex in the signal handlers ...
|
a likely mutex in the signal handlers ...
|
||||||
*/
|
*/
|
||||||
port->MonitorInputChanged (x); /* EMIT SIGNAL */
|
(*i)->MonitorInputChanged (x); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_monitor_check = next_processed_frames;
|
last_monitor_check = next_processed_frames;
|
||||||
|
|
@ -550,10 +549,8 @@ AudioEngine::process_callback (pframes_t nframes)
|
||||||
|
|
||||||
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
||||||
|
|
||||||
Port *port = (*i);
|
if ((*i)->sends_output()) {
|
||||||
|
(*i)->get_buffer(nframes).silence(nframes);
|
||||||
if (port->sends_output()) {
|
|
||||||
port->get_buffer(nframes).silence(nframes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -774,16 +771,16 @@ AudioEngine::port_registration_failure (const std::string& portname)
|
||||||
throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
|
throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
Port*
|
boost::shared_ptr<Port>
|
||||||
AudioEngine::register_port (DataType dtype, const string& portname, bool input)
|
AudioEngine::register_port (DataType dtype, const string& portname, bool input)
|
||||||
{
|
{
|
||||||
Port* newport;
|
boost::shared_ptr<Port> newport;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (dtype == DataType::AUDIO) {
|
if (dtype == DataType::AUDIO) {
|
||||||
newport = new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput));
|
newport.reset (new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput)));
|
||||||
} else if (dtype == DataType::MIDI) {
|
} else if (dtype == DataType::MIDI) {
|
||||||
newport = new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput));
|
newport.reset (new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput)));
|
||||||
} else {
|
} else {
|
||||||
throw PortRegistrationFailure("unable to create port (unknown type)");
|
throw PortRegistrationFailure("unable to create port (unknown type)");
|
||||||
}
|
}
|
||||||
|
|
@ -807,20 +804,20 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Port *
|
boost::shared_ptr<Port>
|
||||||
AudioEngine::register_input_port (DataType type, const string& portname)
|
AudioEngine::register_input_port (DataType type, const string& portname)
|
||||||
{
|
{
|
||||||
return register_port (type, portname, true);
|
return register_port (type, portname, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Port *
|
boost::shared_ptr<Port>
|
||||||
AudioEngine::register_output_port (DataType type, const string& portname)
|
AudioEngine::register_output_port (DataType type, const string& portname)
|
||||||
{
|
{
|
||||||
return register_port (type, portname, false);
|
return register_port (type, portname, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
AudioEngine::unregister_port (Port& port)
|
AudioEngine::unregister_port (boost::shared_ptr<Port> port)
|
||||||
{
|
{
|
||||||
/* caller must hold process lock */
|
/* caller must hold process lock */
|
||||||
|
|
||||||
|
|
@ -834,18 +831,13 @@ AudioEngine::unregister_port (Port& port)
|
||||||
{
|
{
|
||||||
RCUWriter<Ports> writer (ports);
|
RCUWriter<Ports> writer (ports);
|
||||||
boost::shared_ptr<Ports> ps = writer.get_copy ();
|
boost::shared_ptr<Ports> ps = writer.get_copy ();
|
||||||
|
ps->erase (port);
|
||||||
for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
|
|
||||||
if ((*i) == &port) {
|
|
||||||
delete *i;
|
|
||||||
ps->erase (i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* writer goes out of scope, forces update */
|
/* writer goes out of scope, forces update */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ports.flush ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -867,8 +859,8 @@ AudioEngine::connect (const string& source, const string& destination)
|
||||||
string d = make_port_name_non_relative (destination);
|
string d = make_port_name_non_relative (destination);
|
||||||
|
|
||||||
|
|
||||||
Port* src = get_port_by_name (s);
|
boost::shared_ptr<Port> src = get_port_by_name (s);
|
||||||
Port* dst = get_port_by_name (d);
|
boost::shared_ptr<Port> dst = get_port_by_name (d);
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
ret = src->connect (d);
|
ret = src->connect (d);
|
||||||
|
|
@ -907,8 +899,8 @@ AudioEngine::disconnect (const string& source, const string& destination)
|
||||||
string s = make_port_name_non_relative (source);
|
string s = make_port_name_non_relative (source);
|
||||||
string d = make_port_name_non_relative (destination);
|
string d = make_port_name_non_relative (destination);
|
||||||
|
|
||||||
Port* src = get_port_by_name (s);
|
boost::shared_ptr<Port> src = get_port_by_name (s);
|
||||||
Port* dst = get_port_by_name (d);
|
boost::shared_ptr<Port> dst = get_port_by_name (d);
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
ret = src->disconnect (d);
|
ret = src->disconnect (d);
|
||||||
|
|
@ -922,7 +914,7 @@ AudioEngine::disconnect (const string& source, const string& destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
AudioEngine::disconnect (Port& port)
|
AudioEngine::disconnect (boost::shared_ptr<Port> port)
|
||||||
{
|
{
|
||||||
GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
|
GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
|
||||||
|
|
||||||
|
|
@ -935,7 +927,7 @@ AudioEngine::disconnect (Port& port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return port.disconnect_all ();
|
return port->disconnect_all ();
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDOUR::framecnt_t
|
ARDOUR::framecnt_t
|
||||||
|
|
@ -968,10 +960,10 @@ AudioEngine::frames_per_cycle () const
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param name Full or short name of port
|
/** @param name Full or short name of port
|
||||||
* @return Corresponding Port* or 0. This object remains the property of the AudioEngine
|
* @return Corresponding Port or 0.
|
||||||
* so must not be deleted.
|
|
||||||
*/
|
*/
|
||||||
Port*
|
|
||||||
|
boost::shared_ptr<Port>
|
||||||
AudioEngine::get_port_by_name (const string& portname)
|
AudioEngine::get_port_by_name (const string& portname)
|
||||||
{
|
{
|
||||||
if (!_running) {
|
if (!_running) {
|
||||||
|
|
@ -979,13 +971,13 @@ AudioEngine::get_port_by_name (const string& portname)
|
||||||
fatal << _("get_port_by_name() called before engine was started") << endmsg;
|
fatal << _("get_port_by_name() called before engine was started") << endmsg;
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
boost::shared_ptr<Port> ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!port_is_mine (portname)) {
|
if (!port_is_mine (portname)) {
|
||||||
/* not an ardour port */
|
/* not an ardour port */
|
||||||
return 0;
|
return boost::shared_ptr<Port> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const rel = make_port_name_relative (portname);
|
std::string const rel = make_port_name_relative (portname);
|
||||||
|
|
@ -998,7 +990,7 @@ AudioEngine::get_port_by_name (const string& portname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return boost::shared_ptr<Port> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char **
|
const char **
|
||||||
|
|
@ -1241,14 +1233,9 @@ AudioEngine::remove_all_ports ()
|
||||||
/* process lock MUST be held by caller
|
/* process lock MUST be held by caller
|
||||||
*/
|
*/
|
||||||
|
|
||||||
vector<Port*> to_be_deleted;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
RCUWriter<Ports> writer (ports);
|
RCUWriter<Ports> writer (ports);
|
||||||
boost::shared_ptr<Ports> ps = writer.get_copy ();
|
boost::shared_ptr<Ports> ps = writer.get_copy ();
|
||||||
for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
|
|
||||||
to_be_deleted.push_back (*i);
|
|
||||||
}
|
|
||||||
ps->clear ();
|
ps->clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1256,14 +1243,6 @@ AudioEngine::remove_all_ports ()
|
||||||
|
|
||||||
ports.flush ();
|
ports.flush ();
|
||||||
|
|
||||||
/* now do the actual deletion, given that "ports" is now empty, thus
|
|
||||||
preventing anyone else from getting a handle on a Port
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (vector<Port*>::iterator p = to_be_deleted.begin(); p != to_be_deleted.end(); ++p) {
|
|
||||||
delete *p;
|
|
||||||
}
|
|
||||||
|
|
||||||
port_remove_in_progress = false;
|
port_remove_in_progress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -421,8 +421,8 @@ Bundle::connected_to (boost::shared_ptr<Bundle> other, AudioEngine & engine)
|
||||||
for (uint32_t j = 0; j < A.size(); ++j) {
|
for (uint32_t j = 0; j < A.size(); ++j) {
|
||||||
for (uint32_t k = 0; k < B.size(); ++k) {
|
for (uint32_t k = 0; k < B.size(); ++k) {
|
||||||
|
|
||||||
Port* p = engine.get_port_by_name (A[j]);
|
boost::shared_ptr<Port> p = engine.get_port_by_name (A[j]);
|
||||||
Port* q = engine.get_port_by_name (B[k]);
|
boost::shared_ptr<Port> q = engine.get_port_by_name (B[k]);
|
||||||
|
|
||||||
if (!p && !q) {
|
if (!p && !q) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -461,7 +461,7 @@ Delivery::flush_buffers (framecnt_t nframes, framepos_t time)
|
||||||
PortSet& ports (_output->ports());
|
PortSet& ports (_output->ports());
|
||||||
|
|
||||||
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
|
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
|
||||||
(*i).flush_buffers (nframes, time);
|
i->flush_buffers (nframes, time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -478,7 +478,7 @@ Delivery::transport_stopped (framepos_t now)
|
||||||
PortSet& ports (_output->ports());
|
PortSet& ports (_output->ports());
|
||||||
|
|
||||||
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
|
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
|
||||||
(*i).transport_stopped ();
|
i->transport_stopped ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -490,7 +490,7 @@ Delivery::realtime_locate ()
|
||||||
PortSet& ports (_output->ports());
|
PortSet& ports (_output->ports());
|
||||||
|
|
||||||
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
|
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
|
||||||
(*i).realtime_locate ();
|
i->realtime_locate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,15 +62,17 @@ PortExportChannel::read (Sample const *& data, framecnt_t frames) const
|
||||||
assert(frames <= buffer_size);
|
assert(frames <= buffer_size);
|
||||||
|
|
||||||
if (ports.size() == 1) {
|
if (ports.size() == 1) {
|
||||||
data = (*ports.begin())->get_audio_buffer(frames).data();
|
boost::shared_ptr<AudioPort> p = ports.begin()->lock ();
|
||||||
|
data = p->get_audio_buffer(frames).data();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset (buffer.get(), 0, frames * sizeof (Sample));
|
memset (buffer.get(), 0, frames * sizeof (Sample));
|
||||||
|
|
||||||
for (PortSet::const_iterator it = ports.begin(); it != ports.end(); ++it) {
|
for (PortSet::const_iterator it = ports.begin(); it != ports.end(); ++it) {
|
||||||
if (*it != 0) {
|
boost::shared_ptr<AudioPort> p = it->lock ();
|
||||||
Sample* port_buffer = (*it)->get_audio_buffer(frames).data();
|
if (p) {
|
||||||
|
Sample* port_buffer = p->get_audio_buffer(frames).data();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < frames; ++i) {
|
for (uint32_t i = 0; i < frames; ++i) {
|
||||||
buffer[i] += (float) port_buffer[i];
|
buffer[i] += (float) port_buffer[i];
|
||||||
|
|
@ -86,8 +88,9 @@ PortExportChannel::get_state (XMLNode * node) const
|
||||||
{
|
{
|
||||||
XMLNode * port_node;
|
XMLNode * port_node;
|
||||||
for (PortSet::const_iterator it = ports.begin(); it != ports.end(); ++it) {
|
for (PortSet::const_iterator it = ports.begin(); it != ports.end(); ++it) {
|
||||||
if ((port_node = node->add_child ("Port"))) {
|
boost::shared_ptr<Port> p = it->lock ();
|
||||||
port_node->add_property ("name", (*it)->name());
|
if (p && (port_node = node->add_child ("Port"))) {
|
||||||
|
port_node->add_property ("name", p->name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +103,7 @@ PortExportChannel::set_state (XMLNode * node, Session & session)
|
||||||
for (XMLNodeList::iterator it = xml_ports.begin(); it != xml_ports.end(); ++it) {
|
for (XMLNodeList::iterator it = xml_ports.begin(); it != xml_ports.end(); ++it) {
|
||||||
if ((prop = (*it)->property ("name"))) {
|
if ((prop = (*it)->property ("name"))) {
|
||||||
std::string const & name = prop->value();
|
std::string const & name = prop->value();
|
||||||
AudioPort * port = dynamic_cast<AudioPort *> (session.engine().get_port_by_name (name));
|
boost::shared_ptr<AudioPort> port = boost::dynamic_pointer_cast<AudioPort> (session.engine().get_port_by_name (name));
|
||||||
if (port) {
|
if (port) {
|
||||||
ports.insert (port);
|
ports.insert (port);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ IO::check_bundles_connected ()
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
IO::disconnect (Port* our_port, string other_port, void* src)
|
IO::disconnect (boost::shared_ptr<Port> our_port, string other_port, void* src)
|
||||||
{
|
{
|
||||||
if (other_port.length() == 0 || our_port == 0) {
|
if (other_port.length() == 0 || our_port == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -196,7 +196,7 @@ IO::disconnect (Port* our_port, string other_port, void* src)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
IO::connect (Port* our_port, string other_port, void* src)
|
IO::connect (boost::shared_ptr<Port> our_port, string other_port, void* src)
|
||||||
{
|
{
|
||||||
if (other_port.length() == 0 || our_port == 0) {
|
if (other_port.length() == 0 || our_port == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -223,7 +223,7 @@ IO::connect (Port* our_port, string other_port, void* src)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
IO::remove_port (Port* port, void* src)
|
IO::remove_port (boost::shared_ptr<Port> port, void* src)
|
||||||
{
|
{
|
||||||
ChanCount before = _ports.count ();
|
ChanCount before = _ports.count ();
|
||||||
ChanCount after = before;
|
ChanCount after = before;
|
||||||
|
|
@ -251,7 +251,7 @@ IO::remove_port (Port* port, void* src)
|
||||||
change.type = IOChange::Type (change.type | IOChange::ConnectionsChanged);
|
change.type = IOChange::Type (change.type | IOChange::ConnectionsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
_session.engine().unregister_port (*port);
|
_session.engine().unregister_port (port);
|
||||||
check_bundles_connected ();
|
check_bundles_connected ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +286,7 @@ IO::remove_port (Port* port, void* src)
|
||||||
int
|
int
|
||||||
IO::add_port (string destination, void* src, DataType type)
|
IO::add_port (string destination, void* src, DataType type)
|
||||||
{
|
{
|
||||||
Port* our_port;
|
boost::shared_ptr<Port> our_port;
|
||||||
|
|
||||||
if (type == DataType::NIL) {
|
if (type == DataType::NIL) {
|
||||||
type = _default_type;
|
type = _default_type;
|
||||||
|
|
@ -364,7 +364,7 @@ IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed)
|
||||||
{
|
{
|
||||||
assert (!AudioEngine::instance()->process_lock().trylock());
|
assert (!AudioEngine::instance()->process_lock().trylock());
|
||||||
|
|
||||||
Port* port = 0;
|
boost::shared_ptr<Port> port;
|
||||||
|
|
||||||
changed = false;
|
changed = false;
|
||||||
|
|
||||||
|
|
@ -378,7 +378,7 @@ IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed)
|
||||||
|
|
||||||
assert(port);
|
assert(port);
|
||||||
_ports.remove(port);
|
_ports.remove(port);
|
||||||
_session.engine().unregister_port (*port);
|
_session.engine().unregister_port (port);
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
@ -894,7 +894,7 @@ IO::make_connections (const XMLNode& node, int version, bool in)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Port* p = port_by_name (prop->value());
|
boost::shared_ptr<Port> p = port_by_name (prop->value());
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
for (XMLNodeConstIterator c = (*i)->children().begin(); c != (*i)->children().end(); ++c) {
|
for (XMLNodeConstIterator c = (*i)->children().begin(); c != (*i)->children().end(); ++c) {
|
||||||
|
|
@ -1337,14 +1337,14 @@ IO::find_port_hole (const char* base)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AudioPort*
|
boost::shared_ptr<AudioPort>
|
||||||
IO::audio(uint32_t n) const
|
IO::audio(uint32_t n) const
|
||||||
{
|
{
|
||||||
return _ports.nth_audio_port (n);
|
return _ports.nth_audio_port (n);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MidiPort*
|
boost::shared_ptr<MidiPort>
|
||||||
IO::midi(uint32_t n) const
|
IO::midi(uint32_t n) const
|
||||||
{
|
{
|
||||||
return _ports.nth_midi_port (n);
|
return _ports.nth_midi_port (n);
|
||||||
|
|
@ -1599,21 +1599,19 @@ IO::copy_to_outputs (BufferSet& bufs, DataType type, pframes_t nframes, framecnt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Port*
|
boost::shared_ptr<Port>
|
||||||
IO::port_by_name (const std::string& str) const
|
IO::port_by_name (const std::string& str) const
|
||||||
{
|
{
|
||||||
/* to be called only from ::set_state() - no locking */
|
/* to be called only from ::set_state() - no locking */
|
||||||
|
|
||||||
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
||||||
|
|
||||||
const Port& p(*i);
|
if (i->name() == str) {
|
||||||
|
return boost::const_pointer_cast<Port> (*i);
|
||||||
if (p.name() == str) {
|
|
||||||
return const_cast<Port*>(&p);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return boost::shared_ptr<Port> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -1629,7 +1627,7 @@ IO::physically_connected () const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IO::has_port (Port* p) const
|
IO::has_port (boost::shared_ptr<Port> p) const
|
||||||
{
|
{
|
||||||
Glib::Mutex::Lock lm (io_lock);
|
Glib::Mutex::Lock lm (io_lock);
|
||||||
return _ports.contains (p);
|
return _ports.contains (p);
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,6 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F
|
||||||
: Diskstream(sess, name, flag)
|
: Diskstream(sess, name, flag)
|
||||||
, _playback_buf(0)
|
, _playback_buf(0)
|
||||||
, _capture_buf(0)
|
, _capture_buf(0)
|
||||||
, _source_port(0)
|
|
||||||
, _note_mode(Sustained)
|
, _note_mode(Sustained)
|
||||||
, _frames_written_to_ringbuffer(0)
|
, _frames_written_to_ringbuffer(0)
|
||||||
, _frames_read_from_ringbuffer(0)
|
, _frames_read_from_ringbuffer(0)
|
||||||
|
|
@ -94,7 +93,6 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
|
||||||
: Diskstream(sess, node)
|
: Diskstream(sess, node)
|
||||||
, _playback_buf(0)
|
, _playback_buf(0)
|
||||||
, _capture_buf(0)
|
, _capture_buf(0)
|
||||||
, _source_port(0)
|
|
||||||
, _note_mode(Sustained)
|
, _note_mode(Sustained)
|
||||||
, _frames_written_to_ringbuffer(0)
|
, _frames_written_to_ringbuffer(0)
|
||||||
, _frames_read_from_ringbuffer(0)
|
, _frames_read_from_ringbuffer(0)
|
||||||
|
|
@ -171,7 +169,7 @@ MidiDiskstream::non_realtime_input_change ()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ni == 0) {
|
if (ni == 0) {
|
||||||
_source_port = 0;
|
_source_port.reset ();
|
||||||
} else {
|
} else {
|
||||||
_source_port = _io->midi(0);
|
_source_port = _io->midi(0);
|
||||||
}
|
}
|
||||||
|
|
@ -496,7 +494,9 @@ MidiDiskstream::process (framepos_t transport_frame, pframes_t nframes, bool& ne
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_source_port == 0) {
|
boost::shared_ptr<MidiPort> sp = _source_port.lock ();
|
||||||
|
|
||||||
|
if (sp == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -527,7 +527,7 @@ MidiDiskstream::process (framepos_t transport_frame, pframes_t nframes, bool& ne
|
||||||
if (nominally_recording || rec_nframes) {
|
if (nominally_recording || rec_nframes) {
|
||||||
|
|
||||||
// Pump entire port buffer into the ring buffer (FIXME: split cycles?)
|
// Pump entire port buffer into the ring buffer (FIXME: split cycles?)
|
||||||
MidiBuffer& buf = _source_port->get_midi_buffer(nframes);
|
MidiBuffer& buf = sp->get_midi_buffer(nframes);
|
||||||
for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
|
for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
|
||||||
const Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false);
|
const Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false);
|
||||||
assert(ev.buffer());
|
assert(ev.buffer());
|
||||||
|
|
@ -1196,8 +1196,10 @@ MidiDiskstream::engage_record_enable ()
|
||||||
|
|
||||||
g_atomic_int_set (&_record_enabled, 1);
|
g_atomic_int_set (&_record_enabled, 1);
|
||||||
|
|
||||||
if (_source_port && Config->get_monitoring_model() == HardwareMonitoring) {
|
boost::shared_ptr<MidiPort> sp = _source_port.lock ();
|
||||||
_source_port->request_monitor_input (!(_session.config.get_auto_input() && rolling));
|
|
||||||
|
if (sp && Config->get_monitoring_model() == HardwareMonitoring) {
|
||||||
|
sp->request_monitor_input (!(_session.config.get_auto_input() && rolling));
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordEnableChanged (); /* EMIT SIGNAL */
|
RecordEnableChanged (); /* EMIT SIGNAL */
|
||||||
|
|
@ -1372,8 +1374,11 @@ MidiDiskstream::allocate_temporary_buffers ()
|
||||||
void
|
void
|
||||||
MidiDiskstream::monitor_input (bool yn)
|
MidiDiskstream::monitor_input (bool yn)
|
||||||
{
|
{
|
||||||
if (_source_port)
|
boost::shared_ptr<MidiPort> sp = _source_port.lock ();
|
||||||
_source_port->ensure_monitor_input (yn);
|
|
||||||
|
if (sp) {
|
||||||
|
sp->ensure_monitor_input (yn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -690,7 +690,7 @@ MidiTrack::map_input_active (bool yn)
|
||||||
PortSet& ports (_input->ports());
|
PortSet& ports (_input->ports());
|
||||||
|
|
||||||
for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
|
for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
|
||||||
MidiPort* mp = dynamic_cast<MidiPort*> (&*p);
|
boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
|
||||||
if (yn != mp->input_active()) {
|
if (yn != mp->input_active()) {
|
||||||
mp->set_input_active (yn);
|
mp->set_input_active (yn);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -383,7 +383,7 @@ Port::get_connected_latency_range (jack_latency_range_t& range, bool playback) c
|
||||||
latency compensation.
|
latency compensation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Port* remote_port = AudioEngine::instance()->get_port_by_name (*c);
|
boost::shared_ptr<Port> remote_port = AudioEngine::instance()->get_port_by_name (*c);
|
||||||
if (remote_port) {
|
if (remote_port) {
|
||||||
lr = remote_port->private_latency_range ((playback ? JackPlaybackLatency : JackCaptureLatency));
|
lr = remote_port->private_latency_range ((playback ? JackPlaybackLatency : JackCaptureLatency));
|
||||||
DEBUG_TRACE (DEBUG::Latency, string_compose (
|
DEBUG_TRACE (DEBUG::Latency, string_compose (
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ PortSet::PortSet()
|
||||||
_ports.push_back( PortVec() );
|
_ports.push_back( PortVec() );
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sort_ports_by_name (Port* a, Port* b)
|
static bool sort_ports_by_name (boost::shared_ptr<Port> a, boost::shared_ptr<Port> b)
|
||||||
{
|
{
|
||||||
string aname (a->name());
|
string aname (a->name());
|
||||||
string bname (b->name());
|
string bname (b->name());
|
||||||
|
|
@ -72,7 +72,7 @@ static bool sort_ports_by_name (Port* a, Port* b)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PortSet::add(Port* port)
|
PortSet::add (boost::shared_ptr<Port> port)
|
||||||
{
|
{
|
||||||
PortVec& v = _ports[port->type()];
|
PortVec& v = _ports[port->type()];
|
||||||
|
|
||||||
|
|
@ -84,7 +84,7 @@ PortSet::add(Port* port)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PortSet::remove(Port* port)
|
PortSet::remove (boost::shared_ptr<Port> port)
|
||||||
{
|
{
|
||||||
for (std::vector<PortVec>::iterator l = _ports.begin(); l != _ports.end(); ++l) {
|
for (std::vector<PortVec>::iterator l = _ports.begin(); l != _ports.end(); ++l) {
|
||||||
PortVec::iterator i = find(l->begin(), l->end(), port);
|
PortVec::iterator i = find(l->begin(), l->end(), port);
|
||||||
|
|
@ -112,16 +112,16 @@ PortSet::num_ports() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PortSet::contains(const Port* port) const
|
PortSet::contains (boost::shared_ptr<const Port> port) const
|
||||||
{
|
{
|
||||||
for (std::vector<PortVec>::const_iterator l = _ports.begin(); l != _ports.end(); ++l)
|
for (std::vector<PortVec>::const_iterator l = _ports.begin(); l != _ports.end(); ++l)
|
||||||
if (find((*l).begin(), (*l).end(), port) != (*l).end())
|
if (find (l->begin(), l->end(), port) != l->end())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Port*
|
boost::shared_ptr<Port>
|
||||||
PortSet::port(size_t n) const
|
PortSet::port(size_t n) const
|
||||||
{
|
{
|
||||||
// This is awesome. Awesomely slow.
|
// This is awesome. Awesomely slow.
|
||||||
|
|
@ -129,16 +129,17 @@ PortSet::port(size_t n) const
|
||||||
size_t size_so_far = 0;
|
size_t size_so_far = 0;
|
||||||
|
|
||||||
for (std::vector<PortVec>::const_iterator l = _ports.begin(); l != _ports.end(); ++l) {
|
for (std::vector<PortVec>::const_iterator l = _ports.begin(); l != _ports.end(); ++l) {
|
||||||
if (n < size_so_far + (*l).size())
|
if (n < size_so_far + l->size()) {
|
||||||
return (*l)[n - size_so_far];
|
return (*l)[n - size_so_far];
|
||||||
else
|
} else {
|
||||||
size_so_far += (*l).size();
|
size_so_far += l->size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL; // n out of range
|
return boost::shared_ptr<Port> (); // n out of range
|
||||||
}
|
}
|
||||||
|
|
||||||
Port*
|
boost::shared_ptr<Port>
|
||||||
PortSet::port(DataType type, size_t n) const
|
PortSet::port(DataType type, size_t n) const
|
||||||
{
|
{
|
||||||
if (type == DataType::NIL) {
|
if (type == DataType::NIL) {
|
||||||
|
|
@ -150,16 +151,16 @@ PortSet::port(DataType type, size_t n) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioPort*
|
boost::shared_ptr<AudioPort>
|
||||||
PortSet::nth_audio_port(size_t n) const
|
PortSet::nth_audio_port(size_t n) const
|
||||||
{
|
{
|
||||||
return dynamic_cast<AudioPort*>(port(DataType::AUDIO, n));
|
return boost::dynamic_pointer_cast<AudioPort> (port (DataType::AUDIO, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
MidiPort*
|
boost::shared_ptr<MidiPort>
|
||||||
PortSet::nth_midi_port(size_t n) const
|
PortSet::nth_midi_port(size_t n) const
|
||||||
{
|
{
|
||||||
return dynamic_cast<MidiPort*>(port(DataType::MIDI, n));
|
return boost::dynamic_pointer_cast<MidiPort> (port (DataType::MIDI, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namepace ARDOUR
|
} // namepace ARDOUR
|
||||||
|
|
|
||||||
|
|
@ -546,7 +546,7 @@ Session::when_engine_running ()
|
||||||
uint32_t limit = _master_out->n_outputs().n_total();
|
uint32_t limit = _master_out->n_outputs().n_total();
|
||||||
|
|
||||||
for (uint32_t n = 0; n < limit; ++n) {
|
for (uint32_t n = 0; n < limit; ++n) {
|
||||||
Port* p = _master_out->output()->nth (n);
|
boost::shared_ptr<Port> p = _master_out->output()->nth (n);
|
||||||
string connect_to;
|
string connect_to;
|
||||||
if (outputs[p->type()].size() > n) {
|
if (outputs[p->type()].size() > n) {
|
||||||
connect_to = outputs[p->type()][n];
|
connect_to = outputs[p->type()][n];
|
||||||
|
|
@ -576,8 +576,8 @@ Session::when_engine_running ()
|
||||||
|
|
||||||
if (_master_out) {
|
if (_master_out) {
|
||||||
for (uint32_t n = 0; n < limit; ++n) {
|
for (uint32_t n = 0; n < limit; ++n) {
|
||||||
AudioPort* p = _monitor_out->input()->ports().nth_audio_port (n);
|
boost::shared_ptr<AudioPort> p = _monitor_out->input()->ports().nth_audio_port (n);
|
||||||
AudioPort* o = _master_out->output()->ports().nth_audio_port (n);
|
boost::shared_ptr<AudioPort> o = _master_out->output()->ports().nth_audio_port (n);
|
||||||
|
|
||||||
if (o) {
|
if (o) {
|
||||||
string connect_to = o->name();
|
string connect_to = o->name();
|
||||||
|
|
@ -617,7 +617,7 @@ Session::when_engine_running ()
|
||||||
|
|
||||||
for (uint32_t n = 0; n < limit; ++n) {
|
for (uint32_t n = 0; n < limit; ++n) {
|
||||||
|
|
||||||
Port* p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
|
boost::shared_ptr<Port> p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
|
||||||
string connect_to;
|
string connect_to;
|
||||||
if (outputs[DataType::AUDIO].size() > (n % mod)) {
|
if (outputs[DataType::AUDIO].size() > (n % mod)) {
|
||||||
connect_to = outputs[DataType::AUDIO][n % mod];
|
connect_to = outputs[DataType::AUDIO][n % mod];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue