X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fardour%2Froute.h;h=3d4f7f139a19287a4c9d025c2e62a7aedd92ed29;hb=14004b75a6d18a74fa59ac06c203af693164b774;hp=6bc37ee51efae7b54c62153e8f65abe23872e7d0;hpb=ef6b25432d9c46d71b08c0f7d5f2686df428c4e8;p=ardour.git diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 6bc37ee51e..3d4f7f139a 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2002 Paul Davis + Copyright (C) 2000-2002 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 @@ -15,342 +15,471 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ */ #ifndef __ardour_route_h__ #define __ardour_route_h__ #include +#include #include -#include #include +#include #include #include +#include -#include #include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include +#include "pbd/fastlog.h" +#include "pbd/xml++.h" +#include "pbd/undo.h" +#include "pbd/stateful.h" +#include "pbd/controllable.h" +#include "pbd/destructible.h" + +#include "ardour/ardour.h" +#include "ardour/io.h" +#include "ardour/types.h" +#include "ardour/mute_master.h" +#include "ardour/route_group_member.h" +#include "ardour/graphnode.h" namespace ARDOUR { -class Insert; -class Send; +class Amp; +class Delivery; +class IOProcessor; +class Panner; +class Processor; class RouteGroup; +class Send; +class InternalReturn; +class MonitorProcessor; -enum mute_type { - PRE_FADER = 0x1, - POST_FADER = 0x2, - CONTROL_OUTS = 0x4, - MAIN_OUTS = 0x8 -}; - -class Route : public IO +class Route : public SessionObject, public AutomatableControls, public RouteGroupMember, public GraphNode { - protected: - - typedef list > RedirectList; public: + typedef std::list > ProcessorList; + enum Flag { Hidden = 0x1, MasterOut = 0x2, - ControlOut = 0x4 + MonitorOut = 0x4 }; - - Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max, - Flag flags = Flag(0), DataType default_type = DataType::AUDIO); - Route (Session&, const XMLNode&, DataType default_type = DataType::AUDIO); + Route (Session&, std::string name, Flag flags = Flag(0), DataType default_type = DataType::AUDIO); virtual ~Route(); + virtual int init (); + + boost::shared_ptr input() const { return _input; } + boost::shared_ptr output() const { return _output; } + + ChanCount n_inputs() const { return _input->n_ports(); } + ChanCount n_outputs() const { return _output->n_ports(); } + + bool active() const { return _active; } + void set_active (bool yn); + + static std::string ensure_track_or_route_name(std::string, Session &); + std::string comment() { return _comment; } void set_comment (std::string str, void *src); - long order_key(std::string name) const; - void set_order_key (std::string name, long n); + bool set_name (const std::string& str); + + long order_key (std::string const &) const; + void set_order_key (std::string const &, long); - bool hidden() const { return _flags & Hidden; } - bool master() const { return _flags & MasterOut; } - bool control() const { return _flags & ControlOut; } + bool is_hidden() const { return _flags & Hidden; } + bool is_master() const { return _flags & MasterOut; } + bool is_monitor() const { return _flags & MonitorOut; } /* these are the core of the API of a Route. see the protected sections as well */ + virtual int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, + int declick, bool can_record, bool rec_monitors_input, bool& need_butler); - virtual 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); + virtual int no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, + bool state_changing, bool can_record, bool rec_monitors_input); - virtual int no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, - nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input); + virtual int silent_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, + bool can_record, bool rec_monitors_input, bool& need_butler); - virtual int silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, - nframes_t offset, bool can_record, bool rec_monitors_input); virtual void toggle_monitor_input (); virtual bool can_record() { return false; } - virtual void set_record_enable (bool yn, void *src) {} + + 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_processors); virtual void set_pending_declick (int); /* end of vfunc-based API */ - /* override IO::set_gain() to provide group control */ + void shift (nframes64_t, nframes64_t); void set_gain (gain_t val, void *src); void inc_gain (gain_t delta, void *src); - bool active() const { return _active; } - void set_active (bool yn); + void set_mute_points (MuteMaster::MutePoint); + MuteMaster::MutePoint mute_points () const; + + bool muted () const; + void set_mute (bool yn, void* src); + + /* controls use set_solo() to modify this route's solo state + */ void set_solo (bool yn, void *src); - bool soloed() const { return _soloed; } + bool soloed () const { return self_soloed () || soloed_by_others (); } + + bool soloed_by_others () const { return _soloed_by_others_upstream||_soloed_by_others_downstream; } + bool soloed_by_others_upstream () const { return _soloed_by_others_upstream; } + bool soloed_by_others_downstream () const { return _soloed_by_others_downstream; } + bool self_soloed () const { return _self_solo; } + + void set_solo_isolated (bool yn, void *src); + bool solo_isolated() const; void set_solo_safe (bool yn, void *src); - bool solo_safe() const { return _solo_safe; } + bool solo_safe() const; - void set_mute (bool yn, void *src); - bool muted() const { return _muted; } + void set_listen (bool yn, void* src); + bool listening () const; - void set_mute_config (mute_type, bool, void *src); - bool get_mute_config (mute_type); - - void set_edit_group (RouteGroup *, void *); - void drop_edit_group (void *); - RouteGroup *edit_group () { return _edit_group; } + void set_phase_invert (bool yn); + bool phase_invert() const; + + void set_denormal_protection (bool yn); + bool denormal_protection() const; - void set_mix_group (RouteGroup *, void *); - void drop_mix_group (void *); - RouteGroup *mix_group () { return _mix_group; } + void set_meter_point (MeterPoint); + void infer_meter_point () const; + MeterPoint meter_point() const { return _meter_point; } + void meter (); - virtual void set_meter_point (MeterPoint, void *src); - MeterPoint meter_point() const { return _meter_point; } + /* Processors */ - /* Redirects */ + boost::shared_ptr amp() const { return _amp; } + PeakMeter& peak_meter() { return *_meter.get(); } + const PeakMeter& peak_meter() const { return *_meter.get(); } + boost::shared_ptr shared_peak_meter() const { return _meter; } - void flush_redirects (); + void flush_processors (); - template void foreach_redirect (T *obj, void (T::*func)(boost::shared_ptr)) { - Glib::RWLock::ReaderLock lm (redirect_lock); - for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - (obj->*func) (*i); + void foreach_processor (boost::function)> method) { + Glib::RWLock::ReaderLock lm (_processor_lock); + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + method (boost::weak_ptr (*i)); } } - boost::shared_ptr 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()) { - return boost::shared_ptr (); + boost::shared_ptr nth_processor (uint32_t n) { + Glib::RWLock::ReaderLock lm (_processor_lock); + ProcessorList::iterator i; + for (i = _processors.begin(); i != _processors.end() && n; ++i, --n) {} + if (i == _processors.end()) { + return boost::shared_ptr (); } else { return *i; } } - - ChanCount max_redirect_outs () const { return redirect_max_outs; } - - // FIXME: remove/replace err_streams parameters with something appropriate - // they are used by 'wierd_plugin_dialog'(sic) to display the number of input streams - // at the insertion point if the insert fails - int add_redirect (boost::shared_ptr, void *src, uint32_t* err_streams = 0); - int add_redirects (const RedirectList&, void *src, uint32_t* err_streams = 0); - int remove_redirect (boost::shared_ptr, void *src, uint32_t* err_streams = 0); - int copy_redirects (const Route&, Placement, uint32_t* err_streams = 0); - int sort_redirects (uint32_t* err_streams = 0); - - void clear_redirects (void *src); - void all_redirects_flip(); - void all_redirects_active (bool state); + + boost::shared_ptr nth_plugin (uint32_t n); + boost::shared_ptr nth_send (uint32_t n); + + bool processor_is_prefader (boost::shared_ptr p); + + bool has_io_processor_named (const std::string&); + ChanCount max_processor_streams () const { return processor_max_streams; } + + /* special processors */ + + boost::shared_ptr monitor_send() const { return _monitor_send; } + boost::shared_ptr main_outs() const { return _main_outs; } + boost::shared_ptr internal_return() const { return _intreturn; } + boost::shared_ptr monitor_control() const { return _monitor_control; } + boost::shared_ptr internal_send_for (boost::shared_ptr target) const; + void add_internal_return (); + BufferSet* get_return_buffer () const; + void release_return_buffer () const; + void put_monitor_send_at (Placement); + + /** A record of the stream configuration at some point in the processor list. + * Used to return where and why an processor list configuration request failed. + */ + struct ProcessorStreams { + ProcessorStreams(size_t i=0, ChanCount c=ChanCount()) : index(i), count(c) {} + + uint32_t index; ///< Index of processor where configuration failed + ChanCount count; ///< Input requested of processor + }; + + int add_processor (boost::shared_ptr, Placement placement, ProcessorStreams* err = 0); + int add_processor (boost::shared_ptr, ProcessorList::iterator iter, ProcessorStreams* err = 0, bool activation_allowed = true); + int add_processors (const ProcessorList&, boost::shared_ptr before, ProcessorStreams* err = 0); + int add_processors (const ProcessorList&, ProcessorList::iterator iter, ProcessorStreams* err = 0); + int remove_processor (boost::shared_ptr, ProcessorStreams* err = 0); + int remove_processors (const ProcessorList&, ProcessorStreams* err = 0); + int reorder_processors (const ProcessorList& new_order, ProcessorStreams* err = 0); + void disable_processors (Placement); + void disable_processors (); + void disable_plugins (Placement); + void disable_plugins (); + void ab_plugins (bool forward); + void clear_processors (Placement); + void all_processors_flip(); + void all_processors_active (Placement, bool state); virtual nframes_t update_total_latency(); - nframes_t signal_latency() const { return _own_latency; } - virtual void set_latency_delay (nframes_t); - - sigc::signal solo_changed; - sigc::signal solo_safe_changed; - sigc::signal comment_changed; - sigc::signal mute_changed; - sigc::signal pre_fader_changed; - sigc::signal post_fader_changed; - sigc::signal control_outs_changed; - sigc::signal main_outs_changed; - sigc::signal redirects_changed; - sigc::signal record_enable_changed; - sigc::signal edit_group_changed; - sigc::signal mix_group_changed; - sigc::signal active_changed; - sigc::signal meter_change; + void set_latency_delay (nframes_t); + void set_user_latency (nframes_t); + nframes_t initial_delay() const { return _initial_delay; } + + PBD::Signal0 active_changed; + PBD::Signal0 phase_invert_changed; + PBD::Signal0 denormal_protection_changed; + PBD::Signal1 listen_changed; + PBD::Signal2 solo_changed; + PBD::Signal1 solo_safe_changed; + PBD::Signal1 solo_isolated_changed; + PBD::Signal1 comment_changed; + PBD::Signal1 mute_changed; + PBD::Signal0 mute_points_changed; + + /** the processors have changed; the parameter indicates what changed */ + PBD::Signal1 processors_changed; + PBD::Signal1 record_enable_changed; + /** the metering point has changed */ + PBD::Signal0 meter_change; + PBD::Signal0 signal_latency_changed; + PBD::Signal0 initial_delay_changed; /* gui's call this for their own purposes. */ - sigc::signal gui_changed; + PBD::Signal2 gui_changed; /* stateful */ XMLNode& get_state(); - int set_state(const XMLNode& node); + int set_state (const XMLNode&, int version); virtual XMLNode& get_template(); - sigc::signal SelectedChanged; + XMLNode& get_processor_state (); + virtual void set_processor_state (const XMLNode&); + + int save_as_template (const std::string& path, const std::string& name); - int set_control_outs (const vector& ports); - IO* control_outs() { return _control_outs; } + PBD::Signal1 SelectedChanged; - bool feeds (boost::shared_ptr); - set > fed_by; + int listen_via (boost::shared_ptr, Placement p, bool active, bool aux); + void drop_listen (boost::shared_ptr); - struct ToggleControllable : public PBD::Controllable { - enum ToggleType { - MuteControl = 0, - SoloControl - }; - - ToggleControllable (std::string name, Route&, ToggleType); - void set_value (float); - float get_value (void) const; + /** + * return true if this route feeds the first argument via at least one + * (arbitrarily long) signal pathway. + */ + bool feeds (boost::shared_ptr, bool* via_send_only = 0); - Route& route; - ToggleType type; + /** + * return true if this route feeds the first argument directly, via + * either its main outs or a send. + */ + bool direct_feeds (boost::shared_ptr, bool* via_send_only = 0); + + struct FeedRecord { + boost::weak_ptr r; + bool sends_only; + + FeedRecord (boost::shared_ptr rp, bool sendsonly) + : r (rp) + , sends_only (sendsonly) {} + }; + + struct FeedRecordCompare { + bool operator() (const FeedRecord& a, const FeedRecord& b) const { + return a.r < b.r; + } + }; + + typedef std::set FedBy; + + const FedBy& fed_by() const { return _fed_by; } + void clear_fed_by (); + bool add_fed_by (boost::shared_ptr, bool sends_only); + bool not_fed() const { return _fed_by.empty(); } + + /* Controls (not all directly owned by the Route */ + + boost::shared_ptr get_control (const Evoral::Parameter& param); + + struct SoloControllable : public AutomationControl { + SoloControllable (std::string name, Route&); + void set_value (float); + float get_value (void) const; + + Route& route; + }; + + struct MuteControllable : public AutomationControl { + MuteControllable (std::string name, Route&); + void set_value (float); + float get_value (void) const; + + Route& route; }; - PBD::Controllable& solo_control() { + boost::shared_ptr solo_control() const { return _solo_control; } - PBD::Controllable& mute_control() { + boost::shared_ptr mute_control() const { return _mute_control; } - - void automation_snapshot (nframes_t now); + + boost::shared_ptr mute_master() const { + return _mute_master; + } + + /* Route doesn't own these items, but sub-objects that it does own have them + and to make UI code a bit simpler, we provide direct access to them + here. + */ + + boost::shared_ptr panner() const; + boost::shared_ptr gain_control() const; + + void automation_snapshot (nframes_t now, bool force=false); void protect_automation (); - - void set_remote_control_id (uint32_t id); + + void set_remote_control_id (uint32_t id, bool notify_class_listeners = true); uint32_t remote_control_id () const; - sigc::signal RemoteControlIDChanged; + + /* for things concerned about *this* route's RID */ + + PBD::Signal0 RemoteControlIDChanged; + + /* for things concerned about any route's RID changes */ + + static PBD::Signal0 RemoteControlIDChange; + + void sync_order_keys (std::string const &); + static PBD::Signal1 SyncOrderKeys; protected: friend class Session; - void set_solo_mute (bool yn); - void set_block_size (nframes_t nframes); + void catch_up_on_solo_mute_override (); + void mod_solo_by_others_upstream (int32_t); + void mod_solo_by_others_downstream (int32_t); bool has_external_redirects() const; void curve_reallocate (); + void just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes); + virtual void set_block_size (nframes_t nframes); protected: - unsigned char _flags; + nframes_t check_initial_delay (nframes_t, nframes_t&); - /* tight cache-line access here is more important than sheer speed of - access. - */ + void passthru (sframes_t start_frame, sframes_t end_frame, + nframes_t nframes, int declick); - bool _muted : 1; - bool _soloed : 1; - bool _solo_muted : 1; - bool _solo_safe : 1; - bool _recordable : 1; - bool _active : 1; - bool _mute_affects_pre_fader : 1; - bool _mute_affects_post_fader : 1; - bool _mute_affects_control_outs : 1; - bool _mute_affects_main_outs : 1; - bool _silent : 1; - bool _declickable : 1; - int _pending_declick; - - MeterPoint _meter_point; - - gain_t solo_gain; - gain_t mute_gain; - gain_t desired_solo_gain; - gain_t desired_mute_gain; - - nframes_t check_initial_delay (nframes_t, nframes_t&, nframes_t&); - - nframes_t _initial_delay; - nframes_t _roll_delay; - nframes_t _own_latency; - RedirectList _redirects; - Glib::RWLock redirect_lock; - IO *_control_outs; - Glib::Mutex control_outs_lock; - RouteGroup *_edit_group; - RouteGroup *_mix_group; - std::string _comment; - bool _have_internal_generator; - - ToggleControllable _solo_control; - ToggleControllable _mute_control; - - void passthru (nframes_t start_frame, nframes_t end_frame, - nframes_t nframes, nframes_t offset, int declick, bool meter_inputs); + virtual void write_out_of_band_data (BufferSet& /* bufs */, sframes_t /* start_frame */, sframes_t /* end_frame */, + nframes_t /* nframes */) {} 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, - bool meter); + sframes_t start_frame, sframes_t end_frame, + nframes_t nframes, bool with_processors, int declick); + + boost::shared_ptr _input; + boost::shared_ptr _output; + + bool _active; + nframes_t _initial_delay; + nframes_t _roll_delay; + + ProcessorList _processors; + mutable Glib::RWLock _processor_lock; + boost::shared_ptr _main_outs; + boost::shared_ptr _monitor_send; + boost::shared_ptr _intreturn; + boost::shared_ptr _monitor_control; + + Flag _flags; + int _pending_declick; + MeterPoint _meter_point; + uint32_t _phase_invert; + bool _self_solo; + uint32_t _soloed_by_others_upstream; + uint32_t _soloed_by_others_downstream; + uint32_t _solo_isolated; + + bool _denormal_protection; + + bool _recordable : 1; + bool _silent : 1; + bool _declickable : 1; + + boost::shared_ptr _solo_control; + boost::shared_ptr _mute_control; + boost::shared_ptr _mute_master; + + std::string _comment; + bool _have_internal_generator; + bool _solo_safe; + DataType _default_type; + FedBy _fed_by; + + virtual ChanCount input_streams () const; protected: - virtual XMLNode& state(bool); - void passthru_silence (nframes_t start_frame, nframes_t end_frame, - nframes_t nframes, nframes_t offset, int declick, - bool meter); - - void silence (nframes_t nframes, nframes_t offset); - - sigc::connection input_signal_connection; + int configure_processors (ProcessorStreams*); + + void passthru_silence (sframes_t start_frame, sframes_t end_frame, + nframes_t nframes, int declick); - ChanCount redirect_max_outs; + void silence (nframes_t); + void silence_unlocked (nframes_t); + + ChanCount processor_max_streams; uint32_t _remote_control_id; uint32_t pans_required() const; ChanCount n_process_buffers (); + + virtual int _set_state (const XMLNode&, int, bool call_base); - virtual int _set_state (const XMLNode&, bool call_base); + boost::shared_ptr _amp; + boost::shared_ptr _meter; private: - void init (); + int _set_state_2X (const XMLNode&, int); + void set_processor_state_2X (XMLNodeList const &, int); static uint32_t order_key_cnt; - typedef std::map OrderKeys; + + typedef std::map OrderKeys; OrderKeys order_keys; void input_change_handler (IOChange, void *src); void output_change_handler (IOChange, void *src); - bool legal_redirect (Redirect&); - int reset_plugin_counts (uint32_t*); /* locked */ - int _reset_plugin_counts (uint32_t*); /* unlocked */ + bool _in_configure_processors; - /* plugin count handling */ + int configure_processors_unlocked (ProcessorStreams*); - struct InsertCount { - boost::shared_ptr insert; - int32_t cnt; - int32_t in; - int32_t out; + bool add_processor_from_xml (const XMLNode&, ProcessorList::iterator iter); + bool add_processor_from_xml_2X (const XMLNode&, int, ProcessorList::iterator iter); - InsertCount (boost::shared_ptr ins) : insert (ins), cnt (-1) {} - }; - - int32_t apply_some_plugin_counts (std::list& iclist); - int32_t check_some_plugin_counts (std::list& iclist, int32_t required_inputs, uint32_t* err_streams); + void placement_range (Placement p, ProcessorList::iterator& start, ProcessorList::iterator& end); + + void set_self_solo (bool yn); + void set_mute_master_solo (); - void set_deferred_state (); - void add_redirect_from_xml (const XMLNode&); - void redirect_active_proxy (Redirect*, void*); + void set_processor_positions (); }; } // namespace ARDOUR