diff options
Diffstat (limited to 'libs/ardour')
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, ¶m) != 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, ¶m) != 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; } |