summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/SConscript1
-rw-r--r--libs/ardour/ardour/amp.h2
-rw-r--r--libs/ardour/ardour/audiofilesource.h3
-rw-r--r--libs/ardour/ardour/automatable.h78
-rw-r--r--libs/ardour/ardour/automation_event.h4
-rw-r--r--libs/ardour/ardour/curve.h2
-rw-r--r--libs/ardour/ardour/diskstream.h9
-rw-r--r--libs/ardour/ardour/insert.h70
-rw-r--r--libs/ardour/ardour/io.h33
-rw-r--r--libs/ardour/ardour/meter.h13
-rw-r--r--libs/ardour/ardour/midi_track.h2
-rw-r--r--libs/ardour/ardour/playlist.h10
-rw-r--r--libs/ardour/ardour/plugin_insert.h4
-rw-r--r--libs/ardour/ardour/port_insert.h6
-rw-r--r--libs/ardour/ardour/redirect.h93
-rw-r--r--libs/ardour/ardour/route.h75
-rw-r--r--libs/ardour/ardour/send.h8
-rw-r--r--libs/ardour/ardour/session.h6
-rw-r--r--libs/ardour/ardour/smf_source.h3
-rw-r--r--libs/ardour/ardour/source.h12
-rw-r--r--libs/ardour/ardour/track.h2
-rw-r--r--libs/ardour/audio_diskstream.cc2
-rw-r--r--libs/ardour/audio_track.cc27
-rw-r--r--libs/ardour/audiofilesource.cc2
-rw-r--r--libs/ardour/automatable.cc267
-rw-r--r--libs/ardour/diskstream.cc16
-rw-r--r--libs/ardour/insert.cc215
-rw-r--r--libs/ardour/io.cc53
-rw-r--r--libs/ardour/meter.cc14
-rw-r--r--libs/ardour/midi_diskstream.cc2
-rw-r--r--libs/ardour/midi_track.cc46
-rw-r--r--libs/ardour/playlist.cc23
-rw-r--r--libs/ardour/plugin_insert.cc149
-rw-r--r--libs/ardour/port_insert.cc72
-rw-r--r--libs/ardour/redirect.cc403
-rw-r--r--libs/ardour/route.cc549
-rw-r--r--libs/ardour/route_group.cc1
-rw-r--r--libs/ardour/send.cc107
-rw-r--r--libs/ardour/session.cc54
-rw-r--r--libs/ardour/session_state.cc2
-rw-r--r--libs/ardour/session_transport.cc12
-rw-r--r--libs/ardour/smf_source.cc2
-rw-r--r--libs/ardour/source.cc10
-rw-r--r--libs/ardour/track.cc22
44 files changed, 1328 insertions, 1158 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index c3025ddf97..f56d85f088 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -74,6 +74,7 @@ gain.cc
gdither.cc
globals.cc
import.cc
+automatable.cc
insert.cc
plugin_insert.cc
port_insert.cc
diff --git a/libs/ardour/ardour/amp.h b/libs/ardour/ardour/amp.h
index c3049c1e8b..e5a4c189e9 100644
--- a/libs/ardour/ardour/amp.h
+++ b/libs/ardour/ardour/amp.h
@@ -28,6 +28,8 @@ class BufferSet;
/** Applies a declick operation to all audio inputs, passing the same number of
* audio outputs, and passing through any other types unchanged.
+ *
+ * FIXME: make this an insert.
*/
class Amp {
public:
diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h
index 149ceb7dc3..78d10f9d64 100644
--- a/libs/ardour/ardour/audiofilesource.h
+++ b/libs/ardour/ardour/audiofilesource.h
@@ -56,7 +56,8 @@ class AudioFileSource : public AudioSource {
virtual ~AudioFileSource ();
- int set_name (Glib::ustring newname, bool destructive);
+ bool set_name (const std::string& newname) { return (set_source_name(newname, destructive()) == 0); }
+ int set_source_name (Glib::ustring newname, bool destructive);
Glib::ustring path() const { return _path; }
Glib::ustring peak_path (Glib::ustring audio_path);
diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h
new file mode 100644
index 0000000000..c6621b9780
--- /dev/null
+++ b/libs/ardour/ardour/automatable.h
@@ -0,0 +1,78 @@
+/*
+ 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
+ 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_automatable_h__
+#define __ardour_automatable_h__
+
+#include <set>
+#include <map>
+#include <ardour/session_object.h>
+#include <ardour/automation_event.h>
+
+namespace ARDOUR {
+
+class Session;
+
+class Automatable : public SessionObject
+{
+public:
+ Automatable(Session&, const std::string& name);
+
+ virtual ~Automatable() {}
+
+ virtual AutomationList& automation_list(uint32_t n);
+
+ virtual void automation_snapshot (nframes_t now) {};
+
+ virtual bool find_next_event(nframes_t start, nframes_t end, ControlEvent& ev) const;
+
+ virtual string describe_parameter(uint32_t which);
+ virtual float default_parameter_value(uint32_t which) { return 1.0f; }
+
+ void what_has_automation(std::set<uint32_t>&) const;
+ void what_has_visible_automation(std::set<uint32_t>&) const;
+ const std::set<uint32_t>& what_can_be_automated() const { return _can_automate_list; }
+
+ void mark_automation_visible(uint32_t, bool);
+
+protected:
+
+ void can_automate(uint32_t);
+
+ virtual void automation_list_creation_callback(uint32_t, AutomationList&) {}
+
+ int set_automation_state(const XMLNode&);
+ XMLNode& get_automation_state();
+
+ int load_automation (const std::string& path);
+ int old_set_automation_state(const XMLNode&);
+
+ mutable Glib::Mutex _automation_lock;
+
+ // FIXME: map with int keys is a bit silly. this could be O(1)
+ std::map<uint32_t,AutomationList*> _parameter_automation;
+ std::set<uint32_t> _visible_parameter_automation;
+ std::set<uint32_t> _can_automate_list;
+
+ nframes_t _last_automation_snapshot;
+};
+
+} // namespace ARDOUR
+
+#endif /* __ardour_automatable_h__ */
diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h
index 5a9792c11d..f04dcdc112 100644
--- a/libs/ardour/ardour/automation_event.h
+++ b/libs/ardour/ardour/automation_event.h
@@ -114,10 +114,10 @@ class AutomationList : public PBD::StatefulDestructible
AutoStyle automation_style() const { return _style; }
sigc::signal<void> automation_state_changed;
- bool automation_playback() {
+ bool automation_playback() const {
return (_state & Play) || ((_state & Touch) && !_touching);
}
- bool automation_write () {
+ bool automation_write () const {
return (_state & Write) || ((_state & Touch) && _touching);
}
diff --git a/libs/ardour/ardour/curve.h b/libs/ardour/ardour/curve.h
index dd63439f08..605eda2e4b 100644
--- a/libs/ardour/ardour/curve.h
+++ b/libs/ardour/ardour/curve.h
@@ -60,7 +60,7 @@ class Curve : public AutomationList
void solve ();
- static sigc::signal<void, Curve*> CurveCreated;
+ static sigc::signal<void, Curve*> CurveCreated;
protected:
ControlEvent* point_factory (double,double) const;
diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h
index 4809e17868..3dd6555011 100644
--- a/libs/ardour/ardour/diskstream.h
+++ b/libs/ardour/ardour/diskstream.h
@@ -53,7 +53,7 @@ class Session;
class Playlist;
class IO;
-class Diskstream : public PBD::StatefulDestructible
+class Diskstream : public SessionObject
{
public:
enum Flag {
@@ -65,9 +65,8 @@ class Diskstream : public PBD::StatefulDestructible
Diskstream (Session &, const string& name, Flag f = Recordable);
Diskstream (Session &, const XMLNode&);
virtual ~Diskstream();
-
- string name () const { return _name; }
- virtual int set_name (string str);
+
+ bool set_name (const string& str);
ARDOUR::IO* io() const { return _io; }
void set_io (ARDOUR::IO& io);
@@ -238,8 +237,6 @@ class Diskstream : public PBD::StatefulDestructible
uint32_t i_am_the_modifier;
- string _name;
- ARDOUR::Session& _session;
ARDOUR::IO* _io;
ChanCount _n_channels;
diff --git a/libs/ardour/ardour/insert.h b/libs/ardour/ardour/insert.h
index 618b7c6446..3fc9fbd1e4 100644
--- a/libs/ardour/ardour/insert.h
+++ b/libs/ardour/ardour/insert.h
@@ -24,11 +24,16 @@
#include <string>
#include <exception>
+#include <pbd/statefuldestructible.h>
+
#include <sigc++/signal.h>
+
+#include <ardour/types.h>
#include <ardour/ardour.h>
-#include <ardour/redirect.h>
#include <ardour/plugin_state.h>
-#include <ardour/types.h>
+#include <ardour/buffer_set.h>
+#include <ardour/automatable.h>
+
class XMLNode;
@@ -36,26 +41,71 @@ namespace ARDOUR {
class Session;
-class Insert : public Redirect
+/* A mixer strip element - plugin, send, meter, etc.
+ */
+class Insert : public Automatable
{
public:
- Insert(Session& s, std::string name, Placement p);
- Insert(Session& s, std::string name, Placement p, int imin, int imax, int omin, int omax);
+ static const string state_node_name;
+
+ Insert(Session&, const string& name, Placement p); // TODO: remove placement in favour of sort key
virtual ~Insert() { }
+
+ static boost::shared_ptr<Insert> clone (boost::shared_ptr<const Insert>);
+
+ uint32_t sort_key() const { return _sort_key; }
+ void set_sort_key (uint32_t key);
+
+ Placement placement() const { return _placement; }
+ void set_placement (Placement);
+
+ bool active () const { return _active; }
+ void set_active (bool yn);
+
+ bool get_next_ab_is_active () const { return _next_ab_is_active; }
+ void set_next_ab_is_active (bool yn) { _next_ab_is_active = yn; }
+
+ virtual nframes_t latency() { return 0; }
+
+ virtual void transport_stopped (nframes_t frame) {}
+
+ virtual void set_block_size (nframes_t nframes) {}
virtual void run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset) = 0;
+ virtual void silence (nframes_t nframes, nframes_t offset) {}
+
+ virtual void activate () { _active = true; ActiveChanged.emit(); }
+ virtual void deactivate () { _active = false; ActiveChanged.emit(); }
- virtual void activate () {}
- virtual void deactivate () {}
+ virtual bool configure_io (ChanCount in, ChanCount out) { _configured_input = in; return (_configured = true); }
+
+ /* Act as a pass through, if not overridden */
+ 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; }
+ virtual ChanCount input_streams () const { return _configured_input; }
+
+ virtual XMLNode& state (bool full);
+ virtual XMLNode& get_state (void);
+ virtual int set_state (const XMLNode&);
+
+ void *get_gui () const { return _gui; }
+ void set_gui (void *p) { _gui = p; }
+
+ static sigc::signal<void,Insert*> InsertCreated;
- virtual bool can_support_input_configuration (ChanCount in) const = 0;
- virtual ChanCount output_for_input_configuration (ChanCount in) const = 0;
- virtual bool configure_io (ChanCount in, ChanCount out) = 0;
+ sigc::signal<void> ActiveChanged;
+ sigc::signal<void> PlacementChanged;
protected:
+ bool _active;
+ bool _next_ab_is_active;
bool _configured;
ChanCount _configured_input;
+ Placement _placement;
+ uint32_t _sort_key;
+ void* _gui; /* generic, we don't know or care what this is */
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 0b86eb4088..3952d14c0e 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -34,6 +34,7 @@
#include <pbd/controllable.h>
#include <ardour/ardour.h>
+#include <ardour/session_object.h>
#include <ardour/utils.h>
#include <ardour/curve.h>
#include <ardour/types.h>
@@ -63,13 +64,13 @@ class BufferSet;
* An IO can contain ports of varying types, making routes/inserts/etc with
* varied combinations of types (eg MIDI and audio) possible.
*/
-class IO : public PBD::StatefulDestructible
+class IO : public SessionObject
{
public:
static const string state_node_name;
- IO (Session&, string name,
+ IO (Session&, const string& name,
int input_min = -1, int input_max = -1,
int output_min = -1, int output_max = -1,
DataType default_type = DataType::AUDIO);
@@ -90,10 +91,9 @@ class IO : public PBD::StatefulDestructible
DataType default_type() const { return _default_type; }
void set_default_type(DataType t) { _default_type = t; }
-
- const string& name() const { return _name; }
- virtual int set_name (string str, void *src);
+ bool set_name (const string& str);
+
virtual void silence (nframes_t, nframes_t offset);
void collect_input (BufferSet& bufs, nframes_t nframes, nframes_t offset);
@@ -179,7 +179,6 @@ class IO : public PBD::StatefulDestructible
sigc::signal<void,IOChange,void*> output_changed;
sigc::signal<void,void*> gain_changed;
- sigc::signal<void,void*> name_changed;
virtual XMLNode& state (bool full);
XMLNode& get_state (void);
@@ -229,26 +228,16 @@ class IO : public PBD::StatefulDestructible
void clear_automation ();
- bool gain_automation_recording() const {
- return (_gain_automation_curve.automation_state() & (Write|Touch));
- }
-
- bool gain_automation_playback() const {
- return (_gain_automation_curve.automation_state() & Play) ||
- ((_gain_automation_curve.automation_state() & Touch) &&
- !_gain_automation_curve.touching());
- }
-
virtual void set_gain_automation_state (AutoState);
AutoState gain_automation_state() const { return _gain_automation_curve.automation_state(); }
- sigc::signal<void> gain_automation_state_changed;
+ //sigc::signal<void> gain_automation_state_changed;
virtual void set_gain_automation_style (AutoStyle);
AutoStyle gain_automation_style () const { return _gain_automation_curve.automation_style(); }
- sigc::signal<void> gain_automation_style_changed;
+ //sigc::signal<void> gain_automation_style_changed;
- virtual void transport_stopped (nframes_t now);
- void automation_snapshot (nframes_t now);
+ virtual void transport_stopped (nframes_t now); // interface: matches Insert
+ void automation_snapshot (nframes_t now); // interface: matches Automatable
ARDOUR::Curve& gain_automation_curve () { return _gain_automation_curve; }
@@ -272,7 +261,6 @@ class IO : public PBD::StatefulDestructible
mutable Glib::Mutex io_lock;
protected:
- Session& _session;
Panner* _panner;
BufferSet* _output_buffers; //< Set directly to output port buffers
gain_t _gain;
@@ -282,7 +270,6 @@ class IO : public PBD::StatefulDestructible
PortSet _outputs;
PortSet _inputs;
PeakMeter* _meter;
- string _name;
Bundle* _input_bundle;
Bundle* _output_bundle;
bool no_panner_reset;
@@ -336,6 +323,8 @@ class IO : public PBD::StatefulDestructible
private:
+ friend class Send;
+
/* are these the best variable names ever, or what? */
sigc::connection input_bundle_configuration_connection;
diff --git a/libs/ardour/ardour/meter.h b/libs/ardour/ardour/meter.h
index ed38fc4f0a..7e0bf8ac53 100644
--- a/libs/ardour/ardour/meter.h
+++ b/libs/ardour/ardour/meter.h
@@ -21,6 +21,7 @@
#include <vector>
#include <ardour/types.h>
+#include <ardour/insert.h>
#include <pbd/fastlog.h>
namespace ARDOUR {
@@ -32,16 +33,17 @@ class Session;
/** Meters peaks on the input and stores them for access.
*/
-class PeakMeter {
+class PeakMeter : public Insert {
public:
- PeakMeter(Session& s) : _session(s) {}
+ PeakMeter(Session& s) : Insert(s, "meter", PreFader) {}
- void setup (const ChanCount& in);
void reset ();
void reset_max ();
-
+
+ bool configure_io (ChanCount in, ChanCount out);
+
/** Compute peaks */
- void run (BufferSet& bufs, nframes_t nframes, nframes_t offset=0);
+ void run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset);
float peak_power (uint32_t n) {
if (n < _visible_peak_power.size()) {
@@ -64,7 +66,6 @@ private:
friend class IO;
void meter();
- Session& _session;
std::vector<float> _peak_power;
std::vector<float> _visible_peak_power;
std::vector<float> _max_peak_power;
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index c88878c167..fb350b8838 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -37,8 +37,6 @@ public:
MidiTrack (Session&, const XMLNode&);
~MidiTrack ();
- int set_name (string str, void *src);
-
int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
nframes_t offset, int declick, bool can_record, bool rec_monitors_input);
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index 9eb66f66b6..55947a84a5 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -38,6 +38,7 @@
#include <pbd/statefuldestructible.h>
#include <ardour/ardour.h>
+#include <ardour/session_object.h>
#include <ardour/crossfade_compare.h>
#include <ardour/location.h>
#include <ardour/data_type.h>
@@ -47,7 +48,7 @@ namespace ARDOUR {
class Session;
class Region;
-class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_from_this<Playlist> {
+class Playlist : public SessionObject, public boost::enable_shared_from_this<Playlist> {
public:
typedef list<boost::shared_ptr<Region> > RegionList;
@@ -67,8 +68,7 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f
void release();
bool used () const { return _refcnt != 0; }
- std::string name() const { return _name; }
- void set_name (std::string str);
+ bool set_name (const string& str);
const DataType& data_type() const { return _type; }
@@ -130,8 +130,6 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f
uint32_t read_data_count() const { return _read_data_count; }
- Session& session() { return _session; }
-
const PBD::ID& get_orig_diskstream_id () const { return _orig_diskstream_id; }
void set_orig_diskstream_id (const PBD::ID& did) { _orig_diskstream_id = did; }
@@ -170,8 +168,6 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f
RegionList regions; /* the current list of regions in the playlist */
std::set<boost::shared_ptr<Region> > all_regions; /* all regions ever added to this playlist */
- string _name;
- Session& _session;
DataType _type;
mutable gint block_notifications;
mutable gint ignore_state_changes;
diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h
index 37cf0d49b2..4acacae7f5 100644
--- a/libs/ardour/ardour/plugin_insert.h
+++ b/libs/ardour/ardour/plugin_insert.h
@@ -22,13 +22,13 @@
#include <vector>
#include <string>
-#include <exception>
#include <sigc++/signal.h>
#include <ardour/ardour.h>
#include <ardour/plugin_state.h>
#include <ardour/types.h>
#include <ardour/insert.h>
+#include <ardour/automation_event.h>
class XMLNode;
@@ -105,7 +105,7 @@ class PluginInsert : public Insert
void parameter_changed (uint32_t, float);
- vector<boost::shared_ptr<Plugin> > _plugins;
+ std::vector<boost::shared_ptr<Plugin> > _plugins;
void automation_run (BufferSet& bufs, nframes_t nframes, nframes_t offset);
void connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t offset, bool with_auto, nframes_t now = 0);
diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h
index 4898efc789..5d9cd583cb 100644
--- a/libs/ardour/ardour/port_insert.h
+++ b/libs/ardour/ardour/port_insert.h
@@ -26,7 +26,7 @@
#include <sigc++/signal.h>
#include <ardour/ardour.h>
-#include <ardour/insert.h>
+#include <ardour/redirect.h>
#include <ardour/plugin_state.h>
#include <ardour/types.h>
@@ -37,8 +37,10 @@ namespace ARDOUR {
class Session;
/** Port inserts: send output to a Jack port, pick up input at a Jack port
+ *
+ * PortInsert IS-A Redirect IS-A Insert, IO
*/
-class PortInsert : public Insert
+class PortInsert : public Redirect
{
public:
PortInsert (Session&, Placement);
diff --git a/libs/ardour/ardour/redirect.h b/libs/ardour/ardour/redirect.h
index fbbb295a24..bc12bb6a8a 100644
--- a/libs/ardour/ardour/redirect.h
+++ b/libs/ardour/ardour/redirect.h
@@ -32,6 +32,7 @@
#include <pbd/undo.h>
#include <ardour/ardour.h>
+#include <ardour/insert.h>
#include <ardour/io.h>
#include <ardour/automation_event.h>
@@ -46,97 +47,37 @@ namespace ARDOUR {
class Session;
-class Redirect : public IO
+/** A mixer strip element (Insert) with Jack ports (IO).
+ */
+class Redirect : public Insert
{
public:
- static const string state_node_name;
-
Redirect (Session&, const string& name, Placement,
int input_min = -1, int input_max = -1, int output_min = -1, int output_max = -1);
Redirect (const Redirect&);
virtual ~Redirect ();
+
+ virtual ChanCount output_streams() const { return _io->n_outputs(); }
+ virtual ChanCount input_streams () const { return _io->n_inputs(); }
+ virtual ChanCount natural_output_streams() const { return _io->n_outputs(); }
+ virtual ChanCount natural_input_streams () const { return _io->n_inputs(); }
- static boost::shared_ptr<Redirect> clone (boost::shared_ptr<const Redirect>);
-
- bool active () const { return _active; }
- void set_active (bool yn, void *src);
-
- virtual ChanCount output_streams() const { return n_outputs(); }
- virtual ChanCount input_streams () const { return n_inputs(); }
- virtual ChanCount natural_output_streams() const { return n_outputs(); }
- virtual ChanCount natural_input_streams () const { return n_inputs(); }
-
- uint32_t sort_key() const { return _sort_key; }
- void set_sort_key (uint32_t key);
-
- Placement placement() const { return _placement; }
- void set_placement (Placement, void *src);
+ boost::shared_ptr<IO> io() { return _io; }
+ boost::shared_ptr<const IO> io() const { return _io; }
+
+ virtual void automation_snapshot (nframes_t now) { _io->automation_snapshot(now); }
virtual void run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset) = 0;
- virtual void activate () = 0;
- virtual void deactivate () = 0;
- virtual nframes_t latency() { return 0; }
-
- virtual void set_block_size (nframes_t nframes) {}
+ void silence (nframes_t nframes, nframes_t offset);
- sigc::signal<void,Redirect*,void*> active_changed;
- sigc::signal<void,Redirect*,void*> placement_changed;
- sigc::signal<void,Redirect*,bool> AutomationPlaybackChanged;
+ sigc::signal<void,Redirect*,bool> AutomationPlaybackChanged;
sigc::signal<void,Redirect*,uint32_t> AutomationChanged;
-
- static sigc::signal<void,Redirect*> RedirectCreated;
- XMLNode& state (bool full);
- XMLNode& get_state (void);
+ XMLNode& state (bool full_state);
int set_state (const XMLNode&);
-
- void *get_gui () const { return _gui; }
- void set_gui (void *p) { _gui = p; }
-
- virtual string describe_parameter (uint32_t which);
- virtual float default_parameter_value (uint32_t which) {
- return 1.0f;
- }
-
- void what_has_automation (set<uint32_t>&) const;
- void what_has_visible_automation (set<uint32_t>&) const;
- const set<uint32_t>& what_can_be_automated () const { return can_automate_list; }
-
- void mark_automation_visible (uint32_t, bool);
-
- AutomationList& automation_list (uint32_t);
- bool find_next_event (nframes_t, nframes_t, ControlEvent&) const;
-
- virtual void transport_stopped (nframes_t frame) {};
-
- bool get_next_ab_is_active () const { return _next_ab_is_active; }
- void set_next_ab_is_active (bool yn);
protected:
- /* children may use this stuff as they see fit */
-
- map<uint32_t,AutomationList*> parameter_automation;
- set<uint32_t> visible_parameter_automation;
-
- mutable Glib::Mutex _automation_lock;
-
- void can_automate (uint32_t);
- set<uint32_t> can_automate_list;
-
- virtual void automation_list_creation_callback (uint32_t, AutomationList&) {}
-
- int set_automation_state (const XMLNode&);
- XMLNode& get_automation_state ();
-
- private:
- bool _active;
- bool _next_ab_is_active;
- Placement _placement;
- uint32_t _sort_key;
- void* _gui; /* generic, we don't know or care what this is */
-
- int old_set_automation_state (const XMLNode&);
- int load_automation (std::string path);
+ boost::shared_ptr<IO> _io;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index b5d1fa03d6..4f5f863fee 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -59,7 +59,8 @@ class Route : public IO
{
protected:
- typedef list<boost::shared_ptr<Redirect> > RedirectList;
+ typedef list<boost::shared_ptr<Insert> > InsertList;
+
public:
enum Flag {
@@ -99,7 +100,7 @@ class Route : public IO
virtual bool can_record() { return false; }
virtual void set_record_enable (bool yn, void *src) {}
virtual bool record_enabled() const { return false; }
- virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_redirects);
+ virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_inserts);
virtual void set_pending_declick (int);
/* end of vfunc-based API */
@@ -136,54 +137,54 @@ class Route : public IO
virtual void set_meter_point (MeterPoint, void *src);
MeterPoint meter_point() const { return _meter_point; }
- /* Redirects */
+ /* Inserts */
- void flush_redirects ();
+ void flush_inserts ();
- template<class T> void foreach_redirect (T *obj, void (T::*func)(boost::shared_ptr<Redirect>)) {
- Glib::RWLock::ReaderLock lm (redirect_lock);
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ template<class T> void foreach_insert (T *obj, void (T::*func)(boost::shared_ptr<Insert>)) {
+ Glib::RWLock::ReaderLock lm (insert_lock);
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
(obj->*func) (*i);
}
}
- boost::shared_ptr<Redirect> nth_redirect (uint32_t n) {
- Glib::RWLock::ReaderLock lm (redirect_lock);
- RedirectList::iterator i;
- for (i = _redirects.begin(); i != _redirects.end() && n; ++i, --n);
- if (i == _redirects.end()) {
+ boost::shared_ptr<Insert> nth_insert (uint32_t n) {
+ Glib::RWLock::ReaderLock lm (insert_lock);
+ InsertList::iterator i;
+ for (i = _inserts.begin(); i != _inserts.end() && n; ++i, --n);
+ if (i == _inserts.end()) {
return boost::shared_ptr<Redirect> ();
} else {
return *i;
}
}
- ChanCount max_redirect_outs () const { return redirect_max_outs; }
+ ChanCount max_insert_outs () const { return insert_max_outs; }
ChanCount pre_fader_streams() const;
- /** A record of the stream configuration at some point in the redirect list.
- * Used to return where and why a redirect list configuration request failed.
+ /** A record of the stream configuration at some point in the insert list.
+ * Used to return where and why an insert list configuration request failed.
*/
struct InsertStreams {
InsertStreams(size_t i=0, ChanCount c=ChanCount()) : index(i), count(c) {}
- size_t index; ///< Index of redirect where configuration failed
- ChanCount count; ///< Input requested of redirect
+ size_t index; ///< Index of insert where configuration failed
+ ChanCount count; ///< Input requested of insert
};
- int add_redirect (boost::shared_ptr<Redirect>, void *src, InsertStreams* err = 0);
- int add_redirects (const RedirectList&, void *src, InsertStreams* err = 0);
- int remove_redirect (boost::shared_ptr<Redirect>, void *src, InsertStreams* err = 0);
- int copy_redirects (const Route&, Placement, InsertStreams* err = 0);
- int sort_redirects (InsertStreams* err = 0);
- void disable_redirects (Placement);
- void disable_redirects ();
+ int add_insert (boost::shared_ptr<Insert>, InsertStreams* err = 0);
+ int add_inserts (const InsertList&, InsertStreams* err = 0);
+ int remove_insert (boost::shared_ptr<Insert>, InsertStreams* err = 0);
+ int copy_inserts (const Route&, Placement, InsertStreams* err = 0);
+ int sort_inserts (InsertStreams* err = 0);
+ void disable_inserts (Placement);
+ void disable_inserts ();
void disable_plugins (Placement);
void disable_plugins ();
void ab_plugins (bool forward);
- void clear_redirects (Placement, void *src);
- void all_redirects_flip();
- void all_redirects_active (Placement, bool state);
+ void clear_inserts (Placement);
+ void all_inserts_flip();
+ void all_inserts_active (Placement, bool state);
virtual nframes_t update_total_latency();
nframes_t signal_latency() const { return _own_latency; }
@@ -197,7 +198,7 @@ class Route : public IO
sigc::signal<void,void*> post_fader_changed;
sigc::signal<void,void*> control_outs_changed;
sigc::signal<void,void*> main_outs_changed;
- sigc::signal<void,void*> redirects_changed;
+ sigc::signal<void> inserts_changed;
sigc::signal<void,void*> record_enable_changed;
sigc::signal<void,void*> edit_group_changed;
sigc::signal<void,void*> mix_group_changed;
@@ -214,8 +215,8 @@ class Route : public IO
int set_state(const XMLNode& node);
virtual XMLNode& get_template();
- XMLNode& get_redirect_state ();
- int set_redirect_state (const XMLNode&);
+ XMLNode& get_insert_state ();
+ int set_insert_state (const XMLNode&);
sigc::signal<void,void*> SelectedChanged;
@@ -294,8 +295,8 @@ class Route : public IO
nframes_t _initial_delay;
nframes_t _roll_delay;
nframes_t _own_latency;
- RedirectList _redirects;
- Glib::RWLock redirect_lock;
+ InsertList _inserts;
+ Glib::RWLock insert_lock;
IO *_control_outs;
Glib::Mutex control_outs_lock;
RouteGroup *_edit_group;
@@ -311,7 +312,7 @@ class Route : public IO
virtual void process_output_buffers (BufferSet& bufs,
nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, nframes_t offset, bool with_redirects, int declick,
+ nframes_t nframes, nframes_t offset, bool with_inserts, int declick,
bool meter);
protected:
@@ -326,14 +327,14 @@ class Route : public IO
sigc::connection input_signal_connection;
- ChanCount redirect_max_outs;
+ ChanCount insert_max_outs;
uint32_t _remote_control_id;
uint32_t pans_required() const;
ChanCount n_process_buffers ();
virtual int _set_state (const XMLNode&, bool call_base);
- virtual void _set_redirect_states (const XMLNodeList&);
+ virtual void _set_insert_states (const XMLNodeList&);
private:
void init ();
@@ -354,7 +355,6 @@ class Route : public IO
void input_change_handler (IOChange, void *src);
void output_change_handler (IOChange, void *src);
- bool legal_redirect (Redirect&);
int reset_plugin_counts (InsertStreams*); /* locked */
int _reset_plugin_counts (InsertStreams*); /* unlocked */
@@ -372,8 +372,7 @@ class Route : public IO
bool check_some_plugin_counts (std::list<InsertCount>& iclist, ChanCount required_inputs, InsertStreams* err_streams);
void set_deferred_state ();
- void add_redirect_from_xml (const XMLNode&);
- void redirect_active_proxy (Redirect*, void*);
+ void add_insert_from_xml (const XMLNode&);
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h
index d3ce6ddee8..dc509514e2 100644
--- a/libs/ardour/ardour/send.h
+++ b/libs/ardour/ardour/send.h
@@ -42,6 +42,9 @@ class Send : public Redirect
uint32_t bit_slot() const { return bitslot; }
+ ChanCount output_streams() const;
+ ChanCount input_streams () const;
+
void run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset);
void activate() {}
@@ -54,7 +57,10 @@ class Send : public Redirect
int set_state(const XMLNode& node);
uint32_t pans_required() const { return _expected_inputs.n_audio(); }
- void expect_inputs (const ChanCount&);
+
+ virtual bool can_support_input_configuration (ChanCount in) const;
+ virtual ChanCount output_for_input_configuration (ChanCount in) const;
+ virtual bool configure_io (ChanCount in, ChanCount out);
static uint32_t how_many_sends();
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 685e7f2284..1fea324406 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -1374,7 +1374,7 @@ class Session : public PBD::StatefulDestructible
void set_play_loop (bool yn);
void overwrite_some_buffers (Diskstream*);
- void flush_all_redirects ();
+ void flush_all_inserts ();
void locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
void start_locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
void force_locate (nframes_t frame, bool with_roll = false);
@@ -1521,8 +1521,8 @@ class Session : public PBD::StatefulDestructible
uint32_t insert_cnt;
- void add_redirect (Redirect *);
- void remove_redirect (Redirect *);
+ void add_insert (Insert *);
+ void remove_insert (Insert *);
/* S/W RAID */
diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h
index 086c77537d..e4d2611271 100644
--- a/libs/ardour/ardour/smf_source.h
+++ b/libs/ardour/ardour/smf_source.h
@@ -61,7 +61,8 @@ class SMFSource : public MidiSource {
virtual void mark_capture_end () {}
virtual void clear_capture_marks() {}
- int set_name (string newname, bool destructive);
+ bool set_name (const std::string& newname) { return (set_source_name(newname, false) == 0); }
+ int set_source_name (string newname, bool destructive);
string path() const { return _path; }
diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h
index 2a6e0c8638..029469f491 100644
--- a/libs/ardour/ardour/source.h
+++ b/libs/ardour/ardour/source.h
@@ -28,6 +28,7 @@
#include <pbd/statefuldestructible.h>
#include <ardour/ardour.h>
+#include <ardour/session_object.h>
#include <ardour/data_type.h>
namespace ARDOUR {
@@ -35,17 +36,14 @@ namespace ARDOUR {
class Session;
class Playlist;
-class Source : public PBD::StatefulDestructible
+class Source : public SessionObject
{
public:
- Source (Session&, std::string name, DataType type);
+ Source (Session&, const std::string& name, DataType type);
Source (Session&, const XMLNode&);
virtual ~Source ();
-
- std::string name() const { return _name; }
- int set_name (std::string str, bool destructive);
-
+
DataType type() { return _type; }
time_t timestamp() const { return _timestamp; }
@@ -76,8 +74,6 @@ class Source : public PBD::StatefulDestructible
protected:
void update_length (nframes_t pos, nframes_t cnt);
- Session& _session;
- string _name;
DataType _type;
time_t _timestamp;
nframes_t _length;
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
index eee04d9bfa..5d87a13886 100644
--- a/libs/ardour/ardour/track.h
+++ b/libs/ardour/ardour/track.h
@@ -37,7 +37,7 @@ class Track : public Route
virtual ~Track ();
- int set_name (string str, void *src);
+ bool set_name (const std::string& str);
TrackMode mode () const { return _mode; }
virtual int set_mode (TrackMode m) { return false; }
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 8ff9c04442..7e583afeb7 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -2024,7 +2024,7 @@ AudioDiskstream::rename_write_sources ()
for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
if ((*chan)->write_source != 0) {
- (*chan)->write_source->set_name (_name, destructive());
+ (*chan)->write_source->set_source_name (_name, destructive());
/* XXX what to do if one of them fails ? */
}
}
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index d0012b6d80..b08990c2ab 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -515,7 +515,7 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
{
- Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
+ Glib::RWLock::ReaderLock lm (insert_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
@@ -524,7 +524,7 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
}
- if (n_outputs().n_total() == 0 && _redirects.empty()) {
+ if (n_outputs().n_total() == 0 && _inserts.empty()) {
return 0;
}
@@ -601,7 +601,7 @@ 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_playback()) {
+ if (am.locked() && _gain_automation_curve.automation_playback()) {
apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
}
}
@@ -620,7 +620,7 @@ int
AudioTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
bool can_record, bool rec_monitors_input)
{
- if (n_outputs().n_total() == 0 && _redirects.empty()) {
+ if (n_outputs().n_total() == 0 && _inserts.empty()) {
return 0;
}
@@ -643,12 +643,12 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes
gain_t gain_automation[nframes];
gain_t gain_buffer[nframes];
float mix_buffer[nframes];
- RedirectList::iterator i;
+ InsertList::iterator i;
bool post_fader_work = false;
gain_t this_gain = _gain;
boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
- Glib::RWLock::ReaderLock rlock (redirect_lock);
+ Glib::RWLock::ReaderLock rlock (insert_lock);
boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist());
assert(apl);
@@ -681,7 +681,7 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes
will already have checked that there are no external port inserts.
*/
- for (i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (i = _inserts.begin(); i != _inserts.end(); ++i) {
boost::shared_ptr<Insert> insert;
if ((insert = boost::dynamic_pointer_cast<Insert>(*i)) != 0) {
@@ -719,7 +719,7 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes
if (post_fader_work) {
- for (i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (i = _inserts.begin(); i != _inserts.end(); ++i) {
boost::shared_ptr<PluginInsert> insert;
if ((insert = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
@@ -800,9 +800,9 @@ AudioTrack::freeze (InterThreadInfo& itt)
_freeze_record.have_mementos = true;
{
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
- for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
+ for (InsertList::iterator r = _inserts.begin(); r != _inserts.end(); ++r) {
boost::shared_ptr<Insert> insert;
@@ -816,7 +816,8 @@ AudioTrack::freeze (InterThreadInfo& itt)
/* now deactivate the insert */
- insert->set_active (false, this);
+ insert->set_active (false);
+ _session.set_dirty ();
}
}
}
@@ -857,8 +858,8 @@ AudioTrack::unfreeze ()
} else {
- Glib::RWLock::ReaderLock lm (redirect_lock); // should this be a write lock? jlc
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ Glib::RWLock::ReaderLock lm (insert_lock); // should this be a write lock? jlc
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
if ((*ii)->id == (*i)->id()) {
(*i)->set_state (((*ii)->state));
diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc
index 5c22e2104a..4bbe28e251 100644
--- a/libs/ardour/audiofilesource.cc
+++ b/libs/ardour/audiofilesource.cc
@@ -573,7 +573,7 @@ AudioFileSource::set_allow_remove_if_empty (bool yn)
}
int
-AudioFileSource::set_name (ustring newname, bool destructive)
+AudioFileSource::set_source_name (ustring newname, bool destructive)
{
Glib::Mutex::Lock lm (_lock);
ustring oldpath = _path;
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
new file mode 100644
index 0000000000..2ce553a188
--- /dev/null
+++ b/libs/ardour/automatable.cc
@@ -0,0 +1,267 @@
+/*
+ Copyright (C) 2001,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
+ 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 <ardour/ardour.h>
+#include <fstream>
+#include <inttypes.h>
+#include <cstdio>
+#include <errno.h>
+#include <pbd/error.h>
+#include <pbd/enumwriter.h>
+#include <ardour/session.h>
+#include <ardour/automatable.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+
+Automatable::Automatable(Session& _session, const string& name)
+ : SessionObject(_session, name)
+ , _last_automation_snapshot(0)
+{}
+
+int
+Automatable::old_set_automation_state (const XMLNode& node)
+{
+ const XMLProperty *prop;
+
+ if ((prop = node.property ("path")) != 0) {
+ load_automation (prop->value());
+ } else {
+ warning << string_compose(_("%1: Automation node has no path property"), _name) << endmsg;
+ }
+
+ if ((prop = node.property ("visible")) != 0) {
+ uint32_t what;
+ stringstream sstr;
+
+ _visible_parameter_automation.clear ();
+
+ sstr << prop->value();
+ while (1) {
+ sstr >> what;
+ if (sstr.fail()) {
+ break;
+ }
+ mark_automation_visible (what, true);
+ }
+ }
+
+ return 0;
+}
+
+int
+Automatable::load_automation (const string& path)
+{
+ string fullpath;
+
+ if (path[0] == '/') { // legacy
+ fullpath = path;
+ } else {
+ fullpath = _session.automation_dir();
+ fullpath += path;
+ }
+ ifstream in (fullpath.c_str());
+
+ if (!in) {
+ warning << string_compose(_("%1: cannot open %2 to load automation data (%3)"), _name, fullpath, strerror (errno)) << endmsg;
+ return 1;
+ }
+
+ Glib::Mutex::Lock lm (_automation_lock);
+ set<uint32_t> tosave;
+ _parameter_automation.clear ();
+
+ while (in) {
+ double when;
+ double value;
+ uint32_t port;
+
+ in >> port; if (!in) break;
+ in >> when; if (!in) goto bad;
+ in >> value; if (!in) goto bad;
+
+ AutomationList& al = automation_list (port);
+ al.add (when, value);
+ tosave.insert (port);
+ }
+
+ return 0;
+
+ bad:
+ error << string_compose(_("%1: cannot load automation data from %2"), _name, fullpath) << endmsg;
+ _parameter_automation.clear ();
+ return -1;
+}
+
+
+void
+Automatable::what_has_automation (set<uint32_t>& s) const
+{
+ Glib::Mutex::Lock lm (_automation_lock);
+ map<uint32_t,AutomationList*>::const_iterator li;
+
+ for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
+ s.insert ((*li).first);
+ }
+}
+
+void
+Automatable::what_has_visible_automation (set<uint32_t>& s) const
+{
+ Glib::Mutex::Lock lm (_automation_lock);
+ set<uint32_t>::const_iterator li;
+
+ for (li = _visible_parameter_automation.begin(); li != _visible_parameter_automation.end(); ++li) {
+ s.insert (*li);
+ }
+}
+AutomationList&
+Automatable::automation_list (uint32_t parameter)
+{
+ AutomationList* al = _parameter_automation[parameter];
+
+ if (al == 0) {
+ al = _parameter_automation[parameter] = new AutomationList (default_parameter_value (parameter));
+ /* let derived classes do whatever they need with this */
+ automation_list_creation_callback (parameter, *al);
+ }
+
+ return *al;
+}
+
+string
+Automatable::describe_parameter (uint32_t which)
+{
+ /* derived classes will override this */
+ return "";
+}
+
+void
+Automatable::can_automate (uint32_t what)
+{
+ _can_automate_list.insert (what);
+}
+
+void
+Automatable::mark_automation_visible (uint32_t what, bool yn)
+{
+ if (yn) {
+ _visible_parameter_automation.insert (what);
+ } else {
+ set<uint32_t>::iterator i;
+
+ if ((i = _visible_parameter_automation.find (what)) != _visible_parameter_automation.end()) {
+ _visible_parameter_automation.erase (i);
+ }
+ }
+}
+
+bool
+Automatable::find_next_event (nframes_t now, nframes_t end, ControlEvent& next_event) const
+{
+ map<uint32_t,AutomationList*>::const_iterator li;
+ AutomationList::TimeComparator cmp;
+
+ next_event.when = max_frames;
+
+ for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
+
+ AutomationList::const_iterator i;
+ const AutomationList& alist (*((*li).second));
+ 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) {
+ if ((*i)->when > now) {
+ break;
+ }
+ }
+
+ if (i != alist.const_end() && (*i)->when < end) {
+
+ if ((*i)->when < next_event.when) {
+ next_event.when = (*i)->when;
+ }
+ }
+ }
+
+ return next_event.when != max_frames;
+}
+
+int
+Automatable::set_automation_state (const XMLNode& node)
+{
+ Glib::Mutex::Lock lm (_automation_lock);
+
+ _parameter_automation.clear ();
+
+ XMLNodeList nlist = node.children();
+ XMLNodeIterator niter;
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ uint32_t param;
+
+ if (sscanf ((*niter)->name().c_str(), "parameter-%" PRIu32, &param) != 1) {
+ error << string_compose (_("%2: badly formatted node name in XML automation state, ignored"), _name) << endmsg;
+ continue;
+ }
+
+ AutomationList& al = automation_list (param);
+ if (al.set_state (*(*niter)->children().front())) {
+ goto bad;
+ }
+ }
+
+ return 0;
+
+ bad:
+ error << string_compose(_("%1: cannot load automation data from XML"), _name) << endmsg;
+ _parameter_automation.clear ();
+ return -1;
+}
+
+XMLNode&
+Automatable::get_automation_state ()
+{
+ Glib::Mutex::Lock lm (_automation_lock);
+ XMLNode* node = new XMLNode (X_("Automation"));
+ string fullpath;
+
+ if (_parameter_automation.empty()) {
+ return *node;
+ }
+
+ map<uint32_t,AutomationList*>::iterator li;
+
+ for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
+
+ XMLNode* child;
+
+ char buf[64];
+ stringstream str;
+ snprintf (buf, sizeof (buf), "parameter-%" PRIu32, li->first);
+ child = new XMLNode (buf);
+ child->add_child_nocopy (li->second->get_state ());
+ }
+
+ return *node;
+}
diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc
index 18aeb32931..8de2faeb15 100644
--- a/libs/ardour/diskstream.cc
+++ b/libs/ardour/diskstream.cc
@@ -67,14 +67,13 @@ sigc::signal<void> Diskstream::DiskOverrun;
sigc::signal<void> Diskstream::DiskUnderrun;
Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
- : _name (name)
- , _session (sess)
+ : SessionObject(sess, name)
{
init (flag);
}
Diskstream::Diskstream (Session& sess, const XMLNode& node)
- : _session (sess)
+ : SessionObject(sess, "unnamed diskstream")
{
init (Recordable);
}
@@ -377,23 +376,24 @@ Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
}
}
-int
-Diskstream::set_name (string str)
+bool
+Diskstream::set_name (const string& str)
{
if (str != _name) {
assert(playlist());
playlist()->set_name (str);
- _name = str;
+
+ SessionObject::set_name(str);
if (!in_set_state && recordable()) {
/* rename existing capture files so that they have the correct name */
return rename_write_sources ();
} else {
- return -1;
+ return false;
}
}
- return 0;
+ return true;
}
void
diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc
index 519bf1ad83..177aa5a98c 100644
--- a/libs/ardour/insert.cc
+++ b/libs/ardour/insert.cc
@@ -22,6 +22,7 @@
#include <sigc++/bind.h>
#include <pbd/failed_constructor.h>
+#include <pbd/enumwriter.h>
#include <pbd/xml++.h>
#include <ardour/insert.h>
@@ -30,6 +31,9 @@
#include <ardour/route.h>
#include <ardour/ladspa_plugin.h>
#include <ardour/buffer_set.h>
+#include <ardour/send.h>
+#include <ardour/port_insert.h>
+#include <ardour/plugin_insert.h>
#ifdef VST_SUPPORT
#include <ardour/vst_plugin.h>
@@ -49,17 +53,214 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-Insert::Insert(Session& s, string name, Placement p)
- : Redirect (s, name, p)
+sigc::signal<void,Insert*> Insert::InsertCreated;
+
+// Always saved as Insert, but may be Redirect in legacy sessions
+const string Insert::state_node_name = "Insert";
+
+Insert::Insert(Session& session, const string& name, Placement p)
+ : Automatable(session, name)
+ , _active(false)
+ , _next_ab_is_active(false)
, _configured(false)
+ , _placement(p)
+ , _gui(0)
{
- // FIXME: default type?
}
-Insert::Insert(Session& s, string name, Placement p, int imin, int imax, int omin, int omax)
- : Redirect (s, name, p, imin, imax, omin, omax)
- , _configured(false)
+boost::shared_ptr<Insert>
+Insert::clone (boost::shared_ptr<const Insert> other)
+{
+ boost::shared_ptr<const Send> send;
+ boost::shared_ptr<const PortInsert> port_insert;
+ boost::shared_ptr<const PluginInsert> plugin_insert;
+
+ if ((send = boost::dynamic_pointer_cast<const Send>(other)) != 0) {
+ return boost::shared_ptr<Insert> (new Send (*send));
+ } else if ((port_insert = boost::dynamic_pointer_cast<const PortInsert>(other)) != 0) {
+ return boost::shared_ptr<Insert> (new PortInsert (*port_insert));
+ } else if ((plugin_insert = boost::dynamic_pointer_cast<const PluginInsert>(other)) != 0) {
+ return boost::shared_ptr<Insert> (new PluginInsert (*plugin_insert));
+ } else {
+ fatal << _("programming error: unknown Insert type in Insert::Clone!\n")
+ << endmsg;
+ /*NOTREACHED*/
+ }
+ return boost::shared_ptr<Insert>();
+}
+
+void
+Insert::set_sort_key (uint32_t key)
+{
+ _sort_key = key;
+}
+
+void
+Insert::set_placement (Placement p)
+{
+ if (_placement != p) {
+ _placement = p;
+ PlacementChanged (); /* EMIT SIGNAL */
+ }
+}
+
+void
+Insert::set_active (bool yn)
+{
+ _active = yn;
+ ActiveChanged ();
+}
+
+XMLNode&
+Insert::get_state (void)
+{
+ return state (true);
+}
+
+/* NODE STRUCTURE
+
+ <Automation [optionally with visible="...." ]>
+ <parameter-N>
+ <AutomationList id=N>
+ <events>
+ X1 Y1
+ X2 Y2
+ ....
+ </events>
+ </parameter-N>
+ <Automation>
+*/
+
+XMLNode&
+Insert::state (bool full_state)
+{
+ XMLNode* node = new XMLNode (state_node_name);
+ stringstream sstr;
+
+ // FIXME: This conflicts with "id" used by plugin for name in legacy sessions (ugh).
+ // Do we need to serialize this?
+ /*
+ char buf[64];
+ id().print (buf, sizeof (buf));
+ node->add_property("id", buf);
+ */
+
+ node->add_property("name", _name);
+ node->add_property("active", active() ? "yes" : "no");
+ node->add_property("placement", enum_2_string (_placement));
+
+ if (_extra_xml){
+ node->add_child_copy (*_extra_xml);
+ }
+
+ if (full_state) {
+
+ XMLNode& automation = Automatable::get_automation_state();
+
+ for (set<uint32_t>::iterator x = _visible_parameter_automation.begin(); x != _visible_parameter_automation.end(); ++x) {
+ if (x != _visible_parameter_automation.begin()) {
+ sstr << ' ';
+ }
+ sstr << *x;
+ }
+
+ automation.add_property ("visible", sstr.str());
+
+ node->add_child_nocopy (automation);
+ }
+
+ return *node;
+}
+
+int
+Insert::set_state (const XMLNode& node)
{
- // FIXME: default type?
+ const XMLProperty *prop;
+
+ if (node.name() != state_node_name) {
+ error << string_compose(_("incorrect XML node \"%1\" passed to Redirect object"), node.name()) << endmsg;
+ return -1;
+ }
+
+ if ((prop = node.property ("name")) == 0) {
+ warning << _("XML node describing an insert is missing the `name' field") << endmsg;
+ } else {
+ set_name(prop->value());
+ }
+
+ XMLNodeList nlist = node.children();
+ XMLNodeIterator niter;
+ bool have_io = false;
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+
+ if ((*niter)->name() == X_("Automation")) {
+
+
+ XMLProperty *prop;
+
+ if ((prop = (*niter)->property ("path")) != 0) {
+ old_set_automation_state (*(*niter));
+ } else {
+ Automatable::set_automation_state (*(*niter));
+ }
+
+ if ((prop = (*niter)->property ("visible")) != 0) {
+ uint32_t what;
+ stringstream sstr;
+
+ _visible_parameter_automation.clear ();
+
+ sstr << prop->value();
+ while (1) {
+ sstr >> what;
+ if (sstr.fail()) {
+ break;
+ }
+ mark_automation_visible (what, true);
+ }
+ }
+
+ } else if ((*niter)->name() == "extra") {
+ _extra_xml = new XMLNode (*(*niter));
+ }
+ }
+
+ if (!have_io && dynamic_cast<IO*>(this)) {
+ error << _("XML node describing a redirect is missing an IO node") << endmsg;
+ return -1;
+ }
+
+ if ((prop = node.property ("active")) == 0) {
+ error << _("XML node describing an insert is missing the `active' field") << endmsg;
+ return -1;
+ }
+
+ if (_active != (prop->value() == "yes")) {
+ _active = !_active;
+ ActiveChanged (); /* EMIT_SIGNAL */
+ }
+
+ if ((prop = node.property ("placement")) == 0) {
+ error << _("XML node describing an insert is missing the `placement' field") << endmsg;
+ return -1;
+ }
+
+ /* hack to handle older sessions before we only used EnumWriter */
+
+ string pstr;
+
+ if (prop->value() == "pre") {
+ pstr = "PreFader";
+ } else if (prop->value() == "post") {
+ pstr = "PostFader";
+ } else {
+ pstr = prop->value();
+ }
+
+ Placement p = Placement (string_2_enum (pstr, p));
+ set_placement (p);
+
+ return 0;
}
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 5df8532959..3069123f16 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -98,12 +98,11 @@ static double direct_gain_to_control (gain_t gain) {
/** @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).
*/
-IO::IO (Session& s, string name,
+IO::IO (Session& s, const string& name,
int input_min, int input_max, int output_min, int output_max,
DataType default_type)
- : _session (s),
+ : SessionObject(s, name),
_output_buffers(new BufferSet()),
- _name (name),
_default_type(default_type),
_gain_control (X_("gaincontrol"), *this),
_gain_automation_curve (0.0, 2.0, 1.0),
@@ -158,7 +157,7 @@ IO::IO (Session& s, string name,
}
IO::IO (Session& s, const XMLNode& node, DataType dt)
- : _session (s),
+ : SessionObject(s, "unnamed io"),
_output_buffers(new BufferSet()),
_default_type (dt),
_gain_control (X_("gaincontrol"), *this),
@@ -324,7 +323,7 @@ IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
collect_input (bufs, nframes, offset);
- _meter->run(bufs, nframes);
+ _meter->run(bufs, start_frame, end_frame, nframes, offset);
}
void
@@ -1130,7 +1129,7 @@ IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
gain_t
IO::effective_gain () const
{
- if (gain_automation_playback()) {
+ if (_gain_automation_curve.automation_playback()) {
return _effective_gain;
} else {
return _desired_gain;
@@ -1826,14 +1825,15 @@ IO::parse_gain_string (const string& str, vector<string>& ports)
return ports.size();
}
-int
-IO::set_name (string name, void* src)
+bool
+IO::set_name (const string& str)
{
- if (name == _name) {
- return 0;
+ if (str == _name) {
+ return true;
}
-
+
/* replace all colons in the name. i wish we didn't have to do this */
+ string name = str;
if (replace_all (name, ":", "-")) {
warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
@@ -1851,10 +1851,7 @@ IO::set_name (string name, void* src)
i->set_name (current_name);
}
- _name = name;
- name_changed (src); /* EMIT SIGNAL */
-
- return 0;
+ return SessionObject::set_name(name);
}
void
@@ -2169,7 +2166,8 @@ IO::GainControllable::get_value (void) const
void
IO::setup_peak_meters()
{
- _meter->setup(std::max(_inputs.count(), _outputs.count()));
+ ChanCount max_streams = std::max(_inputs.count(), _outputs.count());
+ _meter->configure_io(max_streams, max_streams);
}
/**
@@ -2226,28 +2224,17 @@ IO::set_gain_automation_state (AutoState state)
if (changed) {
_session.set_dirty ();
- gain_automation_state_changed (); /* EMIT SIGNAL */
+ //gain_automation_state_changed (); /* EMIT SIGNAL */
}
}
void
IO::set_gain_automation_style (AutoStyle style)
{
- bool changed = false;
-
- {
- Glib::Mutex::Lock lm (automation_lock);
-
- if (style != _gain_automation_curve.automation_style()) {
- changed = true;
- _gain_automation_curve.set_automation_style (style);
- }
- }
-
- if (changed) {
- gain_automation_style_changed (); /* EMIT SIGNAL */
- }
+ Glib::Mutex::Lock lm (automation_lock);
+ _gain_automation_curve.set_automation_style (style);
}
+
void
IO::inc_gain (gain_t factor, void *src)
{
@@ -2276,7 +2263,7 @@ IO::set_gain (gain_t val, void *src)
gain_changed (src);
_gain_control.Changed (); /* EMIT SIGNAL */
- if (_session.transport_stopped() && src != 0 && src != this && gain_automation_recording()) {
+ if (_session.transport_stopped() && src != 0 && src != this && _gain_automation_curve.automation_write()) {
_gain_automation_curve.add (_session.transport_frame(), val);
}
@@ -2318,7 +2305,7 @@ IO::automation_snapshot (nframes_t now)
{
if (last_automation_snapshot > now || (now - last_automation_snapshot) > _automation_interval) {
- if (gain_automation_recording()) {
+ if (_gain_automation_curve.automation_write()) {
_gain_automation_curve.rt_add (now, gain());
}
diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc
index 1de144dc55..a7a287e9c1 100644
--- a/libs/ardour/meter.cc
+++ b/libs/ardour/meter.cc
@@ -34,7 +34,7 @@ namespace ARDOUR {
* be set to 0.
*/
void
-PeakMeter::run (BufferSet& bufs, nframes_t nframes, nframes_t offset)
+PeakMeter::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
{
size_t meterable = std::min(bufs.count().n_total(), _peak_power.size());
@@ -93,9 +93,13 @@ PeakMeter::reset_max ()
}
}
-void
-PeakMeter::setup (const ChanCount& in)
+bool
+PeakMeter::configure_io (ChanCount in, ChanCount out)
{
+ /* we're transparent no matter what. fight the power. */
+ if (out != in)
+ return false;
+
uint32_t limit = in.n_total();
while (_peak_power.size() > limit) {
@@ -113,6 +117,10 @@ PeakMeter::setup (const ChanCount& in)
assert(_peak_power.size() == limit);
assert(_visible_peak_power.size() == limit);
assert(_max_peak_power.size() == limit);
+
+ Insert::configure_io(in, out);
+
+ return true;
}
/** To be driven by the Meter signal from IO.
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 1fddeb7eda..0626f6d423 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -1391,7 +1391,7 @@ int
MidiDiskstream::rename_write_sources ()
{
if (_write_source != 0) {
- _write_source->set_name (_name, destructive());
+ _write_source->set_source_name (_name, destructive());
/* XXX what to do if this fails ? */
}
return 0;
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 7f3287a994..3385727f0e 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -427,7 +427,7 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
int dret;
boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
- if (n_outputs().n_total() == 0 && _redirects.empty()) {
+ if (n_outputs().n_total() == 0 && _inserts.empty()) {
return 0;
}
@@ -498,7 +498,7 @@ int
MidiTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
bool can_record, bool rec_monitors_input)
{
- if (n_outputs().n_midi() == 0 && _redirects.empty()) {
+ if (n_outputs().n_midi() == 0 && _inserts.empty()) {
return 0;
}
@@ -518,29 +518,29 @@ MidiTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_
void
MidiTrack::process_output_buffers (BufferSet& bufs,
nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, nframes_t offset, bool with_redirects, int declick,
+ nframes_t nframes, nframes_t offset, bool with_inserts, int declick,
bool meter)
{
- /* There's no such thing as a MIDI bus for the time being, to avoid diverging from trunk
- * too much until the SoC settles down. We'll do all the MIDI route work here for now,
- * but the long-term goal is to have Route::process_output_buffers handle everything */
+ /* There's no such thing as a MIDI bus for the time being.
+ * We'll do all the MIDI route work here for now, but the long-term goal is to have
+ * Route::process_output_buffers handle everything */
if (meter && (_meter_point == MeterInput || _meter_point == MeterPreFader)) {
- _meter->run(bufs, nframes);
+ _meter->run(bufs, start_frame, end_frame, nframes, offset);
}
- // Run all redirects
- if (with_redirects) {
- Glib::RWLock::ReaderLock rm (redirect_lock, Glib::TRY_LOCK);
+ // Run all inserts
+ if (with_inserts) {
+ Glib::RWLock::ReaderLock rm (insert_lock, Glib::TRY_LOCK);
if (rm.locked()) {
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
(*i)->run (bufs, start_frame, end_frame, nframes, offset);
}
}
}
if (meter && (_meter_point == MeterPostFader)) {
- _meter->run(bufs, nframes);
+ _meter->run(bufs, start_frame, end_frame, nframes, offset);
}
// Main output stage
@@ -552,28 +552,6 @@ MidiTrack::process_output_buffers (BufferSet& bufs,
}
int
-MidiTrack::set_name (string str, void *src)
-{
- int ret;
-
- if (record_enabled() && _session.actively_recording()) {
- /* this messes things up if done while recording */
- return -1;
- }
-
- if (_diskstream->set_name (str)) {
- return -1;
- }
-
- /* save state so that the statefile fully reflects any filename changes */
-
- if ((ret = IO::set_name (str, src)) == 0) {
- _session.save_state ("");
- }
- return ret;
-}
-
-int
MidiTrack::export_stuff (BufferSet& bufs, nframes_t nframes, nframes_t end_frame)
{
return -1;
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index 92e0503bb4..4af7e2b907 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -71,7 +71,7 @@ struct RegionSortByLastLayerOp {
};
Playlist::Playlist (Session& sess, string nom, DataType type, bool hide)
- : _session (sess)
+ : SessionObject(sess, nom)
, _type(type)
{
init (hide);
@@ -81,7 +81,7 @@ Playlist::Playlist (Session& sess, string nom, DataType type, bool hide)
}
Playlist::Playlist (Session& sess, const XMLNode& node, DataType type, bool hide)
- : _session (sess)
+ : SessionObject(sess, "unnamed playlist")
, _type(type)
{
const XMLProperty* prop = node.property("type");
@@ -94,7 +94,7 @@ Playlist::Playlist (Session& sess, const XMLNode& node, DataType type, bool hide
}
Playlist::Playlist (boost::shared_ptr<const Playlist> other, string namestr, bool hide)
- : _name (namestr), _session (other->_session), _type(other->_type), _orig_diskstream_id(other->_orig_diskstream_id)
+ : SessionObject(other->_session, namestr), _type(other->_type), _orig_diskstream_id(other->_orig_diskstream_id)
{
init (hide);
@@ -126,7 +126,7 @@ Playlist::Playlist (boost::shared_ptr<const Playlist> other, string namestr, boo
}
Playlist::Playlist (boost::shared_ptr<const Playlist> other, nframes_t start, nframes_t cnt, string str, bool hide)
- : _name (str), _session (other->_session), _type(other->_type), _orig_diskstream_id(other->_orig_diskstream_id)
+ : SessionObject(other->_session, str), _type(other->_type), _orig_diskstream_id(other->_orig_diskstream_id)
{
RegionLock rlock2 (const_cast<Playlist*> (other.get()));
@@ -247,14 +247,14 @@ Playlist::init (bool hide)
}
Playlist::Playlist (const Playlist& pl)
- : _session (pl._session)
+ : SessionObject(pl._session, pl._name)
, _type(pl.data_type())
{
fatal << _("playlist const copy constructor called") << endmsg;
}
Playlist::Playlist (Playlist& pl)
- : _session (pl._session)
+ : SessionObject(pl._session, pl._name)
, _type(pl.data_type())
{
fatal << _("playlist non-const copy constructor called") << endmsg;
@@ -273,8 +273,8 @@ Playlist::~Playlist ()
/* GoingAway must be emitted by derived classes */
}
-void
-Playlist::set_name (string str)
+bool
+Playlist::set_name (const string& str)
{
/* in a typical situation, a playlist is being used
by one diskstream and also is referenced by the
@@ -283,11 +283,10 @@ Playlist::set_name (string str)
*/
if (_refcnt > 2) {
- return;
+ return false;
+ } else {
+ return SessionObject::set_name(str);
}
-
- _name = str;
- NameChanged(); /* EMIT SIGNAL */
}
/***********************************************************************
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index eefdc5dff1..baf22a6863 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -30,6 +30,7 @@
#include <ardour/route.h>
#include <ardour/ladspa_plugin.h>
#include <ardour/buffer_set.h>
+#include <ardour/automation_event.h>
#ifdef VST_SUPPORT
#include <ardour/vst_plugin.h>
@@ -67,11 +68,11 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placemen
IO::MoreChannels (max(input_streams(), output_streams()));
}
- RedirectCreated (this); /* EMIT SIGNAL */
+ InsertCreated (this); /* EMIT SIGNAL */
}
PluginInsert::PluginInsert (Session& s, const XMLNode& node)
- : Insert (s, "will change", PreFader)
+ : Insert (s, "unnamed plugin insert", PreFader)
{
if (set_state (node)) {
throw failed_constructor();
@@ -88,7 +89,7 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node)
}
PluginInsert::PluginInsert (const PluginInsert& other)
- : Insert (other._session, other.plugin()->name(), other.placement())
+ : Insert (other._session, other._name, other.placement())
{
uint32_t count = other._plugins.size();
@@ -102,7 +103,7 @@ PluginInsert::PluginInsert (const PluginInsert& other)
init ();
- RedirectCreated (this); /* EMIT SIGNAL */
+ InsertCreated (this); /* EMIT SIGNAL */
}
bool
@@ -272,7 +273,7 @@ PluginInsert::connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t off
map<uint32_t,AutomationList*>::iterator li;
uint32_t n;
- for (n = 0, li = parameter_automation.begin(); li != parameter_automation.end(); ++li, ++n) {
+ for (n = 0, li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li, ++n) {
AutomationList& alist (*((*li).second));
@@ -302,14 +303,14 @@ PluginInsert::automation_snapshot (nframes_t now)
{
map<uint32_t,AutomationList*>::iterator li;
- for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
+ for (li =_parameter_automation.begin(); li !=_parameter_automation.end(); ++li) {
AutomationList *alist = ((*li).second);
if (alist != 0 && alist->automation_write ()) {
float val = _plugins[0]->get_parameter ((*li).first);
alist->rt_add (now, val);
- last_automation_snapshot = now;
+ _last_automation_snapshot = now;
}
}
}
@@ -319,7 +320,7 @@ PluginInsert::transport_stopped (nframes_t now)
{
map<uint32_t,AutomationList*>::iterator li;
- for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
+ for (li =_parameter_automation.begin(); li !=_parameter_automation.end(); ++li) {
AutomationList& alist (*(li->second));
alist.reposition_for_rt_add (now);
@@ -353,6 +354,9 @@ PluginInsert::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
connect_and_run (bufs, nframes, offset, false);
}
} else {
+
+ /* FIXME: type, audio only */
+
uint32_t in = _plugins[0]->get_info()->n_inputs.n_audio();
uint32_t out = _plugins[0]->get_info()->n_outputs.n_audio();
@@ -365,7 +369,7 @@ PluginInsert::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
}
}
- bufs.count().set(_default_type, out);
+ bufs.count().set_audio(out);
}
}
@@ -526,26 +530,41 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
return false;
} else {
bool success = set_count (count_for_configuration(in, out));
- if (success) {
- _configured = true;
- _configured_input = in;
- }
+ if (success)
+ Insert::configure_io(in, out);
return success;
}
}
bool
-PluginInsert::can_support_input_configuration (ChanCount in_count) const
+PluginInsert::can_support_input_configuration (ChanCount in) const
{
- int32_t outputs = _plugins[0]->get_info()->n_outputs.get(_default_type);
- int32_t inputs = _plugins[0]->get_info()->n_inputs.get(_default_type);
- int32_t in = in_count.get(_default_type);
+ ChanCount outputs = _plugins[0]->get_info()->n_outputs;
+ ChanCount inputs = _plugins[0]->get_info()->n_inputs;
/* see output_for_input_configuration below */
- if ((inputs == 0)
- || (outputs == 1 && inputs == 1)
- || (inputs == in)
- || ((inputs < in) && (inputs % in == 0))) {
+ if ((inputs.n_total() == 0)
+ || (inputs.n_total() == 1 && outputs == inputs)
+ || (inputs.n_total() == 1 && outputs == inputs
+ && ((inputs.n_audio() == 0 && in.n_audio() == 0)
+ || (inputs.n_midi() == 0 && in.n_midi() == 0)))
+ || (inputs == in)) {
+ return true;
+ }
+
+ bool can_replicate = true;
+
+ /* if number of inputs is a factor of the requested input
+ configuration for every type, we can replicate.
+ */
+ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+ if (inputs.get(*t) >= in.get(*t) || (inputs.get(*t) % in.get(*t) != 0)) {
+ can_replicate = false;
+ break;
+ }
+ }
+
+ if (can_replicate && (in.n_total() % inputs.n_total() == 0)) {
return true;
} else {
return false;
@@ -563,7 +582,9 @@ PluginInsert::output_for_input_configuration (ChanCount in) const
return outputs;
}
- if (inputs.n_total() == 1 && outputs == inputs) {
+ if (inputs.n_total() == 1 && outputs == inputs
+ && ((inputs.n_audio() == 0 && in.n_audio() == 0)
+ || (inputs.n_midi() == 0 && in.n_midi() == 0))) {
/* mono plugin, replicate as needed to match in */
return in;
}
@@ -573,17 +594,26 @@ PluginInsert::output_for_input_configuration (ChanCount in) const
return outputs;
}
- // FIXME: single type plugins only. can we do this for instruments?
- if ((inputs.n_total() == inputs.get(_default_type))
- && ((in.n_total() == in.get(_default_type))
- && (inputs.n_total() < in.n_total())
- && (inputs.n_total() % in.n_total() == 0))) {
+ bool can_replicate = true;
+
+ /* if number of inputs is a factor of the requested input
+ configuration for every type, we can replicate.
+ */
+ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+ if (inputs.get(*t) >= in.get(*t) || (in.get(*t) % inputs.get(*t) != 0)) {
+ can_replicate = false;
+ break;
+ }
+ }
- /* number of inputs is a factor of the requested input
- configuration, so we can replicate.
- */
+ if (can_replicate && (inputs.n_total() % in.n_total() == 0)) {
+ ChanCount output;
+
+ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+ output.set(*t, outputs.get(*t) * (in.get(*t) / inputs.get(*t)));
+ }
- return ChanCount(_default_type, in.n_total() / inputs.n_total());
+ return output;
}
/* sorry */
@@ -606,7 +636,9 @@ PluginInsert::count_for_configuration (ChanCount in, ChanCount out) const
return 1;
}
- if (inputs.n_total() == 1 && outputs == inputs) {
+ if (inputs.n_total() == 1 && outputs == inputs
+ && ((inputs.n_audio() == 0 && in.n_audio() == 0)
+ || (inputs.n_midi() == 0 && in.n_midi() == 0))) {
/* mono plugin, replicate as needed to match in */
return in.n_total();
}
@@ -616,20 +648,14 @@ PluginInsert::count_for_configuration (ChanCount in, ChanCount out) const
return 1;
}
- // FIXME: single type plugins only. can we do this for instruments?
- if ((inputs.n_total() == inputs.get(_default_type))
- && ((in.n_total() == in.get(_default_type))
- && (inputs.n_total() < in.n_total())
- && (inputs.n_total() % in.n_total() == 0))) {
-
- /* number of inputs is a factor of the requested input
- configuration, so we can replicate.
- */
+ // assumes in is valid, so we must be replicating
+ if (inputs.n_total() < in.n_total()
+ && (in.n_total() % inputs.n_total() == 0)) {
return in.n_total() / inputs.n_total();
}
- /* sorry */
+ /* err... */
return 0;
}
@@ -643,20 +669,18 @@ XMLNode&
PluginInsert::state (bool full)
{
char buf[256];
- XMLNode *node = new XMLNode("Insert");
-
- node->add_child_nocopy (Redirect::state (full));
+ XMLNode& node = Insert::state (full);
- node->add_property ("type", _plugins[0]->state_node_name());
+ node.add_property ("type", _plugins[0]->state_node_name());
snprintf(buf, sizeof(buf), "%s", _plugins[0]->name());
- node->add_property("id", string(buf));
+ node.add_property("id", string(buf));
if (_plugins[0]->state_node_name() == "ladspa") {
char buf[32];
snprintf (buf, sizeof (buf), "%ld", _plugins[0]->get_info()->unique_id);
- node->add_property("unique-id", string(buf));
+ node.add_property("unique-id", string(buf));
}
- node->add_property("count", string_compose("%1", _plugins.size()));
- node->add_child_nocopy (_plugins[0]->get_state());
+ node.add_property("count", string_compose("%1", _plugins.size()));
+ node.add_child_nocopy (_plugins[0]->get_state());
/* add port automation state */
XMLNode *autonode = new XMLNode(port_automation_node_name);
@@ -672,9 +696,9 @@ PluginInsert::state (bool full)
autonode->add_child_nocopy (*child);
}
- node->add_child_nocopy (*autonode);
+ node.add_child_nocopy (*autonode);
- return *node;
+ return node;
}
int
@@ -752,23 +776,18 @@ PluginInsert::set_state(const XMLNode& node)
}
}
+ const XMLNode* insert_node = &node;
+
+ // legacy sessions: search for child Redirect node
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- if ((*niter)->name() == Redirect::state_node_name) {
- Redirect::set_state (**niter);
+ if ((*niter)->name() == "Redirect") {
+ insert_node = *niter;
break;
}
}
-
- if (niter == nlist.end()) {
- error << _("XML node describing insert is missing a Redirect node") << endmsg;
- return -1;
- }
-
- if (niter == nlist.end()) {
- error << string_compose(_("XML node describing a plugin insert is missing the `%1' information"), plugin->state_node_name()) << endmsg;
- return -1;
- }
+ Insert::set_state (*insert_node);
+
/* look for port automation node */
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
@@ -835,7 +854,7 @@ PluginInsert::set_state(const XMLNode& node)
}
// The name of the PluginInsert comes from the plugin, nothing else
- set_name(plugin->get_info()->name,this);
+ _name = plugin->get_info()->name;
return 0;
}
diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc
index 25234dbf77..53903c4b34 100644
--- a/libs/ardour/port_insert.cc
+++ b/libs/ardour/port_insert.cc
@@ -41,41 +41,41 @@ using namespace ARDOUR;
using namespace PBD;
PortInsert::PortInsert (Session& s, Placement p)
- : Insert (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), p, 1, -1, 1, -1)
+ : Redirect (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), p, 1, -1, 1, -1)
{
init ();
- RedirectCreated (this); /* EMIT SIGNAL */
+ InsertCreated (this); /* EMIT SIGNAL */
}
PortInsert::PortInsert (const PortInsert& other)
- : Insert (other._session, string_compose (_("insert %1"), (bitslot = other._session.next_insert_id()) + 1), other.placement(), 1, -1, 1, -1)
+ : Redirect (other._session, string_compose (_("insert %1"), (bitslot = other._session.next_insert_id()) + 1), other.placement(), 1, -1, 1, -1)
{
init ();
- RedirectCreated (this); /* EMIT SIGNAL */
+ InsertCreated (this); /* EMIT SIGNAL */
}
void
PortInsert::init ()
{
- if (add_input_port ("", this)) {
+ if (_io->add_input_port ("", this)) {
error << _("PortInsert: cannot add input port") << endmsg;
throw failed_constructor();
}
- if (add_output_port ("", this)) {
+ if (_io->add_output_port ("", this)) {
error << _("PortInsert: cannot add output port") << endmsg;
throw failed_constructor();
}
}
PortInsert::PortInsert (Session& s, const XMLNode& node)
- : Insert (s, "will change", PreFader)
+ : Redirect (s, "unnamed port insert", PreFader)
{
if (set_state (node)) {
throw failed_constructor();
}
- RedirectCreated (this); /* EMIT SIGNAL */
+ InsertCreated (this); /* EMIT SIGNAL */
}
PortInsert::~PortInsert ()
@@ -86,19 +86,19 @@ PortInsert::~PortInsert ()
void
PortInsert::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
{
- if (n_outputs().get(_default_type) == 0) {
+ if (_io->n_outputs().n_total() == 0) {
return;
}
if (!active()) {
/* deliver silence */
- silence (nframes, offset);
+ _io->silence (nframes, offset);
return;
}
- deliver_output(bufs, start_frame, end_frame, nframes, offset);
+ _io->deliver_output(bufs, start_frame, end_frame, nframes, offset);
- collect_input(bufs, nframes, offset);
+ _io->collect_input(bufs, nframes, offset);
}
XMLNode&
@@ -110,14 +110,13 @@ PortInsert::get_state(void)
XMLNode&
PortInsert::state (bool full)
{
- XMLNode *node = new XMLNode("Insert");
+ XMLNode& node = Redirect::state(full);
char buf[32];
- node->add_child_nocopy (Redirect::state(full));
- node->add_property ("type", "port");
+ node.add_property ("type", "port");
snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
- node->add_property ("bitslot", buf);
+ node.add_property ("bitslot", buf);
- return *node;
+ return node;
}
int
@@ -145,17 +144,17 @@ PortInsert::set_state(const XMLNode& node)
_session.mark_insert_id (bitslot);
}
+ const XMLNode* insert_node = &node;
+
+ // legacy sessions: search for child Redirect node
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- if ((*niter)->name() == Redirect::state_node_name) {
- Redirect::set_state (**niter);
+ if ((*niter)->name() == "Redirect") {
+ insert_node = *niter;
break;
}
}
-
- if (niter == nlist.end()) {
- error << _("XML node describing insert is missing a Redirect node") << endmsg;
- return -1;
- }
+
+ Redirect::set_state (*insert_node);
return 0;
}
@@ -170,13 +169,13 @@ PortInsert::latency()
need to take that into account too.
*/
- return _session.engine().frames_per_cycle() + input_latency();
+ return _session.engine().frames_per_cycle() + _io->input_latency();
}
bool
PortInsert::can_support_input_configuration (ChanCount in) const
{
- if (input_maximum() == ChanCount::INFINITE && output_maximum() == ChanCount::INFINITE) {
+ if (_io->input_maximum() == ChanCount::INFINITE && _io->output_maximum() == ChanCount::INFINITE) {
/* not configured yet */
@@ -188,7 +187,7 @@ PortInsert::can_support_input_configuration (ChanCount in) const
many output ports it will have.
*/
- if (output_maximum() == in) {
+ if (_io->output_maximum() == in) {
return true;
}
@@ -220,23 +219,28 @@ PortInsert::configure_io (ChanCount in, ChanCount out)
to the number of input ports we need.
*/
- set_output_maximum (in);
- set_output_minimum (in);
- set_input_maximum (out);
- set_input_minimum (out);
+ _io->set_output_maximum (in);
+ _io->set_output_minimum (in);
+ _io->set_input_maximum (out);
+ _io->set_input_minimum (out);
+
+ bool success = (_io->ensure_io (out, in, false, this) == 0);
- return (ensure_io (out, in, false, this) == 0);
+ if (success)
+ return Insert::configure_io(in, out);
+ else
+ return false;
}
ChanCount
PortInsert::output_streams() const
{
- return n_inputs ();
+ return _io->n_inputs ();
}
ChanCount
PortInsert::input_streams() const
{
- return n_outputs ();
+ return _io->n_outputs ();
}
diff --git a/libs/ardour/redirect.cc b/libs/ardour/redirect.cc
index d63618943e..b5216cf323 100644
--- a/libs/ardour/redirect.cc
+++ b/libs/ardour/redirect.cc
@@ -42,17 +42,13 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-const string Redirect::state_node_name = "Redirect";
-sigc::signal<void,Redirect*> Redirect::RedirectCreated;
-
Redirect::Redirect (Session& s, const string& name, Placement p,
int input_min, int input_max,
int output_min, int output_max)
- : IO (s, name, input_min, input_max, output_min, output_max)
+ : Insert(s, name, p)
+ , _io(new IO(s, name, input_min, input_max, output_min, output_max))
{
- _placement = p;
_active = false;
- _next_ab_is_active = false;
_sort_key = 0;
_gui = 0;
_extra_xml = 0;
@@ -63,161 +59,22 @@ Redirect::~Redirect ()
notify_callbacks ();
}
-boost::shared_ptr<Redirect>
-Redirect::clone (boost::shared_ptr<const Redirect> other)
-{
- boost::shared_ptr<const Send> send;
- boost::shared_ptr<const PortInsert> port_insert;
- boost::shared_ptr<const PluginInsert> plugin_insert;
-
- if ((send = boost::dynamic_pointer_cast<const Send>(other)) != 0) {
- return boost::shared_ptr<Redirect> (new Send (*send));
- } else if ((port_insert = boost::dynamic_pointer_cast<const PortInsert>(other)) != 0) {
- return boost::shared_ptr<Redirect> (new PortInsert (*port_insert));
- } else if ((plugin_insert = boost::dynamic_pointer_cast<const PluginInsert>(other)) != 0) {
- return boost::shared_ptr<Redirect> (new PluginInsert (*plugin_insert));
- } else {
- fatal << _("programming error: unknown Redirect type in Redirect::Clone!\n")
- << endmsg;
- /*NOTREACHED*/
- }
- return boost::shared_ptr<Redirect>();
-}
-
-void
-Redirect::set_sort_key (uint32_t key)
-{
- _sort_key = key;
-}
-
-void
-Redirect::set_placement (Placement p, void *src)
-{
- if (_placement != p) {
- _placement = p;
- placement_changed (this, src); /* EMIT SIGNAL */
- }
-}
-
-/* NODE STRUCTURE
-
- <Automation [optionally with visible="...." ]>
- <parameter-N>
- <AutomationList id=N>
- <events>
- X1 Y1
- X2 Y2
- ....
- </events>
- </parameter-N>
- <Automation>
-*/
-
-int
-Redirect::set_automation_state (const XMLNode& node)
-{
- Glib::Mutex::Lock lm (_automation_lock);
-
- parameter_automation.clear ();
-
- XMLNodeList nlist = node.children();
- XMLNodeIterator niter;
-
- for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- uint32_t param;
-
- if (sscanf ((*niter)->name().c_str(), "parameter-%" PRIu32, &param) != 1) {
- error << string_compose (_("%2: badly formatted node name in XML automation state, ignored"), _name) << endmsg;
- continue;
- }
-
- AutomationList& al = automation_list (param);
- if (al.set_state (*(*niter)->children().front())) {
- goto bad;
- }
- }
-
- return 0;
-
- bad:
- error << string_compose(_("%1: cannot load automation data from XML"), _name) << endmsg;
- parameter_automation.clear ();
- return -1;
-}
-
-XMLNode&
-Redirect::get_automation_state ()
-{
- Glib::Mutex::Lock lm (_automation_lock);
- XMLNode* node = new XMLNode (X_("Automation"));
- string fullpath;
-
- if (parameter_automation.empty()) {
- return *node;
- }
-
- map<uint32_t,AutomationList*>::iterator li;
-
- for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
-
- XMLNode* child;
-
- char buf[64];
- stringstream str;
- snprintf (buf, sizeof (buf), "parameter-%" PRIu32, li->first);
- child = new XMLNode (buf);
- child->add_child_nocopy (li->second->get_state ());
- }
-
- return *node;
-}
-
-XMLNode&
-Redirect::get_state (void)
-{
- return state (true);
-}
-
XMLNode&
Redirect::state (bool full_state)
{
- XMLNode* node = new XMLNode (state_node_name);
- stringstream sstr;
-
- node->add_property("active", active() ? "yes" : "no");
- node->add_property("placement", enum_2_string (_placement));
- node->add_child_nocopy (IO::state (full_state));
-
- if (_extra_xml){
- node->add_child_copy (*_extra_xml);
- }
+ XMLNode& node = Insert::state(full_state);
- if (full_state) {
-
- XMLNode& automation = get_automation_state();
-
- for (set<uint32_t>::iterator x = visible_parameter_automation.begin(); x != visible_parameter_automation.end(); ++x) {
- if (x != visible_parameter_automation.begin()) {
- sstr << ' ';
- }
- sstr << *x;
- }
-
- automation.add_property ("visible", sstr.str());
+ node.add_child_nocopy (_io->state (full_state));
- node->add_child_nocopy (automation);
- }
-
- return *node;
+ return node;
}
-
int
Redirect::set_state (const XMLNode& node)
{
- const XMLProperty *prop;
+ Insert::set_state(node);
- if (node.name() != state_node_name) {
+ if (node.name() != "Insert" && node.name() != "Redirect") {
error << string_compose(_("incorrect XML node \"%1\" passed to Redirect object"), node.name()) << endmsg;
return -1;
}
@@ -227,260 +84,22 @@ Redirect::set_state (const XMLNode& node)
bool have_io = false;
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
-
if ((*niter)->name() == IO::state_node_name) {
-
- IO::set_state (**niter);
have_io = true;
-
- } else if ((*niter)->name() == X_("Automation")) {
-
-
- XMLProperty *prop;
-
- if ((prop = (*niter)->property ("path")) != 0) {
- old_set_automation_state (*(*niter));
- } else {
- set_automation_state (*(*niter));
- }
-
- if ((prop = (*niter)->property ("visible")) != 0) {
- uint32_t what;
- stringstream sstr;
-
- visible_parameter_automation.clear ();
-
- sstr << prop->value();
- while (1) {
- sstr >> what;
- if (sstr.fail()) {
- break;
- }
- mark_automation_visible (what, true);
- }
- }
-
- } else if ((*niter)->name() == "extra") {
- _extra_xml = new XMLNode (*(*niter));
+ _io->set_state(**niter);
}
}
if (!have_io) {
- error << _("XML node describing an IO is missing an IO node") << endmsg;
- return -1;
- }
-
- if ((prop = node.property ("active")) == 0) {
- error << _("XML node describing a redirect is missing the `active' field") << endmsg;
- return -1;
- }
-
- if (_active != (prop->value() == "yes")) {
- _active = !_active;
- active_changed (this, this); /* EMIT_SIGNAL */
- }
-
- if ((prop = node.property ("placement")) == 0) {
- error << _("XML node describing a redirect is missing the `placement' field") << endmsg;
+ error << _("XML node describing a redirect is missing an IO node") << endmsg;
return -1;
}
- /* hack to handle older sessions before we only used EnumWriter */
-
- string pstr;
-
- if (prop->value() == "pre") {
- pstr = "PreFader";
- } else if (prop->value() == "post") {
- pstr = "PostFader";
- } else {
- pstr = prop->value();
- }
-
- Placement p = Placement (string_2_enum (pstr, p));
- set_placement (p, this);
-
return 0;
}
-int
-Redirect::old_set_automation_state (const XMLNode& node)
-{
- const XMLProperty *prop;
-
- if ((prop = node.property ("path")) != 0) {
- load_automation (prop->value());
- } else {
- warning << string_compose(_("%1: Automation node has no path property"), _name) << endmsg;
- }
-
- if ((prop = node.property ("visible")) != 0) {
- uint32_t what;
- stringstream sstr;
-
- visible_parameter_automation.clear ();
-
- sstr << prop->value();
- while (1) {
- sstr >> what;
- if (sstr.fail()) {
- break;
- }
- mark_automation_visible (what, true);
- }
- }
-
- return 0;
-}
-
-int
-Redirect::load_automation (string path)
-{
- string fullpath;
-
- if (path[0] == '/') { // legacy
- fullpath = path;
- } else {
- fullpath = _session.automation_dir();
- fullpath += path;
- }
- ifstream in (fullpath.c_str());
-
- if (!in) {
- warning << string_compose(_("%1: cannot open %2 to load automation data (%3)"), _name, fullpath, strerror (errno)) << endmsg;
- return 1;
- }
-
- Glib::Mutex::Lock lm (_automation_lock);
- set<uint32_t> tosave;
- parameter_automation.clear ();
-
- while (in) {
- double when;
- double value;
- uint32_t port;
-
- in >> port; if (!in) break;
- in >> when; if (!in) goto bad;
- in >> value; if (!in) goto bad;
-
- AutomationList& al = automation_list (port);
- al.add (when, value);
- tosave.insert (port);
- }
-
- return 0;
-
- bad:
- error << string_compose(_("%1: cannot load automation data from %2"), _name, fullpath) << endmsg;
- parameter_automation.clear ();
- return -1;
-}
-
-
-void
-Redirect::what_has_automation (set<uint32_t>& s) const
-{
- Glib::Mutex::Lock lm (_automation_lock);
- map<uint32_t,AutomationList*>::const_iterator li;
-
- for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
- s.insert ((*li).first);
- }
-}
-
-void
-Redirect::what_has_visible_automation (set<uint32_t>& s) const
-{
- Glib::Mutex::Lock lm (_automation_lock);
- set<uint32_t>::const_iterator li;
-
- for (li = visible_parameter_automation.begin(); li != visible_parameter_automation.end(); ++li) {
- s.insert (*li);
- }
-}
-AutomationList&
-Redirect::automation_list (uint32_t parameter)
-{
- AutomationList* al = parameter_automation[parameter];
-
- if (al == 0) {
- al = parameter_automation[parameter] = new AutomationList (default_parameter_value (parameter));
- /* let derived classes do whatever they need with this */
- automation_list_creation_callback (parameter, *al);
- }
-
- return *al;
-}
-
-string
-Redirect::describe_parameter (uint32_t which)
-{
- /* derived classes will override this */
- return "";
-}
-
-void
-Redirect::can_automate (uint32_t what)
-{
- can_automate_list.insert (what);
-}
-
-void
-Redirect::mark_automation_visible (uint32_t what, bool yn)
-{
- if (yn) {
- visible_parameter_automation.insert (what);
- } else {
- set<uint32_t>::iterator i;
-
- if ((i = visible_parameter_automation.find (what)) != visible_parameter_automation.end()) {
- visible_parameter_automation.erase (i);
- }
- }
-}
-
-bool
-Redirect::find_next_event (nframes_t now, nframes_t end, ControlEvent& next_event) const
-{
- map<uint32_t,AutomationList*>::const_iterator li;
- AutomationList::TimeComparator cmp;
-
- next_event.when = max_frames;
-
- for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
-
- AutomationList::const_iterator i;
- const AutomationList& alist (*((*li).second));
- 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) {
- if ((*i)->when > now) {
- break;
- }
- }
-
- if (i != alist.const_end() && (*i)->when < end) {
-
- if ((*i)->when < next_event.when) {
- next_event.when = (*i)->when;
- }
- }
- }
-
- return next_event.when != max_frames;
-}
-
-void
-Redirect::set_active (bool yn, void* src)
-{
- _active = yn;
- active_changed (this, src);
- _session.set_dirty ();
-}
-
void
-Redirect::set_next_ab_is_active (bool yn)
+Redirect::silence (nframes_t nframes, nframes_t offset)
{
- _next_ab_is_active = yn;
+ _io->silence(nframes, offset);
}
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index d682dd63b8..883bc0f6aa 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -76,7 +76,7 @@ Route::Route (Session& sess, const XMLNode& node, DataType default_type)
void
Route::init ()
{
- redirect_max_outs.reset();
+ insert_max_outs.reset();
_muted = false;
_soloed = false;
_solo_safe = false;
@@ -115,8 +115,8 @@ Route::init ()
Route::~Route ()
{
- clear_redirects (PreFader, this);
- clear_redirects (PostFader, this);
+ clear_inserts (PreFader);
+ clear_inserts (PostFader);
for (OrderKeys::iterator i = order_keys.begin(); i != order_keys.end(); ++i) {
free ((void*)(i->first));
@@ -238,13 +238,13 @@ Route::set_gain (gain_t val, void *src)
void
Route::process_output_buffers (BufferSet& bufs,
nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, nframes_t offset, bool with_redirects, int declick,
+ nframes_t nframes, nframes_t offset, bool with_inserts, int declick,
bool meter)
{
// This is definitely very audio-only for now
assert(_default_type == DataType::AUDIO);
- RedirectList::iterator i;
+ InsertList::iterator i;
bool post_fader_work = false;
bool mute_declick_applied = false;
gain_t dmg, dsg, dg;
@@ -315,7 +315,7 @@ Route::process_output_buffers (BufferSet& bufs,
-------------------------------------------------------------------------------------------------- */
if (meter && (_meter_point == MeterInput)) {
- _meter->run(bufs, nframes);
+ _meter->run(bufs, start_frame, end_frame, nframes, offset);
}
if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) {
@@ -373,15 +373,11 @@ Route::process_output_buffers (BufferSet& bufs,
PRE-FADER REDIRECTS
-------------------------------------------------------------------------------------------------- */
- /* FIXME: Somewhere in these loops is where bufs.count() should go from n_inputs() to redirect_max_outs()
- * (if they differ). Something explicit needs to be done here to make sure the list of redirects will
- * give us what we need (possibly by inserting transparent 'translators' into the list to make it work) */
-
- if (with_redirects) {
- Glib::RWLock::ReaderLock rm (redirect_lock, Glib::TRY_LOCK);
+ if (with_inserts) {
+ Glib::RWLock::ReaderLock rm (insert_lock, Glib::TRY_LOCK);
if (rm.locked()) {
if (mute_gain > 0 || !_mute_affects_pre_fader) {
- for (i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (i = _inserts.begin(); i != _inserts.end(); ++i) {
switch ((*i)->placement()) {
case PreFader:
(*i)->run (bufs, start_frame, end_frame, nframes, offset);
@@ -392,7 +388,7 @@ Route::process_output_buffers (BufferSet& bufs,
}
}
} else {
- for (i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (i = _inserts.begin(); i != _inserts.end(); ++i) {
switch ((*i)->placement()) {
case PreFader:
(*i)->silence (nframes, offset);
@@ -406,9 +402,8 @@ Route::process_output_buffers (BufferSet& bufs,
}
}
- // FIXME: for now, just hope the redirects list did what it was supposed to
- bufs.set_count(n_process_buffers());
-
+ // This really should already be true...
+ bufs.set_count(pre_fader_streams());
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader) {
Amp::run (bufs, nframes, mute_gain, dmg, false);
@@ -421,7 +416,7 @@ Route::process_output_buffers (BufferSet& bufs,
-------------------------------------------------------------------------------------------------- */
if (meter && (_meter_point == MeterPreFader)) {
- _meter->run(bufs, nframes);
+ _meter->run(bufs, start_frame, end_frame, nframes, offset);
}
@@ -543,14 +538,14 @@ Route::process_output_buffers (BufferSet& bufs,
POST-FADER REDIRECTS
-------------------------------------------------------------------------------------------------- */
- /* note that post_fader_work cannot be true unless with_redirects was also true, so don't test both */
+ /* note that post_fader_work cannot be true unless with_inserts was also true, so don't test both */
if (post_fader_work) {
- Glib::RWLock::ReaderLock rm (redirect_lock, Glib::TRY_LOCK);
+ Glib::RWLock::ReaderLock rm (insert_lock, Glib::TRY_LOCK);
if (rm.locked()) {
if (mute_gain > 0 || !_mute_affects_post_fader) {
- for (i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (i = _inserts.begin(); i != _inserts.end(); ++i) {
switch ((*i)->placement()) {
case PreFader:
break;
@@ -560,7 +555,7 @@ Route::process_output_buffers (BufferSet& bufs,
}
}
} else {
- for (i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (i = _inserts.begin(); i != _inserts.end(); ++i) {
switch ((*i)->placement()) {
case PreFader:
break;
@@ -681,7 +676,7 @@ Route::process_output_buffers (BufferSet& bufs,
if ((_gain == 0 && !apply_gain_automation) || dmg == 0) {
_meter->reset();
} else {
- _meter->run(output_buffers(), nframes, offset);
+ _meter->run(output_buffers(), start_frame, end_frame, nframes, offset);
}
}
}
@@ -689,7 +684,7 @@ Route::process_output_buffers (BufferSet& bufs,
ChanCount
Route::n_process_buffers ()
{
- return max (n_inputs(), redirect_max_outs);
+ return max (n_inputs(), insert_max_outs);
}
void
@@ -702,7 +697,7 @@ Route::passthru (nframes_t start_frame, nframes_t end_frame, nframes_t nframes,
collect_input (bufs, nframes, offset);
if (meter_first) {
- _meter->run(bufs, nframes);
+ _meter->run(bufs, start_frame, end_frame, nframes, offset);
meter_first = false;
}
@@ -775,23 +770,23 @@ Route::set_mute (bool yn, void *src)
}
int
-Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, InsertStreams* err)
+Route::add_insert (boost::shared_ptr<Insert> insert, InsertStreams* err)
{
- ChanCount old_rmo = redirect_max_outs;
+ ChanCount old_rmo = insert_max_outs;
if (!_session.engine().connected()) {
return 1;
}
{
- Glib::RWLock::WriterLock lm (redirect_lock);
+ Glib::RWLock::WriterLock lm (insert_lock);
boost::shared_ptr<PluginInsert> pi;
boost::shared_ptr<PortInsert> porti;
- redirect->set_default_type(_default_type);
+ //insert->set_default_type(_default_type);
- if ((pi = boost::dynamic_pointer_cast<PluginInsert>(redirect)) != 0) {
+ if ((pi = boost::dynamic_pointer_cast<PluginInsert>(insert)) != 0) {
pi->set_count (1);
if (pi->natural_input_streams() == ChanCount::ZERO) {
@@ -799,67 +794,53 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, InsertStre
_have_internal_generator = true;
}
- } else if ((porti = boost::dynamic_pointer_cast<PortInsert>(redirect)) != 0) {
-
- /* force new port inserts to start out with an i/o configuration
- that matches this route's i/o configuration.
-
- the "inputs" for the port are supposed to match the output
- of this route.
-
- the "outputs" of the route should match the inputs of this
- route. XXX shouldn't they match the number of active signal
- streams at the point of insertion?
- */
- // FIXME: (yes, they should)
-
- porti->ensure_io (n_outputs (), n_inputs(), false, this);
}
- _redirects.push_back (redirect);
+ _inserts.push_back (insert);
- // Set up redirect list channels. This will set redirect->[input|output]_streams()
+ // Set up insert list channels. This will set insert->[input|output]_streams(),
+ // configure redirect ports properly, etc.
if (_reset_plugin_counts (err)) {
- _redirects.pop_back ();
+ _inserts.pop_back ();
_reset_plugin_counts (0); // it worked before we tried to add it ...
return -1;
}
// Ensure peak vector sizes before the plugin is activated
- ChanCount potential_max_streams = max(redirect->input_streams(), redirect->output_streams());
- _meter->setup(potential_max_streams);
+ ChanCount potential_max_streams = max(insert->input_streams(), insert->output_streams());
+ _meter->configure_io(potential_max_streams, potential_max_streams);
- redirect->activate ();
- redirect->active_changed.connect (mem_fun (*this, &Route::redirect_active_proxy));
+ insert->activate ();
+ insert->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
}
- if (redirect_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
+ if (insert_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
reset_panner ();
}
- redirects_changed (src); /* EMIT SIGNAL */
+ inserts_changed (); /* EMIT SIGNAL */
return 0;
}
int
-Route::add_redirects (const RedirectList& others, void *src, InsertStreams* err)
+Route::add_inserts (const InsertList& others, InsertStreams* err)
{
- ChanCount old_rmo = redirect_max_outs;
+ ChanCount old_rmo = insert_max_outs;
if (!_session.engine().connected()) {
return 1;
}
{
- Glib::RWLock::WriterLock lm (redirect_lock);
+ Glib::RWLock::WriterLock lm (insert_lock);
- RedirectList::iterator existing_end = _redirects.end();
+ InsertList::iterator existing_end = _inserts.end();
--existing_end;
ChanCount potential_max_streams;
- for (RedirectList::const_iterator i = others.begin(); i != others.end(); ++i) {
+ for (InsertList::const_iterator i = others.begin(); i != others.end(); ++i) {
boost::shared_ptr<PluginInsert> pi;
@@ -872,57 +853,61 @@ Route::add_redirects (const RedirectList& others, void *src, InsertStreams* err)
}
// Ensure peak vector sizes before the plugin is activated
- _meter->setup(potential_max_streams);
+ _meter->configure_io(potential_max_streams, potential_max_streams);
- _redirects.push_back (*i);
+ _inserts.push_back (*i);
if (_reset_plugin_counts (err)) {
++existing_end;
- _redirects.erase (existing_end, _redirects.end());
+ _inserts.erase (existing_end, _inserts.end());
_reset_plugin_counts (0); // it worked before we tried to add it ...
return -1;
}
(*i)->activate ();
- (*i)->active_changed.connect (mem_fun (*this, &Route::redirect_active_proxy));
+ (*i)->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
}
}
- if (redirect_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
+ if (insert_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
reset_panner ();
}
- redirects_changed (src); /* EMIT SIGNAL */
+ inserts_changed (); /* EMIT SIGNAL */
return 0;
}
-/** Turn off all redirects with a given placement
- * @param p Placement of redirects to disable
+/** Turn off all inserts with a given placement
+ * @param p Placement of inserts to disable
*/
void
-Route::disable_redirects (Placement p)
+Route::disable_inserts (Placement p)
{
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if ((*i)->placement() == p) {
- (*i)->set_active (false, this);
+ (*i)->set_active (false);
}
}
+
+ _session.set_dirty ();
}
/** Turn off all redirects
*/
void
-Route::disable_redirects ()
+Route::disable_inserts ()
{
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
- (*i)->set_active (false, this);
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
+ (*i)->set_active (false);
}
+
+ _session.set_dirty ();
}
/** Turn off all redirects with a given placement
@@ -932,13 +917,15 @@ Route::disable_redirects ()
void
Route::disable_plugins (Placement p)
{
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if (boost::dynamic_pointer_cast<PluginInsert> (*i) && (*i)->placement() == p) {
- (*i)->set_active (false, this);
+ (*i)->set_active (false);
}
}
+
+ _session.set_dirty ();
}
/** Turn off all plugins
@@ -947,20 +934,22 @@ Route::disable_plugins (Placement p)
void
Route::disable_plugins ()
{
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if (boost::dynamic_pointer_cast<PluginInsert> (*i)) {
- (*i)->set_active (false, this);
+ (*i)->set_active (false);
}
}
+
+ _session.set_dirty ();
}
void
Route::ab_plugins (bool forward)
{
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
if (forward) {
@@ -968,13 +957,13 @@ Route::ab_plugins (bool forward)
we go the other way, we will revert them
*/
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if (!boost::dynamic_pointer_cast<PluginInsert> (*i)) {
continue;
}
if ((*i)->active()) {
- (*i)->set_active (false, this);
+ (*i)->set_active (false);
(*i)->set_next_ab_is_active (true);
} else {
(*i)->set_next_ab_is_active (false);
@@ -985,19 +974,21 @@ Route::ab_plugins (bool forward)
/* backward = if the redirect was marked to go active on the next ab, do so */
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if (!boost::dynamic_pointer_cast<PluginInsert> (*i)) {
continue;
}
if ((*i)->get_next_ab_is_active()) {
- (*i)->set_active (true, this);
+ (*i)->set_active (true);
} else {
- (*i)->set_active (false, this);
+ (*i)->set_active (false);
}
}
}
+
+ _session.set_dirty ();
}
@@ -1005,40 +996,40 @@ Route::ab_plugins (bool forward)
ChanCount
Route::pre_fader_streams() const
{
- boost::shared_ptr<Redirect> redirect;
+ boost::shared_ptr<Insert> insert;
// Find the last pre-fader redirect
- for (RedirectList::const_iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
- if ((*r)->placement() == PreFader) {
- redirect = *r;
+ for (InsertList::const_iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
+ if ((*i)->placement() == PreFader) {
+ insert = *i;
}
}
- if (redirect) {
- return redirect->output_streams();
+ if (insert) {
+ return insert->output_streams();
} else {
return n_inputs ();
}
}
-/** Remove redirects with a given placement.
- * @param p Placement of redirects to remove.
+/** Remove inserts with a given placement.
+ * @param p Placement of inserts to remove.
*/
void
-Route::clear_redirects (Placement p, void *src)
+Route::clear_inserts (Placement p)
{
- const ChanCount old_rmo = redirect_max_outs;
+ const ChanCount old_rmo = insert_max_outs;
if (!_session.engine().connected()) {
return;
}
{
- Glib::RWLock::WriterLock lm (redirect_lock);
- RedirectList new_list;
+ Glib::RWLock::WriterLock lm (insert_lock);
+ InsertList new_list;
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if ((*i)->placement() == p) {
/* it's the placement we want to get rid of */
(*i)->drop_references ();
@@ -1048,42 +1039,42 @@ Route::clear_redirects (Placement p, void *src)
}
}
- _redirects = new_list;
+ _inserts = new_list;
}
/* FIXME: can't see how this test can ever fire */
- if (redirect_max_outs != old_rmo) {
+ if (insert_max_outs != old_rmo) {
reset_panner ();
}
- redirect_max_outs.reset();
+ insert_max_outs.reset();
_have_internal_generator = false;
- redirects_changed (src); /* EMIT SIGNAL */
+ inserts_changed (); /* EMIT SIGNAL */
}
int
-Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, InsertStreams* err)
+Route::remove_insert (boost::shared_ptr<Insert> insert, InsertStreams* err)
{
- ChanCount old_rmo = redirect_max_outs;
+ ChanCount old_rmo = insert_max_outs;
if (!_session.engine().connected()) {
return 1;
}
- redirect_max_outs.reset();
+ insert_max_outs.reset();
{
- Glib::RWLock::WriterLock lm (redirect_lock);
- RedirectList::iterator i;
+ Glib::RWLock::WriterLock lm (insert_lock);
+ InsertList::iterator i;
bool removed = false;
- for (i = _redirects.begin(); i != _redirects.end(); ++i) {
- if (*i == redirect) {
+ for (i = _inserts.begin(); i != _inserts.end(); ++i) {
+ if (*i == insert) {
- RedirectList::iterator tmp;
+ InsertList::iterator tmp;
/* move along, see failure case for reset_plugin_counts()
- where we may need to reinsert the redirect.
+ where we may need to reinsert the insert.
*/
tmp = i;
@@ -1094,18 +1085,14 @@ Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, InsertS
run.
*/
- boost::shared_ptr<Send> send;
- boost::shared_ptr<PortInsert> port_insert;
+ boost::shared_ptr<Redirect> redirect;
- if ((send = boost::dynamic_pointer_cast<Send> (*i)) != 0) {
- send->disconnect_inputs (this);
- send->disconnect_outputs (this);
- } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (*i)) != 0) {
- port_insert->disconnect_inputs (this);
- port_insert->disconnect_outputs (this);
+ if ((redirect = boost::dynamic_pointer_cast<Redirect> (*i)) != 0) {
+ redirect->io()->disconnect_inputs (this);
+ redirect->io()->disconnect_outputs (this);
}
- _redirects.erase (i);
+ _inserts.erase (i);
i = tmp;
removed = true;
@@ -1120,7 +1107,7 @@ Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, InsertS
if (_reset_plugin_counts (err)) {
/* get back to where we where */
- _redirects.insert (i, redirect);
+ _inserts.insert (i, insert);
/* we know this will work, because it worked before :) */
_reset_plugin_counts (0);
return -1;
@@ -1128,7 +1115,7 @@ Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, InsertS
bool foo = false;
- for (i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (i = _inserts.begin(); i != _inserts.end(); ++i) {
boost::shared_ptr<PluginInsert> pi;
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
@@ -1141,20 +1128,20 @@ Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, InsertS
_have_internal_generator = foo;
}
- if (old_rmo != redirect_max_outs) {
+ if (old_rmo != insert_max_outs) {
reset_panner ();
}
- redirect->drop_references ();
+ insert->drop_references ();
- redirects_changed (src); /* EMIT SIGNAL */
+ inserts_changed (); /* EMIT SIGNAL */
return 0;
}
int
Route::reset_plugin_counts (InsertStreams* err)
{
- Glib::RWLock::WriterLock lm (redirect_lock);
+ Glib::RWLock::WriterLock lm (insert_lock);
return _reset_plugin_counts (err);
}
@@ -1162,7 +1149,7 @@ Route::reset_plugin_counts (InsertStreams* err)
int
Route::_reset_plugin_counts (InsertStreams* err)
{
- RedirectList::iterator r;
+ InsertList::iterator r;
map<Placement,list<InsertCount> > insert_map;
ChanCount initial_streams;
@@ -1171,13 +1158,13 @@ Route::_reset_plugin_counts (InsertStreams* err)
*/
/* divide inserts up by placement so we get the signal flow
- properly modelled. we need to do this because the _redirects
+ properly modelled. we need to do this because the _inserts
list is not sorted by placement
*/
/* ... but it should/will be... */
- for (r = _redirects.begin(); r != _redirects.end(); ++r) {
+ for (r = _inserts.begin(); r != _inserts.end(); ++r) {
boost::shared_ptr<Insert> insert;
@@ -1206,30 +1193,13 @@ Route::_reset_plugin_counts (InsertStreams* err)
apply_some_plugin_counts (insert_map[PreFader]);
apply_some_plugin_counts (insert_map[PostFader]);
- /* recompute max outs of any redirect */
+ /* recompute max outs of any insert */
- redirect_max_outs.reset();
- RedirectList::iterator prev = _redirects.end();
-
- for (r = _redirects.begin(); r != _redirects.end(); prev = r, ++r) {
- boost::shared_ptr<Send> s;
-
- if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) {
- if (r == _redirects.begin()) {
- s->expect_inputs (n_inputs());
- } else {
- s->expect_inputs ((*prev)->output_streams());
- }
-
- } else {
-
- /* don't pay any attention to send output configuration, since it doesn't
- affect the route.
- */
+ insert_max_outs.reset();
+ InsertList::iterator prev = _inserts.end();
- redirect_max_outs = max ((*r)->output_streams (), redirect_max_outs);
-
- }
+ for (r = _inserts.begin(); r != _inserts.end(); prev = r, ++r) {
+ insert_max_outs = max ((*r)->output_streams (), insert_max_outs);
}
/* we're done */
@@ -1299,28 +1269,28 @@ Route::check_some_plugin_counts (list<InsertCount>& iclist, ChanCount required_i
}
int
-Route::copy_redirects (const Route& other, Placement placement, InsertStreams* err)
+Route::copy_inserts (const Route& other, Placement placement, InsertStreams* err)
{
- ChanCount old_rmo = redirect_max_outs;
+ ChanCount old_rmo = insert_max_outs;
- RedirectList to_be_deleted;
+ InsertList to_be_deleted;
{
- Glib::RWLock::WriterLock lm (redirect_lock);
- RedirectList::iterator tmp;
- RedirectList the_copy;
+ Glib::RWLock::WriterLock lm (insert_lock);
+ InsertList::iterator tmp;
+ InsertList the_copy;
- the_copy = _redirects;
+ the_copy = _inserts;
- /* remove all relevant redirects */
+ /* remove all relevant inserts */
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ) {
tmp = i;
++tmp;
if ((*i)->placement() == placement) {
to_be_deleted.push_back (*i);
- _redirects.erase (i);
+ _inserts.erase (i);
}
i = tmp;
@@ -1328,9 +1298,9 @@ Route::copy_redirects (const Route& other, Placement placement, InsertStreams* e
/* now copy the relevant ones from "other" */
- for (RedirectList::const_iterator i = other._redirects.begin(); i != other._redirects.end(); ++i) {
+ for (InsertList::const_iterator i = other._inserts.begin(); i != other._inserts.end(); ++i) {
if ((*i)->placement() == placement) {
- _redirects.push_back (Redirect::clone (*i));
+ _inserts.push_back (Redirect::clone (*i));
}
}
@@ -1340,15 +1310,15 @@ Route::copy_redirects (const Route& other, Placement placement, InsertStreams* e
/* FAILED COPY ATTEMPT: we have to restore order */
- /* delete all cloned redirects */
+ /* delete all cloned inserts */
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ) {
tmp = i;
++tmp;
if ((*i)->placement() == placement) {
- _redirects.erase (i);
+ _inserts.erase (i);
}
i = tmp;
@@ -1356,8 +1326,8 @@ Route::copy_redirects (const Route& other, Placement placement, InsertStreams* e
/* restore the natural order */
- _redirects = the_copy;
- redirect_max_outs = old_rmo;
+ _inserts = the_copy;
+ insert_max_outs = old_rmo;
/* we failed, even though things are OK again */
@@ -1365,84 +1335,88 @@ Route::copy_redirects (const Route& other, Placement placement, InsertStreams* e
} else {
- /* SUCCESSFUL COPY ATTEMPT: delete the redirects we removed pre-copy */
+ /* SUCCESSFUL COPY ATTEMPT: delete the inserts we removed pre-copy */
to_be_deleted.clear ();
}
}
- if (redirect_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
+ if (insert_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
reset_panner ();
}
- redirects_changed (this); /* EMIT SIGNAL */
+ inserts_changed (); /* EMIT SIGNAL */
return 0;
}
void
-Route::all_redirects_flip ()
+Route::all_inserts_flip ()
{
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
- if (_redirects.empty()) {
+ if (_inserts.empty()) {
return;
}
- bool first_is_on = _redirects.front()->active();
+ bool first_is_on = _inserts.front()->active();
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
- (*i)->set_active (!first_is_on, this);
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
+ (*i)->set_active (!first_is_on);
}
+
+ _session.set_dirty ();
}
-/** Set all redirects with a given placement to a given active state.
- * @param p Placement of redirects to change.
- * @param state New active state for those redirects.
+/** Set all inserts with a given placement to a given active state.
+ * @param p Placement of inserts to change.
+ * @param state New active state for those inserts.
*/
void
-Route::all_redirects_active (Placement p, bool state)
+Route::all_inserts_active (Placement p, bool state)
{
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
- if (_redirects.empty()) {
+ if (_inserts.empty()) {
return;
}
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if ((*i)->placement() == p) {
- (*i)->set_active (state, this);
+ (*i)->set_active (state);
}
}
+
+ _session.set_dirty ();
}
-struct RedirectSorter {
- bool operator() (boost::shared_ptr<const Redirect> a, boost::shared_ptr<const Redirect> b) {
+struct InsertSorter {
+ bool operator() (boost::shared_ptr<const Insert> a, boost::shared_ptr<const Insert> b) {
return a->sort_key() < b->sort_key();
}
};
int
-Route::sort_redirects (InsertStreams* err)
+Route::sort_inserts (InsertStreams* err)
{
{
- RedirectSorter comparator;
- Glib::RWLock::WriterLock lm (redirect_lock);
- ChanCount old_rmo = redirect_max_outs;
+ InsertSorter comparator;
+ Glib::RWLock::WriterLock lm (insert_lock);
+ ChanCount old_rmo = insert_max_outs;
/* the sweet power of C++ ... */
- RedirectList as_it_was_before = _redirects;
+ InsertList as_it_was_before = _inserts;
- _redirects.sort (comparator);
+ _inserts.sort (comparator);
if (_reset_plugin_counts (err)) {
- _redirects = as_it_was_before;
- redirect_max_outs = old_rmo;
+ _inserts = as_it_was_before;
+ insert_max_outs = old_rmo;
return -1;
}
}
reset_panner ();
- redirects_changed (this); /* EMIT SIGNAL */
+ inserts_changed (); /* EMIT SIGNAL */
return 0;
}
@@ -1463,7 +1437,7 @@ XMLNode&
Route::state(bool full_state)
{
XMLNode *node = new XMLNode("Route");
- RedirectList:: iterator i;
+ InsertList:: iterator i;
char buf[32];
if (_flags) {
@@ -1528,7 +1502,7 @@ Route::state(bool full_state)
cmt->add_content (_comment);
}
- for (i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (i = _inserts.begin(); i != _inserts.end(); ++i) {
node->add_child_nocopy((*i)->state (full_state));
}
@@ -1540,10 +1514,10 @@ Route::state(bool full_state)
}
XMLNode&
-Route::get_redirect_state ()
+Route::get_insert_state ()
{
XMLNode* root = new XMLNode (X_("redirects"));
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
root->add_child_nocopy ((*i)->state (true));
}
@@ -1551,7 +1525,7 @@ Route::get_redirect_state ()
}
int
-Route::set_redirect_state (const XMLNode& root)
+Route::set_insert_state (const XMLNode& root)
{
if (root.name() != X_("redirects")) {
return -1;
@@ -1561,7 +1535,7 @@ Route::set_redirect_state (const XMLNode& root)
XMLNodeList nnlist;
XMLNodeConstIterator iter;
XMLNodeConstIterator niter;
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
nlist = root.children();
@@ -1588,9 +1562,9 @@ Route::set_redirect_state (const XMLNode& root)
ID id = prop->value ();
- /* now look for a redirect with that ID */
+ /* now look for a insert with that ID */
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if ((*i)->id() == id) {
(*i)->set_state (**iter);
break;
@@ -1620,7 +1594,7 @@ Route::set_deferred_state ()
nlist = deferred_state->children();
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
- add_redirect_from_xml (**niter);
+ add_insert_from_xml (**niter);
}
delete deferred_state;
@@ -1628,16 +1602,16 @@ Route::set_deferred_state ()
}
void
-Route::add_redirect_from_xml (const XMLNode& node)
+Route::add_insert_from_xml (const XMLNode& node)
{
const XMLProperty *prop;
+ // legacy sessions use a different node name for sends
if (node.name() == "Send") {
-
-
+
try {
boost::shared_ptr<Send> send (new Send (_session, node));
- add_redirect (send, this);
+ add_insert (send);
}
catch (failed_constructor &err) {
@@ -1658,15 +1632,18 @@ Route::add_redirect_from_xml (const XMLNode& node)
} else if (prop->value() == "port") {
-
insert.reset (new PortInsert (_session, node));
+
+ } else if (prop->value() == "send") {
+
+ insert.reset (new Send (_session, node));
} else {
error << string_compose(_("unknown Insert type \"%1\"; ignored"), prop->value()) << endmsg;
}
- add_redirect (insert, this);
+ add_insert (insert);
} else {
error << _("Insert XML node has no type property") << endmsg;
@@ -1820,24 +1797,24 @@ Route::_set_state (const XMLNode& node, bool call_base)
}
}
- XMLNodeList redirect_nodes;
+ XMLNodeList insert_nodes;
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
child = *niter;
if (child->name() == X_("Send") || child->name() == X_("Insert")) {
- redirect_nodes.push_back(child);
+ insert_nodes.push_back(child);
}
}
- _set_redirect_states(redirect_nodes);
+ _set_insert_states(insert_nodes);
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
child = *niter;
- // All redirects (sends and inserts) have been applied already
+ // All inserts have been applied already
if (child->name() == X_("Automation")) {
@@ -1897,33 +1874,37 @@ Route::_set_state (const XMLNode& node, bool call_base)
}
void
-Route::_set_redirect_states(const XMLNodeList &nlist)
+Route::_set_insert_states(const XMLNodeList &nlist)
{
XMLNodeConstIterator niter;
char buf[64];
- RedirectList::iterator i, o;
+ InsertList::iterator i, o;
- // Iterate through existing redirects, remove those which are not in the state list
- for (i = _redirects.begin(); i != _redirects.end(); ) {
- RedirectList::iterator tmp = i;
+ // Iterate through existing inserts, remove those which are not in the state list
+ for (i = _inserts.begin(); i != _inserts.end(); ) {
+ InsertList::iterator tmp = i;
++tmp;
- bool redirectInStateList = false;
+ bool insertInStateList = false;
(*i)->id().print (buf, sizeof (buf));
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ // legacy sessions (Redirect as a child of Insert, both is-a IO)
if (strncmp(buf,(*niter)->child(X_("Redirect"))->child(X_("IO"))->property(X_("id"))->value().c_str(), sizeof(buf)) == 0) {
- redirectInStateList = true;
+ insertInStateList = true;
+ break;
+ } else if (strncmp(buf,(*niter)->property(X_("id"))->value().c_str(), sizeof(buf)) == 0) {
+ insertInStateList = true;
break;
}
}
- if (!redirectInStateList) {
- remove_redirect ( *i, this);
+ if (!insertInStateList) {
+ remove_insert (*i);
}
@@ -1931,65 +1912,68 @@ Route::_set_redirect_states(const XMLNodeList &nlist)
}
- // Iterate through state list and make sure all redirects are on the track and in the correct order,
- // set the state of existing redirects according to the new state on the same go
- i = _redirects.begin();
+ // Iterate through state list and make sure all inserts are on the track and in the correct order,
+ // set the state of existing inserts according to the new state on the same go
+ i = _inserts.begin();
for (niter = nlist.begin(); niter != nlist.end(); ++niter, ++i) {
- // Check whether the next redirect in the list
+ // Check whether the next insert in the list
o = i;
- while (o != _redirects.end()) {
+ while (o != _inserts.end()) {
(*o)->id().print (buf, sizeof (buf));
if ( strncmp(buf, (*niter)->child(X_("Redirect"))->child(X_("IO"))->property(X_("id"))->value().c_str(), sizeof(buf)) == 0)
break;
+ else if (strncmp(buf,(*niter)->property(X_("id"))->value().c_str(), sizeof(buf)) == 0)
+ break;
+
++o;
}
- if (o == _redirects.end()) {
- // If the redirect (*niter) is not on the route, we need to create it
+ if (o == _inserts.end()) {
+ // If the insert (*niter) is not on the route, we need to create it
// and move it to the correct location
- RedirectList::iterator prev_last = _redirects.end();
+ InsertList::iterator prev_last = _inserts.end();
--prev_last; // We need this to check whether adding succeeded
- add_redirect_from_xml (**niter);
+ add_insert_from_xml (**niter);
- RedirectList::iterator last = _redirects.end();
+ InsertList::iterator last = _inserts.end();
--last;
if (prev_last == last) {
- cerr << "Could not fully restore state as some redirects were not possible to create" << endl;
+ cerr << "Could not fully restore state as some inserts were not possible to create" << endl;
continue;
}
- boost::shared_ptr<Redirect> tmp = (*last);
- // remove the redirect from the wrong location
- _redirects.erase(last);
- // insert the new redirect at the current location
- _redirects.insert(i, tmp);
+ boost::shared_ptr<Insert> tmp = (*last);
+ // remove the insert from the wrong location
+ _inserts.erase(last);
+ // insert the new insert at the current location
+ _inserts.insert(i, tmp);
- --i; // move pointer to the newly inserted redirect
+ --i; // move pointer to the newly inserted insert
continue;
}
- // We found the redirect (*niter) on the route, first we must make sure the redirect
+ // We found the insert (*niter) on the route, first we must make sure the insert
// is at the location provided in the XML state
if (i != o) {
- boost::shared_ptr<Redirect> tmp = (*o);
+ boost::shared_ptr<Insert> tmp = (*o);
// remove the old copy
- _redirects.erase(o);
- // insert the redirect at the correct location
- _redirects.insert(i, tmp);
+ _inserts.erase(o);
+ // insert the insert at the correct location
+ _inserts.insert(i, tmp);
- --i; // move pointer so it points to the right redirect
+ --i; // move pointer so it points to the right insert
}
(*i)->set_state( (**niter) );
}
- redirects_changed(this);
+ inserts_changed ();
}
void
@@ -2011,10 +1995,10 @@ Route::silence (nframes_t nframes, nframes_t offset)
}
{
- Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
+ Glib::RWLock::ReaderLock lm (insert_lock, Glib::TRY_LOCK);
if (lm.locked()) {
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
boost::shared_ptr<PluginInsert> pi;
if (!_active && (pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) != 0) {
// skip plugins, they don't need anything when we're not active
@@ -2166,13 +2150,20 @@ Route::feeds (boost::shared_ptr<Route> other)
/* check Redirects which may also interconnect Routes */
- for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); r++) {
+ for (InsertList::iterator r = _inserts.begin(); r != _inserts.end(); r++) {
+
+ boost::shared_ptr<Redirect> redirect = boost::dynamic_pointer_cast<Redirect>(*r);
+
+ if ( ! redirect)
+ continue;
+
+ // TODO: support internal redirects here
- no = (*r)->n_outputs().n_total();
+ no = redirect->io()->n_outputs().n_total();
for (i = 0; i < no; ++i) {
for (j = 0; j < ni; ++j) {
- if ((*r)->output(i)->connected_to (other->input (j)->name())) {
+ if (redirect->io()->output(i)->connected_to (other->input (j)->name())) {
return true;
}
}
@@ -2250,24 +2241,24 @@ void
Route::set_active (bool yn)
{
_active = yn;
- active_changed(); /* EMIT SIGNAL */
+ active_changed(); /* EMIT SIGNAL */
}
void
-Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_flush_redirects)
+Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_flush_inserts)
{
nframes_t now = _session.transport_frame();
{
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
if (!did_locate) {
automation_snapshot (now);
}
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
- if (Config->get_plugins_stop_with_transport() && can_flush_redirects) {
+ if (Config->get_plugins_stop_with_transport() && can_flush_inserts) {
(*i)->deactivate ();
(*i)->activate ();
}
@@ -2308,7 +2299,7 @@ Route::pans_required () const
return 0;
}
- return max (n_inputs ().n_audio(), static_cast<size_t>(redirect_max_outs.n_audio()));
+ return max (n_inputs ().n_audio(), static_cast<size_t>(insert_max_outs.n_audio()));
}
int
@@ -2365,15 +2356,15 @@ Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nfra
bool can_record, bool rec_monitors_input)
{
{
- Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
+ Glib::RWLock::ReaderLock lm (insert_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
+ // and it uses the insert list, so we take the lock out here
automation_snapshot (_session.transport_frame());
}
}
- if ((n_outputs().n_total() == 0 && _redirects.empty()) || n_inputs().n_total() == 0 || !_active) {
+ if ((n_outputs().n_total() == 0 && _inserts.empty()) || n_inputs().n_total() == 0 || !_active) {
silence (nframes, offset);
return 0;
}
@@ -2393,7 +2384,7 @@ Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nfra
if (am.locked() && _session.transport_rolling()) {
- if (gain_automation_playback()) {
+ if (_gain_automation_curve.automation_playback()) {
apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
}
}
@@ -2423,13 +2414,15 @@ Route::toggle_monitor_input ()
bool
Route::has_external_redirects () const
{
+ // FIXME: what about sends?
+
boost::shared_ptr<const PortInsert> pi;
- for (RedirectList::const_iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::const_iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if ((pi = boost::dynamic_pointer_cast<const PortInsert>(*i)) != 0) {
- for (PortSet::const_iterator port = pi->outputs().begin();
- port != pi->outputs().end(); ++port) {
+ for (PortSet::const_iterator port = pi->io()->outputs().begin();
+ port != pi->io()->outputs().end(); ++port) {
string port_name = port->name();
string client_name = port_name.substr (0, port_name.find(':'));
@@ -2447,15 +2440,15 @@ Route::has_external_redirects () const
}
void
-Route::flush_redirects ()
+Route::flush_inserts ()
{
/* XXX shouldn't really try to take this lock, since
this is called from the RT audio thread.
*/
- Glib::RWLock::ReaderLock lm (redirect_lock);
+ Glib::RWLock::ReaderLock lm (insert_lock);
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
(*i)->deactivate ();
(*i)->activate ();
}
@@ -2476,7 +2469,7 @@ Route::update_total_latency ()
{
_own_latency = 0;
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if ((*i)->active ()) {
_own_latency += (*i)->latency ();
}
@@ -2511,7 +2504,7 @@ Route::automation_snapshot (nframes_t now)
{
IO::automation_snapshot (now);
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
(*i)->automation_snapshot (now);
}
}
@@ -2561,18 +2554,12 @@ Route::ToggleControllable::get_value (void) const
void
Route::set_block_size (nframes_t nframes)
{
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
(*i)->set_block_size (nframes);
}
}
void
-Route::redirect_active_proxy (Redirect* ignored, void* ignored_src)
-{
- _session.update_latency_compensation (false, false);
-}
-
-void
Route::protect_automation ()
{
switch (gain_automation_state()) {
@@ -2596,7 +2583,7 @@ Route::protect_automation ()
break;
}
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
boost::shared_ptr<PluginInsert> pi;
if ((pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) != 0) {
pi->protect_automation ();
diff --git a/libs/ardour/route_group.cc b/libs/ardour/route_group.cc
index 13b90474cc..f22deb5dbf 100644
--- a/libs/ardour/route_group.cc
+++ b/libs/ardour/route_group.cc
@@ -149,7 +149,6 @@ RouteGroup::set_state (const XMLNode& node)
void
RouteGroup::set_active (bool yn, void *src)
-
{
if (is_active() == yn) {
return;
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index 39c917571a..1ba063b2dc 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -36,7 +36,7 @@ Send::Send (Session& s, Placement p)
: Redirect (s, string_compose (_("send %1"), (bitslot = s.next_send_id()) + 1), p)
{
_metering = false;
- RedirectCreated (this); /* EMIT SIGNAL */
+ InsertCreated (this); /* EMIT SIGNAL */
}
Send::Send (Session& s, const XMLNode& node)
@@ -48,14 +48,14 @@ Send::Send (Session& s, const XMLNode& node)
throw failed_constructor();
}
- RedirectCreated (this); /* EMIT SIGNAL */
+ InsertCreated (this); /* EMIT SIGNAL */
}
Send::Send (const Send& other)
: Redirect (other._session, string_compose (_("send %1"), (bitslot = other._session.next_send_id()) + 1), other.placement())
{
_metering = false;
- RedirectCreated (this); /* EMIT SIGNAL */
+ InsertCreated (this); /* EMIT SIGNAL */
}
Send::~Send ()
@@ -72,12 +72,13 @@ Send::get_state(void)
XMLNode&
Send::state(bool full)
{
- XMLNode *node = new XMLNode("Send");
+ XMLNode& node = Redirect::state(full);
char buf[32];
- node->add_child_nocopy (Redirect::state (full));
+ node.add_property ("type", "send");
snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
- node->add_property ("bitslot", buf);
- return *node;
+ node.add_property ("bitslot", buf);
+
+ return node;
}
int
@@ -94,16 +95,19 @@ Send::set_state(const XMLNode& node)
_session.mark_send_id (bitslot);
}
+ const XMLNode* insert_node = &node;
+
/* Send has regular IO automation (gain, pan) */
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- if ((*niter)->name() == Redirect::state_node_name) {
- Redirect::set_state (**niter);
- break;
+ if ((*niter)->name() == "Redirect") {
+ insert_node = *niter;
} else if ((*niter)->name() == X_("Automation")) {
- IO::set_automation_state (*(*niter));
+ _io->set_automation_state (*(*niter));
}
}
+
+ Redirect::set_state (*insert_node);
if (niter == nlist.end()) {
error << _("XML node describing a send is missing a Redirect node") << endmsg;
@@ -126,21 +130,21 @@ Send::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_
sendbufs.read_from(bufs, nframes);
assert(sendbufs.count() == bufs.count());
- IO::deliver_output (sendbufs, start_frame, end_frame, nframes, offset);
+ _io->deliver_output (sendbufs, start_frame, end_frame, nframes, offset);
if (_metering) {
- if (_gain == 0) {
- _meter->reset();
+ if (_io->_gain == 0) {
+ _io->_meter->reset();
} else {
- _meter->run(output_buffers(), nframes, offset);
+ _io->_meter->run(_io->output_buffers(), start_frame, end_frame, nframes, offset);
}
}
} else {
- silence (nframes, offset);
+ _io->silence (nframes, offset);
if (_metering) {
- _meter->reset();
+ _io->_meter->reset();
}
}
}
@@ -152,15 +156,72 @@ Send::set_metering (bool yn)
if (!_metering) {
/* XXX possible thread hazard here */
- peak_meter().reset();
+ _io->peak_meter().reset();
}
}
-void
-Send::expect_inputs (const ChanCount& expected)
+bool
+Send::can_support_input_configuration (ChanCount in) const
+{
+ if (_io->input_maximum() == ChanCount::INFINITE && _io->output_maximum() == ChanCount::INFINITE) {
+
+ /* not configured yet */
+
+ return true; /* we can support anything the first time we're asked */
+
+ } else {
+
+ /* the "input" config for a port insert corresponds to how
+ many output ports it will have.
+ */
+
+ if (_io->output_maximum() == in) {
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+ChanCount
+Send::output_for_input_configuration (ChanCount in) const
+{
+ // from the internal (Insert) perspective a Send does not modify its input whatsoever
+ return in;
+}
+
+bool
+Send::configure_io (ChanCount in, ChanCount out)
{
- if (expected != _expected_inputs) {
- _expected_inputs = expected;
- reset_panner ();
+ /* we're transparent no matter what. fight the power. */
+ if (out != in)
+ return false;
+
+ _io->set_output_maximum (in);
+ _io->set_output_minimum (in);
+ _io->set_input_maximum (ChanCount::ZERO);
+ _io->set_input_minimum (ChanCount::ZERO);
+
+ bool success = _io->ensure_io (ChanCount::ZERO, in, false, this) == 0;
+
+ if (success) {
+ Insert::configure_io(in, out);
+ _io->reset_panner();
+ return true;
+ } else {
+ return false;
}
}
+
+ChanCount
+Send::output_streams() const
+{
+ return _io->n_outputs ();
+}
+
+ChanCount
+Send::input_streams() const
+{
+ return _io->n_outputs (); // (sic)
+}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 310bd155ee..10860b0c88 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -1887,7 +1887,7 @@ Session::add_routes (RouteList& new_routes, bool save)
(*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), wpr));
(*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
(*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
- (*x)->redirects_changed.connect (mem_fun (*this, &Session::update_latency_compensation_proxy));
+ (*x)->inserts_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false));
if ((*x)->master()) {
_master_out = (*x);
@@ -3529,65 +3529,51 @@ Session::record_enable_change_all (bool yn)
}
void
-Session::add_redirect (Redirect* redirect)
+Session::add_insert (Insert* insert)
{
Send* send;
- Insert* insert;
PortInsert* port_insert;
PluginInsert* plugin_insert;
- if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
- if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
- _port_inserts.insert (_port_inserts.begin(), port_insert);
- } else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
- _plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
- } else {
- fatal << _("programming error: unknown type of Insert created!") << endmsg;
- /*NOTREACHED*/
- }
- } else if ((send = dynamic_cast<Send *> (redirect)) != 0) {
+ if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
+ _port_inserts.insert (_port_inserts.begin(), port_insert);
+ } else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
+ _plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
+ } else if ((send = dynamic_cast<Send *> (insert)) != 0) {
_sends.insert (_sends.begin(), send);
} else {
- fatal << _("programming error: unknown type of Redirect created!") << endmsg;
+ fatal << _("programming error: unknown type of Insert created!") << endmsg;
/*NOTREACHED*/
}
- redirect->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_redirect), redirect));
+ insert->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_insert), insert));
set_dirty();
}
void
-Session::remove_redirect (Redirect* redirect)
+Session::remove_insert (Insert* insert)
{
Send* send;
- Insert* insert;
PortInsert* port_insert;
PluginInsert* plugin_insert;
- if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
- if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
- list<PortInsert*>::iterator x = find (_port_inserts.begin(), _port_inserts.end(), port_insert);
- if (x != _port_inserts.end()) {
- insert_bitset[port_insert->bit_slot()] = false;
- _port_inserts.erase (x);
- }
- } else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
- _plugin_inserts.remove (plugin_insert);
- } else {
- fatal << string_compose (_("programming error: %1"),
- X_("unknown type of Insert deleted!"))
- << endmsg;
- /*NOTREACHED*/
- }
- } else if ((send = dynamic_cast<Send *> (redirect)) != 0) {
+ if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
+ list<PortInsert*>::iterator x = find (_port_inserts.begin(), _port_inserts.end(), port_insert);
+ if (x != _port_inserts.end()) {
+ insert_bitset[port_insert->bit_slot()] = false;
+ _port_inserts.erase (x);
+ }
+ } else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
+ _plugin_inserts.remove (plugin_insert);
+ } else if ((send = dynamic_cast<Send *> (insert)) != 0) {
list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
if (x != _sends.end()) {
send_bitset[send->bit_slot()] = false;
_sends.erase (x);
}
} else {
- fatal << _("programming error: unknown type of Redirect deleted!") << endmsg;
+ fatal << _("programming error: unknown type of Insert deleted!") << endmsg;
/*NOTREACHED*/
}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 5ddcb86cdc..b1a9b87536 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -261,7 +261,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
PlaylistFactory::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
- Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
+ Insert::InsertCreated.connect (mem_fun (*this, &Session::add_insert));
NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index d032e31b93..60cc8b91ae 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -379,7 +379,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
if ((Config->get_slave_source() == None && Config->get_auto_return()) || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
if (pending_locate_flush) {
- flush_all_redirects ();
+ flush_all_inserts ();
}
if (((Config->get_slave_source() == None && Config->get_auto_return()) || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
@@ -573,12 +573,12 @@ Session::set_play_loop (bool yn)
}
void
-Session::flush_all_redirects ()
+Session::flush_all_inserts ()
{
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- (*i)->flush_redirects ();
+ (*i)->flush_inserts ();
}
}
@@ -1267,12 +1267,6 @@ Session::update_latency_compensation (bool with_stop, bool abort)
}
void
-Session::update_latency_compensation_proxy (void* ignored)
-{
- update_latency_compensation (false, false);
-}
-
-void
Session::allow_auto_play (bool yn)
{
auto_play_legal = yn;
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 4f3fbd1fd9..c7c3383a44 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -679,7 +679,7 @@ SMFSource::set_allow_remove_if_empty (bool yn)
}
int
-SMFSource::set_name (string newname, bool destructive)
+SMFSource::set_source_name (string newname, bool destructive)
{
//Glib::Mutex::Lock lm (_lock); FIXME
string oldpath = _path;
diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc
index a7620dbc5a..a11e82f1e8 100644
--- a/libs/ardour/source.cc
+++ b/libs/ardour/source.cc
@@ -42,20 +42,20 @@ using std::max;
using namespace ARDOUR;
-Source::Source (Session& s, string name, DataType type)
- : _session (s)
+Source::Source (Session& s, const string& name, DataType type)
+ : SessionObject(s, name)
, _type(type)
{
- assert(_name.find("/") == string::npos);
+ // not true.. is this supposed to be an assertion?
+ //assert(_name.find("/") == string::npos);
- _name = name;
_timestamp = 0;
_length = 0;
_in_use = 0;
}
Source::Source (Session& s, const XMLNode& node)
- : _session (s)
+ : SessionObject(s, "unnamed source")
, _type(DataType::AUDIO)
{
_timestamp = 0;
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index ebbb617776..f84b53cacb 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 (*this)
{
_declickable = true;
_freeze_record.state = NoFreeze;
@@ -49,8 +49,8 @@ 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)
+ : Route (sess, node)
+ , _rec_enable_control (*this)
{
_freeze_record.state = NoFreeze;
_declickable = true;
@@ -92,7 +92,7 @@ Track::update_total_latency ()
{
_own_latency = 0;
- for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
if ((*i)->active ()) {
_own_latency += (*i)->latency ();
}
@@ -182,25 +182,27 @@ Track::set_record_enable (bool yn, void *src)
_rec_enable_control.Changed ();
}
-int
-Track::set_name (string str, void *src)
+
+bool
+Track::set_name (const string& str)
{
- int ret;
+ bool ret;
if (record_enabled() && _session.actively_recording()) {
/* this messes things up if done while recording */
- return -1;
+ return false;
}
if (_diskstream->set_name (str)) {
- return -1;
+ return false;
}
/* save state so that the statefile fully reflects any filename changes */
- if ((ret = IO::set_name (str, src)) == 0) {
+ if ((ret = IO::set_name (str)) == 0) {
_session.save_state ("");
}
+
return ret;
}