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
_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 || output_buffers().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->add_channel (bundle_channel_name (i, ni));
_bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
}
_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->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 ();
-}
-
/** @return Bundles connected to our inputs */
BundleList
IO::bundles_connected_to_inputs ()
}
}
+
+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 "";
+}
+
+