X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fautomation_list.cc;h=cb09786c649f448b20ce948c66d0427ef74bbc01;hb=5fa05b403ca21a6573d07b921dc14f0769dc9fc7;hp=f456ac210b9590164bec730f1c312ac00ade3fb5;hpb=36e32e564126e4587e3c2bee829c58876e65d285;p=ardour.git diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc index f456ac210b..cb09786c64 100644 --- a/libs/ardour/automation_list.cc +++ b/libs/ardour/automation_list.cc @@ -24,7 +24,7 @@ #include #include #include "ardour/automation_list.h" -#include "ardour/beats_frames_converter.h" +#include "ardour/beats_samples_converter.h" #include "ardour/event_type_map.h" #include "ardour/parameter_descriptor.h" #include "ardour/parameter_types.h" @@ -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 () { @@ -277,7 +307,7 @@ AutomationList::thaw () } bool -AutomationList::paste (const ControlList& alist, double pos, DoubleBeatsFramesConverter const& bfc) +AutomationList::paste (const ControlList& alist, double pos, DoubleBeatsSamplesConverter const& bfc) { AutomationType src_type = (AutomationType)alist.parameter().type(); AutomationType dst_type = (AutomationType)_parameter.type(); @@ -285,13 +315,13 @@ AutomationList::paste (const ControlList& alist, double pos, DoubleBeatsFramesCo if (parameter_is_midi (src_type) == parameter_is_midi (dst_type)) { return ControlList::paste (alist, pos); } - bool to_frame = parameter_is_midi (src_type); + bool to_sample = parameter_is_midi (src_type); ControlList cl (alist); cl.clear (); for (const_iterator i = alist.begin ();i != alist.end (); ++i) { double when = (*i)->when; - if (to_frame) { + if (to_sample) { when = bfc.to ((*i)->when); } else { when = bfc.from ((*i)->when); @@ -310,20 +340,19 @@ 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 save_auto_state, 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()); root->set_property ("interpolation-style", _interpolation); - if (full) { + if (save_auto_state) { /* never serialize state with Write enabled - too dangerous for the user's data */ @@ -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())) ); } -