RAII to postpone processor changes/graph recalculation
[ardour.git] / libs / ardour / ardour / session.h
index 786751dea52a64f2fc80659dde8477e5e58e372c..b2409e3da669f0e0969a40c4f96ba707e82c4bad 100644 (file)
 #include "ardour/luascripting.h"
 #include "ardour/location.h"
 #include "ardour/monitor_processor.h"
+#include "ardour/presentation_info.h"
 #include "ardour/rc_configuration.h"
 #include "ardour/session_configuration.h"
 #include "ardour/session_event.h"
 #include "ardour/interpolation.h"
 #include "ardour/plugin.h"
+#include "ardour/presentation_info.h"
 #include "ardour/route.h"
 #include "ardour/route_graph.h"
 
@@ -86,7 +88,6 @@ class Parser;
 
 namespace PBD {
 class Controllable;
-class ControllableDescriptor;
 }
 
 namespace luabridge {
@@ -112,6 +113,7 @@ class BufferSet;
 class Bundle;
 class Butler;
 class Click;
+class ControllableDescriptor;
 class Diskstream;
 class ExportHandler;
 class ExportStatus;
@@ -132,6 +134,7 @@ class PluginInfo;
 class Port;
 class PortInsert;
 class ProcessThread;
+class Progress;
 class Processor;
 class Region;
 class Return;
@@ -167,6 +170,16 @@ private:
 /** Ardour Session */
 class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionList, public SessionEventManager
 {
+  private:
+       enum SubState {
+               PendingDeclickIn      = 0x1,  ///< pending de-click fade-in for start
+               PendingDeclickOut     = 0x2,  ///< pending de-click fade-out for stop
+               StopPendingCapture    = 0x4,
+               PendingLoopDeclickIn  = 0x8,  ///< pending de-click fade-in at the start of a loop
+               PendingLoopDeclickOut = 0x10, ///< pending de-click fade-out at the end of a loop
+               PendingLocate         = 0x20,
+       };
+
   public:
        enum RecordState {
                Disabled = 0,
@@ -211,11 +224,10 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        bool deletion_in_progress() const { return _state_of_the_state & Deletion; }
        bool routes_deletion_in_progress() const { return _route_deletion_in_progress; }
        bool peaks_cleanup_in_progres() const { return _state_of_the_state & PeakCleanup; }
+       bool loading () const { return _state_of_the_state & Loading; }
 
        PBD::Signal0<void> DirtyChanged;
 
-       PBD::Signal1<void, bool> RouteAddedOrRemoved;
-
        const SessionDirectory& session_directory () const { return *(_session_dir.get()); }
 
        static PBD::Signal1<void,std::string> Dialog;
@@ -244,8 +256,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
         * @param pd Playlist disposition
         * @return list of newly created routes
         */
-       RouteList new_route_from_template (uint32_t how_many, const std::string& template_path, const std::string& name, PlaylistDisposition pd = NewPlaylist);
-       RouteList new_route_from_template (uint32_t how_many, XMLNode&, const std::string& name, PlaylistDisposition pd = NewPlaylist);
+       RouteList new_route_from_template (uint32_t how_many, PresentationInfo::order_t insert_at, const std::string& template_path, const std::string& name, PlaylistDisposition pd = NewPlaylist);
+       RouteList new_route_from_template (uint32_t how_many, PresentationInfo::order_t insert_at, XMLNode&, const std::string& name, PlaylistDisposition pd = NewPlaylist);
        std::vector<std::string> get_paths_for_new_sources (bool allow_replacing, const std::string& import_file_path, uint32_t channels);
 
        int bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,std::string)> callback);
@@ -276,6 +288,14 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
                return routes.reader ();
        }
 
+       /* because the set of Stripables consists of objects managed
+        * independently, in multiple containers within the Session (or objects
+        * owned by the session), we fill out a list in-place rather than
+        * return a pointer to a copy of the (RCU) managed list, as happens
+        * with get_routes()
+        */
+
+       void get_stripables (StripableList&) const;
        boost::shared_ptr<RouteList> get_tracks() const;
        boost::shared_ptr<RouteList> get_routes_with_internal_returns() const;
        boost::shared_ptr<RouteList> get_routes_with_regions_at (framepos_t const) const;
@@ -292,22 +312,20 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
                bool operator() (boost::shared_ptr<Route>, boost::shared_ptr<Route> b);
        };
 
-       void set_order_hint (int32_t order_hint) {_order_hint = order_hint;};
-       void notify_remote_id_change ();
-       void sync_order_keys ();
+       void notify_presentation_info_change ();
 
        template<class T> void foreach_route (T *obj, void (T::*func)(Route&), bool sort = true);
        template<class T> void foreach_route (T *obj, void (T::*func)(boost::shared_ptr<Route>), bool sort = true);
        template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg, bool sort = true);
 
        static char session_name_is_legal (const std::string&);
