/* 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 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. $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 namespace ARDOUR { class Insert; class Send; class RouteGroup; enum mute_type { PRE_FADER = 0x1, POST_FADER = 0x2, CONTROL_OUTS = 0x4, MAIN_OUTS = 0x8 }; class Route : public IO { private: typedef list RedirectList; public: enum Flag { Hidden = 0x1, MasterOut = 0x2, ControlOut = 0x4, }; Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max, Flag flags = Flag(0)); Route (Session&, const XMLNode&); virtual ~Route(); 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 hidden() const { return _flags & Hidden; } bool master() const { return _flags & MasterOut; } bool control() const { return _flags & ControlOut; } /* these are the core of the API of a Route. see the protected sections as well */ virtual int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input); virtual int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input); virtual int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool can_record, bool rec_monitors_input); virtual void toggle_monitor_input (); virtual bool can_record() const { return false; } virtual void set_record_enable (bool yn, void *src) {} virtual bool record_enabled() const { return false; } virtual void transport_stopped (bool abort, bool did_locate, bool flush_redirects); virtual void set_pending_declick (int); /* end of vfunc-based API */ /* override IO::set_gain() to provide group control */ 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_solo (bool yn, void *src); bool soloed() const { return _soloed; } void set_solo_safe (bool yn, void *src); bool solo_safe() const { return _solo_safe; } void set_mute (bool yn, void *src); bool muted() const { return _muted; } void set_mute_config (mute_type, bool, void *src); bool get_mute_config (mute_type); void set_phase_invert (bool yn, void *src); bool phase_invert() const { return _phase_invert; } void set_edit_group (RouteGroup *, void *); RouteGroup *edit_group () { return _edit_group; } void set_mix_group (RouteGroup *, void *); RouteGroup *mix_group () { return _mix_group; } virtual void set_meter_point (MeterPoint, void *src); MeterPoint meter_point() const { return _meter_point; } /* Redirects */ void flush_redirects (); template void foreach_redirect (T *obj, void (T::*func)(Redirect *)) { LockMonitor lm (redirect_lock, __LINE__, __FILE__); for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { (obj->*func) (*i); } } Redirect *nth_redirect (uint32_t n) { LockMonitor lm (redirect_lock, __LINE__, __FILE__); RedirectList::iterator i; for (i = _redirects.begin(); i != _redirects.end() && n; ++i, --n); if (i == _redirects.end()) { return 0; } else { return *i; } } uint32_t max_redirect_outs () const { return redirect_max_outs; } int add_redirect (Redirect *, void *src, uint32_t* err_streams = 0); int add_redirects (const RedirectList&, void *src, uint32_t* err_streams = 0); int remove_redirect (Redirect *, 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); virtual jack_nframes_t update_total_latency(); jack_nframes_t signal_latency() const { return _own_latency; } virtual void set_latency_delay (jack_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; sigc::signal GoingAway; /* gui's call this for their own purposes. */ sigc::signal gui_changed; /* stateful */ XMLNode& get_state(); int set_state(const XMLNode& node); XMLNode& get_template(); sigc::signal SelectedChanged; /* undo */ UndoAction get_memento() const; void set_state (state_id_t); int set_control_outs (const vector& ports); IO* control_outs() { return _control_outs; } bool feeds (Route *); set fed_by; struct MIDIToggleControl : public MIDI::Controllable { enum ToggleType { MuteControl = 0, SoloControl }; MIDIToggleControl (Route&, ToggleType, MIDI::Port *); void set_value (float); void send_feedback (bool); MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force = false); Route& route; ToggleType type; bool setting; bool last_written; }; MIDI::Controllable& midi_solo_control() { return _midi_solo_control; } MIDI::Controllable& midi_mute_control() { return _midi_mute_control; } virtual void reset_midi_control (MIDI::Port*, bool); virtual void send_all_midi_feedback (); virtual MIDI::byte* write_midi_feedback (MIDI::byte*, int32_t& bufsize); void automation_snapshot (jack_nframes_t now); void protect_automation (); protected: friend class Session; void set_solo_mute (bool yn); void set_block_size (jack_nframes_t nframes); bool has_external_redirects() const; void curve_reallocate (); protected: unsigned char _flags; /* tight cache-line access here is more important than sheer speed of access. */ bool _muted : 1; bool _soloed : 1; bool _solo_muted : 1; bool _solo_safe : 1; bool _phase_invert : 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; jack_nframes_t check_initial_delay (jack_nframes_t, jack_nframes_t&, jack_nframes_t&); jack_nframes_t _initial_delay; jack_nframes_t _roll_delay; jack_nframes_t _own_latency; RedirectList _redirects; PBD::NonBlockingLock redirect_lock; IO *_control_outs; PBD::NonBlockingLock control_outs_lock; RouteGroup *_edit_group; RouteGroup *_mix_group; std::string _comment; bool _have_internal_generator; MIDIToggleControl _midi_solo_control; MIDIToggleControl _midi_mute_control; void passthru (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter_inputs); void process_output_buffers (vector& bufs, uint32_t nbufs, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick, bool meter); protected: /* for derived classes */ virtual XMLNode& state(bool); void silence (jack_nframes_t nframes, jack_nframes_t offset); sigc::connection input_signal_connection; state_id_t _current_state_id; uint32_t redirect_max_outs; uint32_t pans_required() const; uint32_t n_process_buffers (); private: void init (); static uint32_t order_key_cnt; 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 */ /* plugin count handling */ struct InsertCount { ARDOUR::Insert& insert; int32_t cnt; int32_t in; int32_t out; InsertCount (ARDOUR::Insert& 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 set_deferred_state (); void add_redirect_from_xml (const XMLNode&); void redirect_active_proxy (Redirect*, void*); }; }; /* namespace ARDOUR*/ #endif /* __ardour_route_h__ */