X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fardour%2Froute.h;h=3fab63bb9b0c3e99555dfe7b8e07c8ebb1edad6a;hb=2db69318cef5bc7b49a3c6e00b3ca3f0f2023374;hp=2696b500ac81fc5141b99a4aa0399791927b7b99;hpb=02583c300f1a909c031b75e9e264696cce0a53e2;p=ardour.git diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 2696b500ac..3fab63bb9b 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -29,6 +29,8 @@ #include #include +#include +#include #include #include "pbd/fastlog.h" @@ -43,6 +45,9 @@ #include "ardour/types.h" #include "ardour/mute_master.h" #include "ardour/route_group_member.h" +#include "ardour/graphnode.h" +#include "ardour/automatable.h" +#include "ardour/unknown_processor.h" namespace ARDOUR { @@ -50,13 +55,18 @@ class Amp; class Delivery; class IOProcessor; class Panner; +class PannerShell; +class PortSet; class Processor; class RouteGroup; class Send; class InternalReturn; class MonitorProcessor; +class Pannable; +class CapturingProcessor; +class InternalSend; -class Route : public SessionObject, public AutomatableControls, public RouteGroupMember +class Route : public SessionObject, public Automatable, public RouteGroupMember, public GraphNode, public boost::enable_shared_from_this { public: @@ -80,7 +90,7 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou ChanCount n_outputs() const { return _output->n_ports(); } bool active() const { return _active; } - void set_active (bool yn); + void set_active (bool yn, void *); static std::string ensure_track_or_route_name(std::string, Session &); @@ -88,54 +98,62 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou void set_comment (std::string str, void *src); bool set_name (const std::string& str); + static void set_name_in_state (XMLNode &, const std::string &); - long order_key (std::string const &) const; - void set_order_key (std::string const &, long); + int32_t order_key (std::string const &) const; + void set_order_key (std::string const &, int32_t); bool is_hidden() const { return _flags & Hidden; } bool is_master() const { return _flags & MasterOut; } bool is_monitor() const { return _flags & MonitorOut; } + virtual MonitorState monitoring_state () const; + virtual MeterState metering_state () const; + /* 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); + virtual int roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, + int declick, bool& need_butler); - 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 (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, + bool state_changing); - virtual int silent_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, - bool can_record, bool rec_monitors_input); + virtual int silent_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, + bool& need_butler); - virtual void toggle_monitor_input (); virtual bool can_record() { return false; } - virtual void set_record_enable (bool /*yn*/, void * /*src*/) {} + virtual void set_record_enabled (bool /*yn*/, void * /*src*/) {} virtual bool record_enabled() const { return false; } - virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_processors); + virtual void nonrealtime_handle_transport_stopped (bool abort, bool did_locate, bool flush_processors); + virtual void realtime_handle_transport_stopped () {} + virtual void realtime_locate () {} virtual void set_pending_declick (int); /* end of vfunc-based API */ - void shift (nframes64_t, nframes64_t); + void shift (framepos_t, framepos_t); void set_gain (gain_t val, void *src); void inc_gain (gain_t delta, void *src); void set_mute_points (MuteMaster::MutePoint); - MuteMaster::MutePoint mute_points() const { return _mute_points; } - void set_mute (bool yn, void* src); - bool muted () const; + 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 self_soloed () || soloed_by_others (); } - bool soloed_by_others () const { return !_solo_isolated && _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; @@ -143,15 +161,17 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou bool solo_safe() const; void set_listen (bool yn, void* src); - bool listening () const; + bool listening_via_monitor () const; - void set_phase_invert (bool yn); - bool phase_invert() const; + void set_phase_invert (uint32_t, bool yn); + void set_phase_invert (boost::dynamic_bitset<>); + bool phase_invert (uint32_t) const; + boost::dynamic_bitset<> phase_invert () const; void set_denormal_protection (bool yn); bool denormal_protection() const; - void set_meter_point (MeterPoint, void *src); + void set_meter_point (MeterPoint, bool force = false); MeterPoint meter_point() const { return _meter_point; } void meter (); @@ -167,6 +187,9 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou void foreach_processor (boost::function)> method) { Glib::RWLock::ReaderLock lm (_processor_lock); for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + if (boost::dynamic_pointer_cast (*i)) { + break; + } method (boost::weak_ptr (*i)); } } @@ -182,24 +205,28 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou } } + boost::shared_ptr processor_by_id (PBD::ID) const; + 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; } + std::list unknown_processors () const; + /* special processors */ - boost::shared_ptr monitor_send() const { return _monitor_send; } + 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); + void add_send_to_internal_return (InternalSend *); + void remove_send_from_internal_return (InternalSend *); + void listen_position_changed (); + boost::shared_ptr add_export_point(/* Add some argument for placement later */); /** 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. @@ -211,10 +238,10 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou ChanCount count; ///< Input requested of processor }; - int add_processor (boost::shared_ptr, Placement placement, ProcessorStreams* err = 0); + int add_processor (boost::shared_ptr, Placement placement, ProcessorStreams* err = 0, bool activation_allowed = true); + int add_processor_by_index (boost::shared_ptr, int, ProcessorStreams* err = 0, bool activation_allowed = true); 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); @@ -224,19 +251,23 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou void disable_plugins (); void ab_plugins (bool forward); void clear_processors (Placement); - void all_processors_flip(); - void all_processors_active (Placement, bool state); + void all_visible_processors_active (bool); - virtual nframes_t update_total_latency(); - void set_latency_delay (nframes_t); - void set_user_latency (nframes_t); - nframes_t initial_delay() const { return _initial_delay; } + framecnt_t set_private_port_latencies (bool playback) const; + void set_public_port_latencies (framecnt_t, bool playback) const; + + framecnt_t update_signal_latency(); + virtual void set_latency_compensation (framecnt_t); + + void set_user_latency (framecnt_t); + framecnt_t initial_delay() const { return _initial_delay; } + framecnt_t signal_latency() const { return _signal_latency; } PBD::Signal0 active_changed; PBD::Signal0 phase_invert_changed; PBD::Signal0 denormal_protection_changed; PBD::Signal1 listen_changed; - PBD::Signal1 solo_changed; + PBD::Signal2 solo_changed; PBD::Signal1 solo_safe_changed; PBD::Signal1 solo_isolated_changed; PBD::Signal1 comment_changed; @@ -247,9 +278,13 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou PBD::Signal1 processors_changed; PBD::Signal1 record_enable_changed; /** the metering point has changed */ - PBD::Signal1 meter_change; + PBD::Signal0 meter_change; PBD::Signal0 signal_latency_changed; PBD::Signal0 initial_delay_changed; + PBD::Signal0 order_key_changed; + + /** Emitted with the process lock held */ + PBD::Signal0 io_changed; /* gui's call this for their own purposes. */ @@ -258,7 +293,7 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou /* stateful */ XMLNode& get_state(); - int set_state (const XMLNode&, int version); + virtual int set_state (const XMLNode&, int version); virtual XMLNode& get_template(); XMLNode& get_processor_state (); @@ -268,30 +303,73 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou PBD::Signal1 SelectedChanged; - int listen_via (boost::shared_ptr, Placement p, bool active, bool aux); + int listen_via_monitor (); + int listen_via (boost::shared_ptr, Placement p); void drop_listen (boost::shared_ptr); + /** + * 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); - std::set > fed_by; + + /** + * return true if this route feeds the first argument directly, via + * either its main outs or a send. This is checked by the actual + * connections, rather than by what the graph is currently doing. + */ + bool direct_feeds_according_to_reality (boost::shared_ptr, bool* via_send_only = 0); + + /** + * return true if this route feeds the first argument directly, via + * either its main outs or a send, according to the graph that + * is currently being processed. + */ + bool direct_feeds_according_to_graph (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); /* 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; + class SoloControllable : public AutomationControl { + public: + SoloControllable (std::string name, boost::shared_ptr); + void set_value (double); + double get_value () const; - Route& route; + private: + boost::weak_ptr _route; }; struct MuteControllable : public AutomationControl { - MuteControllable (std::string name, Route&); - void set_value (float); - float get_value (void) const; + public: + MuteControllable (std::string name, boost::shared_ptr); + void set_value (double); + double get_value () const; - Route& route; + private: + boost::weak_ptr _route; }; boost::shared_ptr solo_control() const { @@ -311,10 +389,12 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou here. */ - boost::shared_ptr panner() const; + boost::shared_ptr panner() const; /* may return null */ + boost::shared_ptr panner_shell() const; boost::shared_ptr gain_control() const; + boost::shared_ptr pannable() const; - void automation_snapshot (nframes_t now, bool force=false); + void automation_snapshot (framepos_t now, bool force=false); void protect_automation (); void set_remote_control_id (uint32_t id, bool notify_class_listeners = true); @@ -335,45 +415,49 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou friend class Session; void catch_up_on_solo_mute_override (); - void mod_solo_by_others (int32_t); - void set_block_size (nframes_t nframes); + 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 (pframes_t nframes); protected: - nframes_t check_initial_delay (nframes_t, nframes_t&); + virtual framecnt_t check_initial_delay (framecnt_t nframes, framecnt_t&) { return nframes; } - void passthru (sframes_t start_frame, sframes_t end_frame, - nframes_t nframes, int declick); + void passthru (framepos_t start_frame, framepos_t end_frame, + pframes_t nframes, int declick); - virtual void write_out_of_band_data (BufferSet& /* bufs */, sframes_t /* start_frame */, sframes_t /* end_frame */, - nframes_t /* nframes */) {} + virtual void write_out_of_band_data (BufferSet& /* bufs */, framepos_t /* start_frame */, framepos_t /* end_frame */, + framecnt_t /* nframes */) {} virtual void process_output_buffers (BufferSet& bufs, - sframes_t start_frame, sframes_t end_frame, - nframes_t nframes, bool with_processors, int declick); + framepos_t start_frame, framepos_t end_frame, + pframes_t nframes, int declick, + bool gain_automation_ok); boost::shared_ptr _input; boost::shared_ptr _output; bool _active; - nframes_t _initial_delay; - nframes_t _roll_delay; + framecnt_t _signal_latency; + framecnt_t _initial_delay; + framecnt_t _roll_delay; ProcessorList _processors; mutable Glib::RWLock _processor_lock; boost::shared_ptr _main_outs; - boost::shared_ptr _monitor_send; + boost::shared_ptr _monitor_send; boost::shared_ptr _intreturn; boost::shared_ptr _monitor_control; + boost::shared_ptr _pannable; Flag _flags; int _pending_declick; MeterPoint _meter_point; - uint32_t _phase_invert; + boost::dynamic_bitset<> _phase_invert; bool _self_solo; - uint32_t _soloed_by_others; + uint32_t _soloed_by_others_upstream; + uint32_t _soloed_by_others_downstream; uint32_t _solo_isolated; bool _denormal_protection; @@ -385,38 +469,41 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou boost::shared_ptr _solo_control; boost::shared_ptr _mute_control; boost::shared_ptr _mute_master; - MuteMaster::MutePoint _mute_points; + + virtual void act_on_mute () {} std::string _comment; bool _have_internal_generator; bool _solo_safe; DataType _default_type; + FedBy _fed_by; - virtual ChanCount input_streams () const; + virtual ChanCount input_streams () const; protected: virtual XMLNode& state(bool); int configure_processors (ProcessorStreams*); - void passthru_silence (sframes_t start_frame, sframes_t end_frame, - nframes_t nframes, int declick); + void passthru_silence (framepos_t start_frame, framepos_t end_frame, + pframes_t nframes, int declick); - void silence (nframes_t nframes); + void silence (framecnt_t); + void silence_unlocked (framecnt_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 void maybe_declick (BufferSet&, framecnt_t, int); boost::shared_ptr _amp; boost::shared_ptr _meter; private: - int _set_state_2X (const XMLNode&, int); + int set_state_2X (const XMLNode&, int); void set_processor_state_2X (XMLNodeList const &, int); static uint32_t order_key_cnt; @@ -427,17 +514,69 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou void input_change_handler (IOChange, void *src); void output_change_handler (IOChange, void *src); + bool input_port_count_changing (ChanCount); + bool _in_configure_processors; int configure_processors_unlocked (ProcessorStreams*); + std::list > try_configure_processors (ChanCount, ProcessorStreams *); + std::list > try_configure_processors_unlocked (ChanCount, ProcessorStreams *); - bool add_processor_from_xml (const XMLNode&, ProcessorList::iterator iter); - bool add_processor_from_xml_2X (const XMLNode&, int, ProcessorList::iterator iter); + bool add_processor_from_xml_2X (const XMLNode&, int); void placement_range (Placement p, ProcessorList::iterator& start, ProcessorList::iterator& end); void set_self_solo (bool yn); - void set_delivery_solo (); + void set_mute_master_solo (); + + void set_processor_positions (); + framecnt_t update_port_latencies (PortSet& ports, PortSet& feeders, bool playback, framecnt_t) const; + + void setup_invisible_processors (); + void unpan (); + + boost::shared_ptr _capturing_processor; + + /** A handy class to keep processor state while we attempt a reconfiguration + * that may fail. + */ + class ProcessorState { + public: + ProcessorState (Route* r) + : _route (r) + , _processors (r->_processors) + , _processor_max_streams (r->processor_max_streams) + { } + + void restore () { + _route->_processors = _processors; + _route->processor_max_streams = _processor_max_streams; + } + + private: + /* this should perhaps be a shared_ptr, but ProcessorStates will + not hang around long enough for it to matter. + */ + Route* _route; + ProcessorList _processors; + ChanCount _processor_max_streams; + }; + + friend class ProcessorState; + + /* no copy construction */ + Route (Route const &); + + void maybe_note_meter_position (); + + /** true if we've made a note of a custom meter position in these variables */ + bool _custom_meter_position_noted; + /** the processor that came after the meter when it was last set to a custom position, + or 0. + */ + boost::weak_ptr _processor_after_last_custom_meter; + /** true if the last custom meter position was at the end of the processor list */ + bool _last_custom_meter_was_at_end; }; } // namespace ARDOUR