fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / io.cc
index 642b2a04351403ab8ef1e6c5ea2dba7f2cf91527..f535467cbe664874408bf32454546d030124b54e 100644 (file)
@@ -43,7 +43,7 @@
 #include "ardour/session.h"
 #include "ardour/user_bundle.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 #define BLOCK_PROCESS_CALLBACK() Glib::Threads::Mutex::Lock em (AudioEngine::instance()->process_lock())
 
@@ -405,6 +405,7 @@ IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed)
 #endif
 
        boost::shared_ptr<Port> port;
+       vector<boost::shared_ptr<Port> > deleted_ports;
 
        changed    = false;
 
@@ -418,11 +419,30 @@ IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed)
 
                        assert(port);
                        _ports.remove(port);
+
+                       /* hold a reference to the port so that we can ensure
+                        * that this thread, and not a JACK notification thread,
+                        * holds the final reference.
+                        */
+
+                       deleted_ports.push_back (port);
                        _session.engine().unregister_port (port);
 
                        changed = true;
                }
 
+               /* this will drop the final reference to the deleted ports,
+                * which will in turn call their destructors, which will in
+                * turn call the backend to unregister them.
+                *
+                * There will no connect/disconnect or register/unregister
+                * callbacks from the backend until we get here, because
+                * they are driven by the Port destructor. The destructor
+                * will not execute until we drop the final reference,
+                * which all happens right .... here.
+                */
+               deleted_ports.clear ();
+
                /* create any necessary new ports */
                while (n_ports().get(*t) < n) {
 
@@ -530,7 +550,7 @@ IO::state (bool /*full_state*/)
        char buf[64];
        string str;
        int n;
-       LocaleGuard lg (X_("C"));
+       LocaleGuard lg;
        Glib::Threads::Mutex::Lock lm (io_lock);
 
        node->add_property("name", _name);
@@ -597,7 +617,7 @@ IO::set_state (const XMLNode& node, int version)
 
        XMLProperty const * prop;
        XMLNodeConstIterator iter;
-       LocaleGuard lg (X_("C"));
+       LocaleGuard lg;
 
        /* force use of non-localized representation of decimal point,
           since we use it a lot in XML files and so forth.
@@ -658,7 +678,7 @@ IO::set_state_2X (const XMLNode& node, int version, bool in)
 {
        XMLProperty const * prop;
        XMLNodeConstIterator iter;
-       LocaleGuard lg (X_("C"));
+       LocaleGuard lg;
 
        /* force use of non-localized representation of decimal point,
           since we use it a lot in XML files and so forth.
@@ -1579,13 +1599,13 @@ IO::bundle_channel_name (uint32_t c, uint32_t n, DataType t) const
                case 2:
                        return c == 0 ? _("L") : _("R");
                default:
-                       snprintf (buf, sizeof(buf), _("%d"), (c + 1));
+                       snprintf (buf, sizeof(buf), "%d", (c + 1));
                        return buf;
                }
 
        } else {
 
-               snprintf (buf, sizeof(buf), _("%d"), (c + 1));
+               snprintf (buf, sizeof(buf), "%d", (c + 1));
                return buf;
 
        }
@@ -1675,7 +1695,7 @@ IO::connected_to (const string& str) const
  *  Caller must hold process lock.
  */
 void
-IO::process_input (boost::shared_ptr<Processor> proc, framepos_t start_frame, framepos_t end_frame, pframes_t nframes)
+IO::process_input (boost::shared_ptr<Processor> proc, framepos_t start_frame, framepos_t end_frame, double speed, pframes_t nframes)
 {
        /* don't read the data into new buffers - just use the port buffers directly */
 
@@ -1686,7 +1706,7 @@ IO::process_input (boost::shared_ptr<Processor> proc, framepos_t start_frame, fr
 
        _buffers.get_backend_port_addresses (_ports, nframes);
        if (proc) {
-               proc->run (_buffers, start_frame, end_frame, nframes, true);
+               proc->run (_buffers, start_frame, end_frame, speed, nframes, true);
        }
 }
 
@@ -1721,12 +1741,14 @@ IO::collect_input (BufferSet& bufs, pframes_t nframes, ChanCount offset)
 void
 IO::copy_to_outputs (BufferSet& bufs, DataType type, pframes_t nframes, framecnt_t offset)
 {
-       // Copy any buffers 1:1 to outputs
-
        PortSet::iterator o = _ports.begin(type);
        BufferSet::iterator i = bufs.begin(type);
        BufferSet::iterator prev = i;
 
+       assert(i != bufs.end(type)); // or second loop will crash
+
+       // Copy any buffers 1:1 to outputs
+
        while (i != bufs.end(type) && o != _ports.end (type)) {
                Buffer& port_buffer (o->get_buffer (nframes));
                port_buffer.read_from (*i, nframes, offset);