-       bool io_name_is_legal (const std::string&);
-       boost::shared_ptr<Route> route_by_name (std::string);
-       boost::shared_ptr<Route> route_by_id (PBD::ID);
-       boost::shared_ptr<Route> route_by_remote_id (uint32_t id);
-       boost::shared_ptr<Stripable> stripable_by_remote_id (uint32_t id);
-       boost::shared_ptr<Route> route_by_selected_count (uint32_t cnt);
-       boost::shared_ptr<Track> track_by_diskstream_id (PBD::ID);
+       bool io_name_is_legal (const std::string&) const;
+       boost::shared_ptr<Route> route_by_name (std::string) const;
+       boost::shared_ptr<Route> route_by_id (PBD::ID) const;
+       boost::shared_ptr<Stripable> get_remote_nth_stripable (PresentationInfo::order_t n, PresentationInfo::Flag) const;
+       boost::shared_ptr<Route> get_remote_nth_route (PresentationInfo::order_t n) const;
+       boost::shared_ptr<Route> route_by_selected_count (uint32_t cnt) const;
+       boost::shared_ptr<Track> track_by_diskstream_id (PBD::ID) const;
        void routes_using_input_from (const std::string& str, RouteList& rl);
 
        bool route_name_unique (std::string) const;
@@ -407,7 +425,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        framepos_t last_transport_start () const { return _last_roll_location; }
        void goto_end ();
-       void goto_start ();
+       void goto_start (bool and_roll = false);
        void use_rf_shuttle_speed ();
        void allow_auto_play (bool yn);
        void request_transport_speed (double speed, bool as_default = true);
@@ -419,6 +437,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        void request_input_change_handling ();
 
        bool locate_pending() const { return static_cast<bool>(post_transport_work()&PostTransportLocate); }
+       bool declick_out_pending() const { return static_cast<bool>(transport_sub_state&(PendingDeclickOut)); }
        bool transport_locked () const;
 
        int wipe ();
@@ -452,6 +471,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        void set_auto_punch_location (Location *);
        void set_auto_loop_location (Location *);
        void set_session_extents (framepos_t start, framepos_t end);
+       void set_end_is_free (bool);
        int location_name(std::string& result, std::string base = std::string(""));
 
        pframes_t get_block_size()        const { return current_block_size; }
@@ -497,6 +517,15 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
         * @return zero on success
         */
        int save_state (std::string snapshot_name, bool pending = false, bool switch_to_snapshot = false, bool template_only = false);
+
+       enum ArchiveEncode {
+               NO_ENCODE,
+               FLAC_16BIT,
+               FLAC_24BIT
+       };
+
+       int archive_session (const std::string&, const std::string&, ArchiveEncode compress_audio = FLAC_16BIT, bool only_used_sources = false, Progress* p = 0);
+
        int restore_state (std::string snapshot_name);
        int save_template (std::string template_name, bool replace_existing = false);
        int save_history (std::string snapshot_name = "");
