summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/SConscript1
-rw-r--r--libs/ardour/ardour/audioregion.h22
-rw-r--r--libs/ardour/ardour/automatable.h28
-rw-r--r--libs/ardour/ardour/automation_control.h59
-rw-r--r--libs/ardour/ardour/io.h54
-rw-r--r--libs/ardour/ardour/panner.h14
-rw-r--r--libs/ardour/ardour/plugin_insert.h1
-rw-r--r--libs/ardour/ardour/processor.h2
-rw-r--r--libs/ardour/ardour/route.h14
-rw-r--r--libs/ardour/ardour/session.h20
-rw-r--r--libs/ardour/ardour/track.h5
-rw-r--r--libs/ardour/audio_track.cc14
-rw-r--r--libs/ardour/audioregion.cc286
-rw-r--r--libs/ardour/automatable.cc164
-rw-r--r--libs/ardour/automation_control.cc85
-rw-r--r--libs/ardour/automation_event.cc14
-rw-r--r--libs/ardour/io.cc114
-rw-r--r--libs/ardour/midi_diskstream.cc5
-rw-r--r--libs/ardour/midi_track.cc15
-rw-r--r--libs/ardour/panner.cc60
-rw-r--r--libs/ardour/plugin_insert.cc89
-rw-r--r--libs/ardour/processor.cc6
-rw-r--r--libs/ardour/route.cc47
-rw-r--r--libs/ardour/session.cc22
-rw-r--r--libs/ardour/session_process.cc8
-rw-r--r--libs/ardour/session_state.cc17
-rw-r--r--libs/ardour/session_transport.cc4
-rw-r--r--libs/ardour/track.cc6
-rw-r--r--libs/gtkmm2ext/barcontroller.cc3
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/barcontroller.h8
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc8
-rw-r--r--libs/surfaces/mackie/route_signal.cc9
32 files changed, 698 insertions, 506 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index dd76aadcba..f93c19649f 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -77,6 +77,7 @@ gdither.cc
globals.cc
import.cc
automatable.cc
+automation_control.cc
processor.cc
io_processor.cc
plugin_insert.cc
diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h
index db763876b0..52a07679af 100644
--- a/libs/ardour/ardour/audioregion.h
+++ b/libs/ardour/ardour/audioregion.h
@@ -67,9 +67,9 @@ class AudioRegion : public Region
bool fade_in_active () const { return _flags & Region::FadeIn; }
bool fade_out_active () const { return _flags & Region::FadeOut; }
- AutomationList& fade_in() { return _fade_in; }
- AutomationList& fade_out() { return _fade_out; }
- AutomationList& envelope() { return _envelope; }
+ boost::shared_ptr<AutomationList> fade_in() { return _fade_in; }
+ boost::shared_ptr<AutomationList> fade_out() { return _fade_out; }
+ boost::shared_ptr<AutomationList> envelope() { return _envelope; }
virtual nframes_t read_peaks (PeakData *buf, nframes_t npeaks,
nframes_t offset, nframes_t cnt,
@@ -162,14 +162,14 @@ class AudioRegion : public Region
void source_offset_changed ();
void listen_to_my_curves ();
- mutable AutomationList _fade_in;
- FadeShape _fade_in_shape;
- mutable AutomationList _fade_out;
- FadeShape _fade_out_shape;
- mutable AutomationList _envelope;
- gain_t _scale_amplitude;
- uint32_t _fade_in_disabled;
- uint32_t _fade_out_disabled;
+ boost::shared_ptr<AutomationList> _fade_in;
+ FadeShape _fade_in_shape;
+ boost::shared_ptr<AutomationList> _fade_out;
+ FadeShape _fade_out_shape;
+ boost::shared_ptr<AutomationList> _envelope;
+ gain_t _scale_amplitude;
+ uint32_t _fade_in_disabled;
+ uint32_t _fade_out_disabled;
protected:
/* default constructor for derived (compound) types */
diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h
index f6d6d86ed0..a1161db80d 100644
--- a/libs/ardour/ardour/automatable.h
+++ b/libs/ardour/ardour/automatable.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000,2007 Paul Davis
+ Copyright (C) 2000, 2007 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,13 +22,16 @@
#include <set>
#include <map>
+#include <boost/shared_ptr.hpp>
#include <ardour/session_object.h>
#include <ardour/automation_event.h>
+#include <ardour/automation_control.h>
#include <ardour/param_id.h>
namespace ARDOUR {
class Session;
+class AutomationControl;
class Automatable : public SessionObject
{
@@ -38,16 +41,17 @@ public:
virtual ~Automatable() {}
// shorthand for gain, pan, etc
- inline AutomationList* automation_list(AutomationType type, bool create_if_missing=false) {
- return automation_list(ParamID(type), create_if_missing);
+ inline boost::shared_ptr<AutomationControl>
+ control(AutomationType type, bool create_if_missing=false) {
+ return control(ParamID(type), create_if_missing);
}
- virtual AutomationList* automation_list(ParamID id, bool create_if_missing=false);
- virtual const AutomationList* automation_list(ParamID id) const;
+ virtual boost::shared_ptr<AutomationControl> control(ParamID id, bool create_if_missing=false);
+ virtual boost::shared_ptr<const AutomationControl> control(ParamID id) const;
- virtual void add_automation_parameter(AutomationList* al);
+ virtual void add_control(boost::shared_ptr<AutomationControl>);
- virtual void automation_snapshot(nframes_t now) {};
+ virtual void automation_snapshot(nframes_t now);
virtual bool find_next_event(nframes_t start, nframes_t end, ControlEvent& ev) const;
@@ -74,7 +78,7 @@ protected:
void can_automate(ParamID);
- virtual void automation_list_creation_callback(ParamID, AutomationList&) {}
+ virtual void auto_state_changed (ParamID which) {}
int set_automation_state(const XMLNode&, ParamID default_param);
XMLNode& get_automation_state();
@@ -83,9 +87,11 @@ protected:
int old_set_automation_state(const XMLNode&);
mutable Glib::Mutex _automation_lock;
-
- std::map<ParamID,AutomationList*> _parameter_automation;
- std::set<ParamID> _visible_parameter_automation;
+
+ typedef std::map<ParamID,boost::shared_ptr<AutomationControl> > Controls;
+
+ Controls _controls;
+ std::set<ParamID> _visible_controls;
std::set<ParamID> _can_automate_list;
nframes_t _last_automation_snapshot;
diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h
new file mode 100644
index 0000000000..d9e7a232af
--- /dev/null
+++ b/libs/ardour/ardour/automation_control.h
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2007 Paul Davis
+ Author: Dave Robillard
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_automation_control_h__
+#define __ardour_automation_control_h__
+
+#include <boost/shared_ptr.hpp>
+#include <pbd/controllable.h>
+
+namespace ARDOUR {
+
+class AutomationList;
+class Session;
+
+
+/** A PBD:Controllable with associated automation data (AutomationList)
+ */
+class AutomationControl : public PBD::Controllable
+{
+public:
+ AutomationControl(ARDOUR::Session&, boost::shared_ptr<ARDOUR::AutomationList>,
+ std::string name="unnamed controllable");
+
+ void set_value(float val);
+ float get_value() const;
+ float user_value() const;
+
+ void set_list(boost::shared_ptr<ARDOUR::AutomationList>);
+
+ boost::shared_ptr<ARDOUR::AutomationList> list() { return _list; }
+ boost::shared_ptr<const ARDOUR::AutomationList> list() const { return _list; }
+
+protected:
+ ARDOUR::Session& _session;
+ boost::shared_ptr<ARDOUR::AutomationList> _list;
+ float _user_value;
+};
+
+
+} // namespace ARDOUR
+
+#endif /* __ardour_automation_control_h__ */
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index fc49f0699f..60e1fc25f1 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -42,6 +42,7 @@
#include <ardour/port_set.h>
#include <ardour/chan_count.h>
#include <ardour/latent.h>
+#include <ardour/automation_control.h>
using std::string;
using std::vector;
@@ -60,6 +61,7 @@ class AudioPort;
class MidiPort;
class BufferSet;
+
/** A collection of input and output ports with connections.
*
* An IO can contain ports of varying types, making routes/inserts/etc with
@@ -103,8 +105,6 @@ class IO : public Automatable, public Latent
void just_meter_input (nframes_t start_frame, nframes_t end_frame,
nframes_t nframes, nframes_t offset);
- virtual void set_gain (gain_t g, void *src);
- void inc_gain (gain_t delta, void *src);
gain_t gain () const { return _desired_gain; }
virtual gain_t effective_gain () const;
@@ -182,8 +182,6 @@ class IO : public Automatable, public Latent
sigc::signal<void,IOChange,void*> input_changed;
sigc::signal<void,IOChange,void*> output_changed;
- sigc::signal<void,void*> gain_changed;
-
virtual XMLNode& state (bool full);
XMLNode& get_state (void);
int set_state (const XMLNode&);
@@ -206,10 +204,6 @@ class IO : public Automatable, public Latent
static sigc::signal<void,ChanCount> MoreChannels;
static sigc::signal<int> PortsCreated;
- PBD::Controllable& gain_control() {
- return _gain_control;
- }
-
static void update_meters();
private:
@@ -221,13 +215,24 @@ class IO : public Automatable, public Latent
public:
/* automation */
+
+ struct GainControl : public AutomationControl {
+ GainControl (std::string name, IO& i, boost::shared_ptr<AutomationList> al)
+ : AutomationControl (i._session, al, name)
+ , _io (i)
+ {}
+
+ void set_value (float val);
+ float get_value (void) const;
+
+ IO& _io;
+ };
- static void set_automation_interval (nframes_t frames) {
- _automation_interval = frames;
+ boost::shared_ptr<GainControl> gain_control() {
+ return _gain_control;
}
-
- static nframes_t automation_interval() {
- return _automation_interval;
+ boost::shared_ptr<const GainControl> gain_control() const {
+ return _gain_control;
}
void clear_automation ();
@@ -237,10 +242,6 @@ class IO : public Automatable, public Latent
virtual void transport_stopped (nframes_t now); // interface: matches Insert
void automation_snapshot (nframes_t now); // interface: matches Automatable
- // FIXME: these will probably become unsafe in the near future
- ARDOUR::AutomationList& gain_automation() { return *automation_list(GainAutomation); }
- const ARDOUR::AutomationList& gain_automation() const { return *automation_list(GainAutomation); }
-
void start_pan_touch (uint32_t which);
void end_pan_touch (uint32_t which);
@@ -282,25 +283,12 @@ class IO : public Automatable, public Latent
virtual uint32_t pans_required() const
{ return _inputs.count().n_audio(); }
- struct GainControllable : public PBD::Controllable {
- GainControllable (std::string name, IO& i) : Controllable (name), io (i) {}
-
- void set_value (float val);
- float get_value (void) const;
-
- IO& io;
- };
-
- GainControllable _gain_control;
+ boost::shared_ptr<GainControl> _gain_control;
- nframes_t last_automation_snapshot;
- static nframes_t _automation_interval;
-
- /*AutoState _gain_automation_state;
- AutoStyle _gain_automation_style;*/
+ virtual void set_gain (gain_t g, void *src);
+ void inc_gain (gain_t delta, void *src);
bool apply_gain_automation;
- //Curve _gain_automation_curve;
virtual int load_automation (std::string path);
diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h
index af3cda94e2..89f56e03c5 100644
--- a/libs/ardour/ardour/panner.h
+++ b/libs/ardour/ardour/panner.h
@@ -76,14 +76,14 @@ class StreamPanner : public sigc::trackable, public PBD::Stateful
virtual void set_automation_state (AutoState) = 0;
virtual void set_automation_style (AutoStyle) = 0;
- PBD::Controllable& control() { return _control; }
+ boost::shared_ptr<PBD::Controllable> control() { return _control; }
/* XXX this is wrong. for multi-dimensional panners, there
must surely be more than 1 automation curve.
*/
/* TODO: Panner is-a Automation solves this */
- virtual AutomationList& automation() = 0;
+ virtual boost::shared_ptr<AutomationList> automation() = 0;
sigc::signal<void> Changed; /* for position */
sigc::signal<void> StateChanged; /* for mute */
@@ -125,7 +125,7 @@ class StreamPanner : public sigc::trackable, public PBD::Stateful
bool can_send_feedback() const;
};
- PanControllable _control;
+ boost::shared_ptr<PanControllable> _control;
void add_state (XMLNode&);
virtual void update () = 0;
@@ -151,7 +151,7 @@ class BaseStereoPanner : public StreamPanner
void set_automation_style (AutoStyle);
/* TODO: StreamPanner is-a Automatable? */
- AutomationList& automation() { return _automation; }
+ boost::shared_ptr<AutomationList> automation() { return _automation; }
/* old school automation loading */
@@ -165,7 +165,7 @@ class BaseStereoPanner : public StreamPanner
float left_interp;
float right_interp;
- AutomationList _automation;
+ boost::shared_ptr<AutomationList> _automation;
};
class EqualPowerStereoPanner : public BaseStereoPanner
@@ -208,7 +208,7 @@ class Multi2dPanner : public StreamPanner
/* TODO: StreamPanner is-a Automatable? */
- AutomationList& automation() { return _automation; }
+ boost::shared_ptr<AutomationList> automation() { return _automation; }
void distribute (AudioBuffer& src, BufferSet& obufs, gain_t gain_coeff, nframes_t nframes);
void distribute_automated (AudioBuffer& src, BufferSet& obufs,
@@ -226,7 +226,7 @@ class Multi2dPanner : public StreamPanner
int load (istream&, string path, uint32_t&);
private:
- AutomationList _automation;
+ boost::shared_ptr<AutomationList> _automation;
void update ();
};
diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h
index e3b1b62b19..90c83057df 100644
--- a/libs/ardour/ardour/plugin_insert.h
+++ b/libs/ardour/ardour/plugin_insert.h
@@ -109,7 +109,6 @@ class PluginInsert : public Processor
void init ();
void set_automatable ();
void auto_state_changed (ParamID which);
- void automation_list_creation_callback (ParamID, AutomationList&);
int32_t count_for_configuration (ChanCount in, ChanCount out) const;
diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h
index 3985306d01..371572610a 100644
--- a/libs/ardour/ardour/processor.h
+++ b/libs/ardour/ardour/processor.h
@@ -80,7 +80,7 @@ class Processor : public Automatable, public Latent
virtual bool configure_io (ChanCount in, ChanCount out) { _configured_input = in; return (_configured = true); }
- /* Act as a pass through, if not overridden */
+ /* Derived classes should override these, or processor appears as a pass-through */
virtual bool can_support_input_configuration (ChanCount in) const { return true; }
virtual ChanCount output_for_input_configuration (ChanCount in) const { return in; }
virtual ChanCount output_streams() const { return _configured_input; }
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index b8c9431e42..1fd6eff0f8 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -81,9 +81,9 @@ class Route : public IO
long order_key (const char* name) const;
void set_order_key (const char* name, long n);
- bool hidden() const { return _flags & Hidden; }
- bool master() const { return _flags & MasterOut; }
- bool control() const { return _flags & ControlOut; }
+ bool is_hidden() const { return _flags & Hidden; }
+ bool is_master() const { return _flags & MasterOut; }
+ bool is_control() const { return _flags & ControlOut; }
/* these are the core of the API of a Route. see the protected sections as well */
@@ -243,11 +243,11 @@ class Route : public IO
ToggleType type;
};
- PBD::Controllable& solo_control() {
+ boost::shared_ptr<PBD::Controllable> solo_control() {
return _solo_control;
}
- PBD::Controllable& mute_control() {
+ boost::shared_ptr<PBD::Controllable> mute_control() {
return _mute_control;
}
@@ -306,8 +306,8 @@ class Route : public IO
std::string _comment;
bool _have_internal_generator;
- ToggleControllable _solo_control;
- ToggleControllable _mute_control;
+ boost::shared_ptr<ToggleControllable> _solo_control;
+ boost::shared_ptr<ToggleControllable> _mute_control;
nframes_t check_initial_delay (nframes_t, nframes_t&, nframes_t&);
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 3a4a21cb8a..2c4c60a911 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -649,9 +649,11 @@ class Session : public PBD::StatefulDestructible
sigc::signal<void> NamedSelectionAdded;
sigc::signal<void> NamedSelectionRemoved;
- /* Curves and AutomationLists (TODO when they go away) */
- void add_curve(Curve*);
- void add_automation_list(AutomationList*);
+ /* Curves and AutomationLists (TODO when they go away) */
+ void add_curve(Curve*);
+ void add_automation_list(AutomationList*);
+
+ nframes_t automation_interval () const { return _automation_interval; }
/* fade curves */
@@ -780,9 +782,9 @@ class Session : public PBD::StatefulDestructible
std::map<PBD::ID, PBD::StatefulThingWithGoingAway*> registry;
- // these commands are implemented in libs/ardour/session_command.cc
+ // these commands are implemented in libs/ardour/session_command.cc
Command* memento_command_factory(XMLNode* n);
- void register_with_memento_command_factory(PBD::ID, PBD::StatefulThingWithGoingAway*);
+ void register_with_memento_command_factory(PBD::ID, PBD::StatefulThingWithGoingAway*);
Command* global_state_command_factory (const XMLNode& n);
@@ -917,9 +919,9 @@ class Session : public PBD::StatefulDestructible
/* Controllables */
- PBD::Controllable* controllable_by_id (const PBD::ID&);
+ boost::shared_ptr<PBD::Controllable> controllable_by_id (const PBD::ID&);
- void add_controllable (PBD::Controllable*);
+ void add_controllable (boost::shared_ptr<PBD::Controllable>);
void remove_controllable (PBD::Controllable*);
protected:
@@ -1648,6 +1650,8 @@ class Session : public PBD::StatefulDestructible
void allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force);
uint32_t _npan_buffers;
+ nframes_t _automation_interval;
+
/* VST support */
long _vst_callback (VSTPlugin*,
@@ -1672,7 +1676,7 @@ class Session : public PBD::StatefulDestructible
LayerModel layer_model;
CrossfadeModel xfade_model;
- typedef std::set<PBD::Controllable*> Controllables;
+ typedef std::set<boost::shared_ptr<PBD::Controllable> > Controllables;
Glib::Mutex controllables_lock;
Controllables controllables;
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
index 06ce398896..4d5545c0dc 100644
--- a/libs/ardour/ardour/track.h
+++ b/libs/ardour/ardour/track.h
@@ -83,7 +83,7 @@ class Track : public Route
XMLNode& get_template();
virtual int set_state(const XMLNode& node) = 0;
- PBD::Controllable& rec_enable_control() { return _rec_enable_control; }
+ boost::shared_ptr<PBD::Controllable> rec_enable_control() { return _rec_enable_control; }
bool record_enabled() const;
void set_record_enable (bool yn, void *src);
@@ -141,8 +141,9 @@ class Track : public Route
XMLNode* pending_state;
sigc::connection recenable_connection;
sigc::connection ic_connection;
- RecEnableControllable _rec_enable_control;
bool _destructive;
+
+ boost::shared_ptr<RecEnableControllable> _rec_enable_control;
};
}; /* namespace ARDOUR*/
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index 9f13aee465..4df8ffea49 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -278,8 +278,8 @@ AudioTrack::_set_state (const XMLNode& node, bool call_base)
child = *niter;
if (child->name() == X_("recenable")) {
- _rec_enable_control.set_state (*child);
- _session.add_controllable (&_rec_enable_control);
+ _rec_enable_control->set_state (*child);
+ _session.add_controllable (_rec_enable_control);
}
}
@@ -334,7 +334,7 @@ AudioTrack::state(bool full_state)
_diskstream->id().print (buf, sizeof (buf));
root.add_property ("diskstream-id", buf);
- root.add_child_nocopy (_rec_enable_control.get_state());
+ root.add_child_nocopy (_rec_enable_control->get_state());
return root;
}
@@ -601,8 +601,8 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
if (!diskstream->record_enabled() && _session.transport_rolling()) {
Glib::Mutex::Lock am (_automation_lock, Glib::TRY_LOCK);
- if (am.locked() && gain_automation().automation_playback()) {
- apply_gain_automation = gain_automation().curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
+ if (am.locked() && gain_control()->list()->automation_playback()) {
+ apply_gain_automation = gain_control()->list()->curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
}
}
@@ -696,9 +696,9 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes
}
}
- if (IO::gain_automation().automation_state() == Play) {
+ if (gain_control()->list()->automation_state() == Play) {
- IO::gain_automation().curve().get_vector (start, start + nframes, gain_automation, nframes);
+ gain_control()->list()->curve().get_vector (start, start + nframes, gain_automation, nframes);
for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
Sample *b = bi->data();
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index a7a5fca912..359c729368 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -72,20 +72,20 @@ AudioRegion::init ()
/* constructor for use by derived types only */
AudioRegion::AudioRegion (nframes_t start, nframes_t length, string name)
- : Region (start, length, name, DataType::AUDIO),
- _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0),
- _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0),
- _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)
+ : Region (start, length, name, DataType::AUDIO)
+ , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0))
+ , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0))
+ , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0))
{
init ();
}
/** Basic AudioRegion constructor (one channel) */
AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length)
- : Region (src, start, length, PBD::basename_nosuffix(src->name()), DataType::AUDIO, 0, Region::Flag(Region::DefaultFlags|Region::External)),
- _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0),
- _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0),
- _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)
+ : Region (src, start, length, PBD::basename_nosuffix(src->name()), DataType::AUDIO, 0, Region::Flag(Region::DefaultFlags|Region::External))
+ , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0))
+ , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0))
+ , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0))
{
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
if (afs) {
@@ -98,9 +98,9 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, n
/* Basic AudioRegion constructor (one channel) */
AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
: Region (src, start, length, name, DataType::AUDIO, layer, flags)
- , _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0)
- , _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)
- , _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)
+ , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0))
+ , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0))
+ , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0))
{
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
if (afs) {
@@ -113,9 +113,9 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, n
/* Basic AudioRegion constructor (many channels) */
AudioRegion::AudioRegion (SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
: Region (srcs, start, length, name, DataType::AUDIO, layer, flags)
- , _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0)
- , _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)
- , _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)
+ , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0))
+ , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0))
+ , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0))
{
init ();
}
@@ -123,10 +123,10 @@ AudioRegion::AudioRegion (SourceList& srcs, nframes_t start, nframes_t length, c
/** Create a new AudioRegion, that is part of an existing one */
AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
- : Region (other, offset, length, name, layer, flags),
- _fade_in (other->_fade_in),
- _fade_out (other->_fade_out),
- _envelope (other->_envelope, (double) offset, (double) offset + length)
+ : Region (other, offset, length, name, layer, flags)
+ , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0))
+ , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0))
+ , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0))
{
/* return to default fades if the existing ones are too long */
_fade_in_disabled = 0;
@@ -134,7 +134,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t
if (_flags & LeftOfSplit) {
- if (_fade_in.back()->when >= _length) {
+ if (_fade_in->back()->when >= _length) {
set_default_fade_in ();
} else {
_fade_in_disabled = other->_fade_in_disabled;
@@ -144,7 +144,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t
}
if (_flags & RightOfSplit) {
- if (_fade_out.back()->when >= _length) {
+ if (_fade_out->back()->when >= _length) {
set_default_fade_out ();
} else {
_fade_out_disabled = other->_fade_out_disabled;
@@ -161,10 +161,10 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t
}
AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
- : Region (other),
- _fade_in (other->_fade_in),
- _fade_out (other->_fade_out),
- _envelope (other->_envelope)
+ : Region (other)
+ , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0))
+ , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0))
+ , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0))
{
_scale_amplitude = other->_scale_amplitude;
_envelope = other->_envelope;
@@ -179,9 +179,9 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
: Region (src, node)
- , _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0)
- , _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)
- , _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)
+ , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0))
+ , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0))
+ , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0))
{
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
if (afs) {
@@ -201,9 +201,9 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& nod
AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
: Region (srcs, node)
- , _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0)
- , _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)
- , _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)
+ , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0))
+ , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0))
+ , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0))
{
set_default_fades ();
_scale_amplitude = 1.0;
@@ -224,9 +224,9 @@ AudioRegion::~AudioRegion ()
void
AudioRegion::listen_to_my_curves ()
{
- _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
- _fade_in.StateChanged.connect (mem_fun (*this, &AudioRegion::fade_in_changed));
- _fade_out.StateChanged.connect (mem_fun (*this, &AudioRegion::fade_out_changed));
+ _envelope->StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
+ _fade_in->StateChanged.connect (mem_fun (*this, &AudioRegion::fade_in_changed));
+ _fade_out->StateChanged.connect (mem_fun (*this, &AudioRegion::fade_out_changed));
}
bool
@@ -395,7 +395,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
if (_flags & FadeIn) {
- nframes_t fade_in_length = (nframes_t) _fade_in.back()->when;
+ nframes_t fade_in_length = (nframes_t) _fade_in->back()->when;
/* see if this read is within the fade in */
@@ -405,7 +405,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
limit = min (to_read, fade_in_length - internal_offset);
- _fade_in.curve().get_vector (internal_offset, internal_offset+limit, gain_buffer, limit);
+ _fade_in->curve().get_vector (internal_offset, internal_offset+limit, gain_buffer, limit);
for (nframes_t n = 0; n < limit; ++n) {
mixdown_buffer[n] *= gain_buffer[n];
@@ -436,7 +436,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
*/
- nframes_t fade_out_length = (nframes_t) _fade_out.back()->when;
+ nframes_t fade_out_length = (nframes_t) _fade_out->back()->when;
nframes_t fade_interval_start = max(internal_offset, _length-fade_out_length);
nframes_t fade_interval_end = min(internal_offset + to_read, _length);
@@ -447,7 +447,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
nframes_t curve_offset = fade_interval_start - (_length-fade_out_length);
nframes_t fade_offset = fade_interval_start - internal_offset;
- _fade_out.curve().get_vector (curve_offset,curve_offset+limit, gain_buffer, limit);
+ _fade_out->curve().get_vector (curve_offset,curve_offset+limit, gain_buffer, limit);
for (nframes_t n = 0, m = fade_offset; n < limit; ++n, ++m) {
mixdown_buffer[m] *= gain_buffer[n];
@@ -459,7 +459,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
/* Regular gain curves */
if (envelope_active()) {
- _envelope.curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
+ _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
if (_scale_amplitude != 1.0f) {
for (nframes_t n = 0; n < to_read; ++n) {
@@ -521,7 +521,7 @@ AudioRegion::state (bool full)
if ((_flags & DefaultFadeIn)) {
child->add_property (X_("default"), X_("yes"));
} else {
- child->add_child_nocopy (_fade_in.get_state ());
+ child->add_child_nocopy (_fade_in->get_state ());
}
child->add_property (X_("active"), _fade_in_disabled ? X_("no") : X_("yes"));
@@ -531,7 +531,7 @@ AudioRegion::state (bool full)
if ((_flags & DefaultFadeOut)) {
child->add_property (X_("default"), X_("yes"));
} else {
- child->add_child_nocopy (_fade_out.get_state ());
+ child->add_child_nocopy (_fade_out->get_state ());
}
child->add_property (X_("active"), _fade_out_disabled ? X_("no") : X_("yes"));
@@ -545,10 +545,10 @@ AudioRegion::state (bool full)
// If there are only two points, the points are in the start of the region and the end of the region
// so, if they are both at 1.0f, that means the default region.
- if (_envelope.size() == 2 &&
- _envelope.front()->value == 1.0f &&
- _envelope.back()->value==1.0f) {
- if (_envelope.front()->when == 0 && _envelope.back()->when == _length) {
+ if (_envelope->size() == 2 &&
+ _envelope->front()->value == 1.0f &&
+ _envelope->back()->value==1.0f) {
+ if (_envelope->front()->when == 0 && _envelope->back()->when == _length) {
default_env = true;
}
}
@@ -556,7 +556,7 @@ AudioRegion::state (bool full)
if (default_env) {
child->add_property ("default", "yes");
} else {
- child->add_child_nocopy (_envelope.get_state ());
+ child->add_child_nocopy (_envelope->get_state ());
}
} else {
@@ -617,28 +617,28 @@ AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool sen
if (child->name() == "Envelope") {
- _envelope.clear ();
+ _envelope->clear ();
- if ((prop = child->property ("default")) != 0 || _envelope.set_state (*child)) {
+ if ((prop = child->property ("default")) != 0 || _envelope->set_state (*child)) {
set_default_envelope ();
}
- _envelope.set_max_xval (_length);
- _envelope.truncate_end (_length);
+ _envelope->set_max_xval (_length);
+ _envelope->truncate_end (_length);
} else if (child->name() == "FadeIn") {
- _fade_in.clear ();
+ _fade_in->clear ();
- if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0 || _fade_in.set_state (*child)) {
+ if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0 || _fade_in->set_state (*child)) {
set_default_fade_in ();
}
} else if (child->name() == "FadeOut") {
- _fade_out.clear ();
+ _fade_out->clear ();
- if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0 || _fade_out.set_state (*child)) {
+ if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0 || _fade_out->set_state (*child)) {
set_default_fade_out ();
}
}
@@ -665,70 +665,70 @@ AudioRegion::set_state (const XMLNode& node)
void
AudioRegion::set_fade_in_shape (FadeShape shape)
{
- set_fade_in (shape, (nframes_t) _fade_in.back()->when);
+ set_fade_in (shape, (nframes_t) _fade_in->back()->when);
}
void
AudioRegion::set_fade_out_shape (FadeShape shape)
{
- set_fade_out (shape, (nframes_t) _fade_out.back()->when);
+ set_fade_out (shape, (nframes_t) _fade_out->back()->when);
}
void
AudioRegion::set_fade_in (FadeShape shape, nframes_t len)
{
- _fade_in.freeze ();
- _fade_in.clear ();
+ _fade_in->freeze ();
+ _fade_in->clear ();
switch (shape) {
case Linear:
- _fade_in.fast_simple_add (0.0, 0.0);
- _fade_in.fast_simple_add (len, 1.0);
+ _fade_in->fast_simple_add (0.0, 0.0);
+ _fade_in->fast_simple_add (len, 1.0);
break;
case Fast:
- _fade_in.fast_simple_add (0, 0);
- _fade_in.fast_simple_add (len * 0.389401, 0.0333333);
- _fade_in.fast_simple_add (len * 0.629032, 0.0861111);
- _fade_in.fast_simple_add (len * 0.829493, 0.233333);
- _fade_in.fast_simple_add (len * 0.9447, 0.483333);
- _fade_in.fast_simple_add (len * 0.976959, 0.697222);
- _fade_in.fast_simple_add (len, 1);
+ _fade_in->fast_simple_add (0, 0);
+ _fade_in->fast_simple_add (len * 0.389401, 0.0333333);
+ _fade_in->fast_simple_add (len * 0.629032, 0.0861111);
+ _fade_in->fast_simple_add (len * 0.829493, 0.233333);
+ _fade_in->fast_simple_add (len * 0.9447, 0.483333);
+ _fade_in->fast_simple_add (len * 0.976959, 0.697222);
+ _fade_in->fast_simple_add (len, 1);
break;
case Slow:
- _fade_in.fast_simple_add (0, 0);
- _fade_in.fast_simple_add (len * 0.0207373, 0.197222);
- _fade_in.fast_simple_add (len * 0.0645161, 0.525);
- _fade_in.fast_simple_add (len * 0.152074, 0.802778);
- _fade_in.fast_simple_add (len * 0.276498, 0.919444);
- _fade_in.fast_simple_add (len * 0.481567, 0.980556);
- _fade_in.fast_simple_add (len * 0.767281, 1);
- _fade_in.fast_simple_add (len, 1);
+ _fade_in->fast_simple_add (0, 0);
+ _fade_in->fast_simple_add (len * 0.0207373, 0.197222);
+ _fade_in->fast_simple_add (len * 0.0645161, 0.525);
+ _fade_in->fast_simple_add (len * 0.152074, 0.802778);
+ _fade_in->fast_simple_add (len * 0.276498, 0.919444);
+ _fade_in->fast_simple_add (len * 0.481567, 0.980556);
+ _fade_in->fast_simple_add (len * 0.767281, 1);
+ _fade_in->fast_simple_add (len, 1);
break;
case LogA:
- _fade_in.fast_simple_add (0, 0);
- _fade_in.fast_simple_add (len * 0.0737327, 0.308333);
- _fade_in.fast_simple_add (len * 0.246544, 0.658333);
- _fade_in.fast_simple_add (len * 0.470046, 0.886111);
- _fade_in.fast_simple_add (len * 0.652074, 0.972222);
- _fade_in.fast_simple_add (len * 0.771889, 0.988889);
- _fade_in.fast_simple_add (len, 1);
+ _fade_in->fast_simple_add (0, 0);
+ _fade_in->fast_simple_add (len * 0.0737327, 0.308333);
+ _fade_in->fast_simple_add (len * 0.246544, 0.658333);
+ _fade_in->fast_simple_add (len * 0.470046, 0.886111);
+ _fade_in->fast_simple_add (len * 0.652074, 0.972222);
+ _fade_in->fast_simple_add (len * 0.771889, 0.988889);
+ _fade_in->fast_simple_add (len, 1);
break;
case LogB:
- _fade_in.fast_simple_add (0, 0);
- _fade_in.fast_simple_add (len * 0.304147, 0.0694444);
- _fade_in.fast_simple_add (len * 0.529954, 0.152778);
- _fade_in.fast_simple_add (len * 0.725806, 0.333333);
- _fade_in.fast_simple_add (len * 0.847926, 0.558333);
- _fade_in.fast_simple_add (len * 0.919355, 0.730556);
- _fade_in.fast_simple_add (len, 1);
+ _fade_in->fast_simple_add (0, 0);
+ _fade_in->fast_simple_add (len * 0.304147, 0.0694444);
+ _fade_in->fast_simple_add (len * 0.529954, 0.152778);
+ _fade_in->fast_simple_add (len * 0.725806, 0.333333);
+ _fade_in->fast_simple_add (len * 0.847926, 0.558333);
+ _fade_in->fast_simple_add (len * 0.919355, 0.730556);
+ _fade_in->fast_simple_add (len, 1);
break;
}
- _fade_in.thaw ();
+ _fade_in->thaw ();
_fade_in_shape = shape;
send_change (FadeInChanged);
@@ -737,56 +737,56 @@ AudioRegion::set_fade_in (FadeShape shape, nframes_t len)
void
AudioRegion::set_fade_out (FadeShape shape, nframes_t len)
{
- _fade_out.freeze ();
- _fade_out.clear ();
+ _fade_out->freeze ();
+ _fade_out->clear ();
switch (shape) {
case Fast:
- _fade_out.fast_simple_add (len * 0, 1);
- _fade_out.fast_simple_add (len * 0.023041, 0.697222);
- _fade_out.fast_simple_add (len * 0.0553, 0.483333);
- _fade_out.fast_simple_add (len * 0.170507, 0.233333);
- _fade_out.fast_simple_add (len * 0.370968, 0.0861111);
- _fade_out.fast_simple_add (len * 0.610599, 0.0333333);
- _fade_out.fast_simple_add (len * 1, 0);
+ _fade_out->fast_simple_add (len * 0, 1);
+ _fade_out->fast_simple_add (len * 0.023041, 0.697222);
+ _fade_out->fast_simple_add (len * 0.0553, 0.483333);
+ _fade_out->fast_simple_add (len * 0.170507, 0.233333);
+ _fade_out->fast_simple_add (len * 0.370968, 0.0861111);
+ _fade_out->fast_simple_add (len * 0.610599, 0.0333333);
+ _fade_out->fast_simple_add (len * 1, 0);
break;
case LogA:
- _fade_out.fast_simple_add (len * 0, 1);
- _fade_out.fast_simple_add (len * 0.228111, 0.988889);
- _fade_out.fast_simple_add (len * 0.347926, 0.972222);
- _fade_out.fast_simple_add (len * 0.529954, 0.886111);
- _fade_out.fast_simple_add (len * 0.753456, 0.658333);
- _fade_out.fast_simple_add (len * 0.9262673, 0.308333);
- _fade_out.fast_simple_add (len * 1, 0);
+ _fade_out->fast_simple_add (len * 0, 1);
+ _fade_out->fast_simple_add (len * 0.228111, 0.988889);
+ _fade_out->fast_simple_add (len * 0.347926, 0.972222);
+ _fade_out->fast_simple_add (len * 0.529954, 0.886111);
+ _fade_out->fast_simple_add (len * 0.753456, 0.658333);
+ _fade_out->fast_simple_add (len * 0.9262673, 0.308333);
+ _fade_out->fast_simple_add (len * 1, 0);
break;
case Slow:
- _fade_out.fast_simple_add (len * 0, 1);
- _fade_out.fast_simple_add (len * 0.305556, 1);
- _fade_out.fast_simple_add (len * 0.548611, 0.991736);
- _fade_out.fast_simple_add (len * 0.759259, 0.931129);
- _fade_out.fast_simple_add (len * 0.918981, 0.68595);
- _fade_out.fast_simple_add (len * 0.976852, 0.22865);
- _fade_out.fast_simple_add (len * 1, 0);
+ _fade_out->fast_simple_add (len * 0, 1);
+ _fade_out->fast_simple_add (len * 0.305556, 1);
+ _fade_out->fast_simple_add (len * 0.548611, 0.991736);
+ _fade_out->fast_simple_add (len * 0.759259, 0.931129);
+ _fade_out->fast_simple_add (len * 0.918981, 0.68595);
+ _fade_out->fast_simple_add (len * 0.976852, 0.22865);
+ _fade_out->fast_simple_add (len * 1, 0);
break;
case LogB:
- _fade_out.fast_simple_add (len * 0, 1);
- _fade_out.fast_simple_add (len * 0.080645, 0.730556);
- _fade_out.fast_simple_add (len * 0.277778, 0.289256);
- _fade_out.fast_simple_add (len * 0.470046, 0.152778);
- _fade_out.fast_simple_add (len * 0.695853, 0.0694444);
- _fade_out.fast_simple_add (len * 1, 0);
+ _fade_out->fast_simple_add (len * 0, 1);
+ _fade_out->fast_simple_add (len * 0.080645, 0.730556);
+ _fade_out->fast_simple_add (len * 0.277778, 0.289256);
+ _fade_out->fast_simple_add (len * 0.470046, 0.152778);
+ _fade_out->fast_simple_add (len * 0.695853, 0.0694444);
+ _fade_out->fast_simple_add (len * 1, 0);
break;
case Linear:
- _fade_out.fast_simple_add (len * 0, 1);
- _fade_out.fast_simple_add (len * 1, 0);
+ _fade_out->fast_simple_add (len * 0, 1);
+ _fade_out->fast_simple_add (len * 1, 0);
break;
}
- _fade_out.thaw ();
+ _fade_out->thaw ();
_fade_out_shape = shape;
send_change (FadeOutChanged);
@@ -795,7 +795,7 @@ AudioRegion::set_fade_out (FadeShape shape, nframes_t len)
void
AudioRegion::set_fade_in_length (nframes_t len)
{
- bool changed = _fade_in.extend_to (len);
+ bool changed = _fade_in->extend_to (len);
if (changed) {
_flags = Flag (_flags & ~DefaultFadeIn);
@@ -806,7 +806,7 @@ AudioRegion::set_fade_in_length (nframes_t len)
void
AudioRegion::set_fade_out_length (nframes_t len)
{
- bool changed = _fade_out.extend_to (len);
+ bool changed = _fade_out->extend_to (len);
if (changed) {
_flags = Flag (_flags & ~DefaultFadeOut);
@@ -848,13 +848,13 @@ AudioRegion::set_fade_out_active (bool yn)
bool
AudioRegion::fade_in_is_default () const
{
- return _fade_in_shape == Linear && _fade_in.back()->when == 64;
+ return _fade_in_shape == Linear && _fade_in->back()->when == 64;
}
bool
AudioRegion::fade_out_is_default () const
{
- return _fade_out_shape == Linear && _fade_out.back()->when == 64;
+ return _fade_out_shape == Linear && _fade_out->back()->when == 64;
}
void
@@ -881,11 +881,11 @@ AudioRegion::set_default_fades ()
void
AudioRegion::set_default_envelope ()
{
- _envelope.freeze ();
- _envelope.clear ();
- _envelope.fast_simple_add (0, 1.0f);
- _envelope.fast_simple_add (_length, 1.0f);
- _envelope.thaw ();
+ _envelope->freeze ();
+ _envelope->clear ();
+ _envelope->fast_simple_add (0, 1.0f);
+ _envelope->fast_simple_add (_length, 1.0f);
+ _envelope->thaw ();
}
void
@@ -895,18 +895,18 @@ AudioRegion::recompute_at_end ()
based on the the existing curve.
*/
- _envelope.freeze ();
- _envelope.truncate_end (_length);
- _envelope.set_max_xval (_length);
- _envelope.thaw ();
+ _envelope->freeze ();
+ _envelope->truncate_end (_length);
+ _envelope->set_max_xval (_length);
+ _envelope->thaw ();
- if (_fade_in.back()->when > _length) {
- _fade_in.extend_to (_length);
+ if (_fade_in->back()->when > _length) {
+ _fade_in->extend_to (_length);
send_change (FadeInChanged);
}
- if (_fade_out.back()->when > _length) {
- _fade_out.extend_to (_length);
+ if (_fade_out->back()->when > _length) {
+ _fade_out->extend_to (_length);
send_change (FadeOutChanged);
}
}
@@ -916,15 +916,15 @@ AudioRegion::recompute_at_start ()
{
/* as above, but the shift was from the front */
- _envelope.truncate_start (_length);
+ _envelope->truncate_start (_length);
- if (_fade_in.back()->when > _length) {
- _fade_in.extend_to (_length);
+ if (_fade_in->back()->when > _length) {
+ _fade_in->extend_to (_length);
send_change (FadeInChanged);
}
- if (_fade_out.back()->when > _length) {
- _fade_out.extend_to (_length);
+ if (_fade_out->back()->when > _length) {
+ _fade_out->extend_to (_length);
send_change (FadeOutChanged);
}
}
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index 9f3ba6deb6..d7c570ecdf 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -54,7 +54,7 @@ Automatable::old_set_automation_state (const XMLNode& node)
uint32_t what;
stringstream sstr;
- _visible_parameter_automation.clear ();
+ _visible_controls.clear ();
sstr << prop->value();
while (1) {
@@ -65,6 +65,8 @@ Automatable::old_set_automation_state (const XMLNode& node)
mark_automation_visible (ParamID(PluginAutomation, what), true);
}
}
+
+ _last_automation_snapshot = 0;
return 0;
}
@@ -89,7 +91,9 @@ Automatable::load_automation (const string& path)
Glib::Mutex::Lock lm (_automation_lock);
set<ParamID> tosave;
- _parameter_automation.clear ();
+ _controls.clear ();
+
+ _last_automation_snapshot = 0;
while (in) {
double when;
@@ -101,8 +105,8 @@ Automatable::load_automation (const string& path)
in >> value; if (!in) goto bad;
/* FIXME: this is legacy and only used for plugin inserts? I think? */
- AutomationList* al = automation_list (ParamID(PluginAutomation, port), true);
- al->add (when, value);
+ boost::shared_ptr<AutomationControl> c = control (ParamID(PluginAutomation, port), true);
+ c->list()->add (when, value);
tosave.insert (ParamID(PluginAutomation, port));
}
@@ -110,32 +114,35 @@ Automatable::load_automation (const string& path)
bad:
error << string_compose(_("%1: cannot load automation data from %2"), _name, fullpath) << endmsg;
- _parameter_automation.clear ();
+ _controls.clear ();
return -1;
}
void
-Automatable::add_automation_parameter(AutomationList* al)
+Automatable::add_control(boost::shared_ptr<AutomationControl> ac)
{
- _parameter_automation[al->param_id()] = al;
-
- /* let derived classes do whatever they need with this */
- automation_list_creation_callback (al->param_id(), *al);
+ ParamID param = ac->list()->param_id();
- cerr << _name << ": added parameter " << al->param_id().to_string() << endl;
+ _controls[param] = ac;
+
+ cerr << _name << ": added parameter " << param.to_string() << endl;
// FIXME: sane default behaviour?
- _visible_parameter_automation.insert(al->param_id());
- _can_automate_list.insert(al->param_id());
+ _visible_controls.insert(param);
+ _can_automate_list.insert(param);
+
+ // Sync everything (derived classes) up to initial values
+ auto_state_changed(param);
}
void
Automatable::what_has_automation (set<ParamID>& s) const
{
Glib::Mutex::Lock lm (_automation_lock);
- map<ParamID,AutomationList*>::const_iterator li;
+ Controls::const_iterator li;
- for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
+ // FIXME: correct semantics?
+ for (li = _controls.begin(); li != _controls.end(); ++li) {
s.insert ((*li).first);
}
}
@@ -146,42 +153,45 @@ Automatable::what_has_visible_automation (set<ParamID>& s) const
Glib::Mutex::Lock lm (_automation_lock);
set<ParamID>::const_iterator li;
- for (li = _visible_parameter_automation.begin(); li != _visible_parameter_automation.end(); ++li) {
+ for (li = _visible_controls.begin(); li != _visible_controls.end(); ++li) {
s.insert (*li);
}
}
/** Returns NULL if we don't have an AutomationList for \a parameter.
*/
-AutomationList*
-Automatable::automation_list (ParamID parameter, bool create_if_missing)
+boost::shared_ptr<AutomationControl>
+Automatable::control (ParamID parameter, bool create_if_missing)
{
- std::map<ParamID,AutomationList*>::iterator i = _parameter_automation.find(parameter);
+ Controls::iterator i = _controls.find(parameter);
- if (i != _parameter_automation.end()) {
+ if (i != _controls.end()) {
return i->second;
} else if (create_if_missing) {
- AutomationList* al = new AutomationList (parameter, FLT_MIN, FLT_MAX, default_parameter_value (parameter));
- add_automation_parameter(al);
- return al;
+ assert(parameter.type() != GainAutomation);
+ boost::shared_ptr<AutomationList> al (new AutomationList (
+ parameter, FLT_MIN, FLT_MAX, default_parameter_value (parameter)));
+ boost::shared_ptr<AutomationControl> ac (new AutomationControl(_session, al));
+ add_control(ac);
+ return ac;
} else {
//warning << "AutomationList " << parameter.to_string() << " not found for " << _name << endmsg;
- return NULL;
+ return boost::shared_ptr<AutomationControl>();
}
}
-const AutomationList*
-Automatable::automation_list (ParamID parameter) const
+boost::shared_ptr<const AutomationControl>
+Automatable::control (ParamID parameter) const
{
- std::map<ParamID,AutomationList*>::const_iterator i = _parameter_automation.find(parameter);
+ Controls::const_iterator i = _controls.find(parameter);
- if (i != _parameter_automation.end()) {
+ if (i != _controls.end()) {
return i->second;
} else {
//warning << "AutomationList " << parameter.to_string() << " not found for " << _name << endmsg;
- return NULL;
+ return boost::shared_ptr<AutomationControl>();
}
}
@@ -196,7 +206,7 @@ Automatable::describe_parameter (ParamID param)
else if (param == ParamID(PanAutomation))
return _("Pan");
else if (param.type() == MidiCCAutomation)
- return string_compose("MIDI CC %1", param.id());
+ return string_compose("CC %1", param.id());
else
return param.to_string();
}
@@ -211,12 +221,12 @@ void
Automatable::mark_automation_visible (ParamID what, bool yn)
{
if (yn) {
- _visible_parameter_automation.insert (what);
+ _visible_controls.insert (what);
} else {
set<ParamID>::iterator i;
- if ((i = _visible_parameter_automation.find (what)) != _visible_parameter_automation.end()) {
- _visible_parameter_automation.erase (i);
+ if ((i = _visible_controls.find (what)) != _visible_controls.end()) {
+ _visible_controls.erase (i);
}
}
}
@@ -224,24 +234,24 @@ Automatable::mark_automation_visible (ParamID what, bool yn)
bool
Automatable::find_next_event (nframes_t now, nframes_t end, ControlEvent& next_event) const
{
- map<ParamID,AutomationList*>::const_iterator li;
+ Controls::const_iterator li;
AutomationList::TimeComparator cmp;
next_event.when = max_frames;
- for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
+ for (li = _controls.begin(); li != _controls.end(); ++li) {
AutomationList::const_iterator i;
- const AutomationList& alist (*((*li).second));
+ boost::shared_ptr<const AutomationList> alist (li->second->list());
ControlEvent cp (now, 0.0f);
- for (i = lower_bound (alist.const_begin(), alist.const_end(), &cp, cmp); i != alist.const_end() && (*i)->when < end; ++i) {
+ for (i = lower_bound (alist->const_begin(), alist->const_end(), &cp, cmp); i != alist->const_end() && (*i)->when < end; ++i) {
if ((*i)->when > now) {
break;
}
}
- if (i != alist.const_end() && (*i)->when < end) {
+ if (i != alist->const_end() && (*i)->when < end) {
if ((*i)->when < next_event.when) {
next_event.when = (*i)->when;
@@ -261,8 +271,9 @@ Automatable::set_automation_state (const XMLNode& node, ParamID legacy_param)
{
Glib::Mutex::Lock lm (_automation_lock);
- _parameter_automation.clear ();
- _visible_parameter_automation.clear ();
+ /* Don't clear controls, since some may be special derived Controllable classes */
+
+ _visible_controls.clear ();
XMLNodeList nlist = node.children();
XMLNodeIterator niter;
@@ -280,7 +291,7 @@ Automatable::set_automation_state (const XMLNode& node, ParamID legacy_param)
ParamID param = (id_prop ? ParamID(id_prop->value()) : legacy_param);
- AutomationList* al = new AutomationList(**niter, param);
+ boost::shared_ptr<AutomationList> al (new AutomationList(**niter, param));
if (!id_prop) {
warning << "AutomationList node without automation-id property, "
@@ -288,13 +299,19 @@ Automatable::set_automation_state (const XMLNode& node, ParamID legacy_param)
al->set_param_id(legacy_param);
}
- add_automation_parameter(al);
+ boost::shared_ptr<AutomationControl> existing = control(param);
+ if (existing)
+ existing->set_list(al);
+ else
+ add_control(boost::shared_ptr<AutomationControl>(new AutomationControl(_session, al)));
} else {
error << "Expected AutomationList node, got '" << (*niter)->name() << endmsg;
}
}
+ _last_automation_snapshot = 0;
+
return 0;
}
@@ -304,16 +321,12 @@ Automatable::get_automation_state ()
Glib::Mutex::Lock lm (_automation_lock);
XMLNode* node = new XMLNode (X_("Automation"));
- cerr << "'" << _name << "'->get_automation_state, # params = " << _parameter_automation.size() << endl;
-
- if (_parameter_automation.empty()) {
+ if (_controls.empty()) {
return *node;
}
- map<ParamID,AutomationList*>::iterator li;
-
- for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
- node->add_child_nocopy (li->second->get_state ());
+ for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li) {
+ node->add_child_nocopy (li->second->list()->get_state ());
}
return *node;
@@ -324,10 +337,8 @@ Automatable::clear_automation ()
{
Glib::Mutex::Lock lm (_automation_lock);
- map<ParamID,AutomationList*>::iterator li;
-
- for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li)
- li->second->clear();
+ for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li)
+ li->second->list()->clear();
}
void
@@ -335,10 +346,10 @@ Automatable::set_parameter_automation_state (ParamID param, AutoState s)
{
Glib::Mutex::Lock lm (_automation_lock);
- AutomationList* al = automation_list (param, true);
+ boost::shared_ptr<AutomationControl> c = control (param, true);
- if (s != al->automation_state()) {
- al->set_automation_state (s);
+ if (s != c->list()->automation_state()) {
+ c->list()->set_automation_state (s);
_session.set_dirty ();
}
}
@@ -348,10 +359,10 @@ Automatable::get_parameter_automation_state (ParamID param)
{
Glib::Mutex::Lock lm (_automation_lock);
- AutomationList* al = automation_list(param);
+ boost::shared_ptr<AutomationControl> c = control(param);
- if (al) {
- return al->automation_state();
+ if (c) {
+ return c->list()->automation_state();
} else {
return Off;
}
@@ -362,10 +373,10 @@ Automatable::set_parameter_automation_style (ParamID param, AutoStyle s)
{
Glib::Mutex::Lock lm (_automation_lock);
- AutomationList* al = automation_list (param, true);
+ boost::shared_ptr<AutomationControl> c = control(param, true);
- if (s != al->automation_style()) {
- al->set_automation_style (s);
+ if (s != c->list()->automation_style()) {
+ c->list()->set_automation_style (s);
_session.set_dirty ();
}
}
@@ -375,10 +386,10 @@ Automatable::get_parameter_automation_style (ParamID param)
{
Glib::Mutex::Lock lm (_automation_lock);
- AutomationList* al = automation_list(param);
+ boost::shared_ptr<AutomationControl> c = control(param);
- if (al) {
- return al->automation_style();
+ if (c) {
+ return c->list()->automation_style();
} else {
return Absolute; // whatever
}
@@ -393,14 +404,14 @@ Automatable::protect_automation ()
for (set<ParamID>::iterator i = automated_params.begin(); i != automated_params.end(); ++i) {
- AutomationList* al = automation_list (*i);
+ boost::shared_ptr<AutomationControl> c = control(*i);
- switch (al->automation_state()) {
+ switch (c->list()->automation_state()) {
case Write:
- al->set_automation_state (Off);
+ c->list()->set_automation_state (Off);
break;
case Touch:
- al->set_automation_state (Play);
+ c->list()->set_automation_state (Play);
break;
default:
break;
@@ -408,3 +419,18 @@ Automatable::protect_automation ()
}
}
+void
+Automatable::automation_snapshot (nframes_t now)
+{
+ if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _session.automation_interval()) {
+
+ for (Controls::iterator i = _controls.begin(); i != _controls.end(); ++i) {
+ if (i->second->list()->automation_write()) {
+ i->second->list()->rt_add (now, i->second->user_value());
+ }
+ }
+
+ _last_automation_snapshot = now;
+ }
+}
+
diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc
new file mode 100644
index 0000000000..8f8e40a641
--- /dev/null
+++ b/libs/ardour/automation_control.cc
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 2007 Paul Davis
+ Author: Dave Robillard
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <iostream>
+#include <ardour/automation_control.h>
+#include <ardour/session.h>
+#include <ardour/automatable.h>
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+
+AutomationControl::AutomationControl(Session& session, boost::shared_ptr<AutomationList> list, string name)
+ : Controllable((name == "unnamed controllable") ? list->param_id().to_string() : name)
+ , _session(session)
+ , _list(list)
+ , _user_value(list->default_value())
+{
+ cerr << "Created AutomationControl " << name << "(" << list->param_id().to_string() << ")" << endl;
+}
+
+
+/** Get the currently effective value (ie the one that corresponds to current output)
+ */
+float
+AutomationControl::get_value() const
+{
+ if (_list->automation_playback())
+ return _list->eval(_session.transport_frame());
+ else
+ return _user_value;
+}
+
+
+void
+AutomationControl::set_value(float value)
+{
+ _user_value = value;
+
+ if (_session.transport_stopped() && _list->automation_write())
+ _list->add(_session.transport_frame(), value);
+
+ Changed(); /* EMIT SIGNAL */
+}
+
+
+/** Get the latest user-set value, which may not equal get_value() when automation
+ * is playing back, etc.
+ *
+ * Automation write/touch works by periodically sampling this value and adding it
+ * to the AutomationList.
+ */
+float
+AutomationControl::user_value() const
+{
+ return _user_value;
+}
+
+
+void
+AutomationControl::set_list(boost::shared_ptr<ARDOUR::AutomationList> list)
+{
+ _list = list;
+ _user_value = list->default_value();
+ Changed(); /* EMIT SIGNAL */
+}
+
diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc
index b620054558..9c1a6126f6 100644
--- a/libs/ardour/automation_event.cc
+++ b/libs/ardour/automation_event.cc
@@ -1195,8 +1195,6 @@ AutomationList::get_state ()
XMLNode&
AutomationList::state (bool full)
{
- cerr << _param_id.to_string() << "->state()" << endl;
-
XMLNode* root = new XMLNode (X_("AutomationList"));
char buf[64];
LocaleGuard lg (X_("POSIX"));
@@ -1208,11 +1206,11 @@ AutomationList::state (bool full)
snprintf (buf, sizeof (buf), "%.12g", _default_value);
root->add_property ("default", buf);
snprintf (buf, sizeof (buf), "%.12g", _min_yval);
- root->add_property ("_min_yval", buf);
+ root->add_property ("min_yval", buf);
snprintf (buf, sizeof (buf), "%.12g", _max_yval);
- root->add_property ("_max_yval", buf);
+ root->add_property ("max_yval", buf);
snprintf (buf, sizeof (buf), "%.12g", _max_xval);
- root->add_property ("_max_xval", buf);
+ root->add_property ("max_xval", buf);
if (full) {
root->add_property ("state", auto_state_to_string (_state));
@@ -1390,19 +1388,19 @@ AutomationList::set_state (const XMLNode& node)
_state = Off;
}
- if ((prop = node.property (X_("_min_yval"))) != 0) {
+ if ((prop = node.property (X_("min_yval"))) != 0) {
_min_yval = atof (prop->value ());
} else {
_min_yval = FLT_MIN;
}
- if ((prop = node.property (X_("_max_yval"))) != 0) {
+ if ((prop = node.property (X_("max_yval"))) != 0) {
_max_yval = atof (prop->value ());
} else {
_max_yval = FLT_MAX;
}
- if ((prop = node.property (X_("_max_xval"))) != 0) {
+ if ((prop = node.property (X_("max_xval"))) != 0) {
_max_xval = atof (prop->value ());
} else {
_max_xval = 0; // means "no limit ;
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index b61a654b25..f04af47f8c 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -62,8 +62,6 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-nframes_t IO::_automation_interval = 0;
-
const string IO::state_node_name = "IO";
bool IO::connecting_legal = false;
bool IO::ports_legal = false;
@@ -81,6 +79,7 @@ Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
others can be imagined.
*/
+#if 0
static gain_t direct_control_to_gain (double fract) {
/* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
/* this maxes at +6dB */
@@ -93,7 +92,7 @@ static double direct_gain_to_control (gain_t gain) {
return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
}
-
+#endif
/** @param default_type The type of port that will be created by ensure_io
* and friends if no type is explicitly requested (to avoid breakage).
@@ -104,7 +103,6 @@ IO::IO (Session& s, const string& name,
: Automatable (s, name),
_output_buffers (new BufferSet()),
_default_type (default_type),
- _gain_control (X_("gaincontrol"), *this),
_input_minimum (ChanCount::ZERO),
_input_maximum (ChanCount::INFINITE),
_output_minimum (ChanCount::ZERO),
@@ -135,15 +133,16 @@ IO::IO (Session& s, const string& name,
_phase_invert = false;
deferred_state = 0;
- add_automation_parameter(new AutomationList(ParamID(GainAutomation), 0.0, 2.0, 1.0));
+ boost::shared_ptr<AutomationList> gl(
+ new AutomationList(ParamID(GainAutomation), 0.0, 2.0, 1.0));
- apply_gain_automation = false;
-
- last_automation_snapshot = 0;
+ _gain_control = boost::shared_ptr<GainControl>(
+ new GainControl(X_("gaincontrol"), *this, gl));
- /*_gain_automation_state = Off;
- _gain_automation_style = Absolute;*/
+ add_control(_gain_control);
+ apply_gain_automation = false;
+
{
// IO::Meter is emitted from another thread so the
// Meter signal must be protected.
@@ -154,14 +153,13 @@ IO::IO (Session& s, const string& name,
// Connect to our own MoreChannels signal to connect output buffers
IO::MoreChannels.connect (mem_fun (*this, &IO::attach_buffers));
- _session.add_controllable (&_gain_control);
+ _session.add_controllable (_gain_control);
}
IO::IO (Session& s, const XMLNode& node, DataType dt)
: Automatable (s, "unnamed io"),
_output_buffers (new BufferSet()),
- _default_type (dt),
- _gain_control (X_("gaincontrol"), *this)
+ _default_type (dt)
{
_meter = new PeakMeter (_session);
@@ -174,6 +172,14 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
_output_bundle = 0;
apply_gain_automation = false;
+
+ boost::shared_ptr<AutomationList> gl(
+ new AutomationList(ParamID(GainAutomation), 0.0, 2.0, 1.0));
+
+ _gain_control = boost::shared_ptr<GainControl>(
+ new GainControl(X_("gaincontrol"), *this, gl));
+
+ add_control(_gain_control);
set_state (node);
@@ -187,7 +193,7 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
// Connect to our own MoreChannels signal to connect output buffers
IO::MoreChannels.connect (mem_fun (*this, &IO::attach_buffers));
- _session.add_controllable (&_gain_control);
+ _session.add_controllable (_gain_control);
}
IO::~IO ()
@@ -1129,8 +1135,8 @@ IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
gain_t
IO::effective_gain () const
{
- if (gain_automation().automation_playback()) {
- return _effective_gain;
+ if (_gain_control->list()->automation_playback()) {
+ return _gain_control->get_value();
} else {
return _desired_gain;
}
@@ -1272,7 +1278,7 @@ IO::state (bool full_state)
}
node->add_child_nocopy (_panner->state (full_state));
- node->add_child_nocopy (_gain_control.get_state ());
+ node->add_child_nocopy (_gain_control->get_state ());
snprintf (buf, sizeof(buf), "%2.12f", gain());
node->add_property ("gain", buf);
@@ -1359,7 +1365,7 @@ IO::set_state (const XMLNode& node)
if ((*iter)->name() == X_("controllable")) {
if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
- _gain_control.set_state (**iter);
+ _gain_control->set_state (**iter);
}
}
}
@@ -1396,8 +1402,6 @@ IO::set_state (const XMLNode& node)
pending_state_node = new XMLNode (node);
}
- last_automation_snapshot = 0;
-
return 0;
}
@@ -1458,7 +1462,7 @@ IO::load_automation (string path)
switch (type) {
case 'g':
- gain_automation().fast_simple_add (when, value);
+ _gain_control->list()->fast_simple_add (when, value);
break;
case 's':
@@ -2131,15 +2135,22 @@ IO::output_bundle_configuration_changed ()
}
void
-IO::GainControllable::set_value (float val)
+IO::GainControl::set_value (float val)
{
- io.set_gain (direct_control_to_gain (val), this);
+ // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
+ if (val > 1.99526231f)
+ val = 1.99526231f;
+
+ _user_value = val;
+ _io.set_gain (val, this);
+
+ Changed(); /* EMIT SIGNAL */
}
float
-IO::GainControllable::get_value (void) const
+IO::GainControl::get_value (void) const
{
- return direct_gain_to_control (io.effective_gain());
+ return AutomationControl::get_value();
}
void
@@ -2193,16 +2204,16 @@ IO::set_parameter_automation_state (ParamID param, AutoState state)
{
Glib::Mutex::Lock lm (_automation_lock);
- ARDOUR::AutomationList& gain_auto = gain_automation();
+ boost::shared_ptr<AutomationList> gain_auto = _gain_control->list();
- if (state != gain_auto.automation_state()) {
+ if (state != gain_auto->automation_state()) {
changed = true;
- last_automation_snapshot = 0;
- gain_auto.set_automation_state (state);
+ _last_automation_snapshot = 0;
+ gain_auto->set_automation_state (state);
if (state != Off) {
// FIXME: shouldn't this use Curve?
- set_gain (gain_auto.eval (_session.transport_frame()), this);
+ set_gain (gain_auto->eval (_session.transport_frame()), this);
}
}
}
@@ -2229,7 +2240,15 @@ void
IO::set_gain (gain_t val, void *src)
{
// max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
- if (val>1.99526231f) val=1.99526231f;
+ if (val > 1.99526231f)
+ val = 1.99526231f;
+
+ if (src != _gain_control.get()) {
+ _gain_control->set_value(val);
+ // bit twisty, this will come back and call us again
+ // (this keeps control in sync with reality)
+ return;
+ }
{
Glib::Mutex::Lock dm (declick_lock);
@@ -2237,17 +2256,11 @@ IO::set_gain (gain_t val, void *src)
}
if (_session.transport_stopped()) {
- _effective_gain = val;
_gain = val;
}
-
- gain_changed (src);
- _gain_control.Changed (); /* EMIT SIGNAL */
- ARDOUR::AutomationList& gain_auto = gain_automation();
-
- if (_session.transport_stopped() && src != 0 && src != this && gain_auto.automation_write()) {
- gain_auto.add (_session.transport_frame(), val);
+ if (_session.transport_stopped() && src != 0 && src != this && _gain_control->list()->automation_write()) {
+ _gain_control->list()->add (_session.transport_frame(), val);
}
@@ -2258,7 +2271,7 @@ void
IO::start_pan_touch (uint32_t which)
{
if (which < _panner->size()) {
- (*_panner)[which]->automation().start_touch();
+ (*_panner)[which]->automation()->start_touch();
}
}
@@ -2266,7 +2279,7 @@ void
IO::end_pan_touch (uint32_t which)
{
if (which < _panner->size()) {
- (*_panner)[which]->automation().stop_touch();
+ (*_panner)[which]->automation()->stop_touch();
}
}
@@ -2274,35 +2287,26 @@ IO::end_pan_touch (uint32_t which)
void
IO::automation_snapshot (nframes_t now)
{
- if (last_automation_snapshot > now || (now - last_automation_snapshot) > _automation_interval) {
-
- ARDOUR::AutomationList& gain_auto = gain_automation();
+ Automatable::automation_snapshot (now);
- if (gain_auto.automation_write()) {
- gain_auto.rt_add (now, gain());
- }
-
+ if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _session.automation_interval()) {
_panner->snapshot (now);
-
- last_automation_snapshot = now;
}
}
void
IO::transport_stopped (nframes_t frame)
{
- ARDOUR::AutomationList& gain_auto = gain_automation();
-
- gain_auto.reposition_for_rt_add (frame);
+ _gain_control->list()->reposition_for_rt_add (frame);
- if (gain_auto.automation_state() != Off) {
+ if (_gain_control->list()->automation_state() != Off) {
/* the src=0 condition is a special signal to not propagate
automation gain changes into the mix group when locating.
*/
// FIXME: shouldn't this use Curve?
- set_gain (gain_auto.eval (frame), 0);
+ set_gain (_gain_control->list()->eval (frame), 0);
}
_panner->transport_stopped (frame);
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 9114f689b2..6386714c16 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -596,7 +596,7 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
// XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
// Write into playback buffer here, and whatnot?
- cerr << "MDS FIXME: collect playback" << endl;
+ //cerr << "MDS FIXME: collect playback" << endl;
}
@@ -1498,9 +1498,8 @@ MidiDiskstream::get_playback(MidiBuffer& dst, nframes_t start, nframes_t end)
dst.clear();
assert(dst.size() == 0);
- // I think this happens with reverse varispeed? maybe?
+ // Reverse. ... We just don't do reverse, ok? Back off.
if (end <= start) {
- cerr << "MDS: Reverse? Skipping" << endl;
return;
}
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 71a2735606..a10161bc72 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -193,8 +193,8 @@ MidiTrack::_set_state (const XMLNode& node, bool call_base)
child = *niter;
if (child->name() == X_("recenable")) {
- _rec_enable_control.set_state (*child);
- _session.add_controllable (&_rec_enable_control);
+ _rec_enable_control->set_state (*child);
+ _session.add_controllable (_rec_enable_control);
}
}
@@ -249,7 +249,7 @@ MidiTrack::state(bool full_state)
_diskstream->id().print (buf, sizeof(buf));
root.add_property ("diskstream-id", buf);
- root.add_child_nocopy (_rec_enable_control.get_state());
+ root.add_child_nocopy (_rec_enable_control->get_state());
return root;
}
@@ -426,6 +426,15 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
{
int dret;
boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
+
+ {
+ Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+ if (lm.locked()) {
+ // automation snapshot can also be called from the non-rt context
+ // and it uses the redirect list, so we take the lock out here
+ automation_snapshot (start_frame);
+ }
+ }
if (n_outputs().n_total() == 0 && _processors.empty()) {
return 0;
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index d5a238e253..fa05ff4451 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -71,11 +71,11 @@ static double direct_pan_to_control (pan_t val) {
StreamPanner::StreamPanner (Panner& p)
: parent (p),
- _control (X_("panner"), *this)
+ _control (new PanControllable(X_("panner"), *this))
{
_muted = false;
- parent.session().add_controllable (&_control);
+ parent.session().add_controllable (_control);
x = 0.5;
y = 0.5;
@@ -132,7 +132,7 @@ StreamPanner::set_position (float xpos, bool link_call)
x = xpos;
update ();
Changed ();
- _control.Changed ();
+ _control->Changed ();
}
}
@@ -190,7 +190,7 @@ StreamPanner::add_state (XMLNode& node)
/*---------------------------------------------------------------------- */
BaseStereoPanner::BaseStereoPanner (Panner& p)
- : StreamPanner (p), _automation (ParamID(PanAutomation), 0.0, 1.0, 0.5)
+ : StreamPanner (p), _automation (new AutomationList(ParamID(PanAutomation), 0.0, 1.0, 0.5))
{
}
@@ -201,36 +201,36 @@ BaseStereoPanner::~BaseStereoPanner ()
void
BaseStereoPanner::snapshot (nframes_t now)
{
- if (_automation.automation_state() == Write || _automation.automation_state() == Touch) {
- _automation.rt_add (now, x);
+ if (_automation->automation_state() == Write || _automation->automation_state() == Touch) {
+ _automation->rt_add (now, x);
}
}
void
BaseStereoPanner::transport_stopped (nframes_t frame)
{
- _automation.reposition_for_rt_add (frame);
+ _automation->reposition_for_rt_add (frame);
- if (_automation.automation_state() != Off) {
- set_position (_automation.eval (frame));
+ if (_automation->automation_state() != Off) {
+ set_position (_automation->eval (frame));
}
}
void
BaseStereoPanner::set_automation_style (AutoStyle style)
{
- _automation.set_automation_style (style);
+ _automation->set_automation_style (style);
}
void
BaseStereoPanner::set_automation_state (AutoState state)
{
- if (state != _automation.automation_state()) {
+ if (state != _automation->automation_state()) {
- _automation.set_automation_state (state);
+ _automation->set_automation_state (state);
if (state != Off) {
- set_position (_automation.eval (parent.session().transport_frame()));
+ set_position (_automation->eval (parent.session().transport_frame()));
}
}
}
@@ -241,7 +241,7 @@ BaseStereoPanner::load (istream& in, string path, uint32_t& linecnt)
char line[128];
LocaleGuard lg (X_("POSIX"));
- _automation.clear ();
+ _automation->clear ();
while (in.getline (line, sizeof (line), '\n')) {
nframes_t when;
@@ -258,12 +258,12 @@ BaseStereoPanner::load (istream& in, string path, uint32_t& linecnt)
continue;
}
- _automation.fast_simple_add (when, value);
+ _automation->fast_simple_add (when, value);
}
/* now that we are done loading */
- _automation.StateChanged ();
+ _automation->StateChanged ();
return 0;
}
@@ -438,7 +438,7 @@ EqualPowerStereoPanner::distribute_automated (AudioBuffer& srcbuf, BufferSet& ob
/* fetch positional data */
- if (!_automation.curve().rt_safe_get_vector (start, end, buffers[0], nframes)) {
+ if (!_automation->curve().rt_safe_get_vector (start, end, buffers[0], nframes)) {
/* fallback */
if (!_muted) {
distribute (srcbuf, obufs, 1.0, nframes);
@@ -518,12 +518,12 @@ EqualPowerStereoPanner::state (bool full_state)
root->add_property (X_("type"), EqualPowerStereoPanner::name);
XMLNode* autonode = new XMLNode (X_("Automation"));
- autonode->add_child_nocopy (_automation.state (full_state));
+ autonode->add_child_nocopy (_automation->state (full_state));
root->add_child_nocopy (*autonode);
StreamPanner::add_state (*root);
- root->add_child_nocopy (_control.get_state ());
+ root->add_child_nocopy (_control->get_state ());
return *root;
}
@@ -546,15 +546,15 @@ EqualPowerStereoPanner::set_state (const XMLNode& node)
if ((*iter)->name() == X_("controllable")) {
if ((prop = (*iter)->property("name")) != 0 && prop->value() == "panner") {
- _control.set_state (**iter);
+ _control->set_state (**iter);
}
} else if ((*iter)->name() == X_("Automation")) {
- _automation.set_state (*((*iter)->children().front()));
+ _automation->set_state (*((*iter)->children().front()));
- if (_automation.automation_state() != Off) {
- set_position (_automation.eval (parent.session().transport_frame()));
+ if (_automation->automation_state() != Off) {
+ set_position (_automation->eval (parent.session().transport_frame()));
}
}
}
@@ -565,7 +565,7 @@ EqualPowerStereoPanner::set_state (const XMLNode& node)
/*----------------------------------------------------------------------*/
Multi2dPanner::Multi2dPanner (Panner& p)
- : StreamPanner (p), _automation (ParamID(PanAutomation), 0.0, 1.0, 0.5) // XXX useless
+ : StreamPanner (p), _automation (new AutomationList(ParamID(PanAutomation), 0.0, 1.0, 0.5)) // XXX useless
{
update ();
}
@@ -930,10 +930,10 @@ Panner::reset (uint32_t nouts, uint32_t npans)
if (changed || ((left == 0.5) && (right == 0.5))) {
front()->set_position (0.0);
- front()->automation().reset_default (0.0);
+ front()->automation()->reset_default (0.0);
back()->set_position (1.0);
- back()->automation().reset_default (1.0);
+ back()->automation()->reset_default (1.0);
changed = true;
}
@@ -990,7 +990,7 @@ AutoState
Panner::automation_state () const
{
if (!empty()) {
- return front()->automation().automation_state ();
+ return front()->automation()->automation_state ();
} else {
return Off;
}
@@ -1000,7 +1000,7 @@ AutoStyle
Panner::automation_style () const
{
if (!empty()) {
- return front()->automation().automation_style ();
+ return front()->automation()->automation_style ();
} else {
return Absolute;
}
@@ -1026,7 +1026,7 @@ void
Panner::clear_automation ()
{
for (vector<StreamPanner*>::iterator i = begin(); i != end(); ++i) {
- (*i)->automation().clear ();
+ (*i)->automation()->clear ();
}
_session.set_dirty ();
}
@@ -1181,7 +1181,7 @@ bool
Panner::touching () const
{
for (vector<StreamPanner*>::const_iterator i = begin(); i != end(); ++i) {
- if ((*i)->automation().touching ()) {
+ if ((*i)->automation()->touching ()) {
return true;
}
}
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index a842277845..08a8343fbb 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -142,8 +142,6 @@ void
PluginInsert::init ()
{
set_automatable ();
-
- set<uint32_t>::iterator s;
}
PluginInsert::~PluginInsert ()
@@ -152,21 +150,15 @@ PluginInsert::~PluginInsert ()
}
void
-PluginInsert::automation_list_creation_callback (ParamID which, AutomationList& alist)
-{
- alist.automation_state_changed.connect (sigc::bind (mem_fun (*this, &PluginInsert::auto_state_changed), (which)));
-}
-
-void
PluginInsert::auto_state_changed (ParamID which)
{
if (which.type() != PluginAutomation)
return;
- AutomationList* alist = automation_list (which);
+ boost::shared_ptr<AutomationControl> c = control (which);
- if (alist && alist->automation_state() != Off) {
- _plugins[0]->set_parameter (which.id(), alist->eval (_session.transport_frame()));
+ if (c && c->list()->automation_state() != Off) {
+ _plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_frame()));
}
}
@@ -213,12 +205,23 @@ PluginInsert::is_generator() const
void
PluginInsert::set_automatable ()
{
- set<ParamID> a;
-
- a = _plugins.front()->automatable ();
+ set<ParamID> a = _plugins.front()->automatable ();
+
+ Plugin::ParameterDescriptor desc;
for (set<ParamID>::iterator i = a.begin(); i != a.end(); ++i) {
- can_automate (*i);
+ if (i->type() == PluginAutomation) {
+ can_automate (*i);
+ _plugins.front()->get_parameter_descriptor(i->id(), desc);
+ boost::shared_ptr<AutomationList> list(new AutomationList(
+ *i,
+ (desc.min_unbound ? FLT_MIN : desc.lower),
+ (desc.max_unbound ? FLT_MAX : desc.upper),
+ _plugins.front()->default_value(i->id())));
+
+ add_control(boost::shared_ptr<AutomationControl>(
+ new AutomationControl(_session, list)));
+ }
}
}
@@ -276,21 +279,20 @@ PluginInsert::connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t off
if (with_auto) {
- map<ParamID,AutomationList*>::iterator li;
- uint32_t n;
+ uint32_t n = 0;
- for (n = 0, li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li, ++n) {
+ for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li, ++n) {
- AutomationList& alist (*((*li).second));
+ boost::shared_ptr<AutomationControl> c = li->second;
- if (alist.param_id().type() == PluginAutomation && alist.automation_playback()) {
+ if (c->list()->param_id().type() == PluginAutomation && c->list()->automation_playback()) {
bool valid;
- float val = alist.rt_safe_eval (now, valid);
+ float val = c->list()->rt_safe_eval (now, valid);
if (valid) {
/* set the first plugin, the others will be set via signals */
- _plugins[0]->set_parameter ((*li).first, val);
+ _plugins[0]->set_parameter (c->list()->param_id(), val);
}
}
@@ -307,16 +309,15 @@ PluginInsert::connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t off
void
PluginInsert::automation_snapshot (nframes_t now)
{
- map<ParamID,AutomationList*>::iterator li;
-
- for (li =_parameter_automation.begin(); li !=_parameter_automation.end(); ++li) {
+ for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li) {
- AutomationList *alist = ((*li).second);
- if (alist != 0 && alist->param_id().type() == PluginAutomation
- && alist->automation_write ()) {
+ boost::shared_ptr<AutomationControl> c = li->second;
+
+ if (c->list() != 0 && c->list()->param_id().type() == PluginAutomation
+ && c->list()->automation_write ()) {
- float val = _plugins[0]->get_parameter ((*li).first);
- alist->rt_add (now, val);
+ float val = _plugins[0]->get_parameter (c->list()->param_id());
+ c->list()->rt_add (now, val);
_last_automation_snapshot = now;
}
}
@@ -325,14 +326,14 @@ PluginInsert::automation_snapshot (nframes_t now)
void
PluginInsert::transport_stopped (nframes_t now)
{
- map<ParamID,AutomationList*>::iterator li;
-
- for (li =_parameter_automation.begin(); li !=_parameter_automation.end(); ++li) {
- AutomationList& alist (*(li->second));
- alist.reposition_for_rt_add (now);
+ for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li) {
+
+ boost::shared_ptr<AutomationControl> c = li->second;
+
+ c->list()->reposition_for_rt_add (now);
- if (alist.param_id().type() == PluginAutomation && alist.automation_state() != Off) {
- _plugins[0]->set_parameter (li->first, alist.eval (now));
+ if (c->list()->param_id().type() == PluginAutomation && c->list()->automation_state() != Off) {
+ _plugins[0]->set_parameter (li->first, c->list()->eval (now));
}
}
}
@@ -390,8 +391,10 @@ PluginInsert::set_parameter (ParamID param, float val)
_plugins[0]->set_parameter (param.id(), val);
- if (automation_list (param) && automation_list (param)->automation_write()) {
- automation_list (param)->add (_session.audible_frame(), val);
+ boost::shared_ptr<AutomationControl> c = control (param);
+
+ if (c && c->list()->automation_write()) {
+ c->list()->add (_session.audible_frame(), val);
}
_session.set_dirty();
@@ -660,7 +663,7 @@ PluginInsert::state (bool full)
child->add_child_nocopy (automation_list (*x).state (full));
autonode->add_child_nocopy (*child);
*/
- autonode->add_child_nocopy (automation_list (*x)->state (full));
+ autonode->add_child_nocopy (control(*x)->list()->state (full));
}
node.add_child_nocopy (*autonode);
@@ -791,7 +794,7 @@ PluginInsert::set_state(const XMLNode& node)
}
if (!child->children().empty()) {
- automation_list (ParamID(PluginAutomation, port_id), true)->set_state (*child->children().front());
+ control (ParamID(PluginAutomation, port_id), true)->list()->set_state (*child->children().front());
} else {
if ((cprop = child->property("auto")) != 0) {
@@ -799,13 +802,13 @@ PluginInsert::set_state(const XMLNode& node)
int x;
sscanf (cprop->value().c_str(), "0x%x", &x);
- automation_list (ParamID(PluginAutomation, port_id), true)->set_automation_state (AutoState (x));
+ control (ParamID(PluginAutomation, port_id), true)->list()->set_automation_state (AutoState (x));
} else {
/* missing */
- automation_list (ParamID(PluginAutomation, port_id), true)->set_automation_state (Off);
+ control (ParamID(PluginAutomation, port_id), true)->list()->set_automation_state (Off);
}
}
diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc
index b192eb85c1..76c780f2db 100644
--- a/libs/ardour/processor.cc
+++ b/libs/ardour/processor.cc
@@ -157,8 +157,8 @@ Processor::state (bool full_state)
XMLNode& automation = Automatable::get_automation_state();
- for (set<ParamID>::iterator x = _visible_parameter_automation.begin(); x != _visible_parameter_automation.end(); ++x) {
- if (x != _visible_parameter_automation.begin()) {
+ for (set<ParamID>::iterator x = _visible_controls.begin(); x != _visible_controls.end(); ++x) {
+ if (x != _visible_controls.begin()) {
sstr << ' ';
}
sstr << *x;
@@ -202,7 +202,7 @@ Processor::set_state (const XMLNode& node)
uint32_t what;
stringstream sstr;
- _visible_parameter_automation.clear ();
+ _visible_controls.clear ();
sstr << prop->value();
while (1) {
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 507d337619..e8e469b446 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -58,16 +58,16 @@ uint32_t Route::order_key_cnt = 0;
Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type)
: IO (sess, name, input_min, input_max, output_min, output_max, default_type),
_flags (flg),
- _solo_control (X_("solo"), *this, ToggleControllable::SoloControl),
- _mute_control (X_("mute"), *this, ToggleControllable::MuteControl)
+ _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl)),
+ _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl))
{
init ();
}
Route::Route (Session& sess, const XMLNode& node, DataType default_type)
: IO (sess, *node.child ("IO"), default_type),
- _solo_control (X_("solo"), *this, ToggleControllable::SoloControl),
- _mute_control (X_("mute"), *this, ToggleControllable::MuteControl)
+ _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl)),
+ _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl))
{
init ();
_set_state (node, false);
@@ -177,33 +177,33 @@ Route::set_gain (gain_t val, void *src)
if (_mix_group->is_relative()) {
-
- gain_t usable_gain = gain();
+ gain_t usable_gain = gain();
if (usable_gain < 0.000001f) {
- usable_gain=0.000001f;
+ usable_gain = 0.000001f;
}
gain_t delta = val;
if (delta < 0.000001f) {
- delta=0.000001f;
+ delta = 0.000001f;
}
delta -= usable_gain;
- if (delta == 0.0f) return;
+ if (delta == 0.0f)
+ return;
gain_t factor = delta / usable_gain;
if (factor > 0.0f) {
factor = _mix_group->get_max_factor(factor);
if (factor == 0.0f) {
- gain_changed (src);
+ _gain_control->Changed(); /* EMIT SIGNAL */
return;
}
} else {
factor = _mix_group->get_min_factor(factor);
if (factor == 0.0f) {
- gain_changed (src);
+ _gain_control->Changed(); /* EMIT SIGNAL */
return;
}
}
@@ -726,7 +726,7 @@ Route::set_solo (bool yn, void *src)
if (_soloed != yn) {
_soloed = yn;
solo_changed (src); /* EMIT SIGNAL */
- _solo_control.Changed (); /* EMIT SIGNAL */
+ _solo_control->Changed (); /* EMIT SIGNAL */
}
}
@@ -763,7 +763,7 @@ Route::set_mute (bool yn, void *src)
_muted = yn;
mute_changed (src); /* EMIT SIGNAL */
- _mute_control.Changed (); /* EMIT SIGNAL */
+ _mute_control->Changed (); /* EMIT SIGNAL */
Glib::Mutex::Lock lm (declick_lock);
desired_mute_gain = (yn?0.0f:1.0f);
@@ -1491,8 +1491,8 @@ Route::state(bool full_state)
node->add_property ("order-keys", order_string);
node->add_child_nocopy (IO::state (full_state));
- node->add_child_nocopy (_solo_control.get_state ());
- node->add_child_nocopy (_mute_control.get_state ());
+ node->add_child_nocopy (_solo_control->get_state ());
+ node->add_child_nocopy (_mute_control->get_state ());
XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
snprintf (buf, sizeof (buf), "%d", _remote_control_id);
@@ -1853,12 +1853,12 @@ Route::_set_state (const XMLNode& node, bool call_base)
} else if (child->name() == X_("controllable") && (prop = child->property("name")) != 0) {
if (prop->value() == "solo") {
- _solo_control.set_state (*child);
- _session.add_controllable (&_solo_control);
+ _solo_control->set_state (*child);
+ _session.add_controllable (_solo_control);
}
else if (prop->value() == "mute") {
- _mute_control.set_state (*child);
- _session.add_controllable (&_mute_control);
+ _mute_control->set_state (*child);
+ _session.add_controllable (_mute_control);
}
}
else if (child->name() == X_("remote_control")) {
@@ -2038,7 +2038,7 @@ Route::set_control_outs (const vector<string>& ports)
_control_outs = 0;
}
- if (control() || master()) {
+ if (is_control() || is_master()) {
/* no control outs for these two special busses */
return 0;
}
@@ -2393,10 +2393,9 @@ Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nfra
if (am.locked() && _session.transport_rolling()) {
- ARDOUR::AutomationList& gain_auto = gain_automation();
-
- if (gain_auto.automation_playback()) {
- apply_gain_automation = gain_auto.curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
+ if (_gain_control->list()->automation_playback()) {
+ apply_gain_automation = _gain_control->list()->curve().rt_safe_get_vector (
+ start_frame, end_frame, _session.gain_automation_buffer(), nframes);
}
}
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index c40dd6fd7a..d5c2817f54 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -122,7 +122,8 @@ Session::Session (AudioEngine &eng,
routes (new RouteList),
auditioner ((Auditioner*) 0),
_click_io ((IO*) 0),
- main_outs (0)
+ main_outs (0),
+ _automation_interval (0)
{
if (!eng.connected()) {
throw failed_constructor();
@@ -221,7 +222,8 @@ Session::Session (AudioEngine &eng,
_send_smpte_update (false),
diskstreams (new DiskstreamList),
routes (new RouteList),
- main_outs (0)
+ main_outs (0),
+ _automation_interval (0)
{
if (!eng.connected()) {
@@ -1267,7 +1269,7 @@ Session::set_frame_rate (nframes_t frames_per_second)
sync_time_vars();
- Route::set_automation_interval ((nframes_t) ceil ((double) frames_per_second * 0.25));
+ _automation_interval = ((nframes_t) ceil ((double) frames_per_second * 0.25));
// XXX we need some equivalent to this, somehow
// SndFileSource::setup_standard_crossfades (frames_per_second);
@@ -1504,7 +1506,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (dynamic_cast<MidiTrack*>((*i).get()) != 0) {
- if (!(*i)->hidden()) {
+ if (!(*i)->is_hidden()) {
n++;
channels_used += (*i)->n_inputs().n_midi();
}
@@ -1585,7 +1587,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (dynamic_cast<AudioTrack*>((*i).get()) != 0) {
- if (!(*i)->hidden()) {
+ if (!(*i)->is_hidden()) {
n++;
channels_used += (*i)->n_inputs().n_audio();
}
@@ -1775,7 +1777,7 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (dynamic_cast<AudioTrack*>((*i).get()) == 0) {
- if (!(*i)->hidden() && (*i)->name() != _("master")) {
+ if (!(*i)->is_hidden() && (*i)->name() != _("master")) {
bus_id++;
}
}
@@ -1892,11 +1894,11 @@ Session::add_routes (RouteList& new_routes, bool save)
(*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
(*x)->processors_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false));
- if ((*x)->master()) {
+ if ((*x)->is_master()) {
_master_out = (*x);
}
- if ((*x)->control()) {
+ if ((*x)->is_control()) {
_control_out = (*x);
}
}
@@ -3436,7 +3438,7 @@ Session::set_all_solo (bool yn)
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->hidden()) {
+ if (!(*i)->is_hidden()) {
(*i)->set_solo (yn, this);
}
}
@@ -3450,7 +3452,7 @@ Session::set_all_mute (bool yn)
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->hidden()) {
+ if (!(*i)->is_hidden()) {
(*i)->set_mute (yn, this);
}
}
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index dc71a40ca2..44b63e0875 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -101,7 +101,7 @@ Session::no_roll (nframes_t nframes, nframes_t offset)
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if ((*i)->hidden()) {
+ if ((*i)->is_hidden()) {
continue;
}
@@ -140,7 +140,7 @@ Session::process_routes (nframes_t nframes, nframes_t offset)
int ret;
- if ((*i)->hidden()) {
+ if ((*i)->is_hidden()) {
continue;
}
@@ -186,7 +186,7 @@ Session::silent_process_routes (nframes_t nframes, nframes_t offset)
int ret;
- if ((*i)->hidden()) {
+ if ((*i)->is_hidden()) {
continue;
}
@@ -819,7 +819,7 @@ Session::process_audition (nframes_t nframes)
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->hidden()) {
+ if (!(*i)->is_hidden()) {
(*i)->silence (nframes, 0);
}
}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 65c48a2296..2924210e0c 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -939,7 +939,7 @@ Session::state(bool full_state)
public_order.sort (cmp);
for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
- if (!(*i)->hidden()) {
+ if (!(*i)->is_hidden()) {
if (full_state) {
child->add_child_nocopy ((*i)->get_state());
} else {
@@ -2055,7 +2055,7 @@ Session::get_global_route_boolean (bool (Route::*method)(void) const)
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->hidden()) {
+ if (!(*i)->is_hidden()) {
RouteBooleanState v;
v.first =* i;
@@ -2076,7 +2076,7 @@ Session::get_global_route_metering ()
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->hidden()) {
+ if (!(*i)->is_hidden()) {
RouteMeterState v;
v.first =* i;
@@ -2622,7 +2622,7 @@ Session::set_deletion_in_progress ()
}
void
-Session::add_controllable (Controllable* c)
+Session::add_controllable (boost::shared_ptr<Controllable> c)
{
/* this adds a controllable to the list managed by the Session.
this is a subset of those managed by the Controllable class
@@ -2633,6 +2633,8 @@ Session::add_controllable (Controllable* c)
Glib::Mutex::Lock lm (controllables_lock);
controllables.insert (c);
}
+
+struct null_deleter { void operator()(void const *) const {} };
void
Session::remove_controllable (Controllable* c)
@@ -2643,14 +2645,15 @@ Session::remove_controllable (Controllable* c)
Glib::Mutex::Lock lm (controllables_lock);
- Controllables::iterator x = controllables.find (c);
+ Controllables::iterator x = controllables.find(
+ boost::shared_ptr<Controllable>(c, null_deleter()));
if (x != controllables.end()) {
controllables.erase (x);
}
}
-Controllable*
+boost::shared_ptr<Controllable>
Session::controllable_by_id (const PBD::ID& id)
{
Glib::Mutex::Lock lm (controllables_lock);
@@ -2661,7 +2664,7 @@ Session::controllable_by_id (const PBD::ID& id)
}
}
- return 0;
+ return boost::shared_ptr<Controllable>();
}
void
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 52f6346789..c122989b68 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -363,7 +363,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->hidden()) {
+ if (!(*i)->is_hidden()) {
(*i)->set_pending_declick (0);
}
}
@@ -1262,7 +1262,7 @@ Session::update_latency_compensation (bool with_stop, bool abort)
update_jack = true;
}
- if (!(*i)->hidden() && ((*i)->active())) {
+ if (!(*i)->is_hidden() && ((*i)->active())) {
_worst_track_latency = max (_worst_track_latency, track_latency);
}
}
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index dd6d7a2067..052105cc85 100644
--- a/libs/ardour/track.cc
+++ b/libs/ardour/track.cc
@@ -40,7 +40,7 @@ using namespace PBD;
Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type)
: Route (sess, name, 1, -1, -1, -1, flag, default_type)
- , _rec_enable_control (*this)
+ , _rec_enable_control (new RecEnableControllable(*this))
{
_declickable = true;
_freeze_record.state = NoFreeze;
@@ -50,7 +50,7 @@ Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, Data
Track::Track (Session& sess, const XMLNode& node, DataType default_type)
: Route (sess, node)
- , _rec_enable_control (*this)
+ , _rec_enable_control (new RecEnableControllable(*this))
{
_freeze_record.state = NoFreeze;
_declickable = true;
@@ -188,7 +188,7 @@ Track::set_record_enable (bool yn, void *src)
set_meter_point (_saved_meter_point, this);
}
- _rec_enable_control.Changed ();
+ _rec_enable_control->Changed ();
}
diff --git a/libs/gtkmm2ext/barcontroller.cc b/libs/gtkmm2ext/barcontroller.cc
index c3c15b4281..142d224171 100644
--- a/libs/gtkmm2ext/barcontroller.cc
+++ b/libs/gtkmm2ext/barcontroller.cc
@@ -349,7 +349,8 @@ BarController::expose (GdkEventExpose* event)
char buf[64];
buf[0] = '\0';
- label_callback (buf, 64);
+ if (label_callback)
+ label_callback (buf, 64);
if (buf[0] != '\0') {
diff --git a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
index c91f4c8a06..ba2e1f3f7b 100644
--- a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
+++ b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
@@ -32,7 +32,10 @@ namespace Gtkmm2ext {
class BarController : public Gtk::Frame
{
public:
- BarController (Gtk::Adjustment& adj, PBD::Controllable&, sigc::slot<void,char*,unsigned int>);
+ typedef sigc::slot<void,char*,unsigned int> LabelCallback;
+
+ BarController (Gtk::Adjustment& adj, PBD::Controllable&, LabelCallback lc = LabelCallback());
+
virtual ~BarController () {}
enum Style {
@@ -40,6 +43,7 @@ class BarController : public Gtk::Frame
RightToLeft,
Line,
CenterOut,
+
TopToBottom,
BottomToTop
};
@@ -64,7 +68,7 @@ class BarController : public Gtk::Frame
Gtk::Adjustment& adjustment;
BindingProxy binding_proxy;
Gtk::DrawingArea darea;
- sigc::slot<void,char*,unsigned int> label_callback;
+ LabelCallback label_callback;
Glib::RefPtr<Pango::Layout> layout;
Style _style;
bool grabbed;
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index 16b35397cf..5ef28d4549 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -228,9 +228,9 @@ MackieControlProtocol::Sorted MackieControlProtocol::get_sorted_routes()
Route & route = **it;
if (
route.active()
- && !route.master()
- && !route.hidden()
- && !route.control()
+ && !route.is_master()
+ && !route.is_hidden()
+ && !route.is_control()
&& remote_ids.find( route.remote_control_id() ) == remote_ids.end()
)
{
@@ -1019,7 +1019,7 @@ void MackieControlProtocol::notify_panner_changed( RouteSignal * route_signal )
// TODO handle plugin automation polling
void MackieControlProtocol::update_automation( RouteSignal & rs )
{
- ARDOUR::AutoState gain_state = rs.route().gain_automation().automation_state();
+ ARDOUR::AutoState gain_state = rs.route().gain_control()->list()->automation_state();
if ( gain_state == Touch || gain_state == Play )
{
notify_gain_changed( &rs );
diff --git a/libs/surfaces/mackie/route_signal.cc b/libs/surfaces/mackie/route_signal.cc
index 85c234436a..b01b5e0cf5 100644
--- a/libs/surfaces/mackie/route_signal.cc
+++ b/libs/surfaces/mackie/route_signal.cc
@@ -20,6 +20,7 @@
#include <ardour/route.h>
#include <ardour/track.h>
#include <ardour/panner.h>
+#include <ardour/types.h>
#include "mackie_control_protocol.h"
@@ -30,13 +31,13 @@ using namespace Mackie;
void RouteSignal::connect()
{
if ( _strip.has_solo() )
- _solo_changed_connection = _route.solo_control().Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_solo_changed ), this ) );
+ _solo_changed_connection = _route.solo_control()->Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_solo_changed ), this ) );
if ( _strip.has_mute() )
- _mute_changed_connection = _route.mute_control().Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_mute_changed ), this ) );
+ _mute_changed_connection = _route.mute_control()->Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_mute_changed ), this ) );
if ( _strip.has_gain() )
- _gain_changed_connection = _route.gain_control().Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_gain_changed ), this ) );
+ _gain_changed_connection = _route.control(ARDOUR::GainAutomation)->Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_gain_changed ), this ) );
_name_changed_connection = _route.NameChanged.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_name_changed ), this ) );
@@ -48,7 +49,7 @@ void RouteSignal::connect()
try
{
_record_enable_changed_connection =
- dynamic_cast<ARDOUR::Track&>( _route ).rec_enable_control().Changed
+ dynamic_cast<ARDOUR::Track&>( _route ).rec_enable_control()->Changed
.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_record_enable_changed ), this ) )
;
}