a putatively better approach to cleaning up ports at session closing
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 21 Jun 2012 15:00:10 +0000 (15:00 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 21 Jun 2012 15:00:10 +0000 (15:00 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@12807 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/port.h
libs/ardour/audioengine.cc
libs/ardour/port.cc
libs/ardour/session.cc

index 37101950d5158dbcd0963d2983a6673fd01efe6b..e225117d940a90adde0d8e4c7bb19b134182ffce 100644 (file)
@@ -126,6 +126,7 @@ public:
 
        PBD::Signal1<void,bool> MonitorInputChanged;
        static PBD::Signal2<void,boost::shared_ptr<Port>,boost::shared_ptr<Port> > PostDisconnect;
+       static PBD::Signal0<void> PortDrop;
 
        static void set_cycle_framecnt (pframes_t n) {
                _cycle_nframes = n;
@@ -167,6 +168,8 @@ private:
        */
        std::set<std::string> _connections;
 
+       void drop ();
+       PBD::ScopedConnection drop_connection;
 };
 
 }
index 26f8311c8d2625f751222e33a3a6a72fdf2578ed..5642db89321dd8cb90f7dfbc09cf9b36ec2d0c65 100644 (file)
@@ -479,6 +479,21 @@ AudioEngine::process_callback (pframes_t nframes)
                /* perform the actual session removal */
                _session = 0;
                session_remove_pending = false;
+
+               /* pump one cycle of silence into the ports
+                  before the session tears them all down
+                  (asynchronously).
+               */
+
+               boost::shared_ptr<Ports> p = ports.reader();
+               
+               for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
+                       
+                       if (i->second->sends_output()) {
+                               i->second->get_buffer (nframes).silence (nframes);
+                       }
+               }
+
                session_removed.signal();
        }
 
@@ -486,15 +501,6 @@ AudioEngine::process_callback (pframes_t nframes)
                if (!_freewheeling) {
                        MIDI::Manager::instance()->cycle_start(nframes);
                        MIDI::Manager::instance()->cycle_end();
-
-                       boost::shared_ptr<Ports> p = ports.reader();
-                       
-                       for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-                               
-                               if (i->second->sends_output()) {
-                                       i->second->get_buffer (nframes).silence (nframes);
-                               }
-                       }
                }
 
                _processed_frames = next_processed_frames;
index b0c4b43c06c7853f3401e53bbbc0b886f5770734..3473b73617a84226bb442a1bc421bc717fc1ce57 100644 (file)
@@ -38,6 +38,7 @@ using namespace ARDOUR;
 using namespace PBD;
 
 PBD::Signal2<void,boost::shared_ptr<Port>, boost::shared_ptr<Port> > Port::PostDisconnect;
+PBD::Signal0<void> Port::PortDrop;
 
 AudioEngine* Port::_engine = 0;
 bool         Port::_connecting_blocked = false;
@@ -71,13 +72,24 @@ Port::Port (std::string const & n, DataType t, Flags f)
                cerr << "Failed to register JACK port \"" << _name << "\", reason is unknown from here\n";
                throw failed_constructor ();
        }
+
+       PortDrop.connect_same_thread (drop_connection, boost::bind (&Port::drop, this));
 }
 
 /** Port destructor */
 Port::~Port ()
 {
-       if (_engine->jack ()) {
-               jack_port_unregister (_engine->jack (), _jack_port);
+       drop ();
+}
+
+void
+Port::drop ()
+{
+       if (_jack_port) {
+               if (_engine->jack ()) {
+                       jack_port_unregister (_engine->jack (), _jack_port);
+               }
+               _jack_port = 0;
        }
 }
 
index 9eb4c223d06b144243da380b902b3187f1e0489e..57581300922cbc859db6542d484dcbcd2873a2ae 100644 (file)
@@ -234,6 +234,12 @@ Session::destroy ()
 
        _engine.remove_session ();
 
+       /* deregister all ports - there will be no process or any other
+        * callbacks from the engine any more.
+        */
+
+       Port::PortDrop (); /* EMIT SIGNAL */
+
        /* clear history so that no references to objects are held any more */
 
        _history.clear ();