+
+/**
+ * Setup bundles that describe our inputs and outputs. Also creates bundles if necessary.
+ */
+
+void
+IO::setup_bundles_for_inputs_and_outputs ()
+{
+ setup_bundle_for_inputs ();
+ setup_bundle_for_outputs ();
+}
+
+
+void
+IO::setup_bundle_for_inputs ()
+{
+ char buf[32];
+
+ if (!_bundle_for_inputs) {
+ _bundle_for_inputs.reset (new Bundle (true));
+ }
+
+ _bundle_for_inputs->suspend_signals ();
+
+ _bundle_for_inputs->set_type (default_type ());
+
+ _bundle_for_inputs->remove_channels ();
+
+ snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
+ _bundle_for_inputs->set_name (buf);
+ uint32_t const ni = inputs().num_ports();
+ for (uint32_t i = 0; i < ni; ++i) {
+ _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_inputs->resume_signals ();
+}
+
+
+void
+IO::setup_bundle_for_outputs ()
+{
+ char buf[32];
+
+ if (!_bundle_for_outputs) {
+ _bundle_for_outputs.reset (new Bundle (false));
+ }
+
+ _bundle_for_outputs->suspend_signals ();
+
+ _bundle_for_outputs->set_type (default_type ());
+
+ _bundle_for_outputs->remove_channels ();
+
+ 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) {
+ _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()));
+ }
+
+ _bundle_for_outputs->resume_signals ();
+}
+
+
+/** @return Bundles connected to our inputs */
+BundleList
+IO::bundles_connected_to_inputs ()
+{
+ BundleList bundles;
+
+ /* User bundles */
+ for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
+ bundles.push_back (i->bundle);
+ }
+
+ /* Session bundles */
+ boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
+ for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
+ if ((*i)->connected_to (_bundle_for_inputs, _session.engine())) {
+ bundles.push_back (*i);
+ }
+ }
+
+ /* Route bundles */
+ boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
+ for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if ((*i)->bundle_for_outputs()->connected_to (_bundle_for_inputs, _session.engine())) {
+ bundles.push_back ((*i)->bundle_for_outputs());
+ }
+ }
+
+ return bundles;
+}
+
+
+/* @return Bundles connected to our outputs */
+BundleList
+IO::bundles_connected_to_outputs ()
+{
+ BundleList bundles;
+
+ /* User bundles */
+ for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
+ bundles.push_back (i->bundle);
+ }
+
+ /* Session bundles */
+ boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
+ for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
+ if ((*i)->connected_to (_bundle_for_outputs, _session.engine())) {
+ bundles.push_back (*i);
+ }
+ }
+
+ /* Route bundles */
+ boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
+ for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if ((*i)->bundle_for_inputs()->connected_to (_bundle_for_outputs, _session.engine())) {
+ bundles.push_back ((*i)->bundle_for_inputs());
+ }
+ }
+
+ return bundles;
+}
+
+
+IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
+{
+ bundle = b;
+ changed = b->Changed.connect (
+ sigc::mem_fun (*io, &IO::bundle_changed)
+ );
+}
+
+void
+IO::prepare_inputs (nframes_t nframes, nframes_t offset)
+{
+ /* io_lock, not taken: function must be called from Session::process() calltree */
+}
+
+void
+IO::flush_outputs (nframes_t nframes, nframes_t offset)
+{
+ /* io_lock, not taken: function must be called from Session::process() calltree */
+ for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
+
+ /* Only run cycle_start() on output ports, because
+ inputs must be done in the correct processing order,
+ which requires interleaving with route processing.
+ */
+
+ (*i).flush_buffers (nframes, offset);
+ }
+
+}
+
+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 "";
+}
+
+