forward port automation handling changes from 2.x, upto and including about rev 6981...
[ardour.git] / libs / ardour / route.cc
index a2988670d99dc8c7ef3918e445996b7cddd61d91..290d9209d93c1bdda31e46f055396f69c9958c5d 100644 (file)
@@ -58,6 +58,7 @@
 #include "ardour/session.h"
 #include "ardour/timestamps.h"
 #include "ardour/utils.h"
+#include "ardour/graph.h"
 
 #include "i18n.h"
 
@@ -71,14 +72,14 @@ PBD::Signal0<void> Route::RemoteControlIDChange;
 
 Route::Route (Session& sess, string name, Flag flg, DataType default_type)
        : SessionObject (sess, name)
-       , AutomatableControls (sess)
+       , Automatable (sess)
+       , GraphNode( sess.route_graph )
         , _active (true)
         , _initial_delay (0)
         , _roll_delay (0)
        , _flags (flg)
         , _pending_declick (true)
         , _meter_point (MeterPostFader)
-        , _phase_invert (0)
         , _self_solo (false)
         , _soloed_by_others_upstream (0)
         , _soloed_by_others_downstream (0)
@@ -107,7 +108,7 @@ Route::init ()
 
        _solo_control->set_flags (Controllable::Flag (_solo_control->flags() | Controllable::Toggle));
        _mute_control->set_flags (Controllable::Flag (_solo_control->flags() | Controllable::Toggle));
-       
+
        add_control (_solo_control);
        add_control (_mute_control);
 
@@ -211,7 +212,7 @@ Route::remote_control_id() const
        return _remote_control_id;
 }
 
-long
+int32_t
 Route::order_key (std::string const & name) const
 {
        OrderKeys::const_iterator i = order_keys.find (name);
@@ -223,17 +224,34 @@ Route::order_key (std::string const & name) const
 }
 
 void
-Route::set_order_key (std::string const & name, long n)
+Route::set_order_key (std::string const & name, int32_t n)
 {
-       order_keys[name] = n;
+       bool changed = false;
+
+       /* This method looks more complicated than it should, but
+          it's important that we don't emit order_key_changed unless
+          it actually has, as expensive things happen on receipt of that
+          signal.
+       */
+
+       if (order_keys.find(name) == order_keys.end() || order_keys[name] != n) {
+               order_keys[name] = n;
+               changed = true;
+       }
 
        if (Config->get_sync_all_route_ordering()) {
                for (OrderKeys::iterator x = order_keys.begin(); x != order_keys.end(); ++x) {
-                       x->second = n;
+                       if (x->second != n) {
+                               x->second = n;
+                               changed = true;
+                       }
                }
        }
 
-       _session.set_dirty ();
+       if (changed) {
+               order_key_changed (); /* EMIT SIGNAL */
+               _session.set_dirty ();
+       }
 }
 
 /** Set all order keys to be the same as that for `base', if such a key
@@ -248,7 +266,7 @@ Route::sync_order_keys (std::string const & base)
        }
 
        OrderKeys::iterator i;
-       uint32_t key;
+       int32_t key;
 
        if ((i = order_keys.find (base)) == order_keys.end()) {
                /* key doesn't exist, use the first existing key (during session initialization) */
@@ -261,8 +279,17 @@ Route::sync_order_keys (std::string const & base)
                i = order_keys.begin();
        }
 
+       bool changed = false;
+       
        for (; i != order_keys.end(); ++i) {
-               i->second = key;
+               if (i->second != key) {
+                       i->second = key;
+                       changed = true;
+               }
+       }
+
+       if (changed) {
+               order_key_changed (); /* EMIT SIGNAL */
        }
 }
 
