summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/automation_controller.cc15
-rw-r--r--libs/ardour/ardour/automation_control.h2
-rw-r--r--libs/ardour/ardour/automation_list.h6
-rw-r--r--libs/ardour/automatable.cc7
-rw-r--r--libs/ardour/automation_control.cc23
-rw-r--r--libs/ardour/automation_list.cc24
-rw-r--r--libs/ardour/route.cc10
-rw-r--r--libs/evoral/evoral/ControlList.hpp1
8 files changed, 70 insertions, 18 deletions
diff --git a/gtk2_ardour/automation_controller.cc b/gtk2_ardour/automation_controller.cc
index 1bce94dca2..691e0f3b58 100644
--- a/gtk2_ardour/automation_controller.cc
+++ b/gtk2_ardour/automation_controller.cc
@@ -196,7 +196,22 @@ void
AutomationController::toggled ()
{
ArdourButton* but = dynamic_cast<ArdourButton*>(_widget);
+ const AutoState as = _controllable->automation_state ();
+
+ const bool to_list = _controllable->list () && _controllable->session().transport_rolling () && (as == Touch || as == Write);
+
if (but) {
+ if (_controllable->session().transport_rolling()) {
+ if (_controllable->automation_state() == Touch && _controllable->list()->in_new_write_pass ()) {
+ _controllable->alist()->start_write_pass ( _controllable->session().audible_frame());
+ }
+ if (_controllable->list()) {
+ _controllable->list()->set_in_write_pass(true, false, _controllable->session().audible_frame());
+ }
+ }
+
+ _controllable->set_double (!but->get_active (), _controllable->session ().transport_frame (), to_list);
+
const bool was_active = _controllable->get_value() >= 0.5;
if (was_active && but->get_active()) {
_adjustment->set_value(0.0);
diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h
index 5d73e4aef9..c634e3474a 100644
--- a/libs/ardour/ardour/automation_control.h
+++ b/libs/ardour/ardour/automation_control.h
@@ -95,13 +95,13 @@ public:
const ParameterDescriptor& desc() const { return _desc; }
const ARDOUR::Session& session() const { return _session; }
+ void commit_transaction ();
protected:
ARDOUR::Session& _session;
const ParameterDescriptor _desc;
- XMLNode* _before; //used for undo of touch start/stop pairs.
};
diff --git a/libs/ardour/ardour/automation_list.h b/libs/ardour/ardour/automation_list.h
index bc47f2fe06..67ee6234bb 100644
--- a/libs/ardour/ardour/automation_list.h
+++ b/libs/ardour/ardour/automation_list.h
@@ -97,6 +97,9 @@ class LIBARDOUR_API AutomationList : public PBD::StatefulDestructible, public Ev
static PBD::Signal1<void,AutomationList*> AutomationListCreated;
+ void start_write_pass (double when);
+ void write_pass_finished (double when, double thinning_factor=0.0);
+
void start_touch (double when);
void stop_touch (bool mark, double when);
bool touching() const { return g_atomic_int_get (const_cast<gint*>(&_touching)); }
@@ -110,6 +113,7 @@ class LIBARDOUR_API AutomationList : public PBD::StatefulDestructible, public Ev
bool operator!= (const AutomationList &) const;
+ XMLNode* before () { return _before; }
private:
void create_curve_if_necessary ();
int deserialize_events (const XMLNode&);
@@ -121,6 +125,8 @@ class LIBARDOUR_API AutomationList : public PBD::StatefulDestructible, public Ev
gint _touching;
bool operator== (const AutomationList&) const { /* not called */ abort(); return false; }
+ XMLNode* _before; //used for undo of touch start/stop pairs.
+
};
} // namespace
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index 0b316890bc..1c72f202b2 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -365,7 +365,7 @@ Automatable::transport_located (framepos_t now)
boost::shared_ptr<AutomationList> l
= boost::dynamic_pointer_cast<AutomationList>(c->list());
- if (l) {
+ if (l && l->automation_state () == Write) {
l->start_write_pass (now);
}
}
@@ -394,7 +394,12 @@ Automatable::transport_stopped (framepos_t now)
when the transport is re-started, a touch will magically
be happening without it ever have being started in the usual way.
*/
+ const bool list_did_write = !l->in_new_write_pass ();
+
l->stop_touch (true, now);
+ if (list_did_write) {
+ c->commit_transaction ();
+ }
l->write_pass_finished (now, Config->get_automation_thinning_factor());
if (l->automation_playback()) {
diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc
index 26ea53cbd2..0e2355e708 100644
--- a/libs/ardour/automation_control.cc
+++ b/libs/ardour/automation_control.cc
@@ -88,8 +88,6 @@ AutomationControl::set_automation_state (AutoState as)
}
if (as == Write) {
- /* get state for undo */
- _before = &alist ()->get_state ();
AutomationWatch::instance().add_automation_watch (shared_from_this());
} else if (as == Touch) {
if (!touching()) {
@@ -127,7 +125,6 @@ AutomationControl::start_touch(double when)
if (alist()->automation_state() == Touch) {
/* subtle. aligns the user value with the playback */
set_value (get_value ());
- _before = &alist ()->get_state ();
alist()->start_touch (when);
if (!_desc.toggled) {
AutomationWatch::instance().add_automation_watch (shared_from_this());
@@ -144,25 +141,25 @@ AutomationControl::stop_touch(bool mark, double when)
if (touching()) {
set_touching (false);
- if (alist()->automation_state() == Write) {
- _session.begin_reversible_command (string_compose (_("write %1 automation"), name ()));
- _session.add_command (new MementoCommand<AutomationList> (*alist ().get (), _before, &alist ()->get_state ()));
- _session.commit_reversible_command ();
- }
-
if (alist()->automation_state() == Touch) {
alist()->stop_touch (mark, when);
if (!_desc.toggled) {
AutomationWatch::instance().remove_automation_watch (shared_from_this());
- }
- _session.begin_reversible_command (string_compose (_("touch %1 automation"), name ()));
- _session.add_command (new MementoCommand<AutomationList> (*alist ().get (), _before, &alist ()->get_state ()));
- _session.commit_reversible_command ();
+ }
}
}
}
+void
+AutomationControl::commit_transaction ()
+{
+ if (alist ()->before ()) {
+ _session.begin_reversible_command (string_compose (_("record %1 automation"), name ()));
+ _session.commit_reversible_command (new MementoCommand<AutomationList> (*alist ().get (), alist ()->before (), &alist ()->get_state ()));
+ }
+}
+
double
AutomationControl::internal_to_interface (double val) const
{
diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc
index 91609f6acb..afff85c1f8 100644
--- a/libs/ardour/automation_list.cc
+++ b/libs/ardour/automation_list.cc
@@ -50,6 +50,7 @@ static void dumpit (const AutomationList& al, string prefix = "")
#endif
AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc)
: ControlList(id, desc)
+ , _before (0)
{
_state = Off;
_style = Absolute;
@@ -63,6 +64,7 @@ AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::Param
AutomationList::AutomationList (const Evoral::Parameter& id)
: ControlList(id, ARDOUR::ParameterDescriptor(id))
+ , _before (0)
{
_state = Off;
_style = Absolute;
@@ -77,6 +79,7 @@ AutomationList::AutomationList (const Evoral::Parameter& id)
AutomationList::AutomationList (const AutomationList& other)
: StatefulDestructible()
, ControlList(other)
+ , _before (0)
{
_style = other._style;
_state = other._state;
@@ -90,6 +93,7 @@ AutomationList::AutomationList (const AutomationList& other)
AutomationList::AutomationList (const AutomationList& other, double start, double end)
: ControlList(other, start, end)
+ , _before (0)
{
_style = other._style;
_state = other._state;
@@ -106,6 +110,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
*/
AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id)
: ControlList(id, ARDOUR::ParameterDescriptor(id))
+ , _before (0)
{
g_atomic_int_set (&_touching, 0);
_state = Off;
@@ -186,6 +191,9 @@ AutomationList::set_automation_state (AutoState s)
{
if (s != _state) {
_state = s;
+ if (s == Write) {
+ _before = &get_state ();
+ }
automation_state_changed (s); /* EMIT SIGNAL */
}
}
@@ -200,6 +208,22 @@ AutomationList::set_automation_style (AutoStyle s)
}
void
+AutomationList::start_write_pass (double when)
+{
+ if (in_new_write_pass ()) {
+ _before = &get_state ();
+ }
+ ControlList::start_write_pass (when);
+}
+
+void
+AutomationList::write_pass_finished (double when, double thinning_factor)
+{
+ ControlList::write_pass_finished (when, thinning_factor);
+ _before = 0;
+}
+
+void
AutomationList::start_touch (double when)
{
if (_state == Touch) {
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index cb3f0d48c9..adbfefb829 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -3904,11 +3904,15 @@ Route::MuteControllable::set_superficial_value(bool muted)
as currently MuteControllable can't be touching.
bool to_list = _list && ((AutomationList*)_list.get())->automation_write();
*/
- const AutoState as = ((AutomationList*)_list.get())->automation_state ();
- bool to_list = _list && _session.transport_rolling () && (as == Touch || as == Write);
+ AutomationList* alist = (AutomationList*)_list.get();
+ const AutoState as = alist->automation_state ();
+ const bool to_list = _list && _session.transport_rolling () && (as == Touch || as == Write);
if (to_list) {
- _list->set_in_write_pass(true, false, _session.audible_frame ());
+ if (as == Touch && _list->in_new_write_pass ()) {
+ alist->start_write_pass (_session.audible_frame ());
+ }
+ _list->set_in_write_pass (true, false, _session.audible_frame ());
}
Control::set_double (muted, _session.transport_frame(), to_list);
diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp
index 80096b65a4..f1a4627a1c 100644
--- a/libs/evoral/evoral/ControlList.hpp
+++ b/libs/evoral/evoral/ControlList.hpp
@@ -267,6 +267,7 @@ public:
void write_pass_finished (double when, double thinning_factor=0.0);
void set_in_write_pass (bool, bool add_point = false, double when = 0.0);
bool in_write_pass () const;
+ bool in_new_write_pass () { return new_write_pass; }
/** Emitted when mark_dirty() is called on this object */
mutable PBD::Signal0<void> Dirty;