mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
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
This commit is contained in:
parent
b6642d14ca
commit
7b6b75f38f
37 changed files with 429 additions and 281 deletions
|
|
@ -19,12 +19,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
|
|
||||||
#include "ardour/automation_list.h"
|
#include "ardour/automation_list.h"
|
||||||
#include "ardour/automation_control.h"
|
#include "ardour/automation_control.h"
|
||||||
#include "ardour/event_type_map.h"
|
#include "ardour/event_type_map.h"
|
||||||
#include "ardour/automatable.h"
|
#include "ardour/automatable.h"
|
||||||
#include "ardour/panner.h"
|
#include "ardour/panner.h"
|
||||||
|
#include "ardour/session.h"
|
||||||
|
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "automation_controller.h"
|
#include "automation_controller.h"
|
||||||
|
|
@ -121,13 +125,24 @@ AutomationController::value_adjusted()
|
||||||
void
|
void
|
||||||
AutomationController::start_touch()
|
AutomationController::start_touch()
|
||||||
{
|
{
|
||||||
_controllable->start_touch();
|
_controllable->start_touch (_controllable->session().transport_frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
void
|
||||||
|
|
|
||||||
|
|
@ -593,14 +593,14 @@ GainMeterBase::meter_point_clicked ()
|
||||||
gint
|
gint
|
||||||
GainMeterBase::start_gain_touch (GdkEventButton*)
|
GainMeterBase::start_gain_touch (GdkEventButton*)
|
||||||
{
|
{
|
||||||
_amp->gain_control()->start_touch ();
|
_amp->gain_control()->start_touch (_amp->session().transport_frame());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
GainMeterBase::end_gain_touch (GdkEventButton*)
|
GainMeterBase::end_gain_touch (GdkEventButton*)
|
||||||
{
|
{
|
||||||
_amp->gain_control()->stop_touch ();
|
_amp->gain_control()->stop_touch (false, _amp->session().transport_frame());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
#ifdef HAVE_SLV2
|
#ifdef HAVE_SLV2
|
||||||
#include "ardour/lv2_plugin.h"
|
#include "ardour/lv2_plugin.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "ardour/session.h"
|
||||||
|
|
||||||
#include <lrdf.h>
|
#include <lrdf.h>
|
||||||
|
|
||||||
|
|
@ -603,13 +604,13 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
|
||||||
void
|
void
|
||||||
GenericPluginUI::start_touch (GenericPluginUI::ControlUI* cui)
|
GenericPluginUI::start_touch (GenericPluginUI::ControlUI* cui)
|
||||||
{
|
{
|
||||||
cui->control->start_touch ();
|
cui->control->start_touch (cui->control->session().transport_frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GenericPluginUI::stop_touch (GenericPluginUI::ControlUI* cui)
|
GenericPluginUI::stop_touch (GenericPluginUI::ControlUI* cui)
|
||||||
{
|
{
|
||||||
cui->control->stop_touch ();
|
cui->control->stop_touch (false, cui->control->session().transport_frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -405,8 +405,10 @@ PannerUI::setup_pan ()
|
||||||
boost::shared_ptr<AutomationControl> ac = _panner->pan_control (asz);
|
boost::shared_ptr<AutomationControl> ac = _panner->pan_control (asz);
|
||||||
|
|
||||||
if (asz) {
|
if (asz) {
|
||||||
bc->StartGesture.connect (sigc::mem_fun (*ac, &AutomationControl::start_touch));
|
bc->StartGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
|
||||||
bc->StopGesture.connect (sigc::mem_fun (*ac, &AutomationControl::stop_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];
|
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
|
bool
|
||||||
PannerUI::pan_button_event (GdkEventButton* ev, uint32_t which)
|
PannerUI::pan_button_event (GdkEventButton* ev, uint32_t which)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,9 @@ namespace ARDOUR {
|
||||||
class Session;
|
class Session;
|
||||||
class Panner;
|
class Panner;
|
||||||
class Delivery;
|
class Delivery;
|
||||||
|
class AutomationControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Gtkmm2ext {
|
namespace Gtkmm2ext {
|
||||||
class FastMeter;
|
class FastMeter;
|
||||||
}
|
}
|
||||||
|
|
@ -167,6 +169,9 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
|
||||||
std::string astyle_string (ARDOUR::AutoStyle);
|
std::string astyle_string (ARDOUR::AutoStyle);
|
||||||
std::string short_astyle_string (ARDOUR::AutoStyle);
|
std::string short_astyle_string (ARDOUR::AutoStyle);
|
||||||
std::string _astyle_string (ARDOUR::AutoStyle, bool);
|
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__ */
|
#endif /* __ardour_gtk_panner_ui_h__ */
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ Amp::configure_io (ChanCount in, ChanCount out)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
if (!_active && !_pending_active) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ public:
|
||||||
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
|
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
|
||||||
bool configure_io (ChanCount in, ChanCount out);
|
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; }
|
bool apply_gain() const { return _apply_gain; }
|
||||||
void apply_gain(bool yn) { _apply_gain = yn; }
|
void apply_gain(bool yn) { _apply_gain = yn; }
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ public:
|
||||||
void clear_controls ();
|
void clear_controls ();
|
||||||
|
|
||||||
virtual void automation_snapshot(nframes_t now, bool force);
|
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);
|
virtual std::string describe_parameter(Evoral::Parameter param);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,14 +64,14 @@ public:
|
||||||
return ((ARDOUR::AutomationList*)_list.get())->set_automation_state(as);
|
return ((ARDOUR::AutomationList*)_list.get())->set_automation_state(as);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void start_touch() {
|
inline void start_touch(double when) {
|
||||||
set_touching (true);
|
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);
|
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
|
/** Set the value and do the right thing based on automation state
|
||||||
|
|
@ -86,6 +86,8 @@ public:
|
||||||
double lower() const { return parameter().min(); }
|
double lower() const { return parameter().min(); }
|
||||||
double upper() const { return parameter().max(); }
|
double upper() const { return parameter().max(); }
|
||||||
|
|
||||||
|
const ARDOUR::Session& session() const { return _session; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ARDOUR::Session& _session;
|
ARDOUR::Session& _session;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -61,19 +61,21 @@ class AutomationList : public PBD::StatefulDestructible, public Evoral::ControlL
|
||||||
PBD::Signal0<void> automation_style_changed;
|
PBD::Signal0<void> automation_style_changed;
|
||||||
|
|
||||||
bool automation_playback() const {
|
bool automation_playback() const {
|
||||||
return (_state & Play) || ((_state & Touch) && !_touching);
|
return (_state & Play) || ((_state & Touch) && !touching());
|
||||||
}
|
}
|
||||||
bool automation_write () const {
|
bool automation_write () const {
|
||||||
return (_state & Write) || ((_state & Touch) && _touching);
|
return ((_state & Write) || ((_state & Touch) && touching()));
|
||||||
}
|
}
|
||||||
|
|
||||||
PBD::Signal0<void> StateChanged;
|
PBD::Signal0<void> StateChanged;
|
||||||
|
|
||||||
static PBD::Signal1<void,AutomationList*> AutomationListCreated;
|
static PBD::Signal1<void,AutomationList*> AutomationListCreated;
|
||||||
|
|
||||||
void start_touch ();
|
void start_touch (double when);
|
||||||
void stop_touch ();
|
void stop_touch (bool mark, double when);
|
||||||
bool touching() const { return _touching; }
|
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 ();
|
XMLNode& get_state ();
|
||||||
int set_state (const XMLNode &, int version);
|
int set_state (const XMLNode &, int version);
|
||||||
|
|
@ -86,9 +88,9 @@ class AutomationList : public PBD::StatefulDestructible, public Evoral::ControlL
|
||||||
|
|
||||||
void maybe_signal_changed ();
|
void maybe_signal_changed ();
|
||||||
|
|
||||||
AutoState _state;
|
AutoState _state;
|
||||||
AutoStyle _style;
|
AutoStyle _style;
|
||||||
bool _touching;
|
gint _touching;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -71,10 +71,7 @@ public:
|
||||||
/* supplemental method used with MIDI */
|
/* supplemental method used with MIDI */
|
||||||
|
|
||||||
void flush_buffers (nframes_t nframes, nframes64_t time);
|
void flush_buffers (nframes_t nframes, nframes64_t time);
|
||||||
void transport_stopped ();
|
|
||||||
|
|
||||||
void no_outs_cuz_we_no_monitor(bool);
|
void no_outs_cuz_we_no_monitor(bool);
|
||||||
|
|
||||||
void cycle_start (nframes_t);
|
void cycle_start (nframes_t);
|
||||||
void increment_output_offset (nframes_t);
|
void increment_output_offset (nframes_t);
|
||||||
void transport_stopped (sframes_t frame);
|
void transport_stopped (sframes_t frame);
|
||||||
|
|
@ -100,8 +97,8 @@ public:
|
||||||
void allow_pan_reset ();
|
void allow_pan_reset ();
|
||||||
|
|
||||||
uint32_t pans_required() const { return _configured_input.n_audio(); }
|
uint32_t pans_required() const { return _configured_input.n_audio(); }
|
||||||
void start_pan_touch (uint32_t which);
|
void start_pan_touch (uint32_t which, double when);
|
||||||
void end_pan_touch (uint32_t which);
|
void end_pan_touch (uint32_t which, bool mark, double when);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Role _role;
|
Role _role;
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class InternalReturn : public Return
|
||||||
XMLNode& get_state(void);
|
XMLNode& get_state(void);
|
||||||
int set_state(const XMLNode&, int version);
|
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 configure_io (ChanCount in, ChanCount out);
|
||||||
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
|
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
|
||||||
int set_block_size (nframes_t);
|
int set_block_size (nframes_t);
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ class InternalSend : public Send
|
||||||
XMLNode& get_state(void);
|
XMLNode& get_state(void);
|
||||||
int set_state(const XMLNode& node, int version);
|
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 feeds (boost::shared_ptr<Route> other) const;
|
||||||
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
|
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
|
||||||
bool configure_io (ChanCount in, ChanCount out);
|
bool configure_io (ChanCount in, ChanCount out);
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ public:
|
||||||
void reflect_inputs (const ChanCount& in);
|
void reflect_inputs (const ChanCount& in);
|
||||||
|
|
||||||
/** Compute peaks */
|
/** 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 input_streams () const { return current_meters; }
|
||||||
ChanCount output_streams () const { return current_meters; }
|
ChanCount output_streams () const { return current_meters; }
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ class MonitorProcessor : public Processor
|
||||||
|
|
||||||
bool display_to_user() const;
|
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);
|
XMLNode& state (bool full);
|
||||||
int set_state (const XMLNode&, int /* version */);
|
int set_state (const XMLNode&, int /* version */);
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ public:
|
||||||
bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) const { return true; };
|
bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) const { return true; };
|
||||||
|
|
||||||
/// The fundamental Panner function
|
/// 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; }
|
bool bypassed() const { return _bypassed; }
|
||||||
void set_bypassed (bool yn);
|
void set_bypassed (bool yn);
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class PluginInsert : public Processor
|
||||||
XMLNode& get_state(void);
|
XMLNode& get_state(void);
|
||||||
int set_state(const XMLNode&, int version);
|
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 silence (nframes_t nframes);
|
||||||
|
|
||||||
void activate ();
|
void activate ();
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ class PortInsert : public IOProcessor
|
||||||
XMLNode& get_state(void);
|
XMLNode& get_state(void);
|
||||||
int set_state (const XMLNode&, int version);
|
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;
|
nframes_t signal_latency() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,15 +63,13 @@ class Processor : public SessionObject, public Automatable, public Latent
|
||||||
|
|
||||||
virtual nframes_t signal_latency() const { return 0; }
|
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 int set_block_size (nframes_t /*nframes*/) { return 0; }
|
||||||
virtual bool requires_fixed_sized_buffers() const { return false; }
|
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;
|
/** @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.
|
* 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 silence (nframes_t /*nframes*/) {}
|
||||||
|
|
||||||
virtual void activate () { _pending_active = true; ActiveChanged(); }
|
virtual void activate () { _pending_active = true; ActiveChanged(); }
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ public:
|
||||||
|
|
||||||
uint32_t bit_slot() const { return _bitslot; }
|
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<Amp> amp() const { return _amp; }
|
||||||
boost::shared_ptr<PeakMeter> meter() const { return _meter; }
|
boost::shared_ptr<PeakMeter> meter() const { return _meter; }
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ class Send : public Delivery
|
||||||
|
|
||||||
uint32_t pans_required() const { return _configured_input.n_audio(); }
|
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 can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
|
||||||
bool configure_io (ChanCount in, ChanCount out);
|
bool configure_io (ChanCount in, ChanCount out);
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
#include "pbd/enumwriter.h"
|
#include "pbd/enumwriter.h"
|
||||||
|
#include "pbd/stacktrace.h"
|
||||||
|
|
||||||
#include "midi++/names.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) {
|
for (Controls::iterator i = controls().begin(); i != controls().end(); ++i) {
|
||||||
boost::shared_ptr<AutomationControl> c
|
boost::shared_ptr<AutomationControl> c
|
||||||
= boost::dynamic_pointer_cast<AutomationControl>(i->second);
|
= 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());
|
c->list()->rt_add (now, i->second->user_double());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -403,20 +404,28 @@ Automatable::automation_snapshot (nframes_t now, bool force)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Automatable::transport_stopped (sframes_t now)
|
Automatable::transport_stopped (framepos_t now)
|
||||||
{
|
{
|
||||||
for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
|
for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
|
||||||
|
|
||||||
boost::shared_ptr<AutomationControl> c
|
boost::shared_ptr<AutomationControl> c
|
||||||
= boost::dynamic_pointer_cast<AutomationControl>(li->second);
|
= 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());
|
= boost::dynamic_pointer_cast<AutomationList>(c->list());
|
||||||
|
|
||||||
c->list()->reposition_for_rt_add (now);
|
if (l) {
|
||||||
|
l->write_pass_finished (now);
|
||||||
|
|
||||||
if (c->automation_state() != Off) {
|
if (l->automation_playback()) {
|
||||||
c->set_value(c->list()->eval(now));
|
c->set_value(c->list()->eval(now));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (l->automation_state() == Write) {
|
||||||
|
l->set_automation_state (Touch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ AutomationList::AutomationList (Evoral::Parameter id)
|
||||||
{
|
{
|
||||||
_state = Off;
|
_state = Off;
|
||||||
_style = Absolute;
|
_style = Absolute;
|
||||||
_touching = false;
|
g_atomic_int_set (&_touching, 0);
|
||||||
|
|
||||||
create_curve_if_necessary();
|
create_curve_if_necessary();
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ AutomationList::AutomationList (const AutomationList& other)
|
||||||
{
|
{
|
||||||
_style = other._style;
|
_style = other._style;
|
||||||
_state = other._state;
|
_state = other._state;
|
||||||
_touching = other._touching;
|
g_atomic_int_set (&_touching, other.touching());
|
||||||
|
|
||||||
create_curve_if_necessary();
|
create_curve_if_necessary();
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
|
||||||
{
|
{
|
||||||
_style = other._style;
|
_style = other._style;
|
||||||
_state = other._state;
|
_state = other._state;
|
||||||
_touching = other._touching;
|
g_atomic_int_set (&_touching, other.touching());
|
||||||
|
|
||||||
create_curve_if_necessary();
|
create_curve_if_necessary();
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
|
||||||
AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id)
|
AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id)
|
||||||
: ControlList(id)
|
: ControlList(id)
|
||||||
{
|
{
|
||||||
_touching = false;
|
g_atomic_int_set (&_touching, 0);
|
||||||
_state = Off;
|
_state = Off;
|
||||||
_style = Absolute;
|
_style = Absolute;
|
||||||
|
|
||||||
|
|
@ -180,6 +180,12 @@ AutomationList::set_automation_state (AutoState s)
|
||||||
{
|
{
|
||||||
if (s != _state) {
|
if (s != _state) {
|
||||||
_state = s;
|
_state = s;
|
||||||
|
|
||||||
|
if (_state == Write) {
|
||||||
|
Glib::Mutex::Lock lm (ControlList::_lock);
|
||||||
|
nascent.push_back (new NascentInfo (false));
|
||||||
|
}
|
||||||
|
|
||||||
automation_state_changed (s); /* EMIT SIGNAL */
|
automation_state_changed (s); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -194,17 +200,37 @@ AutomationList::set_automation_style (AutoStyle s)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AutomationList::start_touch ()
|
AutomationList::start_touch (double when)
|
||||||
{
|
{
|
||||||
_touching = true;
|
if (_state == Touch) {
|
||||||
_new_value = true;
|
Glib::Mutex::Lock lm (ControlList::_lock);
|
||||||
|
nascent.push_back (new NascentInfo (true, when));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_atomic_int_set (&_touching, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AutomationList::stop_touch ()
|
AutomationList::stop_touch (bool mark, double when)
|
||||||
{
|
{
|
||||||
_touching = false;
|
g_atomic_int_set (&_touching, 0);
|
||||||
_new_value = false;
|
|
||||||
|
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
|
void
|
||||||
|
|
@ -247,7 +273,14 @@ AutomationList::state (bool full)
|
||||||
root->add_property ("interpolation-style", enum_2_string (_interpolation));
|
root->add_property ("interpolation-style", enum_2_string (_interpolation));
|
||||||
|
|
||||||
if (full) {
|
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 {
|
} else {
|
||||||
/* never save anything but Off for automation state to a template */
|
/* never save anything but Off for automation state to a template */
|
||||||
root->add_property ("state", auto_state_to_string (Off));
|
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;
|
error << _("automation list: cannot load coordinates from XML, all points ignored") << endmsg;
|
||||||
} else {
|
} else {
|
||||||
mark_dirty ();
|
mark_dirty ();
|
||||||
reposition_for_rt_add (0);
|
|
||||||
maybe_signal_changed ();
|
maybe_signal_changed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -426,6 +458,9 @@ AutomationList::set_state (const XMLNode& node, int version)
|
||||||
|
|
||||||
if ((prop = node.property (X_("state"))) != 0) {
|
if ((prop = node.property (X_("state"))) != 0) {
|
||||||
_state = string_to_auto_state (prop->value());
|
_state = string_to_auto_state (prop->value());
|
||||||
|
if (_state == Write) {
|
||||||
|
_state = Off;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_state = Off;
|
_state = Off;
|
||||||
}
|
}
|
||||||
|
|
@ -462,7 +497,6 @@ AutomationList::set_state (const XMLNode& node, int version)
|
||||||
freeze ();
|
freeze ();
|
||||||
clear ();
|
clear ();
|
||||||
mark_dirty ();
|
mark_dirty ();
|
||||||
reposition_for_rt_add (0);
|
|
||||||
maybe_signal_changed ();
|
maybe_signal_changed ();
|
||||||
thaw ();
|
thaw ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ Delivery::configure_io (ChanCount in, ChanCount out)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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);
|
assert (_output);
|
||||||
|
|
||||||
|
|
@ -418,27 +418,22 @@ Delivery::reset_panners ()
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Delivery::start_pan_touch (uint32_t which)
|
Delivery::start_pan_touch (uint32_t which, double when)
|
||||||
{
|
{
|
||||||
if (which < _panner->npanners()) {
|
if (which < _panner->npanners()) {
|
||||||
_panner->pan_control(which)->start_touch();
|
_panner->pan_control(which)->start_touch(when);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Delivery::end_pan_touch (uint32_t which)
|
Delivery::end_pan_touch (uint32_t which, bool mark, double when)
|
||||||
{
|
{
|
||||||
if (which < _panner->npanners()) {
|
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
|
void
|
||||||
Delivery::flush_buffers (nframes_t nframes, nframes64_t time)
|
Delivery::flush_buffers (nframes_t nframes, nframes64_t time)
|
||||||
|
|
@ -453,15 +448,19 @@ Delivery::flush_buffers (nframes_t nframes, nframes64_t time)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
if (_output) {
|
||||||
(*i).transport_stopped ();
|
PortSet& ports (_output->ports());
|
||||||
}
|
|
||||||
|
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
|
||||||
|
(*i).transport_stopped ();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gain_t
|
gain_t
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ InternalReturn::InternalReturn (Session& s)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
if (!_active && !_pending_active) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ InternalSend::send_to_going_away ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
if ((!_active && !_pending_active) || !target || !_send_to) {
|
||||||
_meter->reset ();
|
_meter->reset ();
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ PBD::Signal0<void> Metering::Meter;
|
||||||
* be set to 0.
|
* be set to 0.
|
||||||
*/
|
*/
|
||||||
void
|
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) {
|
if (!_active && !_pending_active) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -396,12 +396,9 @@ MidiTrack::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_fram
|
||||||
void
|
void
|
||||||
MidiTrack::handle_transport_stopped (bool abort, bool did_locate, bool flush_processors)
|
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);
|
Route::handle_transport_stopped (abort, did_locate, flush_processors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiTrack::push_midi_input_to_step_edit_ringbuffer (nframes_t nframes)
|
MidiTrack::push_midi_input_to_step_edit_ringbuffer (nframes_t nframes)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ MonitorProcessor::state (bool full)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
uint32_t chn = 0;
|
||||||
gain_t target_gain;
|
gain_t target_gain;
|
||||||
|
|
|
||||||
|
|
@ -1489,7 +1489,7 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
if (outbufs.count().n_audio() == 0) {
|
||||||
// Failing to deliver audio we were asked to deliver is a bug
|
// Failing to deliver audio we were asked to deliver is a bug
|
||||||
|
|
|
||||||
|
|
@ -367,7 +367,7 @@ PluginInsert::silence (nframes_t nframes)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
if (_active || _pending_active) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ PortInsert::latency() const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
if (_output->n_ports().n_total() == 0) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ Return::set_state (const XMLNode& node, int version)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
if ((!_active && !_pending_active) || _input->n_ports() == ChanCount::ZERO) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -2621,7 +2621,7 @@ Route::direct_feeds (boost::shared_ptr<Route> other, bool* only_send)
|
||||||
void
|
void
|
||||||
Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors)
|
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);
|
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);
|
automation_snapshot (now, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Automatable::transport_stopped (now);
|
||||||
|
|
||||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||||
|
|
||||||
if (Config->get_plugins_stop_with_transport() && can_flush_processors) {
|
if (Config->get_plugins_stop_with_transport() && can_flush_processors) {
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ Send::deactivate ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
if (_output->n_ports() == ChanCount::ZERO) {
|
||||||
_meter->reset ();
|
_meter->reset ();
|
||||||
|
|
|
||||||
|
|
@ -114,10 +114,10 @@ public:
|
||||||
bool extend_to (double);
|
bool extend_to (double);
|
||||||
void slide (iterator before, double distance);
|
void slide (iterator before, double distance);
|
||||||
|
|
||||||
void reposition_for_rt_add (double when);
|
|
||||||
void rt_add (double when, double value);
|
void rt_add (double when, double value);
|
||||||
void add (double when, double value);
|
void add (double when, double value);
|
||||||
void fast_simple_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 reset_range (double start, double end);
|
||||||
void erase_range (double start, double end);
|
void erase_range (double start, double end);
|
||||||
|
|
@ -130,10 +130,6 @@ public:
|
||||||
boost::shared_ptr<ControlList> copy (double, double);
|
boost::shared_ptr<ControlList> copy (double, double);
|
||||||
void clear (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);
|
bool paste (ControlList&, double position, float times);
|
||||||
|
|
||||||
void set_yrange (double min, double max) {
|
void set_yrange (double min, double max) {
|
||||||
|
|
@ -236,6 +232,11 @@ public:
|
||||||
InterpolationStyle interpolation() const { return _interpolation; }
|
InterpolationStyle interpolation() const { return _interpolation; }
|
||||||
void set_interpolation (InterpolationStyle);
|
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 */
|
/** Emitted when mark_dirty() is called on this object */
|
||||||
mutable PBD::Signal0<void> Dirty;
|
mutable PBD::Signal0<void> Dirty;
|
||||||
/** Emitted when our interpolation style changes */
|
/** Emitted when our interpolation style changes */
|
||||||
|
|
@ -257,25 +258,37 @@ protected:
|
||||||
|
|
||||||
void _x_scale (double factor);
|
void _x_scale (double factor);
|
||||||
|
|
||||||
mutable LookupCache _lookup_cache;
|
mutable LookupCache _lookup_cache;
|
||||||
mutable SearchCache _search_cache;
|
mutable SearchCache _search_cache;
|
||||||
|
|
||||||
Parameter _parameter;
|
Parameter _parameter;
|
||||||
InterpolationStyle _interpolation;
|
InterpolationStyle _interpolation;
|
||||||
EventList _events;
|
EventList _events;
|
||||||
mutable Glib::Mutex _lock;
|
mutable Glib::Mutex _lock;
|
||||||
int8_t _frozen;
|
int8_t _frozen;
|
||||||
bool _changed_when_thawed;
|
bool _changed_when_thawed;
|
||||||
bool _new_value;
|
double _max_xval;
|
||||||
double _max_xval;
|
double _min_yval;
|
||||||
double _min_yval;
|
double _max_yval;
|
||||||
double _max_yval;
|
double _default_value;
|
||||||
double _default_value;
|
bool _sort_pending;
|
||||||
bool _sort_pending;
|
|
||||||
iterator _rt_insertion_point;
|
|
||||||
double _rt_pos;
|
|
||||||
|
|
||||||
Curve* _curve;
|
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
|
} // namespace Evoral
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ ControlList::ControlList (const Parameter& id)
|
||||||
_max_yval = id.max();
|
_max_yval = id.max();
|
||||||
_max_xval = 0; // means "no limit"
|
_max_xval = 0; // means "no limit"
|
||||||
_default_value = 0;
|
_default_value = 0;
|
||||||
_rt_insertion_point = _events.end();
|
|
||||||
_lookup_cache.left = -1;
|
_lookup_cache.left = -1;
|
||||||
_lookup_cache.range.first = _events.end();
|
_lookup_cache.range.first = _events.end();
|
||||||
_search_cache.left = -1;
|
_search_cache.left = -1;
|
||||||
|
|
@ -64,7 +63,6 @@ ControlList::ControlList (const ControlList& other)
|
||||||
_max_yval = other._max_yval;
|
_max_yval = other._max_yval;
|
||||||
_max_xval = other._max_xval;
|
_max_xval = other._max_xval;
|
||||||
_default_value = other._default_value;
|
_default_value = other._default_value;
|
||||||
_rt_insertion_point = _events.end();
|
|
||||||
_lookup_cache.range.first = _events.end();
|
_lookup_cache.range.first = _events.end();
|
||||||
_search_cache.first = _events.end();
|
_search_cache.first = _events.end();
|
||||||
_sort_pending = false;
|
_sort_pending = false;
|
||||||
|
|
@ -87,7 +85,6 @@ ControlList::ControlList (const ControlList& other, double start, double end)
|
||||||
_max_yval = other._max_yval;
|
_max_yval = other._max_yval;
|
||||||
_max_xval = other._max_xval;
|
_max_xval = other._max_xval;
|
||||||
_default_value = other._default_value;
|
_default_value = other._default_value;
|
||||||
_rt_insertion_point = _events.end();
|
|
||||||
_lookup_cache.range.first = _events.end();
|
_lookup_cache.range.first = _events.end();
|
||||||
_search_cache.first = _events.end();
|
_search_cache.first = _events.end();
|
||||||
_sort_pending = false;
|
_sort_pending = false;
|
||||||
|
|
@ -111,6 +108,13 @@ ControlList::~ControlList()
|
||||||
delete (*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;
|
delete _curve;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,7 +207,8 @@ ControlList::extend_to (double when)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlList::_x_scale (double factor)
|
void
|
||||||
|
ControlList::_x_scale (double factor)
|
||||||
{
|
{
|
||||||
for (iterator i = _events.begin(); i != _events.end(); ++i) {
|
for (iterator i = _events.begin(); i != _events.end(); ++i) {
|
||||||
(*i)->when = floor ((*i)->when * factor);
|
(*i)->when = floor ((*i)->when * factor);
|
||||||
|
|
@ -213,90 +218,165 @@ void ControlList::_x_scale (double factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ControlList::reposition_for_rt_add (double /*when*/)
|
ControlList::write_pass_finished (double when)
|
||||||
{
|
{
|
||||||
_rt_insertion_point = _events.end();
|
merge_nascent (when);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ControlList::merge_nascent (double when)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_signal_changed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ControlList::rt_add (double when, double value)
|
ControlList::rt_add (double when, double value)
|
||||||
{
|
{
|
||||||
|
// this is for automation recording
|
||||||
|
|
||||||
|
if (touch_enabled() && !touching()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//cerr << "RT: alist " << this << " add " << value << " @ " << when << endl;
|
//cerr << "RT: alist " << this << " add " << value << " @ " << when << endl;
|
||||||
|
|
||||||
{
|
Glib::Mutex::Lock lm (_lock, Glib::TRY_LOCK);
|
||||||
Glib::Mutex::Lock lm (_lock);
|
|
||||||
|
|
||||||
iterator where;
|
if (lm.locked()) {
|
||||||
ControlEvent cp (when, 0.0);
|
assert (!nascent.empty());
|
||||||
bool done = false;
|
if (!nascent.back()->events.empty()) {
|
||||||
|
assert (when > nascent.back()->events.back()->when);
|
||||||
if ((_rt_insertion_point != _events.end()) && ((*_rt_insertion_point)->when < when) ) {
|
}
|
||||||
|
nascent.back()->events.push_back (new ControlEvent (when, value));
|
||||||
/* 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 {
|
|
||||||
|
|
||||||
where = lower_bound (_events.begin(), _events.end(), &cp, time_comparator);
|
|
||||||
|
|
||||||
if (where != _events.end()) {
|
|
||||||
if ((*where)->when == when) {
|
|
||||||
(*where)->value = value;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!done) {
|
|
||||||
_rt_insertion_point = _events.insert (where, new ControlEvent (when, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
_new_value = false;
|
|
||||||
mark_dirty ();
|
|
||||||
}
|
|
||||||
|
|
||||||
maybe_signal_changed ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -336,7 +416,6 @@ ControlList::add (double when, double value)
|
||||||
if (insert) {
|
if (insert) {
|
||||||
|
|
||||||
_events.insert (insertion_point, new ControlEvent (when, value));
|
_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);
|
Glib::Mutex::Lock lm (_lock);
|
||||||
_events.erase (i);
|
_events.erase (i);
|
||||||
reposition_for_rt_add (0);
|
|
||||||
mark_dirty ();
|
mark_dirty ();
|
||||||
}
|
}
|
||||||
maybe_signal_changed ();
|
maybe_signal_changed ();
|
||||||
|
|
@ -364,7 +442,6 @@ ControlList::erase (iterator start, iterator end)
|
||||||
{
|
{
|
||||||
Glib::Mutex::Lock lm (_lock);
|
Glib::Mutex::Lock lm (_lock);
|
||||||
_events.erase (start, end);
|
_events.erase (start, end);
|
||||||
reposition_for_rt_add (0);
|
|
||||||
mark_dirty ();
|
mark_dirty ();
|
||||||
}
|
}
|
||||||
maybe_signal_changed ();
|
maybe_signal_changed ();
|
||||||
|
|
@ -411,7 +488,6 @@ ControlList::erase_range (double start, double endt)
|
||||||
erased = erase_range_internal (start, endt, _events);
|
erased = erase_range_internal (start, endt, _events);
|
||||||
|
|
||||||
if (erased) {
|
if (erased) {
|
||||||
reposition_for_rt_add (0);
|
|
||||||
mark_dirty ();
|
mark_dirty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -662,7 +738,6 @@ ControlList::truncate_end (double last_coordinate)
|
||||||
_events.back()->value = last_val;
|
_events.back()->value = last_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
reposition_for_rt_add (0);
|
|
||||||
mark_dirty();
|
mark_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -762,8 +837,6 @@ ControlList::truncate_start (double overall_length)
|
||||||
_events.push_front (new ControlEvent (0, first_legal_value));
|
_events.push_front (new ControlEvent (0, first_legal_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
reposition_for_rt_add (0);
|
|
||||||
|
|
||||||
mark_dirty();
|
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 start Start position in model coordinates.
|
||||||
* @param end End 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)
|
ControlList::cut_copy_clear (double start, double end, int op)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<ControlList> nal = create (_parameter);
|
boost::shared_ptr<ControlList> nal = create (_parameter);
|
||||||
|
|
||||||
iterator s, e;
|
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()) {
|
if ((s = lower_bound (_events.begin(), _events.end(), &cp, time_comparator)) == _events.end()) {
|
||||||
return nal;
|
return nal;
|
||||||
}
|
}
|
||||||
|
|
@ -1170,15 +1215,39 @@ ControlList::cut_copy_clear (double start, double end, int op)
|
||||||
cp.when = end;
|
cp.when = end;
|
||||||
e = upper_bound (_events.begin(), _events.end(), &cp, time_comparator);
|
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)));
|
/* 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".
|
||||||
|
*/
|
||||||
|
|
||||||
|
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; ) {
|
for (iterator x = s; x != e; ) {
|
||||||
iterator tmp = x;
|
|
||||||
++tmp;
|
|
||||||
|
|
||||||
changed = true;
|
|
||||||
|
|
||||||
/* adjust new points to be relative to start, which
|
/* adjust new points to be relative to start, which
|
||||||
has been set to zero.
|
has been set to zero.
|
||||||
|
|
@ -1189,52 +1258,37 @@ ControlList::cut_copy_clear (double start, double end, int op)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op != 1) {
|
if (op != 1) {
|
||||||
_events.erase (x);
|
x = _events.erase (x);
|
||||||
}
|
} else {
|
||||||
|
++x;
|
||||||
x = tmp;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op != 2 && nal->_events.back()->when != end - start) {
|
if (e == _events.end() || (*e)->when != end) {
|
||||||
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 (op != 2 && (e != _events.end() && end < (*e)->when)) { // cut/copy
|
||||||
|
nal->_events.push_back (new ControlEvent (end - start, end_value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
mark_dirty ();
|
||||||
reposition_for_rt_add (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return nal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boost::shared_ptr<ControlList>
|
boost::shared_ptr<ControlList>
|
||||||
ControlList::cut (double start, double end)
|
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 ();
|
mark_dirty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1342,7 +1395,6 @@ ControlList::move_ranges (const list< RangeMove<double> >& movements)
|
||||||
_sort_pending = true;
|
_sort_pending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
reposition_for_rt_add (0);
|
|
||||||
mark_dirty ();
|
mark_dirty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue