X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fautomation_list.cc;h=a081418017940f72ffe61d6926e3c8fd236a59e3;hb=1545c426d9e3bc0411f3b5532c0c5a9eb09394c8;hp=f456ac210b9590164bec730f1c312ac00ade3fb5;hpb=36e32e564126e4587e3c2bee829c58876e65d285;p=ardour.git diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc index f456ac210b..a081418017 100644 --- a/libs/ardour/automation_list.cc +++ b/libs/ardour/automation_list.cc @@ -60,6 +60,7 @@ AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::Param { _state = Off; g_atomic_int_set (&_touching, 0); + _interpolation = default_interpolation (); create_curve_if_necessary(); @@ -73,6 +74,7 @@ AutomationList::AutomationList (const Evoral::Parameter& id) { _state = Off; g_atomic_int_set (&_touching, 0); + _interpolation = default_interpolation (); create_curve_if_necessary(); @@ -115,6 +117,7 @@ AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id) , _before (0) { g_atomic_int_set (&_touching, 0); + _interpolation = default_interpolation (); _state = Off; set_state (node, Stateful::loading_state_version); @@ -158,20 +161,22 @@ AutomationList::create_curve_if_necessary() default: break; } + + WritePassStarted.connect_same_thread (_writepass_connection, boost::bind (&AutomationList::snapshot_history, this, false)); } AutomationList& AutomationList::operator= (const AutomationList& other) { if (this != &other) { - - + ControlList::freeze (); + /* ControlList::operator= calls copy_events() which calls + * mark_dirty() and maybe_signal_changed() + */ ControlList::operator= (other); _state = other._state; _touching = other._touching; - - mark_dirty (); - maybe_signal_changed (); + ControlList::thaw (); } return *this; @@ -187,30 +192,54 @@ AutomationList::maybe_signal_changed () } } +AutoState +AutomationList::automation_state() const +{ + Glib::Threads::RWLock::ReaderLock lm (Evoral::ControlList::_lock); + return _state; +} + void AutomationList::set_automation_state (AutoState s) { - if (s != _state) { + { + Glib::Threads::RWLock::ReaderLock lm (Evoral::ControlList::_lock); + + if (s == _state) { + return; + } _state = s; - delete _before; if (s == Write && _desc.toggled) { - _before = &get_state (); - } else { - _before = 0; + snapshot_history (true); } - automation_state_changed (s); /* EMIT SIGNAL */ } + + automation_state_changed (s); /* EMIT SIGNAL */ +} + +Evoral::ControlList::InterpolationStyle +AutomationList::default_interpolation () const +{ + switch (_parameter.type()) { + case GainAutomation: + case BusSendLevel: + case EnvelopeAutomation: + return ControlList::Exponential; + break; + case TrimAutomation: + return ControlList::Logarithmic; + break; + default: + break; + } + /* based on Evoral::ParameterDescriptor log,toggle,.. */ + return ControlList::default_interpolation (); } void AutomationList::start_write_pass (double when) { - delete _before; - if (in_new_write_pass ()) { - _before = &get_state (); - } else { - _before = 0; - } + snapshot_history (true); ControlList::start_write_pass (when); } @@ -223,15 +252,15 @@ AutomationList::write_pass_finished (double when, double thinning_factor) void AutomationList::start_touch (double when) { - if (_state == Touch) { + if (_state == Touch) { start_write_pass (when); - } + } g_atomic_int_set (&_touching, 1); } void -AutomationList::stop_touch (bool mark, double) +AutomationList::stop_touch (double) { if (g_atomic_int_get (&_touching) == 0) { /* this touch has already been stopped (probably by Automatable::transport_stopped), @@ -241,16 +270,6 @@ AutomationList::stop_touch (bool mark, double) } g_atomic_int_set (&_touching, 0); - - if (_state == Touch) { - - if (mark) { - - /* XXX need to mark the last added point with the - * current time - */ - } - } } /* _before may be owned by the undo stack, @@ -265,6 +284,17 @@ AutomationList::clear_history () _before = 0; } +void +AutomationList::snapshot_history (bool need_lock) +{ + if (!in_new_write_pass ()) { + return; + } + delete _before; + _before = &state (true, need_lock); +} + + void AutomationList::thaw () { @@ -310,14 +340,13 @@ AutomationList::memento_command (XMLNode* before, XMLNode* after) XMLNode& AutomationList::get_state () { - return state (true); + return state (true, true); } XMLNode& -AutomationList::state (bool full) +AutomationList::state (bool full, bool need_lock) { XMLNode* root = new XMLNode (X_("AutomationList")); - LocaleGuard lg; root->set_property ("automation-id", EventTypeMap::instance().to_symbol(_parameter)); root->set_property ("id", id()); @@ -342,18 +371,22 @@ AutomationList::state (bool full) } if (!_events.empty()) { - root->add_child_nocopy (serialize_events()); + root->add_child_nocopy (serialize_events (need_lock)); } return *root; } XMLNode& -AutomationList::serialize_events () +AutomationList::serialize_events (bool need_lock) { XMLNode* node = new XMLNode (X_("events")); stringstream str; + Glib::Threads::RWLock::ReaderLock lm (Evoral::ControlList::_lock, Glib::Threads::NOT_LOCK); + if (need_lock) { + lm.acquire (); + } for (iterator xx = _events.begin(); xx != _events.end(); ++xx) { str << PBD::to_string ((*xx)->when); str << ' '; @@ -405,6 +438,7 @@ AutomationList::deserialize_events (const XMLNode& node) ok = false; break; } + y = std::min ((double)_desc.upper, std::max ((double)_desc.lower, y)); fast_simple_add (x, y); } @@ -424,7 +458,6 @@ AutomationList::deserialize_events (const XMLNode& node) int AutomationList::set_state (const XMLNode& node, int version) { - LocaleGuard lg; XMLNodeList nlist = node.children(); XMLNode* nsos; XMLNodeIterator niter; @@ -463,6 +496,7 @@ AutomationList::set_state (const XMLNode& node, int version) continue; } + y = std::min ((double)_desc.upper, std::max ((double)_desc.lower, y)); fast_simple_add (x, y); } @@ -489,7 +523,7 @@ AutomationList::set_state (const XMLNode& node, int version) } if (!node.get_property (X_("interpolation-style"), _interpolation)) { - _interpolation = Linear; + _interpolation = default_interpolation (); } if (node.get_property (X_("state"), _state)) { @@ -541,4 +575,3 @@ AutomationListProperty::clone () const boost::shared_ptr (new AutomationList (*this->_current.get())) ); } -