Various work on Bundles, especially dynamic ones so that you can, for example, pass...
authorCarl Hetherington <carl@carlh.net>
Mon, 8 Oct 2007 23:47:35 +0000 (23:47 +0000)
committerCarl Hetherington <carl@carlh.net>
Mon, 8 Oct 2007 23:47:35 +0000 (23:47 +0000)
git-svn-id: svn://localhost/ardour2/trunk@2530 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/mixer_strip.cc
gtk2_ardour/mixer_strip.h
libs/ardour/ardour/bundle.h
libs/ardour/ardour/io.h
libs/ardour/ardour/session.h
libs/ardour/audio_track.cc
libs/ardour/io.cc
libs/ardour/session.cc
libs/ardour/session_state.cc

index 3fd53c8633a6a4ae44e9d17ca51a58a874285f4e..dfe5a268fa0080e47e466120d72297b8cbbe7c8c 100644 (file)
@@ -43,7 +43,6 @@
 #include <ardour/processor.h>
 #include <ardour/ladspa_plugin.h>
 #include <ardour/bundle.h>
-#include <ardour/session_bundle.h>
 
 #include "ardour_ui.h"
 #include "ardour_dialog.h"
@@ -549,7 +548,9 @@ MixerStrip::output_press (GdkEventButton *ev)
                citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_output)));
                citems.push_back (SeparatorElem());
                
-               _session.foreach_bundle (this, &MixerStrip::add_bundle_to_output_menu);
+               _session.foreach_bundle (
+                       bind (mem_fun (*this, &MixerStrip::add_bundle_to_output_menu), _route->output_bundle ())
+                       );
 
                output_menu.popup (1, ev->time);
                break;
@@ -611,7 +612,9 @@ MixerStrip::input_press (GdkEventButton *ev)
                citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_input)));
                citems.push_back (SeparatorElem());
                
-               _session.foreach_bundle (this, &MixerStrip::add_bundle_to_input_menu);
+               _session.foreach_bundle (
+                       bind (mem_fun (*this, &MixerStrip::add_bundle_to_input_menu), _route->input_bundle ())
+                       );
 
                input_menu.popup (1, ev->time);
                break;
@@ -623,12 +626,12 @@ MixerStrip::input_press (GdkEventButton *ev)
 }
 
 void