@@ -385,9 +412,9 @@ Route::process_output_buffers (BufferSet& bufs,
           ----------------------------------------------------------------------------------------- */
 
        if (declick > 0) {
-               Amp::apply_gain (bufs, nframes, 0.0, 1.0);
+               Amp::declick (bufs, nframes, 1);
        } else if (declick < 0) {
-               Amp::apply_gain (bufs, nframes, 1.0, 0.0);
+               Amp::declick (bufs, nframes, -1);
        }
 
        _pending_declick = 0;
@@ -396,7 +423,7 @@ Route::process_output_buffers (BufferSet& bufs,
           DENORMAL CONTROL/PHASE INVERT
           ----------------------------------------------------------------------------------------- */
 
-       if (_phase_invert) {
+       if (_phase_invert.any ()) {
 
                int chn = 0;
 
@@ -405,7 +432,7 @@ Route::process_output_buffers (BufferSet& bufs,
                        for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i, ++chn) {
                                Sample* const sp = i->data();
 
-                               if (_phase_invert & chn) {
+                               if (_phase_invert[chn]) {
                                        for (nframes_t nx = 0; nx < nframes; ++nx) {
                                                sp[nx]  = -sp[nx];
                                                sp[nx] += 1.0e-27f;
@@ -422,7 +449,7 @@ Route::process_output_buffers (BufferSet& bufs,
                        for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i, ++chn) {
                                Sample* const sp = i->data();
 
-                               if (_phase_invert & (1<<chn)) {
+                               if (_phase_invert[chn]) {
                                        for (nframes_t nx = 0; nx < nframes; ++nx) {
                                                sp[nx] = -sp[nx];
                                        }
@@ -1692,7 +1719,9 @@ Route::state(bool full_state)
        }
 
        node->add_property("active", _active?"yes":"no");
-       node->add_property("phase-invert", _phase_invert?"yes":"no");
+       string p;
+       boost::to_string (_phase_invert, p);
+       node->add_property("phase-invert", p);
        node->add_property("denormal-protection", _denormal_protection?"yes":"no");
        node->add_property("meter-point", enum_2_string (_meter_point));
 
@@ -1839,7 +1868,7 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
        }
 
        if ((prop = node.property (X_("phase-invert"))) != 0) {
-               set_phase_invert (string_is_affirmative (prop->value()));
+               set_phase_invert (boost::dynamic_bitset<> (prop->value ()));
        }
 
        if ((prop = node.property (X_("denormal-protection"))) != 0) {
@@ -1862,7 +1891,7 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
 
        if ((prop = node.property (X_("order-keys"))) != 0) {
 
-               long n;
+               int32_t n;
 
                string::size_type colon, equal;
                string remaining = prop->value();
@@ -1873,7 +1902,7 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
                                error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
                                      << endmsg;
                        } else {
-                               if (sscanf (remaining.substr (equal+1).c_str(), "%ld", &n) != 1) {
+                               if (sscanf (remaining.substr (equal+1).c_str(), "%d", &n) != 1) {
                                        error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
                                              << endmsg;
                                } else {
@@ -1954,7 +1983,11 @@ Route::_set_state_2X (const XMLNode& node, int version)
        }
        
        if ((prop = node.property (X_("phase-invert"))) != 0) {
-               set_phase_invert (string_is_affirmative (prop->value()));
+               boost::dynamic_bitset<> p (_input->n_ports().n_audio ());
+               if (string_is_affirmative (prop->value ())) {
+                       p.set ();
+               }                       
+               set_phase_invert (p);
        }
 
        if ((prop = node.property (X_("denormal-protection"))) != 0) {
@@ -2038,7 +2071,7 @@ Route::_set_state_2X (const XMLNode& node, int version)
 
        if ((prop = node.property (X_("order-keys"))) != 0) {
 
-               long n;
+               int32_t n;
 
                string::size_type colon, equal;
                string remaining = prop->value();
@@ -2049,7 +2082,7 @@ Route::_set_state_2X (const XMLNode& node, int version)
                                error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
                                        << endmsg;
                        } else {
-                               if (sscanf (remaining.substr (equal+1).c_str(), "%ld", &n) != 1) {
+                               if (sscanf (remaining.substr (equal+1).c_str(), "%d", &n) != 1) {
                                        error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
                                                << endmsg;
                                } else {
@@ -2588,7 +2621,7 @@ Route::direct_feeds (boost::shared_ptr<Route> other, bool* only_send)
 void
 Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors)
 {
-       nframes_t now = _session.transport_frame();
+       framepos_t now = _session.transport_frame();
 
        {
                Glib::RWLock::ReaderLock lm (_processor_lock);
@@ -2597,11 +2630,14 @@ Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool c
                        automation_snapshot (now, true);
                }
 
+                Automatable::transport_stopped (now);
+
                for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
 
                        if (Config->get_plugins_stop_with_transport() && can_flush_processors) {
                                (*i)->deactivate ();
                                (*i)->activate ();
+                                (*i)->flush ();
                        }
 
                        (*i)->transport_stopped (now);
@@ -2616,6 +2652,8 @@ Route::input_change_handler (IOChange change, void * /*src*/)
 {
        if ((change & ConfigurationChanged)) {
                configure_processors (0);
+               _phase_invert.resize (_input->n_ports().n_audio ());
+               io_changed (); /* EMIT SIGNAL */
        }
 }
 
@@ -2792,8 +2830,7 @@ Route::flush_processors ()
        Glib::RWLock::ReaderLock lm (_processor_lock);
 
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
-               (*i)->deactivate ();
-               (*i)->activate ();
+                (*i)->flush ();
        }
 }
 
@@ -2990,7 +3027,7 @@ Route::SoloControllable::SoloControllable (std::string name, Route& r)
 }
 
 void
-Route::SoloControllable::set_value (float val)
+Route::SoloControllable::set_value (double val)
 {
        bool bval = ((val >= 0.5f) ? true: false);
 # if 0
@@ -3009,7 +3046,7 @@ Route::SoloControllable::set_value (float val)
 #endif
 }
 
-float
+double
 Route::SoloControllable::get_value (void) const
 {
        if (Config->get_solo_control_is_listen_control()) {
@@ -3029,7 +3066,7 @@ Route::MuteControllable::MuteControllable (std::string name, Route& r)
 }
 
 void
-Route::MuteControllable::set_value (float val)
+Route::MuteControllable::set_value (double val)
 {
        bool bval = ((val >= 0.5f) ? true: false);
 # if 0
@@ -3043,7 +3080,7 @@ Route::MuteControllable::set_value (float val)
 #endif
 }
 
-float
+double
 Route::MuteControllable::get_value (void) const
 {
        return route.muted() ? 1.0f : 0.0f;
@@ -3195,25 +3232,39 @@ Route::internal_send_for (boost::shared_ptr<const Route> target) const
        return boost::shared_ptr<Send>();
 }
 
+/** @param c Audio channel index.
+ *  @param yn true to invert phase, otherwise false.
+ */
 void
-Route::set_phase_invert (bool yn)
+Route::set_phase_invert (uint32_t c, bool yn)
 {
-       if (_phase_invert != yn) {
-                if (yn) {
-                        _phase_invert = 0xffff; // XXX all channels
-                } else {
-                        _phase_invert = 0; // XXX no channels
-                }
+       if (_phase_invert[c] != yn) {
+               _phase_invert[c] = yn;
+               phase_invert_changed (); /* EMIT SIGNAL */
+                _session.set_dirty ();
+       }
+}
 
+void
+Route::set_phase_invert (boost::dynamic_bitset<> p)
+{
+       if (_phase_invert != p) {
+               _phase_invert = p;
                phase_invert_changed (); /* EMIT SIGNAL */
                 _session.set_dirty ();
        }
 }
 
 bool
+Route::phase_invert (uint32_t c) const
+{
+       return _phase_invert[c];
+}
+
+boost::dynamic_bitset<>
 Route::phase_invert () const
 {
-       return _phase_invert != 0;
+       return _phase_invert;
 }
 
 void
@@ -3377,3 +3428,4 @@ Route::set_processor_positions ()
                }
        }
 }
+