#define __ardour_session_h__
#include <string>
-#if __GNUC__ >= 3
-#include <ext/slist>
-using __gnu_cxx::slist;
-#else
-#include <slist.h>
-#endif
+#include <list>
#include <map>
#include <vector>
#include <set>
#include <sndfile.h>
+#include <glibmm/thread.h>
+
#include <pbd/error.h>
-#include <pbd/atomic.h>
-#include <pbd/lockmonitor.h>
#include <pbd/undo.h>
#include <pbd/pool.h>
#include <ardour/gain.h>
#include <ardour/io.h>
+#include <ardour/smpte.h>
+
class XMLTree;
class XMLNode;
class AEffect;
class Port;
class AudioEngine;
class Slave;
-class DiskStream;
+class AudioDiskstream;
class Route;
class AuxInput;
class Source;
-class FileSource;
+class AudioSource;
+class AudioFileSource;
class Auditioner;
class Insert;
class Send;
class Region;
class Playlist;
class VSTPlugin;
+class ControlProtocolManager;
struct AudioExportSpecification;
struct RouteGroup;
bool dirty() const { return _state_of_the_state & Dirty; }
sigc::signal<void> DirtyChanged;
- string sound_dir () const;
- string peak_dir () const;
- string dead_sound_dir () const;
- string automation_dir () const;
+ std::string sound_dir () const;
+ std::string tape_dir () const;
+ std::string peak_dir () const;
+ std::string dead_sound_dir () const;
+ std::string automation_dir () const;
+ static string suffixed_search_path (std::string suffix, bool data);
+ static string control_protocol_path ();
static string template_path ();
static string template_dir ();
static void get_template_list (list<string>&);
+ static string change_audio_path_by_name (string oldpath, string oldname, string newname, bool destructive);
static string peak_path_from_audio_path (string);
- static string old_peak_path_from_audio_path (string);
+ string audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive);
void process (jack_nframes_t nframes);
vector<Sample*>& get_passthru_buffers() { return _passthru_buffers; }
vector<Sample*>& get_silent_buffers (uint32_t howmany);
+ vector<Sample*>& get_send_buffers () { return _send_buffers; }
- DiskStream *diskstream_by_id (id_t id);
- DiskStream *diskstream_by_name (string name);
+ AudioDiskstream *diskstream_by_id (id_t id);
+ AudioDiskstream *diskstream_by_name (string name);
bool have_captured() const { return _have_captured; }
void refill_all_diskstream_buffers ();
uint32_t diskstream_buffer_size() const { return dstream_buffer_size; }
- uint32_t get_next_diskstream_id() const { return n_diskstreams(); }
- uint32_t n_diskstreams() const;
- typedef list<DiskStream *> DiskStreamList;
+ /* XXX fix required here when we get new diskstream types *, but
+ not sure of the direction to take this in until then.
+ */
+
+ uint32_t get_next_diskstream_id() const { return n_audio_diskstreams(); }
+ uint32_t n_audio_diskstreams() const;
+
+ typedef list<AudioDiskstream *> AudioDiskstreamList;
- Session::DiskStreamList disk_streams() const {
- RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
- return diskstreams; /* XXX yes, force a copy */
+ Session::AudioDiskstreamList audio_disk_streams() const {
+ Glib::RWLock::ReaderLock lm (diskstream_lock);
+ return audio_diskstreams; /* XXX yes, force a copy */
}
- void foreach_diskstream (void (DiskStream::*func)(void));
- template<class T> void foreach_diskstream (T *obj, void (T::*func)(DiskStream&));
+ void foreach_audio_diskstream (void (AudioDiskstream::*func)(void));
+ template<class T> void foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&));
- typedef slist<Route *> RouteList;
+ typedef list<Route *> RouteList;
RouteList get_routes() const {
- RWLockMonitor rlock (route_lock, false, __LINE__, __FILE__);
+ Glib::RWLock::ReaderLock rlock (route_lock);
return routes; /* XXX yes, force a copy */
}
template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg);
Route *route_by_name (string);
+ Route *route_by_remote_id (uint32_t id);
bool route_name_unique (string) const;
}
RecordState record_status() const {
- return (RecordState) atomic_read (&_record_status);
+ return (RecordState) g_atomic_int_get (&_record_status);
}
bool actively_recording () {
bool record_enabling_legal () const;
void maybe_enable_record ();
- void disable_record (bool force = false);
+ void disable_record (bool rt_context, bool force = false);
void step_back_from_record ();
sigc::signal<void> going_away;
sigc::signal<void> HaltOnXrun;
sigc::signal<void,Route*> RouteAdded;
- sigc::signal<void,DiskStream*> DiskStreamAdded;
+ sigc::signal<void,AudioDiskstream*> AudioDiskstreamAdded;
void request_roll ();
void request_bounded_roll (jack_nframes_t start, jack_nframes_t end);
void request_auto_loop (bool yn);
jack_nframes_t last_transport_start() const { return _last_roll_location; }
void goto_end () { request_locate (end_location->start(), false);}
- void goto_start () { request_locate (0, false); }
+ void goto_start () { request_locate (start_location->start(), false); }
void use_rf_shuttle_speed ();
void request_transport_speed (float speed);
- void request_overwrite_buffer (DiskStream*);
- void request_diskstream_speed (DiskStream&, float speed);
+ void request_overwrite_buffer (AudioDiskstream*);
+ void request_diskstream_speed (AudioDiskstream&, float speed);
void request_input_change_handling ();
+ bool locate_pending() const { return static_cast<bool>(post_transport_work&PostTransportLocate); }
+ bool transport_locked () const;
+
int wipe ();
- int wipe_diskstream (DiskStream *);
+ int wipe_diskstream (AudioDiskstream *);
int remove_region_from_region_list (Region&);
+ jack_nframes_t get_maximum_extent () const;
jack_nframes_t current_end_frame() const { return end_location->start(); }
+ jack_nframes_t current_start_frame() const { return start_location->start(); }
jack_nframes_t frame_rate() const { return _current_frame_rate; }
double frames_per_smpte_frame() const { return _frames_per_smpte_frame; }
jack_nframes_t frames_per_hour() const { return _frames_per_hour; }
CrossfadingModel,
SeamlessLoop,
MidiFeedback,
- MidiControl
+ MidiControl,
+ TranzportControl,
+ Feedback
};
sigc::signal<void,ControlType> ControlChanged;
RouteGroup* add_edit_group (string);
RouteGroup* add_mix_group (string);
+ void remove_edit_group (RouteGroup&);
+ void remove_mix_group (RouteGroup&);
+
RouteGroup *mix_group_by_name (string);
RouteGroup *edit_group_by_name (string);
sigc::signal<void,RouteGroup*> edit_group_added;
sigc::signal<void,RouteGroup*> mix_group_added;
+ sigc::signal<void> edit_group_removed;
+ sigc::signal<void> mix_group_removed;
- template<class T> void foreach_edit_group (T *obj, void (T::*func)(RouteGroup *)) {
- list<RouteGroup *>::iterator i;
- for (i = edit_groups.begin(); i != edit_groups.end(); i++) {
- (obj->*func)(*i);
+ void foreach_edit_group (sigc::slot<void,RouteGroup*> sl) {
+ for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); i++) {
+ sl (*i);
}
}
- template<class T> void foreach_mix_group (T *obj, void (T::*func)(RouteGroup *)) {
- list<RouteGroup *>::iterator i;
- for (i = mix_groups.begin(); i != mix_groups.end(); i++) {
- (obj->*func)(*i);
+ void foreach_mix_group (sigc::slot<void,RouteGroup*> sl) {
+ for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); i++) {
+ sl (*i);
}
}
int set_smpte_type (float fps, bool drop_frames);
void bbt_time (jack_nframes_t when, BBT_Time&);
+ void smpte_to_sample( SMPTE::Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes ) const;
+ void sample_to_smpte( jack_nframes_t sample, SMPTE::Time& smpte, bool use_offset, bool use_subframes ) const;
+ void smpte_time (SMPTE::Time &);
+ void smpte_time (jack_nframes_t when, SMPTE::Time&);
+ void smpte_time_subframes (jack_nframes_t when, SMPTE::Time&);
- ARDOUR::smpte_wrap_t smpte_increment( SMPTE_Time& smpte ) const;
- ARDOUR::smpte_wrap_t smpte_decrement( SMPTE_Time& smpte ) const;
- ARDOUR::smpte_wrap_t smpte_increment_subframes( SMPTE_Time& smpte ) const;
- ARDOUR::smpte_wrap_t smpte_decrement_subframes( SMPTE_Time& smpte ) const;
- ARDOUR::smpte_wrap_t smpte_increment_seconds( SMPTE_Time& smpte ) const;
- ARDOUR::smpte_wrap_t smpte_increment_minutes( SMPTE_Time& smpte ) const;
- ARDOUR::smpte_wrap_t smpte_increment_hours( SMPTE_Time& smpte ) const;
- void smpte_frames_floor( SMPTE_Time& smpte ) const;
- void smpte_seconds_floor( SMPTE_Time& smpte ) const;
- void smpte_minutes_floor( SMPTE_Time& smpte ) const;
- void smpte_hours_floor( SMPTE_Time& smpte ) const;
- void smpte_to_sample( SMPTE_Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes ) const;
- void sample_to_smpte( jack_nframes_t sample, SMPTE_Time& smpte, bool use_offset, bool use_subframes ) const;
- void smpte_time (SMPTE_Time &);
- void smpte_time (jack_nframes_t when, SMPTE_Time&);
- void smpte_time_subframes (jack_nframes_t when, SMPTE_Time&);
-
- void smpte_duration (jack_nframes_t, SMPTE_Time&) const;
+ void smpte_duration (jack_nframes_t, SMPTE::Time&) const;
void smpte_duration_string (char *, jack_nframes_t) const;
void set_smpte_offset (jack_nframes_t);
jack_nframes_t convert_to_frames_at (jack_nframes_t position, AnyTime&);
- sigc::signal<void> SMPTEOffsetChanged;
+ static sigc::signal<void> SMPTEOffsetChanged;
sigc::signal<void> SMPTETypeChanged;
void request_slave_source (SlaveSource, jack_nframes_t pos = 0);
/* source management */
struct import_status : public InterThreadInfo {
- string doing_what;
-
- /* control info */
- bool multichan;
- bool sample_convert;
- volatile bool freeze;
- string pathname;
+ string doing_what;
+
+ /* control info */
+ bool multichan;
+ bool sample_convert;
+ volatile bool freeze;
+ string pathname;
+
+ /* result */
+ std::vector<AudioRegion*> new_regions;
+
};
int import_audiofile (import_status&);
int start_audio_export (ARDOUR::AudioExportSpecification&);
int stop_audio_export (ARDOUR::AudioExportSpecification&);
- void add_source (Source *);
- int remove_file_source (FileSource&);
+ void add_audio_source (AudioSource *);
+ void remove_source (Source *);
+ int cleanup_audio_file_source (AudioFileSource&);
struct cleanup_report {
vector<string> paths;
sigc::signal<void,Source *> SourceAdded;
sigc::signal<void,Source *> SourceRemoved;
- FileSource *create_file_source (ARDOUR::DiskStream&, int32_t chan, bool destructive);
+ AudioFileSource *create_audio_source_for_session (ARDOUR::AudioDiskstream&, uint32_t which_channel, bool destructive);
+
Source *get_source (ARDOUR::id_t);
/* playlist management */
/* flattening stuff */
- int write_one_track (AudioTrack&, jack_nframes_t start, jack_nframes_t cnt, bool overwrite, vector<Source*>&,
- InterThreadInfo& wot);
+ int write_one_audio_track (AudioTrack&, jack_nframes_t start, jack_nframes_t cnt, bool overwrite, vector<AudioSource*>&,
+ InterThreadInfo& wot);
int freeze (InterThreadInfo&);
/* session-wide solo/mute/rec-enable */
bool get_trace_midi_output(MIDI::Port *port = 0);
void send_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t, MIDI::EventTwoBytes);
- void send_all_midi_feedback ();
void deliver_midi (MIDI::Port*, MIDI::byte*, int32_t size);
void set_frame_rate (jack_nframes_t nframes);
protected:
- friend class DiskStream;
+ friend class AudioDiskstream;
void stop_butler ();
void wait_till_butler_finished();
typedef void (Session::*process_function_type)(jack_nframes_t);
AudioEngine &_engine;
- atomic_t processing_prohibited;
+ mutable gint processing_prohibited;
process_function_type process_function;
process_function_type last_process_function;
jack_nframes_t _current_frame_rate;
int transport_sub_state;
- atomic_t _record_status;
+ mutable gint _record_status;
jack_nframes_t _transport_frame;
Location* end_location;
+ Location* start_location;
Slave *_slave;
SlaveSource _slave_type;
volatile float _transport_speed;
jack_nframes_t last_stop_frame;
vector<Sample *> _passthru_buffers;
vector<Sample *> _silent_buffers;
- map<RunContext,char*> _conversion_buffers;
+ vector<Sample *> _send_buffers;
+ map<RunContext,char*> _conversion_buffers;
jack_nframes_t current_block_size;
jack_nframes_t _worst_output_latency;
jack_nframes_t _worst_input_latency;
bool send_mtc;
bool send_mmc;
bool mmc_control;
- bool midi_feedback;
bool midi_control;
-
+
RingBuffer<Event*> pending_events;
void hookup_io ();
bool pending_abort;
bool pending_auto_loop;
- Sample* butler_mixdown_buffer;
- float* butler_gain_buffer;
- pthread_t butler_thread;
- PBD::NonBlockingLock butler_request_lock;
- pthread_cond_t butler_paused;
- bool butler_should_run;
- atomic_t butler_should_do_transport_work;
- int butler_request_pipe[2];
+ Sample* butler_mixdown_buffer;
+ float* butler_gain_buffer;
+ pthread_t butler_thread;
+ Glib::Mutex butler_request_lock;
+ Glib::Cond butler_paused;
+ bool butler_should_run;
+ mutable gint butler_should_do_transport_work;
+ int butler_request_pipe[2];
struct ButlerRequest {
enum Type {
void remove_empty_sounds ();
void setup_midi_control ();
- int midi_read (MIDI::Port *);
+ //int midi_read (MIDI::Port *);
void enable_record ();
void *do_work();
void set_next_event ();
- void process_event (Event *);
+ void process_event (Event *ev);
/* MIDI Machine Control */
void deliver_mmc (MIDI::MachineControl::Command, jack_nframes_t);
- void deliver_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t, MIDI::EventTwoBytes);
- void deliver_data (MIDI::Port* port, MIDI::byte*, int32_t size);
+ //void deliver_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t, MIDI::EventTwoBytes);
+ //void deliver_data (MIDI::Port* port, MIDI::byte*, int32_t size);
void spp_start (MIDI::Parser&);
void spp_continue (MIDI::Parser&);
MIDI::byte mtc_smpte_bits; /* encoding of SMTPE type for MTC */
MIDI::byte midi_msg[16];
jack_nframes_t outbound_mtc_smpte_frame;
- SMPTE_Time transmitting_smpte_time;
+ SMPTE::Time transmitting_smpte_time;
int next_quarter_frame_to_send;
double _frames_per_smpte_frame; /* has to be floating point because of drop frame */
jack_nframes_t _smpte_offset;
bool _smpte_offset_negative;
- /* cache the most-recently requested time conversions.
- this helps when we have multiple clocks showing the
- same time (e.g. the transport frame)
- */
-
- bool last_smpte_valid;
- jack_nframes_t last_smpte_when;
- SMPTE_Time last_smpte;
-
- int send_full_time_code ();
- int send_midi_time_code ();
-
- void send_full_time_code_in_another_thread ();
- void send_midi_time_code_in_another_thread ();
- void send_time_code_in_another_thread (bool full);
- void send_mmc_in_another_thread (MIDI::MachineControl::Command, jack_nframes_t frame = 0);
-
- /* Feedback */
-
- typedef sigc::slot<int> FeedbackFunctionPtr;
- static void* _feedback_thread_work (void *);
- void* feedback_thread_work ();
- int feedback_generic_midi_function ();
- std::list<FeedbackFunctionPtr> feedback_functions;
- int active_feedback;
- int feedback_request_pipe[2];
- pthread_t feedback_thread;
+ /* cache the most-recently requested time conversions. This helps when we
+ * have multiple clocks showing the same time (e.g. the transport frame) */
+ bool last_smpte_valid;
+ jack_nframes_t last_smpte_when;
+ SMPTE::Time last_smpte;
+
+ bool _send_smpte_update; ///< Flag to send a full frame (SMPTE) MTC message this cycle
- struct FeedbackRequest {
- enum Type {
- Start,
- Stop,
- Quit
- };
- };
+ int send_full_time_code(jack_nframes_t nframes);
+ int send_midi_time_code_for_cycle(jack_nframes_t nframes);
- int init_feedback();
- int start_feedback ();
- int stop_feedback ();
- void terminate_feedback ();
- int poke_feedback (FeedbackRequest::Type);
+ //void send_mmc_in_another_thread (MIDI::MachineControl::Command, jack_nframes_t frame = 0);
jack_nframes_t adjust_apparent_position (jack_nframes_t frames);
static MultiAllocSingleReleasePool pool;
};
- PBD::Lock midi_lock;
- pthread_t midi_thread;
- int midi_request_pipe[2];
- atomic_t butler_active;
- RingBuffer<MIDIRequest*> midi_requests;
+ mutable gint butler_active;
+
+ //PBD::Lock midi_lock;
+ //pthread_t midi_thread;
+ //int midi_request_pipe[2];
- int start_midi_thread ();
+ //RingBuffer<MIDIRequest*> midi_requests;
+ /*int start_midi_thread ();
void terminate_midi_thread ();
void poke_midi_thread ();
static void *_midi_thread_work (void *arg);
- void midi_thread_work ();
+ void midi_thread_work ();*/
void change_midi_ports ();
int use_config_midi_ports ();
bool waiting_to_start;
void set_auto_loop (bool yn);
- void overwrite_some_buffers (DiskStream*);
+ void overwrite_some_buffers (AudioDiskstream*);
void flush_all_redirects ();
void locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
void start_locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
void force_locate (jack_nframes_t frame, bool with_roll = false);
- void set_diskstream_speed (DiskStream*, float speed);
+ void set_diskstream_speed (AudioDiskstream*, float speed);
void set_transport_speed (float speed, bool abort = false);
void stop_transport (bool abort = false);
void start_transport ();
/* disk-streams */
- DiskStreamList diskstreams;
- mutable PBD::NonBlockingRWLock diskstream_lock;
+ AudioDiskstreamList audio_diskstreams;
+ mutable Glib::RWLock diskstream_lock;
uint32_t dstream_buffer_size;
- void add_diskstream (DiskStream*);
+ void add_diskstream (AudioDiskstream*);
int load_diskstreams (const XMLNode&);
/* routes stuff */
RouteList routes;
- mutable PBD::NonBlockingRWLock route_lock;
+ mutable Glib::RWLock route_lock;
void add_route (Route*);
+ uint32_t destructive_index;
int load_routes (const XMLNode&);
Route* XMLRouteFactory (const XMLNode&);
/* REGION MANAGEMENT */
- mutable PBD::Lock region_lock;
+ mutable Glib::Mutex region_lock;
typedef map<ARDOUR::id_t,AudioRegion *> AudioRegionList;
AudioRegionList audio_regions;
/* SOURCES */
- mutable PBD::Lock source_lock;
- typedef std::map<id_t, Source *> SourceList;
+ mutable Glib::Mutex audio_source_lock;
+ typedef std::map<id_t, AudioSource *> AudioSourceList;
- SourceList sources;
+ AudioSourceList audio_sources;
int load_sources (const XMLNode& node);
XMLNode& get_sources_as_xml ();
- void remove_source (Source *);
-
Source *XMLSourceFactory (const XMLNode&);
/* PLAYLISTS */
- mutable PBD::Lock playlist_lock;
+ mutable Glib::Mutex playlist_lock;
typedef set<Playlist *> PlaylistList;
PlaylistList playlists;
PlaylistList unused_playlists;
Playlist *XMLPlaylistFactory (const XMLNode&);
void playlist_length_changed (Playlist *);
- void diskstream_playlist_changed (DiskStream *);
+ void diskstream_playlist_changed (AudioDiskstream *);
/* NAMED SELECTIONS */
- mutable PBD::Lock named_selection_lock;
+ mutable Glib::Mutex named_selection_lock;
typedef set<NamedSelection *> NamedSelectionList;
NamedSelectionList named_selections;
/* INSERT AND SEND MANAGEMENT */
- slist<PortInsert *> _port_inserts;
- slist<PluginInsert *> _plugin_inserts;
- slist<Send *> _sends;
+ list<PortInsert *> _port_inserts;
+ list<PluginInsert *> _plugin_inserts;
+ list<Send *> _sends;
uint32_t send_cnt;
uint32_t insert_cnt;
vector<space_and_path> session_dirs;
vector<space_and_path>::iterator last_rr_session_dir;
uint32_t _total_free_4k_blocks;
- PBD::Lock space_lock;
+ Glib::Mutex space_lock;
static const char* sound_dir_name;
+ static const char* tape_dir_name;
static const char* dead_sound_dir_name;
static const char* peak_dir_name;
- string discover_best_sound_dir ();
+ string discover_best_sound_dir (bool destructive = false);
int ensure_sound_dir (string, string&);
void refresh_disk_space ();
- atomic_t _playback_load;
- atomic_t _capture_load;
- atomic_t _playback_load_min;
- atomic_t _capture_load_min;
+ mutable gint _playback_load;
+ mutable gint _capture_load;
+ mutable gint _playback_load_min;
+ mutable gint _capture_load_min;
/* I/O Connections */
typedef list<Connection *> ConnectionList;
- mutable PBD::Lock connection_lock;
+ mutable Glib::Mutex connection_lock;
ConnectionList _connections;
int load_connections (const XMLNode&);
Sample* click_emphasis_data;
jack_nframes_t click_length;
jack_nframes_t click_emphasis_length;
- mutable PBD::NonBlockingRWLock click_lock;
+ mutable Glib::RWLock click_lock;
static const Sample default_click[];
static const jack_nframes_t default_click_length;