@@ -552,20 +581,40 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        StateOfTheState state_of_the_state() const { return _state_of_the_state; }
 
        class StateProtector {
-                                               public:
-               StateProtector (Session* s) : _session (s) {
-                       g_atomic_int_inc (&s->_suspend_save);
-               }
-               ~StateProtector () {
-                       if (g_atomic_int_dec_and_test (&_session->_suspend_save)) {
-                               while (_session->_save_queued) {
-                                       _session->_save_queued = false;
-                                       _session->save_state ("");
+               public:
+                       StateProtector (Session* s) : _session (s) {
+                               g_atomic_int_inc (&s->_suspend_save);
+                       }
+                       ~StateProtector () {
+                               if (g_atomic_int_dec_and_test (&_session->_suspend_save)) {
+                                       while (_session->_save_queued) {
+                                               _session->_save_queued = false;
+                                               _session->save_state ("");
+                                       }
                                }
                        }
-               }
-                                               private:
-               Session * _session;
+               private:
+                       Session * _session;
+       };
+
+       class ProcessorChangeBlocker {
+               public:
+                       ProcessorChangeBlocker (Session* s, bool rc = true)
+                               : _session (s)
+                               , _reconfigure_on_delete (rc)
+                       {
+                               g_atomic_int_inc (&s->_ignore_route_processor_changes);
+                       }
+                       ~ProcessorChangeBlocker () {
+                               if (g_atomic_int_dec_and_test (&_session->_ignore_route_processor_changes)) {
+                                       if (_reconfigure_on_delete) {
+                                               _session->route_processors_changed (RouteProcessorChange ());
+                                       }
+                               }
+                       }
+               private:
+                       Session* _session;
+                       bool _reconfigure_on_delete;
        };
 
        void add_route_group (RouteGroup *);
@@ -594,29 +643,24 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        std::list<boost::shared_ptr<AudioTrack> > new_audio_track (
                int input_channels,
                int output_channels,
-               TrackMode mode = Normal,
-               RouteGroup* route_group = 0,
-               uint32_t how_many = 1,
-               std::string name_template = ""
-               );
-
-       RouteList new_audio_route (
-               int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many, std::string name_template = ""
+               RouteGroup* route_group,
+               uint32_t how_many,
+               std::string name_template,
+               PresentationInfo::order_t order,
+               TrackMode mode = Normal
                );
 
        std::list<boost::shared_ptr<MidiTrack> > new_midi_track (
                const ChanCount& input, const ChanCount& output,
-               boost::shared_ptr<PluginInfo> instrument = boost::shared_ptr<PluginInfo>(),
-               TrackMode mode = Normal,
-               RouteGroup* route_group = 0, uint32_t how_many = 1, std::string name_template = "",
-               Plugin::PresetRecord* pset = 0
+               boost::shared_ptr<PluginInfo> instrument,
+               Plugin::PresetRecord* pset,
+               RouteGroup* route_group, uint32_t how_many, std::string name_template,
+               PresentationInfo::order_t,
+               TrackMode mode = Normal
                );
 
-       RouteList new_midi_route (RouteGroup* route_group,
-                       uint32_t how_many,
-                       std::string name_template = "",
-                       boost::shared_ptr<PluginInfo> instrument = boost::shared_ptr<PluginInfo>(),
-                       Plugin::PresetRecord* pset = 0);
+       RouteList new_audio_route (int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many, std::string name_template, PresentationInfo::Flag, PresentationInfo::order_t);
+       RouteList new_midi_route (RouteGroup* route_group, uint32_t how_many, std::string name_template, boost::shared_ptr<PluginInfo> instrument, Plugin::PresetRecord*, PresentationInfo::Flag, PresentationInfo::order_t);
 
        void remove_routes (boost::shared_ptr<RouteList>);
        void remove_route (boost::shared_ptr<Route>);
@@ -673,8 +717,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        bool   synced_to_ltc () const { return config.get_external_sync() && Config->get_sync_source() == LTC && g_atomic_int_get (const_cast<gint*>(&_ltc_active)); }
 
        double transport_speed() const { return _transport_speed; }
-       bool   transport_stopped() const { return _transport_speed == 0.0f; }
-       bool   transport_rolling() const { return _transport_speed != 0.0f; }
+       bool   transport_stopped() const { return _transport_speed == 0.0; }
+       bool   transport_rolling() const { return _transport_speed != 0.0; }
 
        bool silent () { return _silent; }
 
@@ -701,7 +745,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        boost::shared_ptr<ExportHandler> get_export_handler ();
        boost::shared_ptr<ExportStatus> get_export_status ();
 
-       int start_audio_export (framepos_t position);
+       int start_audio_export (framepos_t position, bool realtime = false, bool region_export = false, bool comensate_master_latency = false);
 
        PBD::Signal1<int, framecnt_t> ProcessExport;
        static PBD::Signal2<void,std::string, std::string> Exported;
@@ -788,6 +832,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        bool soloing() const { return _non_soloed_outs_muted; }
        bool listening() const { return _listen_cnt > 0; }
        bool solo_isolated() const { return _solo_isolated_cnt > 0; }
+       void cancel_all_solo ();
 
        static const SessionEvent::RTeventCallback rt_cleanup;
 
@@ -870,13 +915,11 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        /** Undo some transactions.
         * @param n Number of transactions to undo.
         */
-       void undo (uint32_t n) {
-               _history.undo (n);
-       }
-
-       void redo (uint32_t n) {
-               _history.redo (n);
-       }
+       void undo (uint32_t n);
+       /** Redo some transactions.
+        * @param n Number of transactions to undo.
+        */
+       void redo (uint32_t n);
 
        UndoHistory& history() { return _history; }
 
@@ -994,7 +1037,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        boost::shared_ptr<Processor> processor_by_id (PBD::ID) const;
 
        boost::shared_ptr<PBD::Controllable> controllable_by_id (const PBD::ID&);
-       boost::shared_ptr<PBD::Controllable> controllable_by_descriptor (const PBD::ControllableDescriptor&);
+       boost::shared_ptr<PBD::Controllable> controllable_by_descriptor (const ARDOUR::ControllableDescriptor&);
 
        void add_controllable (boost::shared_ptr<PBD::Controllable>);
        void remove_controllable (PBD::Controllable*);
@@ -1003,6 +1046,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        SessionConfiguration config;
 
+       SessionConfiguration* cfg () { return &config; }
+
        bool exporting () const {
                return _exporting;
        }
@@ -1124,6 +1169,9 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        VCAManager& vca_manager() { return *_vca_manager; }
 
+       void auto_connect_thread_wakeup ();
+
+
   protected:
        friend class AudioEngine;
        void set_block_size (pframes_t nframes);
@@ -1145,15 +1193,6 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        static void init_name_id_counter (guint n);
        static unsigned int name_id_counter ();
 
-       enum SubState {
-               PendingDeclickIn      = 0x1,  ///< pending de-click fade-in for start
-               PendingDeclickOut     = 0x2,  ///< pending de-click fade-out for stop
-               StopPendingCapture    = 0x4,
-               PendingLoopDeclickIn  = 0x8,  ///< pending de-click fade-in at the start of a loop
-               PendingLoopDeclickOut = 0x10, ///< pending de-click fade-out at the end of a loop
-               PendingLocate         = 0x20,
-       };
-
        /* stuff used in process() should be close together to
           maximise cache hits
        */
@@ -1173,6 +1212,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        mutable gint            _record_status;
        framepos_t              _transport_frame;
        Location*               _session_range_location; ///< session range, or 0 if there is nothing in the session yet
+       bool                    _session_range_end_is_free;
        Slave*                  _slave;
        bool                    _silent;
 
@@ -1225,8 +1265,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        void process_without_events (pframes_t);
        void process_with_events    (pframes_t);
        void process_audition       (pframes_t);
-       int  process_export         (pframes_t);
-       int  process_export_fw      (pframes_t);
+       void process_export         (pframes_t);
+       void process_export_fw      (pframes_t);
 
        void block_processing() { g_atomic_int_set (&processing_prohibited, 1); }
        void unblock_processing() { g_atomic_int_set (&processing_prohibited, 0); }
@@ -1263,7 +1303,10 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        bool _exporting;
        bool _export_rolling;
+       bool _realtime_export;
+       bool _region_export;
        framepos_t _export_preroll;
+       framepos_t _export_latency;
 
        boost::shared_ptr<ExportHandler> export_handler;
        boost::shared_ptr<ExportStatus>  export_status;
@@ -1507,8 +1550,14 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        typedef std::queue<AutoConnectRequest> AutoConnectQueue;
        Glib::Threads::Mutex  _auto_connect_queue_lock;
        AutoConnectQueue _auto_connect_queue;
+       guint _latency_recompute_pending;
+
+       void get_physical_ports (std::vector<std::string>& inputs, std::vector<std::string>& outputs, DataType type,
+                                MidiPortFlags include = MidiPortFlags (0),
+                                MidiPortFlags exclude = MidiPortFlags (0));
 
        void auto_connect (const AutoConnectRequest&);
+       void queue_latency_recompute ();
 
        /* SessionEventManager interface */
 
@@ -1657,8 +1706,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        SerializedRCUManager<RouteList>  routes;
 
-       void add_routes (RouteList&, bool input_auto_connect, bool output_auto_connect, bool save);
-       void add_routes_inner (RouteList&, bool input_auto_connect, bool output_auto_connect);
+       void add_routes (RouteList&, bool input_auto_connect, bool output_auto_connect, bool save, PresentationInfo::order_t);
+       void add_routes_inner (RouteList&, bool input_auto_connect, bool output_auto_connect, PresentationInfo::order_t);
        bool _adding_routes_in_progress;
        bool _reconnecting_routes_in_progress;
        bool _route_deletion_in_progress;
@@ -1975,9 +2024,10 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        */
        GraphEdges _current_route_graph;
 
-       uint32_t next_control_id () const;
-       int32_t _order_hint;
-       bool ignore_route_processor_changes;
+       void ensure_route_presentation_info_gap (PresentationInfo::order_t, uint32_t gap_size);
+
+       friend class    ProcessorChangeBlocker;
+       gint            _ignore_route_processor_changes; /* atomic */
 
        MidiClockTicker* midi_clock;
 
@@ -2004,6 +2054,15 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        std::string _template_state_dir;
 
        VCAManager* _vca_manager;
+
+       boost::shared_ptr<Route> get_midi_nth_route_by_id (PresentationInfo::order_t n) const;
+
+       std::string created_with;
+
+       void midi_track_presentation_info_changed (PBD::PropertyChange const &, boost::weak_ptr<MidiTrack>);
+       void rewire_selected_midi (boost::shared_ptr<MidiTrack>);
+       void rewire_midi_selection_ports ();
+       boost::weak_ptr<MidiTrack> current_midi_target;
 };