m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
}
- // Connect to our own PortCountChanged signal to connect output buffers
- IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
-
_session.add_controllable (_gain_control);
- create_bundles_for_inputs_and_outputs ();
+ setup_bundles_for_inputs_and_outputs ();
}
IO::IO (Session& s, const XMLNode& node, DataType dt)
m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
}
- // Connect to our own PortCountChanged signal to connect output buffers
- IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
-
_session.add_controllable (_gain_control);
- create_bundles_for_inputs_and_outputs ();
+ setup_bundles_for_inputs_and_outputs ();
}
IO::~IO ()
delete _meter;
delete _panner;
- delete _output_buffers;
}
void
}
- if (dg != _gain || dg != 1.0)
+ if (dg != _gain || dg != 1.0) {
Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
+ _gain = dg;
+ }
}
+
+ /* do this so that any processing that comes after deliver_outputs()
+ can use the output buffers.
+ */
+
+ output_buffers().attach_buffers (_outputs, nframes, offset);
// Use the panner to distribute audio to output port buffers
- if( _panner && _panner->npanners() && !_panner->bypassed()) {
+
+ if (0 && _panner && _panner->npanners() && !_panner->bypassed()) {
+
+ /* blech .. we shouldn't be creating and tearing this down every process()
+ cycle. XXX fix me to not waste cycles and do memory allocation etc.
+ */
+
_panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
+
} else {
- const DataType type = DataType::AUDIO;
-
- // Copy any audio 1:1 to outputs
-
- BufferSet::iterator o = output_buffers().begin(type);
- BufferSet::iterator i = bufs.begin(type);
- BufferSet::iterator prev = i;
-
- while (i != bufs.end(type) && o != output_buffers().end (type)) {
- o->read_from(*i, nframes, offset);
- prev = i;
- ++i;
- ++o;
- }
- /* extra outputs get a copy of the last buffer */
+ /* do a 1:1 copy of data to output ports */
- while (o != output_buffers().end(type)) {
- o->read_from(*prev, nframes, offset);
- ++o;
+ if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
+ copy_to_outputs (bufs, DataType::AUDIO, nframes, offset);
+ }
+ if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
+ copy_to_outputs (bufs, DataType::MIDI, nframes, offset);
}
}
+}
- /* ********** MIDI ********** */
+void
+IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset)
+{
+ // Copy any buffers 1:1 to outputs
+
+ PortSet::iterator o = _outputs.begin(type);
+ BufferSet::iterator i = bufs.begin(type);
+ BufferSet::iterator prev = i;
+
+ while (i != bufs.end(type) && o != _outputs.end (type)) {
+
+ Buffer& port_buffer (o->get_buffer (nframes, offset));
+ port_buffer.read_from (*i, nframes, offset);
- // No MIDI, we're done here
- if (bufs.count().n_midi() == 0) {
- return;
+ prev = i;
+ ++i;
+ ++o;
}
-
- const DataType type = DataType::MIDI;
-
- // Copy any MIDI 1:1 to outputs
- assert(bufs.count().n_midi() == output_buffers().count().n_midi());
- BufferSet::iterator o = output_buffers().begin(type);
- for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
- o->read_from(*i, nframes, offset);
+
+ /* extra outputs get a copy of the last buffer */
+
+ while (o != _outputs.end(type)) {
+ Buffer& port_buffer (o->get_buffer (nframes, offset));
+ port_buffer.read_from(*prev, nframes, offset);
+ ++o;
}
}
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
BufferSet::iterator o = outs.begin(*t);
- for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
- o->read_from(i->get_buffer(nframes,offset), nframes, offset);
+ PortSet::iterator e = _inputs.end (*t);
+ for (PortSet::iterator i = _inputs.begin(*t); i != e; ++i, ++o) {
+ Buffer& b (i->get_buffer (nframes,offset));
+ o->read_from (b, nframes, offset);
}
}
return changed;
}
-/** Attach output_buffers to port buffers.
- *
- * Connected to IO's own PortCountChanged signal.
- */
-void
-IO::attach_buffers(ChanCount ignored)
-{
- _output_buffers->attach_buffers(_outputs);
-}
-
int
IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
{
BLOCK_PROCESS_CALLBACK ();
Glib::Mutex::Lock lm2 (io_lock);
- /* Connect to the bundle, not worrying about any connections
- that are already made. */
-
- uint32_t cnt = c->nchannels ();
-
- for (uint32_t n = 0; n < cnt; ++n) {
- const Bundle::PortList& pl = c->channel_ports (n);
-
- for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
-
- if (!_inputs.port(n)->connected_to (*i)) {
-
- if (_session.engine().connect (*i, _inputs.port(n)->name())) {
- return -1;
- }
- }
-
- }
- }
+ c->connect (_bundle_for_inputs, _session.engine());
/* If this is a UserBundle, make a note of what we've done */
}
int
-IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
+IO::disconnect_input_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
{
{
BLOCK_PROCESS_CALLBACK ();
Glib::Mutex::Lock lm2 (io_lock);
- /* Connect to the bundle, not worrying about any connections
- that are already made. */
-
- uint32_t cnt = c->nchannels ();
-
- for (uint32_t n = 0; n < cnt; ++n) {
+ c->disconnect (_bundle_for_inputs, _session.engine());
+
+ /* If this is a UserBundle, make a note of what we've done */
- const Bundle::PortList& pl = c->channel_ports (n);
+ boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
+ if (ub) {
- for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
+ std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
+ while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
+ ++i;
+ }
- if (!_outputs.port(n)->connected_to (*i)) {
-
- if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
- return -1;
- }
- }
+ if (i != _bundles_connected_to_inputs.end()) {
+ _bundles_connected_to_inputs.erase (i);
}
}
+ }
+
+ input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
+ return 0;
+}
+
+int
+IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
+{
+ {
+ BLOCK_PROCESS_CALLBACK ();
+ Glib::Mutex::Lock lm2 (io_lock);
+
+ c->connect (_bundle_for_outputs, _session.engine());
/* If this is a UserBundle, make a note of what we've done */
return 0;
}
+int
+IO::disconnect_output_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
+{
+ {
+ BLOCK_PROCESS_CALLBACK ();
+ Glib::Mutex::Lock lm2 (io_lock);
+
+ c->disconnect (_bundle_for_outputs, _session.engine());
+
+ /* If this is a UserBundle, make a note of what we've done */
+
+ boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
+ if (ub) {
+
+ std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
+ while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
+ ++i;
+ }
+
+ if (i != _bundles_connected_to_outputs.end()) {
+ _bundles_connected_to_outputs.erase (i);
+ }
+ }
+ }
+
+ output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
+ return 0;
+}
+
+
int
IO::disable_connecting ()
{
val = 1.99526231f;
}
+ cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
+
if (src != _gain_control.get()) {
_gain_control->set_value(val);
// bit twisty, this will come back and call us again
/**
- * Setup bundles that describe our inputs and outputs.
+ * Setup bundles that describe our inputs and outputs. Also creates bundles if necessary.
*/
void
{
char buf[32];
+ if (!_bundle_for_inputs) {
+ _bundle_for_inputs.reset (new Bundle (true));
+ }
+ if (!_bundle_for_outputs) {
+ _bundle_for_outputs.reset (new Bundle (false));
+ }
+
_bundle_for_inputs->remove_channels ();
_bundle_for_outputs->remove_channels ();
_bundle_for_inputs->set_name (buf);
uint32_t const ni = inputs().num_ports();
for (uint32_t i = 0; i < ni; ++i) {
- snprintf (buf, sizeof(buf), _("in %d"), (i + 1));
- _bundle_for_inputs->add_channel (buf);
- _bundle_for_inputs->set_port (i, inputs().port(i)->name());
+ _bundle_for_inputs->add_channel (bundle_channel_name (i, ni));
+ _bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
}
snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
_bundle_for_outputs->set_name (buf);
uint32_t const no = outputs().num_ports();
for (uint32_t i = 0; i < no; ++i) {
- snprintf (buf, sizeof(buf), _("out %d"), (i + 1));
- _bundle_for_outputs->add_channel (buf);
- _bundle_for_outputs->set_port (i, outputs().port(i)->name());
+ _bundle_for_outputs->add_channel (bundle_channel_name (i, no));
+ _bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
}
}
-
-/**
- * Create and setup bundles that describe our inputs and outputs.
- */
-
-void
-IO::create_bundles_for_inputs_and_outputs ()
-{
- _bundle_for_inputs = boost::shared_ptr<Bundle> (new Bundle (true));
- _bundle_for_outputs = boost::shared_ptr<Bundle> (new Bundle (false));
- setup_bundles_for_inputs_and_outputs ();
-}
-
-/** Add a bundle to a list if is connected to our inputs.
- * @param b Bundle to check.
- * @param bundles List to add to.
- */
-void
-IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
-{
- if (b->ports_are_outputs() == false) {
- return;
- }
-
- if (b->nchannels() != n_inputs().n_total ()) {
- return;
- }
-
- for (uint32_t i = 0; i < n_inputs().n_total (); ++i) {
-
- Bundle::PortList const & pl = b->channel_ports (i);
-
- if (pl.empty()) {
- return;
- }
-
- if (!input(i)->connected_to (pl[0])) {
- return;
- }
- }
-
- bundles->push_back (b);
-}
-
/** @return Bundles connected to our inputs */
-std::vector<boost::shared_ptr<Bundle> >
+BundleList
IO::bundles_connected_to_inputs ()
{
- std::vector<boost::shared_ptr<Bundle> > bundles;
+ BundleList bundles;
/* User bundles */
for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
}
/* Normal bundles */
- _session.foreach_bundle (
- sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles)
- );
-
- return bundles;
-}
-
-
-/** Add a bundle to a list if is connected to our outputs.
- * @param b Bundle to check.
- * @param bundles List to add to.
- */
-void
-IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
-{
- if (b->ports_are_inputs() == false) {
- return;
- }
-
- if (b->nchannels () != n_outputs().n_total ()) {
- return;
- }
-
- for (uint32_t i = 0; i < n_outputs().n_total (); ++i) {
+ boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
+ for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
+ if ((*i)->ports_are_outputs() == false || (*i)->nchannels() != n_inputs().n_total()) {
+ continue;
+ }
- Bundle::PortList const & pl = b->channel_ports (i);
+ for (uint32_t j = 0; j < n_inputs().n_total(); ++j) {
- if (pl.empty()) {
- return;
- }
+ Bundle::PortList const& pl = (*i)->channel_ports (j);
+ if (!pl.empty() && input(j)->connected_to (pl[0])) {
+ bundles.push_back (*i);
+ }
- if (!output(i)->connected_to (pl[0])) {
- return;
}
}
- bundles->push_back (b);
+ return bundles;
}
/* @return Bundles connected to our outputs */
-std::vector<boost::shared_ptr<Bundle> >
+BundleList
IO::bundles_connected_to_outputs ()
{
- std::vector<boost::shared_ptr<Bundle> > bundles;
+ BundleList bundles;
/* User bundles */
for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
}
/* Auto bundles */
- _session.foreach_bundle (
- sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles)
- );
+ boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
+ for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
+ if ((*i)->ports_are_inputs() == false || (*i)->nchannels() != n_outputs().n_total()) {
+ continue;
+ }
+
+ for (uint32_t j = 0; j < n_outputs().n_total(); ++j) {
+
+ Bundle::PortList const& pl = (*i)->channel_ports (j);
+
+ if (!pl.empty() && output(j)->connected_to (pl[0])) {
+ bundles.push_back (*i);
+ }
+ }
+ }
return bundles;
}
}
}
+
+std::string
+IO::bundle_channel_name (uint32_t c, uint32_t n) const
+{
+ char buf[32];
+
+ switch (n) {
+ case 1:
+ return _("mono");
+ case 2:
+ return c == 0 ? _("L") : _("R");
+ default:
+ snprintf (buf, sizeof(buf), _("%d"), (c + 1));
+ return buf;
+ }
+
+ return "";
+}
+
+