-MixerStrip::bundle_input_chosen (ARDOUR::Bundle *c)
+MixerStrip::bundle_input_chosen (boost::shared_ptr<ARDOUR::Bundle> c)
 {
        if (!ignore_toggle) {
 
                try { 
-                       _route->use_input_bundle (*c, this);
+                       _route->connect_input_ports_to_bundle (c, this);
                }
 
                catch (AudioEngine::PortRegistrationFailure& err) {
@@ -639,12 +642,12 @@ MixerStrip::bundle_input_chosen (ARDOUR::Bundle *c)
 }
 
 void
-MixerStrip::bundle_output_chosen (ARDOUR::Bundle *c)
+MixerStrip::bundle_output_chosen (boost::shared_ptr<ARDOUR::Bundle> c)
 {
        if (!ignore_toggle) {
 
                try { 
-                       _route->use_output_bundle (*c, this);
+                       _route->connect_output_ports_to_bundle (c, this);
                }
 
                catch (AudioEngine::PortRegistrationFailure& err) {
@@ -655,23 +658,23 @@ MixerStrip::bundle_output_chosen (ARDOUR::Bundle *c)
 }
 
 void
-MixerStrip::add_bundle_to_input_menu (ARDOUR::Bundle* c)
+MixerStrip::add_bundle_to_input_menu (boost::shared_ptr<Bundle> b, boost::shared_ptr<Bundle> current)
 {
        using namespace Menu_Helpers;
 
-       if (dynamic_cast<InputBundle *> (c) == 0) {
+       /* the input menu needs to contain only output bundles (that we
+          can connect inputs to */
+       if (boost::dynamic_pointer_cast<OutputBundle, Bundle> (b) == 0) {
                return;
        }
 
        MenuList& citems = input_menu.items();
        
-       if (c->nchannels() == _route->n_inputs().n_total()) {
+       if (b->nchannels() == _route->n_inputs().n_total()) {
 
-               citems.push_back (CheckMenuElem (c->name(), bind (mem_fun(*this, &MixerStrip::bundle_input_chosen), c)));
+               citems.push_back (CheckMenuElem (b->name(), bind (mem_fun(*this, &MixerStrip::bundle_input_chosen), b)));
                
-               ARDOUR::Bundle *current = _route->input_bundle();
-               
-               if (current == c) {
+               if (current == b) {
                        ignore_toggle = true;
                        dynamic_cast<CheckMenuItem *> (&citems.back())->set_active (true);
                        ignore_toggle = false;
@@ -680,22 +683,23 @@ MixerStrip::add_bundle_to_input_menu (ARDOUR::Bundle* c)
 }
 
 void
-MixerStrip::add_bundle_to_output_menu (ARDOUR::Bundle* c)
+MixerStrip::add_bundle_to_output_menu (boost::shared_ptr<Bundle> b, boost::shared_ptr<Bundle> current)
 {
        using namespace Menu_Helpers;
 
-       if (dynamic_cast<OutputBundle *> (c) == 0) {
+       /* the output menu needs to contain only input bundles (that we
+          can connect outputs to */
+       if (boost::dynamic_pointer_cast<InputBundle, Bundle> (b) == 0) {
                return;
        }
 
-       if (c->nchannels() == _route->n_outputs().n_total()) {
+
+       if (b->nchannels() == _route->n_outputs().n_total()) {
 
                MenuList& citems = output_menu.items();
-               citems.push_back (CheckMenuElem (c->name(), bind (mem_fun(*this, &MixerStrip::bundle_output_chosen), c)));
-               
-               ARDOUR::Bundle *current = _route->output_bundle();
+               citems.push_back (CheckMenuElem (b->name(), bind (mem_fun(*this, &MixerStrip::bundle_output_chosen), b)));
                
-               if (current == c) {
+               if (current == b) {
                        ignore_toggle = true;
                        dynamic_cast<CheckMenuItem *> (&citems.back())->set_active (true);
                        ignore_toggle = false;
@@ -748,7 +752,7 @@ MixerStrip::connect_to_pan ()
 void
 MixerStrip::update_input_display ()
 {
-       ARDOUR::Bundle *c;
+       boost::shared_ptr<ARDOUR::Bundle> c;
 
        if ((c = _route->input_bundle()) != 0) {
                input_label.set_text (c->name());
@@ -768,7 +772,7 @@ MixerStrip::update_input_display ()
 void
 MixerStrip::update_output_display ()
 {
-       ARDOUR::Bundle *c;
+       boost::shared_ptr<ARDOUR::Bundle> c;
 
        if ((c = _route->output_bundle()) != 0) {
                output_label.set_text (c->name());
index b7bd20cfbd63f9be7221f96b8d9d81aff565434a..9702ea09d851aa7eb769e21c6def1e15ab0b464d 100644 (file)
@@ -168,13 +168,13 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
        gint output_press (GdkEventButton *);
 
        Gtk::Menu  input_menu;
-       void add_bundle_to_input_menu (ARDOUR::Bundle *);
+       void add_bundle_to_input_menu (boost::shared_ptr<ARDOUR::Bundle>, boost::shared_ptr<ARDOUR::Bundle>);
 
        Gtk::Menu output_menu;
-       void add_bundle_to_output_menu (ARDOUR::Bundle *);
+       void add_bundle_to_output_menu (boost::shared_ptr<ARDOUR::Bundle>, boost::shared_ptr<ARDOUR::Bundle>);
        
-       void bundle_input_chosen (ARDOUR::Bundle *);
-       void bundle_output_chosen (ARDOUR::Bundle *);
+       void bundle_input_chosen (boost::shared_ptr<ARDOUR::Bundle>);
+       void bundle_output_chosen (boost::shared_ptr<ARDOUR::Bundle>);
 
        void edit_input_configuration ();
        void edit_output_configuration ();
index 1ed285a1185c5373a9637a511ed0ec3135d2ca19..9c5f3cb21afc8c0388d101de75af06fef0b831b3 100644 (file)
@@ -121,6 +121,12 @@ class InputBundle : public Bundle {
   
 class OutputBundle : public Bundle {
   public:
+       /**
+        *  OutputBundle constructor.
+        *  \param name Name.
+        *  \param dy true if this Bundle is `dynamic'; ie it is created on-the-fly
+        *  and should not be written to the session file.
+        */  
         OutputBundle (string name, bool dy = false) : Bundle (name, dy) {}
        OutputBundle (const XMLNode&);
 };
index 4ab99c5f12c10443133ea97065b6e405c7dd5eb2..2b0b0f7781deddd90ea74452bae99ff3e9f17f4f 100644 (file)
@@ -120,11 +120,11 @@ class IO : public Automatable, public Latent
        
        int ensure_io (ChanCount in, ChanCount out, bool clear, void *src);
 
-       int use_input_bundle (Bundle&, void *src);
-       int use_output_bundle (Bundle&, void *src);
+       int connect_input_ports_to_bundle (boost::shared_ptr<Bundle>, void *src);
+       int connect_output_ports_to_bundle (boost::shared_ptr<Bundle>, void *src);
 
-       Bundle *input_bundle() const { return _input_bundle; }
-       Bundle *output_bundle() const { return _output_bundle; }
+       boost::shared_ptr<Bundle> input_bundle();
+       boost::shared_ptr<Bundle> output_bundle();
 
        int add_input_port (string source, void *src, DataType type = DataType::NIL);
        int add_output_port (string destination, void *src, DataType type = DataType::NIL);
@@ -179,6 +179,9 @@ class IO : public Automatable, public Latent
 
        void attach_buffers(ChanCount ignored);
 
+        boost::shared_ptr<Bundle> bundle_for_inputs () const { return _bundle_for_inputs; }
+        boost::shared_ptr<Bundle> bundle_for_outputs () const { return _bundle_for_outputs; }
+
        sigc::signal<void,IOChange,void*> input_changed;
        sigc::signal<void,IOChange,void*> output_changed;
 
@@ -268,8 +271,8 @@ class IO : public Automatable, public Latent
        PortSet             _outputs;
        PortSet             _inputs;
        PeakMeter*          _meter;
-       Bundle*             _input_bundle;
-       Bundle*             _output_bundle;
+       boost::shared_ptr<Bundle> _input_bundle; ///< bundle connected to our inputs
+       boost::shared_ptr<Bundle> _output_bundle; ///< bundle connected to our outputs
        bool                 no_panner_reset;
        bool                _phase_invert;
        bool                _denormal_protection;
@@ -326,6 +329,8 @@ class IO : public Automatable, public Latent
        ChanCount _output_minimum;
        ChanCount _output_maximum;
 
+       boost::shared_ptr<Bundle> _bundle_for_inputs;
+       boost::shared_ptr<Bundle> _bundle_for_outputs;
 
        static int parse_io_string (const string&, vector<string>& chns);
 
@@ -356,6 +361,9 @@ class IO : public Automatable, public Latent
 
        int32_t find_input_port_hole ();
        int32_t find_output_port_hole ();
+
+       void create_bundles ();
+       void setup_bundles ();
 };
 
 } // namespace ARDOUR
index 540ad08011c58eb3731047ea56d933859eeb8cdc..94caf8a242b40ee73441ca097e5437abcd001d31 100644 (file)
@@ -710,13 +710,14 @@ class Session : public PBD::StatefulDestructible
 
        /* I/O bundles */
 
-       template<class T> void foreach_bundle (T *obj, void (T::*func)(Bundle *));
-       void add_bundle (Bundle *);
-       void remove_bundle (Bundle *);
-       Bundle *bundle_by_name (string) const;
+       void foreach_bundle (sigc::slot<void, boost::shared_ptr<Bundle> >);
+       void add_bundle (boost::shared_ptr<Bundle>);
+       void remove_bundle (boost::shared_ptr<Bundle>);
+       boost::shared_ptr<Bundle> bundle_by_name (string) const;
+       boost::shared_ptr<Bundle> bundle_by_ports (vector<string> const &) const;
 
-       sigc::signal<void,Bundle *> BundleAdded;
-       sigc::signal<void,Bundle *> BundleRemoved;
+       sigc::signal<void,boost::shared_ptr<Bundle> > BundleAdded;
+       sigc::signal<void,boost::shared_ptr<Bundle> > BundleRemoved;
 
        /* MIDI */
 
@@ -1558,9 +1559,9 @@ class Session : public PBD::StatefulDestructible
 
        /* I/O bundles */
 
-       typedef list<Bundle *> BundleList;
+       typedef list<boost::shared_ptr<Bundle> > BundleList;
        mutable Glib::Mutex bundle_lock;
-       BundleList  _bundles;
+       BundleList _bundles;
        int load_bundles (const XMLNode&);
 
        void reverse_diskstream_buffers ();
index 84302b055f0c4575b2b828568e53a309bf5725d9..bc2f0d9feba60c79aa43a6a34d873f278581d482 100644 (file)
@@ -135,7 +135,7 @@ AudioTrack::deprecated_use_diskstream_connections ()
        }
 
        if ((prop = node.property ("input-connection")) != 0) {
-               Bundle* c = _session.bundle_by_name (prop->value());
+               boost::shared_ptr<Bundle> c = _session.bundle_by_name (prop->value());
                
                if (c == 0) {
                        error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
@@ -150,7 +150,7 @@ AudioTrack::deprecated_use_diskstream_connections ()
                        }
                }
 
-               use_input_bundle(*c, this);
+               connect_input_ports_to_bundle (c, this);
 
        } else if ((prop = node.property ("inputs")) != 0) {
                if (set_inputs (prop->value())) {
index 29cc94ffe70f2ba9772070503822991d9d3aa9a5..0c1ba32c74ab39a057fe0a97ac66d16e111ad7d5 100644 (file)
@@ -126,8 +126,6 @@ IO::IO (Session& s, const string& name,
 
        _gain = 1.0;
        _desired_gain = 1.0;
-       _input_bundle = 0;
-       _output_bundle = 0;
        pending_state_node = 0;
        no_panner_reset = false;
        _phase_invert = false;
@@ -154,6 +152,8 @@ IO::IO (Session& s, const string& name,
        IO::MoreChannels.connect (mem_fun (*this, &IO::attach_buffers));
 
        _session.add_controllable (_gain_control);
+
+       create_bundles ();
 }
 
 IO::IO (Session& s, const XMLNode& node, DataType dt)
@@ -168,8 +168,6 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
        no_panner_reset = false;
        _desired_gain = 1.0;
        _gain = 1.0;
-       _input_bundle = 0;
-       _output_bundle = 0;
 
        apply_gain_automation = false;
        
@@ -194,6 +192,8 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
        IO::MoreChannels.connect (mem_fun (*this, &IO::attach_buffers));
 
        _session.add_controllable (_gain_control);
+
+       create_bundles ();
 }
 
 IO::~IO ()
@@ -335,7 +335,7 @@ IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
 void
 IO::drop_input_bundle ()
 {
-       _input_bundle = 0;
+       _input_bundle.reset ();
        input_bundle_configuration_connection.disconnect();
        input_bundle_connection_connection.disconnect();
        _session.set_dirty ();
@@ -344,7 +344,7 @@ IO::drop_input_bundle ()
 void
 IO::drop_output_bundle ()
 {
-       _output_bundle = 0;
+       _output_bundle.reset ();
        output_bundle_configuration_connection.disconnect();
        output_bundle_connection_connection.disconnect();
        _session.set_dirty ();
@@ -550,6 +550,10 @@ IO::remove_output_port (Port* port, void* src)
                }
        }
 
+       if (change == ConnectionsChanged) {
+               setup_bundles ();
+       }
+
        if (change != NoChange) {
                output_changed (change, src);
                _session.set_dirty ();
@@ -616,6 +620,7 @@ IO::add_output_port (string destination, void* src, DataType type)
        
        // pan_changed (src); /* EMIT SIGNAL */
        output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
+       setup_bundles ();
        _session.set_dirty ();
        
        return 0;
@@ -654,6 +659,10 @@ IO::remove_input_port (Port* port, void* src)
                }
        }
 
+       if (change == ConfigurationChanged) {
+               setup_bundles ();
+       }
+
        if (change != NoChange) {
                input_changed (change, src);
                _session.set_dirty ();
@@ -697,7 +706,7 @@ IO::add_input_port (string source, void* src, DataType type)
                        } else {
                                snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
                        }
-                       
+
                        if ((our_port = _session.engine().register_input_port (type, name)) == 0) {
                                error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
                                return -1;
@@ -721,6 +730,7 @@ IO::add_input_port (string source, void* src, DataType type)
 
        // pan_changed (src); /* EMIT SIGNAL */
        input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
+       setup_bundles ();
        _session.set_dirty ();
        
        return 0;
@@ -1003,6 +1013,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
 
        if (in_changed || out_changed) {
                MoreChannels (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
+               setup_bundles ();
                _session.set_dirty ();
        }
 
@@ -1030,6 +1041,7 @@ IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
 
        if (changed) {
                input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
+               setup_bundles ();
                _session.set_dirty ();
        }
        return 0;
@@ -1127,6 +1139,7 @@ IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
 
        if (changed) {
                 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
+                setup_bundles ();
        }
 
        return 0;
@@ -1201,12 +1214,12 @@ IO::state (bool full_state)
 
        str = "";
 
-       if (_input_bundle) {
+       if (_input_bundle && !_input_bundle->dynamic()) {
                node->add_property ("input-connection", _input_bundle->name());
                need_ins = false;
        }
 
-       if (_output_bundle) {
+       if (_output_bundle && !_output_bundle->dynamic()) {
                node->add_property ("output-connection", _output_bundle->name());
                need_outs = false;
        }
@@ -1540,7 +1553,7 @@ IO::create_ports (const XMLNode& node)
         */
        if ((prop = node.property ("input-connection")) != 0) {
 
-               Bundle* c = _session.bundle_by_name (prop->value());
+               boost::shared_ptr<Bundle> c = _session.bundle_by_name (prop->value());
                
                if (c == 0) {
                        error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
@@ -1563,7 +1576,7 @@ IO::create_ports (const XMLNode& node)
        }
        
        if ((prop = node.property ("output-connection")) != 0) {
-               Bundle* c = _session.bundle_by_name (prop->value());
+               boost::shared_ptr<Bundle> c = _session.bundle_by_name (prop->value());
 
                if (c == 0) {
                        error << string_compose(_("Unknown bundle \"%1\" listed for output of %2"), prop->value(), _name) << endmsg;
@@ -1607,7 +1620,7 @@ IO::make_connections (const XMLNode& node)
        const XMLProperty* prop;
 
        if ((prop = node.property ("input-connection")) != 0) {
-               Bundle* c = _session.bundle_by_name (prop->value());
+               boost::shared_ptr<Bundle> c = _session.bundle_by_name (prop->value());
                
                if (c == 0) {
                        error << string_compose(_("Unknown connection \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
@@ -1622,7 +1635,7 @@ IO::make_connections (const XMLNode& node)
                        }
                } 
 
-               use_input_bundle (*c, this);
+               connect_input_ports_to_bundle (c, this);
 
        } else if ((prop = node.property ("inputs")) != 0) {
                if (set_inputs (prop->value())) {
@@ -1632,7 +1645,7 @@ IO::make_connections (const XMLNode& node)
        }
        
        if ((prop = node.property ("output-bundle")) != 0) {
-               Bundle* c = _session.bundle_by_name (prop->value());
+               boost::shared_ptr<Bundle> c = _session.bundle_by_name (prop->value());
                
                if (c == 0) {
                        error << string_compose(_("Unknown bundle \"%1\" listed for output of %2"), prop->value(), _name) << endmsg;
@@ -1647,7 +1660,7 @@ IO::make_connections (const XMLNode& node)
                        }
                } 
 
-               use_output_bundle (*c, this);
+               connect_output_ports_to_bundle (c, this);
                
        } else if ((prop = node.property ("outputs")) != 0) {
                if (set_outputs (prop->value())) {
@@ -1834,7 +1847,11 @@ IO::set_name (const string& str)
                i->set_name (current_name);
        }
 
-       return SessionObject::set_name(name);
+       bool const r = SessionObject::set_name(name);
+
+       setup_bundles ();
+
+       return r;
 }
 
 void
@@ -1910,7 +1927,7 @@ IO::input_latency () const
 }
 
 int
-IO::use_input_bundle (Bundle& c, void* src)
+IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
 {
        uint32_t limit;
 
@@ -1918,7 +1935,7 @@ IO::use_input_bundle (Bundle& c, void* src)
                BLOCK_PROCESS_CALLBACK ();
                Glib::Mutex::Lock lm2 (io_lock);
                
-               limit = c.nchannels();
+               limit = c->nchannels();
                
                drop_input_bundle ();
                
@@ -1932,7 +1949,7 @@ IO::use_input_bundle (Bundle& c, void* src)
                */
                
                for (uint32_t n = 0; n < limit; ++n) {
-                       const Bundle::PortList& pl = c.channel_ports (n);
+                       const Bundle::PortList& pl = c->channel_ports (n);
                        
                        for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
                                
@@ -1962,7 +1979,7 @@ IO::use_input_bundle (Bundle& c, void* src)
                /* second pass: connect all requested ports where necessary */
                
                for (uint32_t n = 0; n < limit; ++n) {
-                       const Bundle::PortList& pl = c.channel_ports (n);
+                       const Bundle::PortList& pl = c->channel_ports (n);
                        
                        for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
                                
@@ -1976,11 +1993,11 @@ IO::use_input_bundle (Bundle& c, void* src)
                        }
                }
                
-               _input_bundle = &c;
+               _input_bundle = c;
                
-               input_bundle_configuration_connection = c.ConfigurationChanged.connect
+               input_bundle_configuration_connection = c->ConfigurationChanged.connect
                        (mem_fun (*this, &IO::input_bundle_configuration_changed));
-               input_bundle_connection_connection = c.PortsChanged.connect
+               input_bundle_connection_connection = c->PortsChanged.connect
                        (mem_fun (*this, &IO::input_bundle_connection_changed));
        }
 
@@ -1989,7 +2006,7 @@ IO::use_input_bundle (Bundle& c, void* src)
 }
 
 int
-IO::use_output_bundle (Bundle& c, void* src)
+IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
 {
        uint32_t limit; 
 
@@ -1997,7 +2014,7 @@ IO::use_output_bundle (Bundle& c, void* src)
                BLOCK_PROCESS_CALLBACK ();
                Glib::Mutex::Lock lm2 (io_lock);
 
-               limit = c.nchannels();
+               limit = c->nchannels();
                        
                drop_output_bundle ();
 
@@ -2012,7 +2029,7 @@ IO::use_output_bundle (Bundle& c, void* src)
                        
                for (uint32_t n = 0; n < limit; ++n) {
 
-                       const Bundle::PortList& pl = c.channel_ports (n);
+                       const Bundle::PortList& pl = c->channel_ports (n);
                                
                        for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
                                        
@@ -2042,7 +2059,7 @@ IO::use_output_bundle (Bundle& c, void* src)
 
                for (uint32_t n = 0; n < limit; ++n) {
 
-                       const Bundle::PortList& pl = c.channel_ports (n);
+                       const Bundle::PortList& pl = c->channel_ports (n);
                                
                        for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
                                        
@@ -2055,11 +2072,11 @@ IO::use_output_bundle (Bundle& c, void* src)
                        }
                }
 
-               _output_bundle = &c;
+               _output_bundle = c;
 
-               output_bundle_configuration_connection = c.ConfigurationChanged.connect
+               output_bundle_configuration_connection = c->ConfigurationChanged.connect
                        (mem_fun (*this, &IO::output_bundle_configuration_changed));
-               output_bundle_connection_connection = c.PortsChanged.connect
+               output_bundle_connection_connection = c->PortsChanged.connect
                        (mem_fun (*this, &IO::output_bundle_connection_changed));
        }
 
@@ -2113,25 +2130,25 @@ IO::reset_panners ()
 void
 IO::input_bundle_connection_changed (int ignored)
 {
-       use_input_bundle (*_input_bundle, this);
+       connect_input_ports_to_bundle (_input_bundle, this);
 }
 
 void
 IO::input_bundle_configuration_changed ()
 {
-       use_input_bundle (*_input_bundle, this);
+       connect_input_ports_to_bundle (_input_bundle, this);
 }
 
 void
 IO::output_bundle_connection_changed (int ignored)
 {
-       use_output_bundle (*_output_bundle, this);
+       connect_output_ports_to_bundle (_output_bundle, this);
 }
 
 void
 IO::output_bundle_configuration_changed ()
 {
-       use_output_bundle (*_output_bundle, this);
+       connect_output_ports_to_bundle (_output_bundle, this);
 }
 
 void
@@ -2428,3 +2445,100 @@ IO::update_port_total_latencies ()
                _session.engine().update_total_latency (*i);
        }
 }
+
+
+/**
+ *  Setup bundles that describe our inputs and outputs.
+ */
+
+void
+IO::setup_bundles ()
+{
+        char buf[32];
+
+        snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
+        _bundle_for_inputs->set_name (buf, 0);
+        int const ins = n_inputs().n_total();
+        _bundle_for_inputs->set_nchannels (ins);
+        
+        for (int i = 0; i < ins; ++i) {
+                _bundle_for_inputs->add_port_to_channel (i, _inputs.port(i)->name ());
+        }
+
+        snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
+        _bundle_for_outputs->set_name (buf, 0);
+        int const outs = n_outputs().n_total();
+        _bundle_for_outputs->set_nchannels (outs);
+        
+        for (int i = 0; i < outs; ++i) {
+                _bundle_for_outputs->add_port_to_channel (i, _outputs.port(i)->name ());
+        }
+}
+
+
+/**
+ *  Create and setup bundles that describe our inputs and outputs.
+ */
+
+void
+IO::create_bundles ()
+{
+        _bundle_for_inputs = boost::shared_ptr<Bundle> (
+                new InputBundle ("", true)
+                );
+        
+        _bundle_for_outputs = boost::shared_ptr<Bundle> (
+                new OutputBundle ("", true)
+                );
+
+        setup_bundles ();
+}
+
+boost::shared_ptr<Bundle>
+IO::input_bundle()
+{
+       if (_input_bundle) {
+               return _input_bundle;
+       }
+
+       /* XXX: will only report the first bundle found; should really return a list, I think */
+          
+       /* check that _input_bundle is right wrt the connections that are currently made */
+
+       /* make a vector of the first output connected to each of our inputs */
+       std::vector<std::string> connected;
+        for (uint32_t i = 0; i < _inputs.num_ports(); ++i) {
+               const char** c = _inputs.port(i)->get_connections ();
+               if (c) {
+                       connected.push_back (c[0]);
+               }
+       }
+
+       _input_bundle = _session.bundle_by_ports (connected);
+       return _input_bundle;
+}
+
+
+boost::shared_ptr<Bundle>
+IO::output_bundle()
+{
+       if (_output_bundle) {
+               return _output_bundle;
+       }
+       
+       /* XXX: will only report the first bundle found; should really return a list, I think */
+          
+       /* check that _output_bundle is right wrt the connections that are currently made */
+
+       /* make a vector of the first input connected to each of our outputs */
+       std::vector<std::string> connected;
+        for (uint32_t i = 0; i < _outputs.num_ports(); ++i) {
+               const char** c = _outputs.port(i)->get_connections ();
+               if (c) {
+                       connected.push_back (c[0]);
+               }
+       }
+
+       _output_bundle = _session.bundle_by_ports (connected);
+       return _output_bundle;
+}
index ed696446ef0f06475e354311bbc35f8cd871a5c3..742b17af2c0faeac356d30f6277ae77af535daa1 100644 (file)
@@ -487,20 +487,6 @@ Session::destroy ()
                i = tmp;
        }
        
-#ifdef TRACK_DESTRUCTION
-       cerr << "delete bundles\n";
-#endif /* TRACK_DESTRUCTION */
-       for (BundleList::iterator i = _bundles.begin(); i != _bundles.end(); ) {
-               BundleList::iterator tmp;
-
-               tmp = i;
-               ++tmp;
-
-               delete *i;
-
-               i = tmp;
-       }
-
        if (butler_mixdown_buffer) {
                delete [] butler_mixdown_buffer;
        }
@@ -615,7 +601,7 @@ Session::when_engine_running ()
                char buf[32];
                snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
 
-               Bundle* c = new OutputBundle (buf, true);
+               shared_ptr<Bundle> c (new OutputBundle (buf, true));
                c->set_nchannels (1);
                c->add_port_to_channel (0, _engine.get_nth_physical_output (DataType::AUDIO, np));
 
@@ -626,7 +612,7 @@ Session::when_engine_running ()
                char buf[32];
                snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
 
-               Bundle* c = new InputBundle (buf, true);
+               shared_ptr<Bundle> c (new InputBundle (buf, true));
                c->set_nchannels (1);
                c->add_port_to_channel (0, _engine.get_nth_physical_input (DataType::AUDIO, np));
 
@@ -639,7 +625,7 @@ Session::when_engine_running ()
                char buf[32];
                snprintf (buf, sizeof (buf), _("out %" PRIu32 "+%" PRIu32), np+1, np+2);
 
-               Bundle* c = new OutputBundle (buf, true);
+               shared_ptr<Bundle> c (new OutputBundle (buf, true));
                c->set_nchannels (2);
                c->add_port_to_channel (0, _engine.get_nth_physical_output (DataType::AUDIO, np));
                c->add_port_to_channel (1, _engine.get_nth_physical_output (DataType::AUDIO, np+1));
@@ -651,7 +637,7 @@ Session::when_engine_running ()
                char buf[32];
                snprintf (buf, sizeof (buf), _("in %" PRIu32 "+%" PRIu32), np+1, np+2);
 
-               Bundle* c = new InputBundle (buf, true);
+               shared_ptr<Bundle> c (new InputBundle (buf, true));
                c->set_nchannels (2);
                c->add_port_to_channel (0, _engine.get_nth_physical_input (DataType::AUDIO, np));
                c->add_port_to_channel (1, _engine.get_nth_physical_input (DataType::AUDIO, np+1));
@@ -701,7 +687,7 @@ Session::when_engine_running ()
                        
                }
 
-               Bundle* c = new OutputBundle (_("Master Out"), true);
+               shared_ptr<Bundle> c (new OutputBundle (_("Master Out"), true));
 
                c->set_nchannels (_master_out->n_inputs().n_total());
                for (uint32_t n = 0; n < _master_out->n_inputs ().n_total(); ++n) {
@@ -1902,7 +1888,10 @@ Session::add_routes (RouteList& new_routes, bool save)
                
                if ((*x)->is_control()) {
                        _control_out = (*x);
-               } 
+               }
+
+               add_bundle ((*x)->bundle_for_inputs());
+               add_bundle ((*x)->bundle_for_outputs());
        }
 
        if (_control_out && IO::connecting_legal) {
@@ -3609,7 +3598,7 @@ Session::available_capture_duration ()
 }
 
 void
-Session::add_bundle (ARDOUR::Bundle* bundle)
+Session::add_bundle (shared_ptr<Bundle> bundle)
 {
        {
                Glib::Mutex::Lock guard (bundle_lock);
@@ -3622,7 +3611,7 @@ Session::add_bundle (ARDOUR::Bundle* bundle)
 }
 
 void
-Session::remove_bundle (ARDOUR::Bundle* bundle)
+Session::remove_bundle (shared_ptr<Bundle> bundle)
 {
        bool removed = false;
 
@@ -3643,7 +3632,7 @@ Session::remove_bundle (ARDOUR::Bundle* bundle)
        set_dirty();
 }
 
-ARDOUR::Bundle *
+shared_ptr<Bundle>
 Session::bundle_by_name (string name) const
 {
        Glib::Mutex::Lock lm (bundle_lock);
@@ -3654,7 +3643,36 @@ Session::bundle_by_name (string name) const
                }
        }
 
-       return 0;
+       return boost::shared_ptr<Bundle> ();
+}
+
+boost::shared_ptr<Bundle>
+Session::bundle_by_ports (std::vector<std::string> const & wanted_ports) const
+{
+       Glib::Mutex::Lock lm (bundle_lock);
+
+       for (BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
+               if ((*i)->nchannels() != wanted_ports.size()) {
+                       continue;
+               }
+
+               bool match = true;
+               for (uint32_t j = 0; j < (*i)->nchannels(); ++j) {
+                       Bundle::PortList const p = (*i)->channel_ports (j);
+                       if (p.empty() || p[0] != wanted_ports[j]) {
+                               /* not this bundle */
+                               match = false;
+                               break;
+                       }
+               }
+
+               if (match) {
+                       /* matched bundle */
+                       return *i;
+               }
+       }
+
+       return boost::shared_ptr<Bundle> ();
 }
 
 void
@@ -4105,3 +4123,11 @@ Session::compute_initial_length ()
        return _engine.frame_rate() * 60 * 5;
 }
 
+void
+Session::foreach_bundle (sigc::slot<void, boost::shared_ptr<Bundle> > sl)
+{
+       Glib::Mutex::Lock lm (bundle_lock);
+       for (BundleList::iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
+               sl (*i);
+       }
+}
index 21c0405f211169f1ad40182c81ff06eead04aa2f..618660e98fa0a6080d0cbf167c5f9d04ccfb2e2b 100644 (file)
@@ -1881,9 +1881,9 @@ Session::load_bundles (const XMLNode& node)
 
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
                if ((*niter)->name() == "InputConnection") {
-                       add_bundle (new ARDOUR::InputBundle (**niter));
+                       add_bundle (boost::shared_ptr<Bundle> (new InputBundle (**niter)));
                } else if ((*niter)->name() == "OutputConnection") {
-                       add_bundle (new ARDOUR::OutputBundle (**niter));
+                       add_bundle (boost::shared_ptr<Bundle> (new OutputBundle (**niter)));
                } else {
                        error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
                        return -1;