#include <set>
#include <string>
#include <vector>
+#include <queue>
#include <stdint.h>
#include <boost/dynamic_bitset.hpp>
#include "pbd/error.h"
#include "pbd/event_loop.h"
#include "pbd/rcu.h"
+#include "pbd/reallocpool.h"
#include "pbd/statefuldestructible.h"
#include "pbd/signals.h"
#include "pbd/undo.h"
-#include "evoral/types.hpp"
+#include "lua/luastate.h"
+
+#include "evoral/Range.hpp"
#include "midi++/types.h"
#include "midi++/mmc.h"
#include "ardour/chan_count.h"
#include "ardour/delivery.h"
#include "ardour/interthread_info.h"
+#include "ardour/luascripting.h"
#include "ardour/location.h"
#include "ardour/monitor_processor.h"
#include "ardour/rc_configuration.h"
class ControllableDescriptor;
}
+namespace luabridge {
+ class LuaRef;
+}
+
namespace Evoral {
class Curve;
}
std::string _message;
};
+/** Ardour Session */
class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionList, public SessionEventManager
{
public:
static int get_info_from_path (const std::string& xmlpath, float& sample_rate, SampleFormat& data_format);
static std::string get_snapshot_from_instant (const std::string& session_dir);
+ /** a monotonic counter used for naming user-visible things uniquely
+ * (curently the sidechain port).
+ * Use sparingly to keep the numbers low, prefer PBD::ID for all
+ * internal, not user-visible IDs */
+ static unsigned int next_name_id ();
+
std::string path() const { return _path; }
std::string name() const { return _name; }
std::string snap_name() const { return _current_snapshot_name; }
std::string new_audio_source_path_for_embedded (const std::string& existing_path);
std::string new_audio_source_path (const std::string&, uint32_t nchans, uint32_t chan, bool destructive, bool take_required);
std::string new_midi_source_path (const std::string&);
+ /** create a new track or bus from a template (XML path)
+ * @param how_many how many tracks or busses to create
+ * @param template_path path to xml template file
+ * @param name name (prefix) of the route to create
+ * @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);
std::vector<std::string> get_paths_for_new_sources (bool allow_replacing, const std::string& import_file_path, uint32_t channels);
void process (pframes_t nframes);
BufferSet& get_silent_buffers (ChanCount count = ChanCount::ZERO);
- BufferSet& get_scratch_buffers (ChanCount count = ChanCount::ZERO, bool silence = true );
+ BufferSet& get_noinplace_buffers (ChanCount count = ChanCount::ZERO);
+ BufferSet& get_scratch_buffers (ChanCount count = ChanCount::ZERO, bool silence = true);
BufferSet& get_route_buffers (ChanCount count = ChanCount::ZERO, bool silence = true);
BufferSet& get_mix_buffers (ChanCount count = ChanCount::ZERO);
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<Route> route_by_selected_count (uint32_t cnt);
boost::shared_ptr<Track> track_by_diskstream_id (PBD::ID);
void routes_using_input_from (const std::string& str, RouteList& rl);
void maybe_enable_record ();
void disable_record (bool rt_context, bool force = false);
void step_back_from_record ();
+
+ void set_all_tracks_record_enabled(bool);
void maybe_write_autosave ();
};
int save_as (SaveAs&);
+ /** save session
+ * @param snapshot_name name of the session (use an empty string for the current name)
+ * @param pending save a 'recovery', not full state (default: false)
+ * @param switch_to_snapshot switch to given snapshot after saving (default: false)
+ * @param template_only save a session template (default: false)
+ * @return zero on success
+ */
int save_state (std::string snapshot_name, bool pending = false, bool switch_to_snapshot = false, bool template_only = false);
int restore_state (std::string snapshot_name);
int save_template (std::string template_name, bool replace_existing = false);
RouteGroup* route_group = 0, uint32_t how_many = 1, std::string name_template = ""
);
+ RouteList new_midi_route (RouteGroup* route_group, uint32_t how_many, std::string name_template = "", boost::shared_ptr<PluginInfo> instrument = boost::shared_ptr<PluginInfo>());
+
void remove_routes (boost::shared_ptr<RouteList>);
void remove_route (boost::shared_ptr<Route>);
*/
static PBD::Signal2<int, framecnt_t, framecnt_t> AskAboutSampleRateMismatch;
+ /** non interactive message */
+ static PBD::Signal2<void, framecnt_t, framecnt_t> NotifyAboutSampleRateMismatch;
+
/** handlers should return !0 for use pending state, 0 for ignore it.
*/
static PBD::Signal0<int> AskAboutPendingState;
PBD::Signal1<void,bool> AuditionActive;
+ /* session script */
+ void register_lua_function (const std::string&, const std::string&, const LuaScriptParamList&);
+ void unregister_lua_function (const std::string& name);
+ std::vector<std::string> registered_lua_functions ();
+ uint32_t registered_lua_function_count () const { return _n_lua_scripts; }
+ void scripts_changed (); // called from lua, updates _n_lua_scripts
+
/* flattening stuff */
boost::shared_ptr<Region> write_one_track (Track&, framepos_t start, framepos_t end,
static const SessionEvent::RTeventCallback rt_cleanup;
- void set_solo (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
+ void set_solo (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
void clear_all_solo_state (boost::shared_ptr<RouteList>);
void set_just_one_solo (boost::shared_ptr<Route>, bool, SessionEvent::RTeventCallback after = rt_cleanup);
- void set_mute (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
- void set_listen (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
- void set_record_enabled (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
- void set_record_safe (boost::shared_ptr<RouteList>, bool yn, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
- void set_solo_isolated (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
- void set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
- void set_exclusive_input_active (boost::shared_ptr<RouteList> rt, bool onoff, bool flip_others=false);
+ void set_mute (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+ void set_listen (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+ void set_record_enabled (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+ void set_record_safe (boost::shared_ptr<RouteList>, bool yn, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+ void set_solo_isolated (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+ void set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+ void set_exclusive_input_active (boost::shared_ptr<RouteList> rt, bool onoff, bool flip_others = false);
PBD::Signal1<void,bool> SoloActive;
PBD::Signal0<void> SoloChanged;
std::string next_undo() const { return _history.next_undo(); }
std::string next_redo() const { return _history.next_redo(); }
+ /** begin collecting undo information
+ *
+ * This call must always be followed by either
+ * begin_reversible_command() or commit_reversible_command()
+ *
+ * @param cmd_name human readable name for the undo operation
+ */
void begin_reversible_command (const std::string& cmd_name);
void begin_reversible_command (GQuark);
+ /** abort an open undo command
+ * This must only be called after begin_reversible_command ()
+ */
void abort_reversible_command ();
+ /** finalize an undo command and commit pending transactions
+ *
+ * This must only be called after begin_reversible_command ()
+ * @param cmd (additional) command to add
+ */
void commit_reversible_command (Command* cmd = 0);
void add_command (Command *const cmd);
+ /** create an StatefulDiffCommand from the given object and add it to the stack.
+ *
+ * This function must only be called after begin_reversible_command.
+ * Failing to do so may lead to a crash.
+ *
+ * @param sfd the object to diff
+ * @returns the allocated StatefulDiffCommand (already added via add_command)
+ */
+ PBD::StatefulDiffCommand* add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd);
+
/** @return The list of operations that are currently in progress */
std::list<GQuark> const & current_operations () {
return _current_trans_quarks;
/* Controllables */
+ 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&);
friend class AudioEngine;
void set_block_size (pframes_t nframes);
void set_frame_rate (framecnt_t nframes);
+#ifdef USE_TRACKS_CODE_FEATURES
void reconnect_existing_routes (bool withLock, bool reconnect_master = true, bool reconnect_inputs = true, bool reconnect_outputs = true);
+#endif
protected:
friend class Route;
int create (const std::string& mix_template, BusProfile*);
void destroy ();
+ static guint _name_id_counter;
+ 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
process_function_type last_process_function;
bool _bounce_processing_active;
bool waiting_for_sync_offset;
- framecnt_t _base_frame_rate;
- framecnt_t _current_frame_rate; //this includes video pullup offset
- framecnt_t _nominal_frame_rate; //ignores audioengine setting, "native" SR
+ framecnt_t _base_frame_rate; // sample-rate of the session at creation time, "native" SR
+ framecnt_t _nominal_frame_rate; // overridden by audioengine setting
+ framecnt_t _current_frame_rate; // this includes video pullup offset
int transport_sub_state;
mutable gint _record_status;
framepos_t _transport_frame;
framepos_t post_export_position;
bool _exporting;
- bool _export_started;
bool _export_rolling;
+ framepos_t _export_preroll;
boost::shared_ptr<ExportHandler> export_handler;
boost::shared_ptr<ExportStatus> export_status;
bool pending_abort;
bool pending_auto_loop;
+ PBD::ReallocPool _mempool;
+ LuaState lua;
+ Glib::Threads::Mutex lua_lock;
+ luabridge::LuaRef * _lua_run;
+ luabridge::LuaRef * _lua_add;
+ luabridge::LuaRef * _lua_del;
+ luabridge::LuaRef * _lua_list;
+ luabridge::LuaRef * _lua_load;
+ luabridge::LuaRef * _lua_save;
+ luabridge::LuaRef * _lua_cleanup;
+ uint32_t _n_lua_scripts;
+
+ void setup_lua ();
+ void try_run_lua (pframes_t);
+
Butler* _butler;
static const PostTransportWork ProcessCannotProceedMask =
pthread_cond_t _rt_emit_cond;
bool _rt_emit_pending;
+ /* Auto Connect Thread */
+ static void *auto_connect_thread (void *);
+ void auto_connect_thread_run ();
+ void auto_connect_thread_start ();
+ void auto_connect_thread_terminate ();
+
+ pthread_t _auto_connect_thread;
+ bool _ac_thread_active;
+ pthread_mutex_t _auto_connect_mutex;
+ pthread_cond_t _auto_connect_cond;
+
+ struct AutoConnectRequest {
+ public:
+ AutoConnectRequest (boost::shared_ptr <Route> r, bool ci,
+ const ChanCount& is,
+ const ChanCount& os,
+ const ChanCount& io,
+ const ChanCount& oo)
+ : route (boost::weak_ptr<Route> (r))
+ , connect_inputs (ci)
+ , input_start (is)
+ , output_start (os)
+ , input_offset (io)
+ , output_offset (oo)
+ {}
+
+ boost::weak_ptr <Route> route;
+ bool connect_inputs;
+ ChanCount input_start;
+ ChanCount output_start;
+ ChanCount input_offset;
+ ChanCount output_offset;
+ };
+
+ typedef std::queue<AutoConnectRequest> AutoConnectQueue;
+ Glib::Threads::Mutex _auto_connect_queue_lock;
+ AutoConnectQueue _auto_connect_queue;
+
+ void auto_connect (const AutoConnectRequest&);
/* SessionEventManager interface */
bool find_route_name (std::string const &, uint32_t& id, std::string& name, bool);
void count_existing_track_channels (ChanCount& in, ChanCount& out);
- void auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing_inputs, ChanCount& existing_outputs,
- bool with_lock, bool connect_inputs = true,
- ChanCount input_start = ChanCount (), ChanCount output_start = ChanCount ());
+ void auto_connect_route (boost::shared_ptr<Route>, bool, const ChanCount&, const ChanCount&, const ChanCount& io = ChanCount(), const ChanCount& oo = ChanCount());
void midi_output_change_handler (IOChange change, void* /*src*/, boost::weak_ptr<Route> midi_track);
/* track numbering */
/* mixer stuff */
- void route_listen_changed (bool group_override, boost::weak_ptr<Route>);
- void route_mute_changed (void *src);
- void route_solo_changed (bool self_solo_change, bool group_override, boost::weak_ptr<Route>);
- void route_solo_isolated_changed (void *src, boost::weak_ptr<Route>);
+ void route_listen_changed (PBD::Controllable::GroupControlDisposition, boost::weak_ptr<Route>);
+ void route_mute_changed ();
+ void route_solo_changed (bool self_solo_change, PBD::Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route>);
+ void route_solo_isolated_changed (boost::weak_ptr<Route>);
void update_route_solo_state (boost::shared_ptr<RouteList> r = boost::shared_ptr<RouteList>());
void listen_position_changed ();
/* realtime "apply to set of routes" operations */
template<typename T> SessionEvent*
- get_rt_event (boost::shared_ptr<RouteList> rl, T targ, SessionEvent::RTeventCallback after, bool group_override,
- void (Session::*method) (boost::shared_ptr<RouteList>, T, bool)) {
+ get_rt_event (boost::shared_ptr<RouteList> rl, T targ, SessionEvent::RTeventCallback after, PBD::Controllable::GroupControlDisposition group_override,
+ void (Session::*method) (boost::shared_ptr<RouteList>, T, PBD::Controllable::GroupControlDisposition)) {
SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
ev->rt_slot = boost::bind (method, this, rl, targ, group_override);
ev->rt_return = after;
return ev;
}
- void rt_set_solo (boost::shared_ptr<RouteList>, bool yn, bool group_override);
- void rt_clear_all_solo_state (boost::shared_ptr<RouteList>, bool yn, bool group_override);
- void rt_set_just_one_solo (boost::shared_ptr<RouteList>, bool yn, bool /* ignored*/ );
- void rt_set_mute (boost::shared_ptr<RouteList>, bool yn, bool group_override);
- void rt_set_listen (boost::shared_ptr<RouteList>, bool yn, bool group_override);
- void rt_set_solo_isolated (boost::shared_ptr<RouteList>, bool yn, bool group_override);
- void rt_set_record_enabled (boost::shared_ptr<RouteList>, bool yn, bool group_override);
- void rt_set_record_safe (boost::shared_ptr<RouteList>, bool yn, bool group_override);
- void rt_set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, bool group_override);
+ void rt_set_solo (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+ void rt_clear_all_solo_state (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+ void rt_set_just_one_solo (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition /* ignored*/ );
+ void rt_set_mute (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+ void rt_set_listen (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+ void rt_set_solo_isolated (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+ void rt_set_record_enabled (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+ void rt_set_record_safe (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+ void rt_set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, PBD::Controllable::GroupControlDisposition group_override);
/** temporary list of Diskstreams used only during load of 2.X sessions */
std::list<boost::shared_ptr<Diskstream> > _diskstreams_2X;