summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2010-08-19 21:09:40 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2010-08-19 21:09:40 +0000
commit7b6b75f38ff6b34de3f70e36045498f227c1727d (patch)
treed7bc76a8745daa5051b2bcce7f84910f3ad72aac
parentb6642d14ca64153b5731d1a3a79e4d00060541ca (diff)
forward port automation handling changes from 2.x, upto and including about rev 6981 (will need full testing in the 3.X context). as on 2.x, this removes real-time visual updates to automation curves during write/touch automation recording
git-svn-id: svn://localhost/ardour2/branches/3.0@7653 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/automation_controller.cc21
-rw-r--r--gtk2_ardour/gain_meter.cc4
-rw-r--r--gtk2_ardour/generic_pluginui.cc5
-rw-r--r--gtk2_ardour/panner_ui.cc26
-rw-r--r--gtk2_ardour/panner_ui.h5
-rw-r--r--libs/ardour/amp.cc2
-rw-r--r--libs/ardour/ardour/amp.h2
-rw-r--r--libs/ardour/ardour/automatable.h2
-rw-r--r--libs/ardour/ardour/automation_control.h10
-rw-r--r--libs/ardour/ardour/automation_list.h20
-rw-r--r--libs/ardour/ardour/delivery.h7
-rw-r--r--libs/ardour/ardour/internal_return.h2
-rw-r--r--libs/ardour/ardour/internal_send.h2
-rw-r--r--libs/ardour/ardour/meter.h2
-rw-r--r--libs/ardour/ardour/monitor_processor.h2
-rw-r--r--libs/ardour/ardour/panner.h2
-rw-r--r--libs/ardour/ardour/plugin_insert.h2
-rw-r--r--libs/ardour/ardour/port_insert.h2
-rw-r--r--libs/ardour/ardour/processor.h4
-rw-r--r--libs/ardour/ardour/return.h2
-rw-r--r--libs/ardour/ardour/send.h2
-rw-r--r--libs/ardour/automatable.cc27
-rw-r--r--libs/ardour/automation_list.cc60
-rw-r--r--libs/ardour/delivery.cc31
-rw-r--r--libs/ardour/internal_return.cc2
-rw-r--r--libs/ardour/internal_send.cc2
-rw-r--r--libs/ardour/meter.cc2
-rw-r--r--libs/ardour/midi_track.cc3
-rw-r--r--libs/ardour/monitor_processor.cc2
-rw-r--r--libs/ardour/panner.cc2
-rw-r--r--libs/ardour/plugin_insert.cc2
-rw-r--r--libs/ardour/port_insert.cc2
-rw-r--r--libs/ardour/return.cc2
-rw-r--r--libs/ardour/route.cc4
-rw-r--r--libs/ardour/send.cc2
-rw-r--r--libs/evoral/evoral/ControlList.hpp57
-rw-r--r--libs/evoral/src/ControlList.cpp378
37 files changed, 426 insertions, 278 deletions
diff --git a/gtk2_ardour/automation_controller.cc b/gtk2_ardour/automation_controller.cc
index f63f2ed70c..aa23cb2601 100644
--- a/gtk2_ardour/automation_controller.cc
+++ b/gtk2_ardour/automation_controller.cc
@@ -19,12 +19,16 @@
*/
#include <iomanip>
+
#include "pbd/error.h"
+
#include "ardour/automation_list.h"
#include "ardour/automation_control.h"
#include "ardour/event_type_map.h"
#include "ardour/automatable.h"
#include "ardour/panner.h"
+#include "ardour/session.h"
+
#include "ardour_ui.h"
#include "utils.h"
#include "automation_controller.h"
@@ -121,13 +125,24 @@ AutomationController::value_adjusted()
void
AutomationController::start_touch()
{
- _controllable->start_touch();
+ _controllable->start_touch (_controllable->session().transport_frame());
}
void
-AutomationController::end_touch()
+AutomationController::end_touch ()
{
- _controllable->stop_touch();
+ if (_controllable->automation_state() == Touch) {
+
+ bool mark = false;
+ double when = 0;
+
+ if (_controllable->session().transport_rolling()) {
+ mark = true;
+ when = _controllable->session().transport_frame();
+ }
+
+ _controllable->stop_touch (mark, when);
+ }
}
void
diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc
index b8a6ad2df9..9ae59f63e6 100644
--- a/gtk2_ardour/gain_meter.cc
+++ b/gtk2_ardour/gain_meter.cc
@@ -593,14 +593,14 @@ GainMeterBase::meter_point_clicked ()
gint
GainMeterBase::start_gain_touch (GdkEventButton*)
{
- _amp->gain_control()->start_touch ();
+ _amp->gain_control()->start_touch (_amp->session().transport_frame());
return FALSE;
}
gint
GainMeterBase::end_gain_touch (GdkEventButton*)
{
- _amp->gain_control()->stop_touch ();
+ _amp->gain_control()->stop_touch (false, _amp->session().transport_frame());
return FALSE;
}
diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc
index 40f8e16ef8..5e14ecf034 100644
--- a/gtk2_ardour/generic_pluginui.cc
+++ b/gtk2_ardour/generic_pluginui.cc
@@ -45,6 +45,7 @@
#ifdef HAVE_SLV2
#include "ardour/lv2_plugin.h"
#endif
+#include "ardour/session.h"
#include <lrdf.h>
@@ -603,13 +604,13 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
void
GenericPluginUI::start_touch (GenericPluginUI::ControlUI* cui)
{
- cui->control->start_touch ();
+ cui->control->start_touch (cui->control->session().transport_frame());
}
void
GenericPluginUI::stop_touch (GenericPluginUI::ControlUI* cui)
{
- cui->control->stop_touch ();
+ cui->control->stop_touch (false, cui->control->session().transport_frame());
}
void
diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc
index 69387ad3a2..263a8ec518 100644
--- a/gtk2_ardour/panner_ui.cc
+++ b/gtk2_ardour/panner_ui.cc
@@ -405,8 +405,10 @@ PannerUI::setup_pan ()
boost::shared_ptr<AutomationControl> ac = _panner->pan_control (asz);
if (asz) {
- bc->StartGesture.connect (sigc::mem_fun (*ac, &AutomationControl::start_touch));
- bc->StopGesture.connect (sigc::mem_fun (*ac, &AutomationControl::stop_touch));
+ bc->StartGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
+ boost::weak_ptr<AutomationControl> (ac)));
+ bc->StopGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),
+ boost::weak_ptr<AutomationControl>(ac)));
}
char buf[64];
@@ -459,6 +461,26 @@ PannerUI::setup_pan ()
}
}
+void
+PannerUI::start_touch (boost::weak_ptr<AutomationControl> wac)
+{
+ boost::shared_ptr<AutomationControl> ac = wac.lock();
+ if (!ac) {
+ return;
+ }
+ ac->start_touch (ac->session().transport_frame());
+}
+
+void
+PannerUI::stop_touch (boost::weak_ptr<AutomationControl> wac)
+{
+ boost::shared_ptr<AutomationControl> ac = wac.lock();
+ if (!ac) {
+ return;
+ }
+ ac->stop_touch (false, ac->session().transport_frame());
+}
+
bool
PannerUI::pan_button_event (GdkEventButton* ev, uint32_t which)
{
diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h
index 4ed8767fb1..a1558981f6 100644
--- a/gtk2_ardour/panner_ui.h
+++ b/gtk2_ardour/panner_ui.h
@@ -45,7 +45,9 @@ namespace ARDOUR {
class Session;
class Panner;
class Delivery;
+ class AutomationControl;
}
+
namespace Gtkmm2ext {
class FastMeter;
}
@@ -167,6 +169,9 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
std::string astyle_string (ARDOUR::AutoStyle);
std::string short_astyle_string (ARDOUR::AutoStyle);
std::string _astyle_string (ARDOUR::AutoStyle, bool);
+
+ void start_touch (boost::weak_ptr<ARDOUR::AutomationControl>);
+ void stop_touch (boost::weak_ptr<ARDOUR::AutomationControl>);
};
#endif /* __ardour_gtk_panner_ui_h__ */
diff --git a/libs/ardour/amp.cc b/libs/ardour/amp.cc
index f2448c06aa..6002a2549d 100644
--- a/libs/ardour/amp.cc
+++ b/libs/ardour/amp.cc
@@ -70,7 +70,7 @@ Amp::configure_io (ChanCount in, ChanCount out)
}
void
-Amp::run (BufferSet& bufs, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t nframes, bool)
+Amp::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, nframes_t nframes, bool)
{
if (!_active && !_pending_active) {
return;
diff --git a/libs/ardour/ardour/amp.h b/libs/ardour/ardour/amp.h
index 52aceaf85f..011fef13c0 100644
--- a/libs/ardour/ardour/amp.h
+++ b/libs/ardour/ardour/amp.h
@@ -43,7 +43,7 @@ public:
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
- void run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool);
+ void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool);
bool apply_gain() const { return _apply_gain; }
void apply_gain(bool yn) { _apply_gain = yn; }
diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h
index e0fe38e67e..469025c693 100644
--- a/libs/ardour/ardour/automatable.h
+++ b/libs/ardour/ardour/automatable.h
@@ -61,7 +61,7 @@ public:
void clear_controls ();
virtual void automation_snapshot(nframes_t now, bool force);
- virtual void transport_stopped (sframes_t now);
+ virtual void transport_stopped (framepos_t now);
virtual std::string describe_parameter(Evoral::Parameter param);
diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h
index 2d22b9e661..006e74346f 100644
--- a/libs/ardour/ardour/automation_control.h
+++ b/libs/ardour/ardour/automation_control.h
@@ -64,14 +64,14 @@ public:
return ((ARDOUR::AutomationList*)_list.get())->set_automation_state(as);
}
- inline void start_touch() {
+ inline void start_touch(double when) {
set_touching (true);
- return ((ARDOUR::AutomationList*)_list.get())->start_touch();
+ return ((ARDOUR::AutomationList*)_list.get())->start_touch(when);
}
- inline void stop_touch() {
+ inline void stop_touch(bool mark, double when) {
set_touching (false);
- return ((ARDOUR::AutomationList*)_list.get())->stop_touch();
+ return ((ARDOUR::AutomationList*)_list.get())->stop_touch(mark, when);
}
/** Set the value and do the right thing based on automation state
@@ -86,6 +86,8 @@ public:
double lower() const { return parameter().min(); }
double upper() const { return parameter().max(); }
+ const ARDOUR::Session& session() const { return _session; }
+
protected:
ARDOUR::Session& _session;
};
diff --git a/libs/ardour/ardour/automation_list.h b/libs/ardour/ardour/automation_list.h
index acb071cca7..9a5420e74b 100644
--- a/libs/ardour/ardour/automation_list.h
+++ b/libs/ardour/ardour/automation_list.h
@@ -61,19 +61,21 @@ class AutomationList : public PBD::StatefulDestructible, public Evoral::ControlL
PBD::Signal0<void> automation_style_changed;
bool automation_playback() const {
- return (_state & Play) || ((_state & Touch) && !_touching);
+ return (_state & Play) || ((_state & Touch) && !touching());
}
bool automation_write () const {
- return (_state & Write) || ((_state & Touch) && _touching);
- }
+ return ((_state & Write) || ((_state & Touch) && touching()));
+ }
PBD::Signal0<void> StateChanged;
static PBD::Signal1<void,AutomationList*> AutomationListCreated;
- void start_touch ();
- void stop_touch ();
- bool touching() const { return _touching; }
+ void start_touch (double when);
+ void stop_touch (bool mark, double when);
+ bool touching() const { return g_atomic_int_get (&_touching); }
+ bool writing() const { return _state == Write; }
+ bool touch_enabled() const { return _state == Touch; }
XMLNode& get_state ();
int set_state (const XMLNode &, int version);
@@ -86,9 +88,9 @@ class AutomationList : public PBD::StatefulDestructible, public Evoral::ControlL
void maybe_signal_changed ();
- AutoState _state;
- AutoStyle _style;
- bool _touching;
+ AutoState _state;
+ AutoStyle _style;
+ gint _touching;
};
} // namespace
diff --git a/libs/ardour/ardour/delivery.h b/libs/ardour/ardour/delivery.h
index ec808a9820..f7cbc29af7 100644
--- a/libs/ardour/ardour/delivery.h
+++ b/libs/ardour/ardour/delivery.h
@@ -71,10 +71,7 @@ public:
/* supplemental method used with MIDI */
void flush_buffers (nframes_t nframes, nframes64_t time);
- void transport_stopped ();
-
void no_outs_cuz_we_no_monitor(bool);
-
void cycle_start (nframes_t);
void increment_output_offset (nframes_t);
void transport_stopped (sframes_t frame);
@@ -100,8 +97,8 @@ public:
void allow_pan_reset ();
uint32_t pans_required() const { return _configured_input.n_audio(); }
- void start_pan_touch (uint32_t which);
- void end_pan_touch (uint32_t which);
+ void start_pan_touch (uint32_t which, double when);
+ void end_pan_touch (uint32_t which, bool mark, double when);
protected:
Role _role;
diff --git a/libs/ardour/ardour/internal_return.h b/libs/ardour/ardour/internal_return.h
index 2b8e618337..75de954752 100644
--- a/libs/ardour/ardour/internal_return.h
+++ b/libs/ardour/ardour/internal_return.h
@@ -38,7 +38,7 @@ class InternalReturn : public Return
XMLNode& get_state(void);
int set_state(const XMLNode&, int version);
- void run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool);
+ void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool);
bool configure_io (ChanCount in, ChanCount out);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
int set_block_size (nframes_t);
diff --git a/libs/ardour/ardour/internal_send.h b/libs/ardour/ardour/internal_send.h
index 0764982a93..d2a769982c 100644
--- a/libs/ardour/ardour/internal_send.h
+++ b/libs/ardour/ardour/internal_send.h
@@ -39,7 +39,7 @@ class InternalSend : public Send
XMLNode& get_state(void);
int set_state(const XMLNode& node, int version);
- void run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool);
+ void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool);
bool feeds (boost::shared_ptr<Route> other) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
diff --git a/libs/ardour/ardour/meter.h b/libs/ardour/ardour/meter.h
index 80adcd4156..dad86d5185 100644
--- a/libs/ardour/ardour/meter.h
+++ b/libs/ardour/ardour/meter.h
@@ -68,7 +68,7 @@ public:
void reflect_inputs (const ChanCount& in);
/** Compute peaks */
- void run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool);
+ void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool);
ChanCount input_streams () const { return current_meters; }
ChanCount output_streams () const { return current_meters; }
diff --git a/libs/ardour/ardour/monitor_processor.h b/libs/ardour/ardour/monitor_processor.h
index e453551b0b..0f23d7029f 100644
--- a/libs/ardour/ardour/monitor_processor.h
+++ b/libs/ardour/ardour/monitor_processor.h
@@ -110,7 +110,7 @@ class MonitorProcessor : public Processor
bool display_to_user() const;
- void run (BufferSet& /*bufs*/, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t /*nframes*/, bool /*result_required*/);
+ void run (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framepos_t /*end_frame*/, nframes_t /*nframes*/, bool /*result_required*/);
XMLNode& state (bool full);
int set_state (const XMLNode&, int /* version */);
diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h
index 62512f6181..087471032d 100644
--- a/libs/ardour/ardour/panner.h
+++ b/libs/ardour/ardour/panner.h
@@ -228,7 +228,7 @@ public:
bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) const { return true; };
/// The fundamental Panner function
- void run (BufferSet& src, BufferSet& dest, sframes_t start_frame, sframes_t end_frames, nframes_t nframes);
+ void run (BufferSet& src, BufferSet& dest, framepos_t start_frame, framepos_t end_frames, nframes_t nframes);
bool bypassed() const { return _bypassed; }
void set_bypassed (bool yn);
diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h
index e4487eb6c0..1fcce61f39 100644
--- a/libs/ardour/ardour/plugin_insert.h
+++ b/libs/ardour/ardour/plugin_insert.h
@@ -52,7 +52,7 @@ class PluginInsert : public Processor
XMLNode& get_state(void);
int set_state(const XMLNode&, int version);
- void run (BufferSet& in, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool);
+ void run (BufferSet& in, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool);
void silence (nframes_t nframes);
void activate ();
diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h
index d30edc7162..f4e20a8045 100644
--- a/libs/ardour/ardour/port_insert.h
+++ b/libs/ardour/ardour/port_insert.h
@@ -50,7 +50,7 @@ class PortInsert : public IOProcessor
XMLNode& get_state(void);
int set_state (const XMLNode&, int version);
- void run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool);
+ void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool);
nframes_t signal_latency() const;
diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h
index 1e65bc58bd..55e0cfb2d6 100644
--- a/libs/ardour/ardour/processor.h
+++ b/libs/ardour/ardour/processor.h
@@ -63,15 +63,13 @@ class Processor : public SessionObject, public Automatable, public Latent
virtual nframes_t signal_latency() const { return 0; }
- virtual void transport_stopped (sframes_t /*frame*/) {}
-
virtual int set_block_size (nframes_t /*nframes*/) { return 0; }
virtual bool requires_fixed_sized_buffers() const { return false; }
/** @param result_required true if, on return from this method, bufs is required to contain valid data;
* if false, the method need not bother writing to bufs if it doesn't want to.
*/
- virtual void run (BufferSet& /*bufs*/, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t /*nframes*/, bool result_required) {}
+ virtual void run (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framepos_t /*end_frame*/, nframes_t /*nframes*/, bool result_required) {}
virtual void silence (nframes_t /*nframes*/) {}
virtual void activate () { _pending_active = true; ActiveChanged(); }
diff --git a/libs/ardour/ardour/return.h b/libs/ardour/ardour/return.h
index 63915e5d78..2dcb6eb270 100644
--- a/libs/ardour/ardour/return.h
+++ b/libs/ardour/ardour/return.h
@@ -42,7 +42,7 @@ public:
uint32_t bit_slot() const { return _bitslot; }
- void run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool);
+ void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool);
boost::shared_ptr<Amp> amp() const { return _amp; }
boost::shared_ptr<PeakMeter> meter() const { return _meter; }
diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h
index a060363a23..af806b3c1f 100644
--- a/libs/ardour/ardour/send.h
+++ b/libs/ardour/ardour/send.h
@@ -55,7 +55,7 @@ class Send : public Delivery
uint32_t pans_required() const { return _configured_input.n_audio(); }
- void run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool);
+ void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index 5ae4e96b4e..68c42ba7b5 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -27,6 +27,7 @@
#include "pbd/error.h"
#include "pbd/enumwriter.h"
+#include "pbd/stacktrace.h"
#include "midi++/names.h"
@@ -393,7 +394,7 @@ Automatable::automation_snapshot (nframes_t now, bool force)
for (Controls::iterator i = controls().begin(); i != controls().end(); ++i) {
boost::shared_ptr<AutomationControl> c
= boost::dynamic_pointer_cast<AutomationControl>(i->second);
- if (c->automation_write()) {
+ if (_a_session.transport_rolling() && c->automation_write()) {
c->list()->rt_add (now, i->second->user_double());
}
}
@@ -403,20 +404,28 @@ Automatable::automation_snapshot (nframes_t now, bool force)
}
void
-Automatable::transport_stopped (sframes_t now)
+Automatable::transport_stopped (framepos_t now)
{
for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
boost::shared_ptr<AutomationControl> c
= boost::dynamic_pointer_cast<AutomationControl>(li->second);
- boost::shared_ptr<AutomationList> l
+ if (c) {
+ boost::shared_ptr<AutomationList> l
= boost::dynamic_pointer_cast<AutomationList>(c->list());
-
- c->list()->reposition_for_rt_add (now);
-
- if (c->automation_state() != Off) {
- c->set_value(c->list()->eval(now));
- }
+
+ if (l) {
+ l->write_pass_finished (now);
+
+ if (l->automation_playback()) {
+ c->set_value(c->list()->eval(now));
+ }
+
+ if (l->automation_state() == Write) {
+ l->set_automation_state (Touch);
+ }
+ }
+ }
}
}
diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc
index 2270b2eff7..53fdb233c6 100644
--- a/libs/ardour/automation_list.cc
+++ b/libs/ardour/automation_list.cc
@@ -53,7 +53,7 @@ AutomationList::AutomationList (Evoral::Parameter id)
{
_state = Off;
_style = Absolute;
- _touching = false;
+ g_atomic_int_set (&_touching, 0);
create_curve_if_necessary();
@@ -67,7 +67,7 @@ AutomationList::AutomationList (const AutomationList& other)
{
_style = other._style;
_state = other._state;
- _touching = other._touching;
+ g_atomic_int_set (&_touching, other.touching());
create_curve_if_necessary();
@@ -80,7 +80,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
{
_style = other._style;
_state = other._state;
- _touching = other._touching;
+ g_atomic_int_set (&_touching, other.touching());
create_curve_if_necessary();
@@ -94,7 +94,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id)
: ControlList(id)
{
- _touching = false;
+ g_atomic_int_set (&_touching, 0);
_state = Off;
_style = Absolute;
@@ -180,6 +180,12 @@ AutomationList::set_automation_state (AutoState s)
{
if (s != _state) {
_state = s;
+
+ if (_state == Write) {
+ Glib::Mutex::Lock lm (ControlList::_lock);
+ nascent.push_back (new NascentInfo (false));
+ }
+
automation_state_changed (s); /* EMIT SIGNAL */
}
}
@@ -194,17 +200,37 @@ AutomationList::set_automation_style (AutoStyle s)
}
void
-AutomationList::start_touch ()
+AutomationList::start_touch (double when)
{
- _touching = true;
- _new_value = true;
+ if (_state == Touch) {
+ Glib::Mutex::Lock lm (ControlList::_lock);
+ nascent.push_back (new NascentInfo (true, when));
+ }
+
+ g_atomic_int_set (&_touching, 1);
}
void
-AutomationList::stop_touch ()
+AutomationList::stop_touch (bool mark, double when)
{
- _touching = false;
- _new_value = false;
+ g_atomic_int_set (&_touching, 0);
+
+ if (_state == Touch) {
+ Glib::Mutex::Lock lm (ControlList::_lock);
+
+ if (mark) {
+ nascent.back()->end_time = when;
+
+ } else {
+
+ /* nascent info created in start touch but never used. just get rid of it.
+ */
+
+ NascentInfo* ninfo = nascent.back ();
+ nascent.erase (nascent.begin());
+ delete ninfo;
+ }
+ }
}
void
@@ -247,7 +273,14 @@ AutomationList::state (bool full)
root->add_property ("interpolation-style", enum_2_string (_interpolation));
if (full) {
- root->add_property ("state", auto_state_to_string (_state));
+ /* never serialize state with Write enabled - too dangerous
+ for the user's data
+ */
+ if (_state != Write) {
+ root->add_property ("state", auto_state_to_string (_state));
+ } else {
+ root->add_property ("state", auto_state_to_string (Off));
+ }
} else {
/* never save anything but Off for automation state to a template */
root->add_property ("state", auto_state_to_string (Off));
@@ -327,7 +360,6 @@ AutomationList::deserialize_events (const XMLNode& node)
error << _("automation list: cannot load coordinates from XML, all points ignored") << endmsg;
} else {
mark_dirty ();
- reposition_for_rt_add (0);
maybe_signal_changed ();
}
@@ -426,6 +458,9 @@ AutomationList::set_state (const XMLNode& node, int version)
if ((prop = node.property (X_("state"))) != 0) {
_state = string_to_auto_state (prop->value());
+ if (_state == Write) {
+ _state = Off;
+ }
} else {
_state = Off;
}
@@ -462,7 +497,6 @@ AutomationList::set_state (const XMLNode& node, int version)
freeze ();
clear ();
mark_dirty ();
- reposition_for_rt_add (0);
maybe_signal_changed ();
thaw ();
}
diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc
index d5c982c0cc..50a87eb000 100644
--- a/libs/ardour/delivery.cc
+++ b/libs/ardour/delivery.cc
@@ -221,7 +221,7 @@ Delivery::configure_io (ChanCount in, ChanCount out)
}
void
-Delivery::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool result_required)
+Delivery::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool result_required)
{
assert (_output);
@@ -418,27 +418,22 @@ Delivery::reset_panners ()
void
-Delivery::start_pan_touch (uint32_t which)
+Delivery::start_pan_touch (uint32_t which, double when)
{
if (which < _panner->npanners()) {
- _panner->pan_control(which)->start_touch();
+ _panner->pan_control(which)->start_touch(when);
}
}
void
-Delivery::end_pan_touch (uint32_t which)
+Delivery::end_pan_touch (uint32_t which, bool mark, double when)
{
if (which < _panner->npanners()) {
- _panner->pan_control(which)->stop_touch();
+ _panner->pan_control(which)->stop_touch(mark, when);
}
}
-void
-Delivery::transport_stopped (sframes_t frame)
-{
- _panner->transport_stopped (frame);
-}
void
Delivery::flush_buffers (nframes_t nframes, nframes64_t time)
@@ -453,15 +448,19 @@ Delivery::flush_buffers (nframes_t nframes, nframes64_t time)
}
void
-Delivery::transport_stopped ()
+Delivery::transport_stopped (framepos_t now)
{
- /* turn off any notes that are on */
+ Processor::transport_stopped (now);
- PortSet& ports (_output->ports());
+ _panner->transport_stopped (now);
- for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
- (*i).transport_stopped ();
- }
+ if (_output) {
+ PortSet& ports (_output->ports());
+
+ for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
+ (*i).transport_stopped ();
+ }
+ }
}
gain_t
diff --git a/libs/ardour/internal_return.cc b/libs/ardour/internal_return.cc
index e1f39b79a3..db3c68a352 100644
--- a/libs/ardour/internal_return.cc
+++ b/libs/ardour/internal_return.cc
@@ -37,7 +37,7 @@ InternalReturn::InternalReturn (Session& s)
}
void
-InternalReturn::run (BufferSet& bufs, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t nframes, bool)
+InternalReturn::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, nframes_t nframes, bool)
{
if (!_active && !_pending_active) {
return;
diff --git a/libs/ardour/internal_send.cc b/libs/ardour/internal_send.cc
index a1425e3059..9c4238b134 100644
--- a/libs/ardour/internal_send.cc
+++ b/libs/ardour/internal_send.cc
@@ -80,7 +80,7 @@ InternalSend::send_to_going_away ()
}
void
-InternalSend::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool)
+InternalSend::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool)
{
if ((!_active && !_pending_active) || !target || !_send_to) {
_meter->reset ();
diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc
index 3c53f56db4..443146cf13 100644
--- a/libs/ardour/meter.cc
+++ b/libs/ardour/meter.cc
@@ -39,7 +39,7 @@ PBD::Signal0<void> Metering::Meter;
* be set to 0.
*/
void
-PeakMeter::run (BufferSet& bufs, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t nframes, bool)
+PeakMeter::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, nframes_t nframes, bool)
{
if (!_active && !_pending_active) {
return;
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 25418ec968..f79ed520c0 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -396,12 +396,9 @@ MidiTrack::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_fram
void
MidiTrack::handle_transport_stopped (bool abort, bool did_locate, bool flush_processors)
{
-
- _main_outs->transport_stopped ();
Route::handle_transport_stopped (abort, did_locate, flush_processors);
}
-
void
MidiTrack::push_midi_input_to_step_edit_ringbuffer (nframes_t nframes)
{
diff --git a/libs/ardour/monitor_processor.cc b/libs/ardour/monitor_processor.cc
index bcdc28a4ae..8ea5e70aab 100644
--- a/libs/ardour/monitor_processor.cc
+++ b/libs/ardour/monitor_processor.cc
@@ -245,7 +245,7 @@ MonitorProcessor::state (bool full)
}
void
-MonitorProcessor::run (BufferSet& bufs, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t nframes, bool /*result_required*/)
+MonitorProcessor::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, nframes_t nframes, bool /*result_required*/)
{
uint32_t chn = 0;
gain_t target_gain;
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index c400199943..3f6b23672a 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -1489,7 +1489,7 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes
}
void
-Panner::run (BufferSet& inbufs, BufferSet& outbufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
+Panner::run (BufferSet& inbufs, BufferSet& outbufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes)
{
if (outbufs.count().n_audio() == 0) {
// Failing to deliver audio we were asked to deliver is a bug
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index 73655b24b1..d6dfc014cf 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -367,7 +367,7 @@ PluginInsert::silence (nframes_t nframes)
}
void
-PluginInsert::run (BufferSet& bufs, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t nframes, bool)
+PluginInsert::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, nframes_t nframes, bool)
{
if (_active || _pending_active) {
diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc
index 087d2577ad..20c6b127d2 100644
--- a/libs/ardour/port_insert.cc
+++ b/libs/ardour/port_insert.cc
@@ -101,7 +101,7 @@ PortInsert::latency() const
}
void
-PortInsert::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool)
+PortInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool)
{
if (_output->n_ports().n_total() == 0) {
return;
diff --git a/libs/ardour/return.cc b/libs/ardour/return.cc
index 10879d7722..d8c8dd22f8 100644
--- a/libs/ardour/return.cc
+++ b/libs/ardour/return.cc
@@ -103,7 +103,7 @@ Return::set_state (const XMLNode& node, int version)
}
void
-Return::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool)
+Return::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool)
{
if ((!_active && !_pending_active) || _input->n_ports() == ChanCount::ZERO) {
return;
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 0f9e7ba241..290d9209d9 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -2621,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);
@@ -2630,6 +2630,8 @@ 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) {
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index 4624006ca9..9d5d2398c7 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -71,7 +71,7 @@ Send::deactivate ()
}
void
-Send::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool)
+Send::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, nframes_t nframes, bool)
{
if (_output->n_ports() == ChanCount::ZERO) {
_meter->reset ();
diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp
index 28b9ba2fcd..9d3ba09ef1 100644
--- a/libs/evoral/evoral/ControlList.hpp
+++ b/libs/evoral/evoral/ControlList.hpp
@@ -114,10 +114,10 @@ public:
bool extend_to (double);
void slide (iterator before, double distance);
- void reposition_for_rt_add (double when);
void rt_add (double when, double value);
void add (double when, double value);
void fast_simple_add (double when, double value);
+ void merge_nascent (double when);
void reset_range (double start, double end);
void erase_range (double start, double end);
@@ -130,10 +130,6 @@ public:
boost::shared_ptr<ControlList> copy (double, double);
void clear (double, double);
- boost::shared_ptr<ControlList> cut (iterator, iterator);
- boost::shared_ptr<ControlList> copy (iterator, iterator);
- void clear (iterator, iterator);
-
bool paste (ControlList&, double position, float times);
void set_yrange (double min, double max) {
@@ -236,6 +232,11 @@ public:
InterpolationStyle interpolation() const { return _interpolation; }
void set_interpolation (InterpolationStyle);
+ virtual bool touching() const { return false; }
+ virtual bool writing() const { return false; }
+ virtual bool touch_enabled() const { return false; }
+ void write_pass_finished (double when);
+
/** Emitted when mark_dirty() is called on this object */
mutable PBD::Signal0<void> Dirty;
/** Emitted when our interpolation style changes */
@@ -257,25 +258,37 @@ protected:
void _x_scale (double factor);
- mutable LookupCache _lookup_cache;
- mutable SearchCache _search_cache;
-
- Parameter _parameter;
- InterpolationStyle _interpolation;
- EventList _events;
- mutable Glib::Mutex _lock;
- int8_t _frozen;
- bool _changed_when_thawed;
- bool _new_value;
- double _max_xval;
- double _min_yval;
- double _max_yval;
- double _default_value;
- bool _sort_pending;
- iterator _rt_insertion_point;
- double _rt_pos;
+ mutable LookupCache _lookup_cache;
+ mutable SearchCache _search_cache;
+
+ Parameter _parameter;
+ InterpolationStyle _interpolation;
+ EventList _events;
+ mutable Glib::Mutex _lock;
+ int8_t _frozen;
+ bool _changed_when_thawed;
+ double _max_xval;
+ double _min_yval;
+ double _max_yval;
+ double _default_value;
+ bool _sort_pending;
Curve* _curve;
+
+ struct NascentInfo {
+ EventList events;
+ bool is_touch;
+ double start_time;
+ double end_time;
+
+ NascentInfo (bool touching, double start = -1.0)
+ : is_touch (touching)
+ , start_time (start)
+ , end_time (-1.0)
+ {}
+ };
+
+ std::list<NascentInfo*> nascent;
};
} // namespace Evoral
diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp
index 72b032e0cf..b49b294288 100644
--- a/libs/evoral/src/ControlList.cpp
+++ b/libs/evoral/src/ControlList.cpp
@@ -45,7 +45,6 @@ ControlList::ControlList (const Parameter& id)
_max_yval = id.max();
_max_xval = 0; // means "no limit"
_default_value = 0;
- _rt_insertion_point = _events.end();
_lookup_cache.left = -1;
_lookup_cache.range.first = _events.end();
_search_cache.left = -1;
@@ -64,7 +63,6 @@ ControlList::ControlList (const ControlList& other)
_max_yval = other._max_yval;
_max_xval = other._max_xval;
_default_value = other._default_value;
- _rt_insertion_point = _events.end();
_lookup_cache.range.first = _events.end();
_search_cache.first = _events.end();
_sort_pending = false;
@@ -87,7 +85,6 @@ ControlList::ControlList (const ControlList& other, double start, double end)
_max_yval = other._max_yval;
_max_xval = other._max_xval;
_default_value = other._default_value;
- _rt_insertion_point = _events.end();
_lookup_cache.range.first = _events.end();
_search_cache.first = _events.end();
_sort_pending = false;
@@ -110,6 +107,13 @@ ControlList::~ControlList()
for (EventList::iterator x = _events.begin(); x != _events.end(); ++x) {
delete (*x);
}
+
+ for (list<NascentInfo*>::iterator n = nascent.begin(); n != nascent.end(); ++n) {
+ for (EventList::iterator x = (*n)->events.begin(); x != (*n)->events.end(); ++x) {
+ delete *x;
+ }
+ delete (*n);
+ }
delete _curve;
}
@@ -203,7 +207,8 @@ ControlList::extend_to (double when)
return true;
}
-void ControlList::_x_scale (double factor)
+void
+ControlList::_x_scale (double factor)
{
for (iterator i = _events.begin(); i != _events.end(); ++i) {
(*i)->when = floor ((*i)->when * factor);
@@ -213,90 +218,165 @@ void ControlList::_x_scale (double factor)
}
void
-ControlList::reposition_for_rt_add (double /*when*/)
+ControlList::write_pass_finished (double when)
{
- _rt_insertion_point = _events.end();
+ merge_nascent (when);
}
void
-ControlList::rt_add (double when, double value)
+ControlList::merge_nascent (double when)
{
- //cerr << "RT: alist " << this << " add " << value << " @ " << when << endl;
-
- {
- Glib::Mutex::Lock lm (_lock);
-
- iterator where;
- ControlEvent cp (when, 0.0);
- bool done = false;
-
- if ((_rt_insertion_point != _events.end()) && ((*_rt_insertion_point)->when < when) ) {
-
- /* we have a previous insertion point, so we should delete
- everything between it and the position where we are going
- to insert this point.
- */
-
- iterator after = _rt_insertion_point;
-
- if (++after != _events.end()) {
- iterator far = after;
-
- while (far != _events.end()) {
- if ((*far)->when > when) {
- break;
- }
- ++far;
- }
-
- if (_new_value) {
- where = far;
- _rt_insertion_point = where;
-
- if ((*where)->when == when) {
- (*where)->value = value;
- done = true;
- }
- } else {
- where = _events.erase (after, far);
- }
-
- } else {
-
- where = after;
-
- }
-
- iterator previous = _rt_insertion_point;
- --previous;
-
- if (_rt_insertion_point != _events.begin() && (*_rt_insertion_point)->value == value && (*previous)->value == value) {
- (*_rt_insertion_point)->when = when;
- done = true;
-
- }
-
- } else {
+ {
+ Glib::Mutex::Lock lm (_lock);
+
+ if (nascent.empty()) {
+ return;
+ }
+
+ for (list<NascentInfo*>::iterator n = nascent.begin(); n != nascent.end(); ++n) {
+
+ NascentInfo* ninfo = *n;
+ EventList& nascent_events (ninfo->events);
+ bool need_adjacent_start_clamp;
+ bool need_adjacent_end_clamp;
+
+ if (nascent_events.empty()) {
+ delete ninfo;
+ continue;
+ }
+
+ if (ninfo->start_time < 0.0) {
+ ninfo->start_time = nascent_events.front()->when;
+ }
+
+ if (ninfo->end_time < 0.0) {
+ ninfo->end_time = when;
+ }
+
+ bool preexisting = !_events.empty();
+
+ if (!preexisting) {
+
+ _events = nascent_events;
+
+ } else if (ninfo->end_time < _events.front()->when) {
+
+ /* all points in nascent are before the first existing point */
+
+ _events.insert (_events.begin(), nascent_events.begin(), nascent_events.end());
+
+ } else if (ninfo->start_time > _events.back()->when) {
+
+ /* all points in nascent are after the last existing point */
+
+ _events.insert (_events.end(), nascent_events.begin(), nascent_events.end());
+
+ } else {
+
+ /* find the range that overaps with nascent events,
+ and insert the contents of nascent events.
+ */
+
+ iterator i;
+ iterator range_begin = _events.end();
+ iterator range_end = _events.end();
+ double end_value = unlocked_eval (ninfo->end_time);
+ double start_value = unlocked_eval (ninfo->start_time - 1);
+
+ need_adjacent_end_clamp = true;
+ need_adjacent_start_clamp = true;
+
+ for (i = _events.begin(); i != _events.end(); ++i) {
+
+ if ((*i)->when == ninfo->start_time) {
+ /* existing point at same time, remove it
+ and the consider the next point instead.
+ */
+ i = _events.erase (i);
+
+ if (i == _events.end()) {
+ break;
+ }
+
+ if (range_begin == _events.end()) {
+ range_begin = i;
+ need_adjacent_start_clamp = false;
+ } else {
+ need_adjacent_end_clamp = false;
+ }
+
+ if ((*i)->when > ninfo->end_time) {
+ range_end = i;
+ break;
+ }
+
+ } else if ((*i)->when > ninfo->start_time) {
+
+ if (range_begin == _events.end()) {
+ range_begin = i;
+ }
+
+ if ((*i)->when > ninfo->end_time) {
+ range_end = i;
+ break;
+ }
+ }
+ }
+
+ assert (range_begin != _events.end());
+
+ if (range_begin != _events.begin()) {
+ /* clamp point before */
+ if (need_adjacent_start_clamp) {
+ _events.insert (range_begin, new ControlEvent (ninfo->start_time, start_value));
+ }
+ }
+
+ _events.insert (range_begin, nascent_events.begin(), nascent_events.end());
+
+ if (range_end != _events.end()) {
+ /* clamp point after */
+ if (need_adjacent_end_clamp) {
+ _events.insert (range_begin, new ControlEvent (ninfo->end_time, end_value));
+ }
+ }
+
+ _events.erase (range_begin, range_end);
+ }
+
+ delete ninfo;
+ }
+
+ nascent.clear ();
+
+ if (writing()) {
+ nascent.push_back (new NascentInfo (false));
+ }
+ }
- where = lower_bound (_events.begin(), _events.end(), &cp, time_comparator);
+ maybe_signal_changed ();
+}
- if (where != _events.end()) {
- if ((*where)->when == when) {
- (*where)->value = value;
- done = true;
- }
- }
- }
+void
+ControlList::rt_add (double when, double value)
+{
+ // this is for automation recording
+
+ if (touch_enabled() && !touching()) {
+ return;
+ }
- if (!done) {
- _rt_insertion_point = _events.insert (where, new ControlEvent (when, value));
- }
+ //cerr << "RT: alist " << this << " add " << value << " @ " << when << endl;
- _new_value = false;
- mark_dirty ();
- }
+ Glib::Mutex::Lock lm (_lock, Glib::TRY_LOCK);
- maybe_signal_changed ();
+ if (lm.locked()) {
+ assert (!nascent.empty());
+ if (!nascent.back()->events.empty()) {
+ assert (when > nascent.back()->events.back()->when);
+ }
+ nascent.back()->events.push_back (new ControlEvent (when, value));
+ }
}
void
@@ -336,7 +416,6 @@ ControlList::add (double when, double value)
if (insert) {
_events.insert (insertion_point, new ControlEvent (when, value));
- reposition_for_rt_add (0);
}
@@ -352,7 +431,6 @@ ControlList::erase (iterator i)
{
Glib::Mutex::Lock lm (_lock);
_events.erase (i);
- reposition_for_rt_add (0);
mark_dirty ();
}
maybe_signal_changed ();
@@ -364,7 +442,6 @@ ControlList::erase (iterator start, iterator end)
{
Glib::Mutex::Lock lm (_lock);
_events.erase (start, end);
- reposition_for_rt_add (0);
mark_dirty ();
}
maybe_signal_changed ();
@@ -411,7 +488,6 @@ ControlList::erase_range (double start, double endt)
erased = erase_range_internal (start, endt, _events);
if (erased) {
- reposition_for_rt_add (0);
mark_dirty ();
}
@@ -662,7 +738,6 @@ ControlList::truncate_end (double last_coordinate)
_events.back()->value = last_val;
}
- reposition_for_rt_add (0);
mark_dirty();
}
@@ -762,8 +837,6 @@ ControlList::truncate_start (double overall_length)
_events.push_front (new ControlEvent (0, first_legal_value));
}
- reposition_for_rt_add (0);
-
mark_dirty();
}
@@ -1115,35 +1188,6 @@ ControlList::rt_safe_earliest_event_linear_unlocked (double start, double& x, do
}
}
-boost::shared_ptr<ControlList>
-ControlList::cut (iterator start, iterator end)
-{
- boost::shared_ptr<ControlList> nal = create (_parameter);
-
- {
- Glib::Mutex::Lock lm (_lock);
-
- for (iterator x = start; x != end; ) {
- iterator tmp;
-
- tmp = x;
- ++tmp;
-
- nal->_events.push_back (new ControlEvent (**x));
- _events.erase (x);
-
- reposition_for_rt_add (0);
-
- x = tmp;
- }
-
- mark_dirty ();
- }
-
- maybe_signal_changed ();
-
- return nal;
-}
/** @param start Start position in model coordinates.
* @param end End position in model coordinates.
@@ -1153,15 +1197,16 @@ boost::shared_ptr<ControlList>
ControlList::cut_copy_clear (double start, double end, int op)
{
boost::shared_ptr<ControlList> nal = create (_parameter);
-
iterator s, e;
- bool changed = false;
+ ControlEvent cp (start, 0.0);
{
- Glib::Mutex::Lock lm (_lock);
+ Glib::Mutex::Lock lm (_lock);
+
+ /* first, determine s & e, two iterators that define the range of points
+ affected by this operation
+ */
- /* find the first event in our list that is at or before `start' in time */
- ControlEvent cp (start, 0.0);
if ((s = lower_bound (_events.begin(), _events.end(), &cp, time_comparator)) == _events.end()) {
return nal;
}
@@ -1170,70 +1215,79 @@ ControlList::cut_copy_clear (double start, double end, int op)
cp.when = end;
e = upper_bound (_events.begin(), _events.end(), &cp, time_comparator);
- if (op != 2 && (*s)->when != start) {
- nal->_events.push_back (new ControlEvent (0, unlocked_eval (start)));
- }
- for (iterator x = s; x != e; ) {
- iterator tmp = x;
- ++tmp;
+ /* if "start" isn't the location of an existing point,
+ evaluate the curve to get a value for the start. Add a point to
+ both the existing event list, and if its not a "clear" operation,
+ to the copy ("nal") as well.
+
+ Note that the time positions of the points in each list are different
+ because we want the copy ("nal") to have a zero time reference.
+ */
+
+
+ /* before we begin any cut/clear operations, get the value of the curve
+ at "end".
+ */
- changed = true;
+ double end_value = unlocked_eval (end);
+
+ if ((*s)->when != start) {
+
+ double val = unlocked_eval (start);
+
+ if (op == 0) { // cut
+ if (start > _events.front()->when) {
+ _events.insert (s, (new ControlEvent (start, val)));
+ }
+ }
+
+ if (op != 2) { // ! clear
+ nal->_events.push_back (new ControlEvent (0, val));
+ }
+ }
+
+ for (iterator x = s; x != e; ) {
/* adjust new points to be relative to start, which
has been set to zero.
*/
-
+
if (op != 2) {
nal->_events.push_back (new ControlEvent ((*x)->when - start, (*x)->value));
}
if (op != 1) {
- _events.erase (x);
- }
-
- x = tmp;
+ x = _events.erase (x);
+ } else {
+ ++x;
+ }
}
+
+ if (e == _events.end() || (*e)->when != end) {
- if (op != 2 && nal->_events.back()->when != end - start) {
- nal->_events.push_back (new ControlEvent (end - start, unlocked_eval (end)));
- }
+ /* only add a boundary point if there is a point after "end"
+ */
+
+ if (op == 0 && (e != _events.end() && end < (*e)->when)) { // cut
+ _events.insert (e, new ControlEvent (end, end_value));
+ }
- if (changed) {
- reposition_for_rt_add (0);
+ if (op != 2 && (e != _events.end() && end < (*e)->when)) { // cut/copy
+ nal->_events.push_back (new ControlEvent (end - start, end_value));
+ }
}
- mark_dirty ();
+ mark_dirty ();
}
- maybe_signal_changed ();
+ if (op != 1) {
+ maybe_signal_changed ();
+ }
return nal;
-
}
-boost::shared_ptr<ControlList>
-ControlList::copy (iterator start, iterator end)
-{
- boost::shared_ptr<ControlList> nal = create (_parameter);
-
- {
- Glib::Mutex::Lock lm (_lock);
-
- for (iterator x = start; x != end; ) {
- iterator tmp;
-
- tmp = x;
- ++tmp;
-
- nal->_events.push_back (new ControlEvent (**x));
-
- x = tmp;
- }
- }
-
- return nal;
-}
boost::shared_ptr<ControlList>
ControlList::cut (double start, double end)
@@ -1293,7 +1347,6 @@ ControlList::paste (ControlList& alist, double pos, float /*times*/)
}
}
- reposition_for_rt_add (0);
mark_dirty ();
}
@@ -1342,7 +1395,6 @@ ControlList::move_ranges (const list< RangeMove<double> >& movements)
_sort_pending = true;
}
- reposition_for_rt_add (0);
mark_dirty ();
}