summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-11-08 16:28:21 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-11-08 16:28:21 +0000
commitff122d0fe8fde6a8a4edc71f9dbba5d161036300 (patch)
treebde7638b27de0f51ae1d02c4bf486c712abcfbe8 /libs/ardour
parent660fd702af13ace2d0399e47d5e9a644a6e3a8d7 (diff)
monster commit: transport mgmt changes from 2.X (omnibus edition); make slave use nframes64_t ; avoid crashes in Drags when commiting reversible transactions that do not exist
git-svn-id: svn://localhost/ardour2/branches/3.0@6034 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/session.h184
-rw-r--r--libs/ardour/ardour/slave.h50
-rw-r--r--libs/ardour/audio_diskstream.cc3
-rw-r--r--libs/ardour/enums.cc3
-rw-r--r--libs/ardour/filesystem_paths.cc35
-rw-r--r--libs/ardour/jack_slave.cc5
-rw-r--r--libs/ardour/midi_clock_slave.cc32
-rw-r--r--libs/ardour/midi_diskstream.cc2
-rw-r--r--libs/ardour/mtc_slave.cc8
-rw-r--r--libs/ardour/session.cc10
-rw-r--r--libs/ardour/session_butler.cc4
-rw-r--r--libs/ardour/session_events.cc40
-rw-r--r--libs/ardour/session_export.cc2
-rw-r--r--libs/ardour/session_process.cc2
-rw-r--r--libs/ardour/session_state.cc3
-rw-r--r--libs/ardour/session_time.cc6
-rw-r--r--libs/ardour/session_transport.cc394
-rw-r--r--libs/ardour/slave.cc8
18 files changed, 418 insertions, 373 deletions
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 3a980982c3..6ac36f98b6 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -132,8 +132,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
Recording = 2
};
- struct Event {
- enum Type {
+ struct Event {
+ enum Type {
SetTransportSpeed,
SetDiskstreamSpeed,
Locate,
@@ -148,78 +148,82 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
SetSlaveSource,
Audition,
InputConfigurationChange,
- SetAudioRange,
- SetPlayRange,
-
+ SetPlayAudioRange,
+
/* only one of each of these events can be queued at any one time */
-
+
StopOnce,
AutoLoop
};
-
- enum Action {
- Add,
- Remove,
- Replace,
- Clear
- };
-
- Type type;
- Action action;
- nframes_t action_frame;
- nframes_t target_frame;
- double speed;
-
- union {
- void* ptr;
- bool yes_or_no;
- nframes_t target2_frame;
- SlaveSource slave;
- Route* route;
- };
-
- std::list<AudioRange> audio_range;
- std::list<MusicRange> music_range;
-
- boost::shared_ptr<Region> region;
-
- Event(Type t, Action a, nframes_t when, nframes_t where, double spd, bool yn = false)
+
+ enum Action {
+ Add,
+ Remove,
+ Replace,
+ Clear
+ };
+
+ Type type;
+ Action action;
+ nframes64_t action_frame;
+ nframes64_t target_frame;
+ double speed;
+
+ union {
+ void* ptr;
+ bool yes_or_no;
+ nframes64_t target2_frame;
+ SlaveSource slave;
+ Route* route;
+ };
+
+ union {
+ bool second_yes_or_no;
+ };
+
+ std::list<AudioRange> audio_range;
+ std::list<MusicRange> music_range;
+
+ boost::shared_ptr<Region> region;
+
+ Event(Type t, Action a, nframes_t when, nframes_t where, double spd, bool yn = false, bool yn2 = false)
: type (t)
, action (a)
, action_frame (when)
, target_frame (where)
, speed (spd)
, yes_or_no (yn)
+ , second_yes_or_no (yn2)
{}
- void set_ptr (void* p) {
- ptr = p;
- }
-
- bool before (const Event& other) const {
- return action_frame < other.action_frame;
- }
-
- bool after (const Event& other) const {
- return action_frame > other.action_frame;
- }
-
- static bool compare (const Event *e1, const Event *e2) {
- return e1->before (*e2);
- }
-
- void *operator new (size_t) {
- return pool.alloc ();
- }
-
- void operator delete (void *ptr, size_t /*size*/) {
- pool.release (ptr);
- }
-
- static const nframes_t Immediate = 0;
-
- private:
- static MultiAllocSingleReleasePool pool;
+ void set_ptr (void* p) {
+ ptr = p;
+ }
+
+ bool before (const Event& other) const {
+ return action_frame < other.action_frame;
+ }
+
+ bool after (const Event& other) const {
+ return action_frame > other.action_frame;
+ }
+
+ static bool compare (const Event *e1, const Event *e2) {
+ return e1->before (*e2);
+ }
+
+ void *operator new (size_t) {
+ return pool.alloc ();
+ }
+
+ void operator delete (void *ptr, size_t /*size*/) {
+ pool.release (ptr);
+ }
+
+ static const nframes_t Immediate = 0;
+
+ private:
+ static MultiAllocSingleReleasePool pool;
};
/* creating from an XML file */
@@ -375,9 +379,9 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
/* Transport mechanism signals */
sigc::signal<void> TransportStateChange; /* generic */
- sigc::signal<void,nframes_t> PositionChanged; /* sent after any non-sequential motion */
+ sigc::signal<void,nframes64_t> PositionChanged; /* sent after any non-sequential motion */
sigc::signal<void> DurationChanged;
- sigc::signal<void,nframes_t> Xrun;
+ sigc::signal<void,nframes64_t> Xrun;
sigc::signal<void> TransportLooped;
/** emitted when a locate has occurred */
@@ -388,7 +392,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
void request_roll_at_and_return (nframes_t start, nframes_t return_to);
void request_bounded_roll (nframes_t start, nframes_t end);
- void request_stop (bool abort = false);
+ void request_stop (bool abort = false, bool clear_state = false);
void request_locate (nframes_t frame, bool with_roll = false);
void request_play_loop (bool yn, bool leave_rolling = false);
@@ -406,7 +410,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
void request_diskstream_speed (Diskstream&, double speed);
void request_input_change_handling ();
- bool locate_pending() const { return static_cast<bool>(post_transport_work&PostTransportLocate); }
+ bool locate_pending() const { return static_cast<bool>(post_transport_work()&PostTransportLocate); }
bool transport_locked () const;
int wipe ();
@@ -533,8 +537,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
/* Time */
- nframes_t transport_frame () const {return _transport_frame; }
- nframes_t audible_frame () const;
+ nframes64_t transport_frame () const {return _transport_frame; }
+ nframes64_t audible_frame () const;
nframes64_t requested_return_frame() const { return _requested_return_frame; }
enum PullupFormat {
@@ -914,10 +918,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
/* ranges */
- void set_audio_range (std::list<AudioRange>&);
- void set_music_range (std::list<MusicRange>&);
-
- void request_play_range (bool yn, bool leave_rolling = false);
+ void request_play_range (std::list<AudioRange>*, bool leave_rolling = false);
bool get_play_range () const { return _play_range; }
/* buffers for gain and pan */
@@ -997,7 +998,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
nframes_t _nominal_frame_rate; //ignores audioengine setting, "native" SR
int transport_sub_state;
mutable gint _record_status;
- volatile nframes_t _transport_frame;
+ volatile nframes64_t _transport_frame;
Location* end_location;
Location* start_location;
Slave* _slave;
@@ -1010,7 +1011,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
CubicInterpolation interpolation;
bool auto_play_legal;
- nframes_t _last_slave_transport_frame;
+ nframes64_t _last_slave_transport_frame;
nframes_t maximum_output_latency;
volatile nframes64_t _requested_return_frame;
BufferSet* _scratch_buffers;
@@ -1026,6 +1027,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
bool _non_soloed_outs_muted;
uint32_t _listen_cnt;
bool _writable;
+ bool _was_seamless;
void set_worst_io_latencies ();
void set_worst_io_latencies_x (IOChange, void *) {
@@ -1180,7 +1182,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
PostTransportScrub = 0x8000,
PostTransportReverse = 0x10000,
PostTransportInputChange = 0x20000,
- PostTransportCurveRealloc = 0x40000
+ PostTransportCurveRealloc = 0x40000,
+ PostTransportClearSubstate = 0x80000
};
static const PostTransportWork ProcessCannotProceedMask =
@@ -1192,9 +1195,13 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
PostTransportScrub|
PostTransportAudition|
PostTransportLocate|
- PostTransportStop);
+ PostTransportStop|
+ PostTransportClearSubstate);
- PostTransportWork post_transport_work;
+ gint _post_transport_work; /* accessed only atomic ops */
+ PostTransportWork post_transport_work() const { return (PostTransportWork) g_atomic_int_get (&_post_transport_work); }
+ void set_post_transport_work (PostTransportWork ptw) { g_atomic_int_set (&_post_transport_work, (gint) ptw); }
+ void add_post_transport_work (PostTransportWork ptw);
uint32_t cumulative_rf_motion;
uint32_t rf_scale;
@@ -1337,8 +1344,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
int no_roll (nframes_t nframes);
int fail_roll (nframes_t nframes);
- bool non_realtime_work_pending() const { return static_cast<bool>(post_transport_work); }
- bool process_can_proceed() const { return !(post_transport_work & ProcessCannotProceedMask); }
+ bool non_realtime_work_pending() const { return static_cast<bool>(post_transport_work()); }
+ bool process_can_proceed() const { return !(post_transport_work() & ProcessCannotProceedMask); }
struct MIDIRequest {
enum Type {
@@ -1361,18 +1368,19 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
void change_midi_ports ();
int use_config_midi_ports ();
- void set_play_loop (bool yn, bool leave_rolling);
+ void set_play_loop (bool yn);
+ void unset_play_loop ();
void overwrite_some_buffers (Diskstream*);
void flush_all_inserts ();
int micro_locate (nframes_t distance);
- void locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
- void start_locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
- void force_locate (nframes_t frame, bool with_roll = false);
+ void locate (nframes64_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false);
+ void start_locate (nframes64_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false);
+ void force_locate (nframes64_t frame, bool with_roll = false);
void set_diskstream_speed (Diskstream*, double speed);
- void set_transport_speed (double speed, bool abort = false);
- void stop_transport (bool abort = false);
+ void set_transport_speed (double speed, bool abort = false, bool clear_state = false);
+ void stop_transport (bool abort = false, bool clear_state = false);
void start_transport ();
- void realtime_stop (bool abort);
+ void realtime_stop (bool abort, bool clear_state);
void non_realtime_start_scrub ();
void non_realtime_set_speed ();
void non_realtime_locate ();
@@ -1619,8 +1627,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
std::list<AudioRange> current_audio_range;
bool _play_range;
- void set_play_range (bool yn, bool leave_rolling);
- void setup_auto_play ();
+ void set_play_range (std::list<AudioRange>&, bool leave_rolling);
+ void unset_play_range ();
/* main outs */
uint32_t main_outs;
diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h
index 0f005d6f1b..9036c97a27 100644
--- a/libs/ardour/ardour/slave.h
+++ b/libs/ardour/ardour/slave.h
@@ -107,7 +107,7 @@ class Slave {
* @param position - The transport position requested
* @return - The return value is currently ignored (see Session::follow_slave)
*/
- virtual bool speed_and_position (double& speed, nframes_t& position) = 0;
+ virtual bool speed_and_position (double& speed, nframes64_t& position) = 0;
/**
* reports to ARDOUR whether the Slave is currently synced to its external
@@ -161,13 +161,13 @@ class Slave {
class ISlaveSessionProxy {
public:
virtual TempoMap& tempo_map() const { return *((TempoMap *) 0); }
- virtual nframes_t frame_rate() const { return 0; }
- virtual nframes_t audible_frame () const { return 0; }
- virtual nframes_t transport_frame () const { return 0; }
- virtual nframes_t frames_since_cycle_start () const { return 0; }
- virtual nframes_t frame_time () const { return 0; }
+ virtual nframes_t frame_rate() const { return 0; }
+ virtual nframes64_t audible_frame () const { return 0; }
+ virtual nframes64_t transport_frame () const { return 0; }
+ virtual nframes_t frames_since_cycle_start () const { return 0; }
+ virtual nframes64_t frame_time () const { return 0; }
- virtual void request_locate (nframes_t /*frame*/, bool with_roll = false) {
+ virtual void request_locate (nframes64_t /*frame*/, bool with_roll = false) {
(void) with_roll;
}
virtual void request_transport_speed (double /*speed*/) {}
@@ -181,14 +181,14 @@ class SlaveSessionProxy : public ISlaveSessionProxy {
public:
SlaveSessionProxy(Session &s) : session(s) {}
- TempoMap& tempo_map() const;
- nframes_t frame_rate() const;
- nframes_t audible_frame () const;
- nframes_t transport_frame () const;
- nframes_t frames_since_cycle_start () const;
- nframes_t frame_time () const;
+ TempoMap& tempo_map() const;
+ nframes_t frame_rate() const;
+ nframes64_t audible_frame () const;
+ nframes64_t transport_frame () const;
+ nframes_t frames_since_cycle_start () const;
+ nframes64_t frame_time () const;
- void request_locate (nframes_t frame, bool with_roll = false);
+ void request_locate (nframes64_t frame, bool with_roll = false);
void request_transport_speed (double speed);
};
@@ -211,7 +211,7 @@ class MTC_Slave : public Slave, public sigc::trackable {
~MTC_Slave ();
void rebind (MIDI::Port&);
- bool speed_and_position (double&, nframes_t&);
+ bool speed_and_position (double&, nframes64_t&);
bool locked() const;
bool ok() const;
@@ -256,7 +256,7 @@ class MIDIClock_Slave : public Slave, public sigc::trackable {
~MIDIClock_Slave ();
void rebind (MIDI::Port&);
- bool speed_and_position (double&, nframes_t&);
+ bool speed_and_position (double&, nframes64_t&);
bool locked() const;
bool ok() const;
@@ -311,17 +311,17 @@ class MIDIClock_Slave : public Slave, public sigc::trackable {
double b, c, omega;
void reset ();
- void start (MIDI::Parser& parser, nframes_t timestamp);
- void contineu (MIDI::Parser& parser, nframes_t timestamp);
- void stop (MIDI::Parser& parser, nframes_t timestamp);
+ void start (MIDI::Parser& parser, nframes64_t timestamp);
+ void contineu (MIDI::Parser& parser, nframes64_t timestamp);
+ void stop (MIDI::Parser& parser, nframes64_t timestamp);
void position (MIDI::Parser& parser, MIDI::byte* message, size_t size);
// we can't use continue because it is a C++ keyword
- void calculate_one_ppqn_in_frames_at(nframes_t time);
- nframes_t calculate_song_position(uint16_t song_position_in_sixteenth_notes);
+ void calculate_one_ppqn_in_frames_at(nframes64_t time);
+ nframes64_t calculate_song_position(uint16_t song_position_in_sixteenth_notes);
void calculate_filter_coefficients();
- void update_midi_clock (MIDI::Parser& parser, nframes_t timestamp);
+ void update_midi_clock (MIDI::Parser& parser, nframes64_t timestamp);
void read_current (SafeTime *) const;
- bool stop_if_no_more_clock_events(nframes_t& pos, nframes_t now);
+ bool stop_if_no_more_clock_events(nframes64_t& pos, nframes64_t now);
/// whether transport should be rolling
bool _started;
@@ -337,7 +337,7 @@ class ADAT_Slave : public Slave
ADAT_Slave () {}
~ADAT_Slave () {}
- bool speed_and_position (double& speed, nframes_t& pos) {
+ bool speed_and_position (double& speed, nframes64_t& pos) {
speed = 0;
pos = 0;
return false;
@@ -355,7 +355,7 @@ class JACK_Slave : public Slave
JACK_Slave (jack_client_t*);
~JACK_Slave ();
- bool speed_and_position (double& speed, nframes_t& pos);
+ bool speed_and_position (double& speed, nframes64_t& pos);
bool starting() const { return _starting; }
bool locked() const;
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index fbd10b92e3..3248cd9b2d 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -626,6 +626,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
nframes_t total = chaninfo->playback_vector.len[0] + chaninfo->playback_vector.len[1];
if (necessary_samples > total) {
+ cerr << _name << " Need " << necessary_samples << " total = " << total << endl;
cerr << "underrun for " << _name << endl;
DiskUnderrun ();
goto out;
@@ -1754,7 +1755,7 @@ AudioDiskstream::get_state ()
if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
snprintf (buf, sizeof (buf), "%" PRId64, pi->start());
} else {
- snprintf (buf, sizeof (buf), "%" PRIu32, _session.transport_frame());
+ snprintf (buf, sizeof (buf), "%" PRId64, _session.transport_frame());
}
cs_child->add_property (X_("at"), buf);
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 8ab2a6f8cf..885ebeb27a 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -299,8 +299,7 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Session::Event, SetSlaveSource);
REGISTER_CLASS_ENUM (Session::Event, Audition);
REGISTER_CLASS_ENUM (Session::Event, InputConfigurationChange);
- REGISTER_CLASS_ENUM (Session::Event, SetAudioRange);
- REGISTER_CLASS_ENUM (Session::Event, SetPlayRange);
+ REGISTER_CLASS_ENUM (Session::Event, SetPlayAudioRange);
REGISTER_CLASS_ENUM (Session::Event, StopOnce);
REGISTER_CLASS_ENUM (Session::Event, AutoLoop);
REGISTER (_Session_Event_Type);
diff --git a/libs/ardour/filesystem_paths.cc b/libs/ardour/filesystem_paths.cc
index 2f2afe3c7b..932416ef41 100644
--- a/libs/ardour/filesystem_paths.cc
+++ b/libs/ardour/filesystem_paths.cc
@@ -16,6 +16,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <cstdlib>
#include "pbd/error.h"
#include "pbd/filesystem_paths.h"
@@ -36,18 +37,30 @@ using std::string;
sys::path
user_config_directory ()
{
- const string home_dir = Glib::get_home_dir ();
-
- if (home_dir.empty ()) {
- const string error_msg = "Unable to determine home directory";
-
- // log the error
- error << error_msg << endmsg;
-
- throw sys::filesystem_error(error_msg);
+ const char* c = 0;
+ sys::path p;
+
+ /* adopt freedesktop standards, and put .ardour3 into $XDG_CONFIG_HOME or ~/.config
+ */
+
+ if ((c = getenv ("XDG_CONFIG_HOME")) != 0) {
+ p = c;
+ } else {
+ const string home_dir = Glib::get_home_dir();
+
+ if (home_dir.empty ()) {
+ const string error_msg = "Unable to determine home directory";
+
+ // log the error
+ error << error_msg << endmsg;
+
+ throw sys::filesystem_error(error_msg);
+ }
+
+ p = home_dir;
+ p /= ".config";
}
-
- sys::path p(home_dir);
+
p /= user_config_dir_name;
return p;
diff --git a/libs/ardour/jack_slave.cc b/libs/ardour/jack_slave.cc
index 9f92f1b21f..0f425d09c6 100644
--- a/libs/ardour/jack_slave.cc
+++ b/libs/ardour/jack_slave.cc
@@ -36,7 +36,7 @@ JACK_Slave::JACK_Slave (jack_client_t* j)
: jack (j)
{
double x;
- nframes_t p;
+ nframes64_t p;
/* call this to initialize things */
speed_and_position (x, p);
}
@@ -64,10 +64,11 @@ JACK_Slave::ok() const
}
bool
-JACK_Slave::speed_and_position (double& sp, nframes_t& position)
+JACK_Slave::speed_and_position (double& sp, nframes64_t& position)
{
jack_position_t pos;
jack_transport_state_t state;
+
state = jack_transport_query (jack, &pos);
switch (state) {
diff --git a/libs/ardour/midi_clock_slave.cc b/libs/ardour/midi_clock_slave.cc
index a41864571d..53f819e54a 100644
--- a/libs/ardour/midi_clock_slave.cc
+++ b/libs/ardour/midi_clock_slave.cc
@@ -87,7 +87,7 @@ MIDIClock_Slave::rebind (MIDI::Port& p)
}
void
-MIDIClock_Slave::calculate_one_ppqn_in_frames_at(nframes_t time)
+MIDIClock_Slave::calculate_one_ppqn_in_frames_at(nframes64_t time)
{
const Tempo& current_tempo = session->tempo_map().tempo_at(time);
const Meter& current_meter = session->tempo_map().meter_at(time);
@@ -101,14 +101,14 @@ MIDIClock_Slave::calculate_one_ppqn_in_frames_at(nframes_t time)
one_ppqn_in_frames = frames_per_quarter_note / double (ppqn);
}
-ARDOUR::nframes_t
+ARDOUR::nframes64_t
MIDIClock_Slave::calculate_song_position(uint16_t song_position_in_sixteenth_notes)
{
- nframes_t song_position_frames = 0;
+ nframes64_t song_position_frames = 0;
for (uint16_t i = 1; i <= song_position_in_sixteenth_notes; ++i) {
// one quarter note contains ppqn pulses, so a sixteenth note is ppqn / 4 pulses
calculate_one_ppqn_in_frames_at(song_position_frames);
- song_position_frames += one_ppqn_in_frames * nframes_t(ppqn / 4);
+ song_position_frames += one_ppqn_in_frames * (nframes64_t)(ppqn / 4);
}
return song_position_frames;
@@ -124,7 +124,7 @@ MIDIClock_Slave::calculate_filter_coefficients()
}
void
-MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, nframes_t timestamp)
+MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, nframes64_t timestamp)
{
// some pieces of hardware send MIDI Clock all the time
if ( (!_starting) && (!_started) ) {
@@ -133,7 +133,7 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, nframes_t timestamp)
calculate_one_ppqn_in_frames_at(should_be_position);
- nframes_t elapsed_since_start = timestamp - first_timestamp;
+ nframes64_t elapsed_since_start = timestamp - first_timestamp;
double error = 0;
if (_starting || last_timestamp == 0) {
@@ -195,7 +195,7 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, nframes_t timestamp)
}
void
-MIDIClock_Slave::start (Parser& /*parser*/, nframes_t /*timestamp*/)
+MIDIClock_Slave::start (Parser& /*parser*/, nframes64_t /*timestamp*/)
{
#ifdef DEBUG_MIDI_CLOCK
cerr << "MIDIClock_Slave got start message at time " << timestamp << " engine time: " << session->frame_time() << endl;
@@ -223,7 +223,7 @@ MIDIClock_Slave::reset ()
}
void
-MIDIClock_Slave::contineu (Parser& /*parser*/, nframes_t /*timestamp*/)
+MIDIClock_Slave::contineu (Parser& /*parser*/, nframes64_t /*timestamp*/)
{
#ifdef DEBUG_MIDI_CLOCK
std::cerr << "MIDIClock_Slave got continue message" << endl;
@@ -236,7 +236,7 @@ MIDIClock_Slave::contineu (Parser& /*parser*/, nframes_t /*timestamp*/)
void
-MIDIClock_Slave::stop (Parser& /*parser*/, nframes_t /*timestamp*/)
+MIDIClock_Slave::stop (Parser& /*parser*/, nframes64_t /*timestamp*/)
{
#ifdef DEBUG_MIDI_CLOCK
std::cerr << "MIDIClock_Slave got stop message" << endl;
@@ -255,7 +255,7 @@ MIDIClock_Slave::stop (Parser& /*parser*/, nframes_t /*timestamp*/)
// that is the position of the last MIDI Clock
// message and that is probably what the master
// expects where we are right now
- nframes_t stop_position = should_be_position;
+ nframes64_t stop_position = should_be_position;
// find out the last MIDI beat: go back #midi_clocks mod 6
// and lets hope the tempo didnt change in those last 6 beats :)
@@ -282,7 +282,7 @@ MIDIClock_Slave::position (Parser& /*parser*/, byte* message, size_t size)
assert((lsb <= 0x7f) && (msb <= 0x7f));
uint16_t position_in_sixteenth_notes = (uint16_t(msb) << 7) | uint16_t(lsb);
- nframes_t position_in_frames = calculate_song_position(position_in_sixteenth_notes);
+ nframes64_t position_in_frames = calculate_song_position(position_in_sixteenth_notes);
#ifdef DEBUG_MIDI_CLOCK
cerr << "Song Position: " << position_in_sixteenth_notes << " frames: " << position_in_frames << endl;
@@ -313,7 +313,7 @@ MIDIClock_Slave::starting() const
}
bool
-MIDIClock_Slave::stop_if_no_more_clock_events(nframes_t& pos, nframes_t now)
+MIDIClock_Slave::stop_if_no_more_clock_events(nframes64_t& pos, nframes64_t now)
{
/* no timecode for 1/4 second ? conclude that its stopped */
if (last_timestamp &&
@@ -332,7 +332,7 @@ MIDIClock_Slave::stop_if_no_more_clock_events(nframes_t& pos, nframes_t now)
}
bool
-MIDIClock_Slave::speed_and_position (double& speed, nframes_t& pos)
+MIDIClock_Slave::speed_and_position (double& speed, nframes64_t& pos)
{
if (!_started || _starting) {
speed = 0.0;
@@ -340,7 +340,7 @@ MIDIClock_Slave::speed_and_position (double& speed, nframes_t& pos)
return true;
}
- nframes_t engine_now = session->frame_time();
+ nframes64_t engine_now = session->frame_time();
if (stop_if_no_more_clock_events(pos, engine_now)) {
return false;
@@ -353,8 +353,8 @@ MIDIClock_Slave::speed_and_position (double& speed, nframes_t& pos)
if (engine_now > last_timestamp) {
// we are in between MIDI clock messages
// so we interpolate position according to speed
- nframes_t elapsed = engine_now - last_timestamp;
- pos = nframes_t (should_be_position + double(elapsed) * speed);
+ nframes64_t elapsed = engine_now - last_timestamp;
+ pos = (nframes64_t) (should_be_position + double(elapsed) * speed);
} else {
// A new MIDI clock message has arrived this cycle
pos = should_be_position;
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index f61211def8..f06b00ae00 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -1223,7 +1223,7 @@ MidiDiskstream::get_state ()
if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
snprintf (buf, sizeof (buf), "%" PRId64, pi->start());
} else {
- snprintf (buf, sizeof (buf), "%" PRIu32, _session.transport_frame());
+ snprintf (buf, sizeof (buf), "%" PRId64, _session.transport_frame());
}
cs_child->add_property (X_("at"), buf);
diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc
index 4034ef32be..3619cc4c69 100644
--- a/libs/ardour/mtc_slave.cc
+++ b/libs/ardour/mtc_slave.cc
@@ -72,7 +72,7 @@ void
MTC_Slave::update_mtc_qtr (Parser& /*p*/)
{
cycles_t cnow = get_cycles ();
- nframes_t now = session.engine().frame_time();
+ nframes64_t now = session.engine().frame_time();
nframes_t qtr;
static cycles_t last_qtr = 0;
@@ -91,7 +91,7 @@ MTC_Slave::update_mtc_qtr (Parser& /*p*/)
void
MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
{
- nframes_t now = session.engine().frame_time();
+ nframes64_t now = session.engine().frame_time();
Timecode::Time timecode;
timecode.hours = msg[3];
@@ -258,9 +258,9 @@ MTC_Slave::ok() const
}
bool
-MTC_Slave::speed_and_position (double& speed, nframes_t& pos)
+MTC_Slave::speed_and_position (double& speed, nframes64_t& pos)
{
- nframes_t now = session.engine().frame_time();
+ nframes64_t now = session.engine().frame_time();
SafeTime last;
nframes_t frame_rate;
nframes_t elapsed;
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 031c2aa58a..8b3d832204 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -132,7 +132,6 @@ Session::Session (AudioEngine &eng,
pending_events (2048),
state_tree (0),
_butler (new Butler (this)),
- post_transport_work((PostTransportWork)0),
_send_timecode_update (false),
midi_thread (pthread_t (0)),
midi_requests (128), // the size of this should match the midi request pool size
@@ -218,7 +217,6 @@ Session::Session (AudioEngine &eng,
pending_events (2048),
state_tree (0),
_butler (new Butler (this)),
- post_transport_work((PostTransportWork)0),
_send_timecode_update (false),
midi_thread (pthread_t (0)),
midi_requests (16),
@@ -1229,12 +1227,12 @@ Session::maybe_enable_record ()
set_dirty();
}
-nframes_t
+nframes64_t
Session::audible_frame () const
{
- nframes_t ret;
+ nframes64_t ret;
+ nframes64_t tf;
nframes_t offset;
- nframes_t tf;
/* the first of these two possible settings for "offset"
mean that the audible frame is stationary until
@@ -3517,7 +3515,7 @@ void
Session::set_audition (boost::shared_ptr<Region> r)
{
pending_audition_region = r;
- post_transport_work = PostTransportWork (post_transport_work | PostTransportAudition);
+ add_post_transport_work (PostTransportAudition);
_butler->schedule_transport_work ();
}
diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc
index 41b4851ce5..0ffc14ff3a 100644
--- a/libs/ardour/session_butler.cc
+++ b/libs/ardour/session_butler.cc
@@ -68,7 +68,7 @@ static inline uint32_t next_power_of_two (uint32_t n)
void
Session::schedule_curve_reallocation ()
{
- post_transport_work = PostTransportWork (post_transport_work | PostTransportCurveRealloc);
+ add_post_transport_work (PostTransportCurveRealloc);
_butler->schedule_transport_work ();
}
@@ -100,7 +100,7 @@ Session::overwrite_some_buffers (Diskstream* ds)
}
}
- post_transport_work = PostTransportWork (post_transport_work | PostTransportOverWrite);
+ add_post_transport_work (PostTransportOverWrite);
_butler->schedule_transport_work ();
}
diff --git a/libs/ardour/session_events.cc b/libs/ardour/session_events.cc
index 65635b773f..fb993faa68 100644
--- a/libs/ardour/session_events.cc
+++ b/libs/ardour/session_events.cc
@@ -23,6 +23,7 @@
#include "ardour/timestamps.h"
#include "pbd/error.h"
+#include "pbd/enumwriter.h"
#include <glibmm/thread.h>
#include "ardour/ardour.h"
@@ -38,28 +39,6 @@ using namespace PBD;
MultiAllocSingleReleasePool Session::Event::pool ("event", sizeof (Session::Event), 512);
-static const char* event_names[] = {
- "SetTransportSpeed",
- "SetDiskstreamSpeed",
- "Locate",
- "LocateRoll",
- "LocateRollLocate",
- "SetLoop",
- "PunchIn",
- "PunchOut",
- "RangeStop",
- "RangeLocate",
- "Overwrite",
- "SetSlaveSource",
- "Audition",
- "InputConfigurationChange",
- "SetAudioRange",
- "SetMusicRange",
- "SetPlayRange",
- "StopOnce",
- "AutoLoop"
-};
-
void
Session::add_event (nframes_t frame, Event::Type type, nframes_t target_frame)
{
@@ -161,7 +140,7 @@ Session::merge_event (Event* ev)
for (Events::iterator i = events.begin(); i != events.end(); ++i) {
if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
error << string_compose(_("Session: cannot have two events of type %1 at the same frame (%2)."),
- event_names[ev->type], ev->action_frame) << endmsg;
+ enum_2_string (ev->type), ev->action_frame) << endmsg;
return;
}
}
@@ -321,7 +300,7 @@ Session::process_event (Event* ev)
switch (ev->type) {
case Event::SetLoop:
- set_play_loop (ev->yes_or_no, (ev->speed == 1.0f));
+ set_play_loop (ev->yes_or_no);
break;
case Event::AutoLoop:
@@ -362,7 +341,7 @@ Session::process_event (Event* ev)
case Event::SetTransportSpeed:
- set_transport_speed (ev->speed, ev->yes_or_no);
+ set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
break;
case Event::PunchIn:
@@ -425,17 +404,12 @@ Session::process_event (Event* ev)
break;
case Event::InputConfigurationChange:
- post_transport_work = PostTransportWork (post_transport_work | PostTransportInputChange);
+ add_post_transport_work (PostTransportInputChange);
_butler->schedule_transport_work ();
break;
- case Event::SetAudioRange:
- current_audio_range = ev->audio_range;
- setup_auto_play ();
- break;
-
- case Event::SetPlayRange:
- set_play_range (ev->yes_or_no, (ev->speed == 1.0f));
+ case Event::SetPlayAudioRange:
+ set_play_range (ev->audio_range, (ev->speed == 1.0f));
break;
default:
diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc
index 3eda11bab7..0bf87591cd 100644
--- a/libs/ardour/session_export.cc
+++ b/libs/ardour/session_export.cc
@@ -210,7 +210,7 @@ Session::stop_audio_export ()
stuff that stop_transport() implements.
*/
- realtime_stop (true);
+ realtime_stop (true, true);
_butler->schedule_transport_work ();
if (!export_status->aborted()) {
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index ea63e71307..4bbe852687 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -480,7 +480,7 @@ bool
Session::follow_slave (nframes_t nframes)
{
double slave_speed;
- nframes_t slave_transport_frame;
+ nframes64_t slave_transport_frame;
nframes_t this_delta;
int dir;
bool starting;
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index f60cf8e85f..1a4758186e 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -197,11 +197,10 @@ Session::first_stage_init (string fullpath, string snapshot_name)
_worst_input_latency = 0;
_worst_track_latency = 0;
_state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
-
+ _was_seamless = Config->get_seamless_loop ();
_slave = 0;
session_send_mmc = false;
session_send_mtc = false;
- post_transport_work = PostTransportWork (0);
g_atomic_int_set (&_playback_load, 100);
g_atomic_int_set (&_capture_load, 100);
g_atomic_int_set (&_playback_load_min, 100);
diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc
index 9a6eebbaf8..1e1ecd3ed9 100644
--- a/libs/ardour/session_time.cc
+++ b/libs/ardour/session_time.cc
@@ -452,7 +452,7 @@ Session::jack_sync_callback (jack_transport_state_t state,
switch (state) {
case JackTransportStopped:
- if (slave && _transport_frame != pos->frame && post_transport_work == 0) {
+ if (slave && _transport_frame != pos->frame && post_transport_work() == 0) {
request_locate (pos->frame, false);
// cerr << "SYNC: stopped, locate to " << pos->frame << " from " << _transport_frame << endl;
return false;
@@ -461,9 +461,9 @@ Session::jack_sync_callback (jack_transport_state_t state,
}
case JackTransportStarting:
- // cerr << "SYNC: starting @ " << pos->frame << " a@ " << _transport_frame << " our work = " << post_transport_work << " pos matches ? " << (_transport_frame == pos->frame) << endl;
+ // cerr << "SYNC: starting @ " << pos->frame << " a@ " << _transport_frame << " our work = " << post_transport_work() << " pos matches ? " << (_transport_frame == pos->frame) << endl;
if (slave) {
- return _transport_frame == pos->frame && post_transport_work == 0;
+ return _transport_frame == pos->frame && post_transport_work() == 0;
} else {
return true;
}
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 16ba54a369..10429e9639 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -51,6 +51,25 @@ using namespace sigc;
using namespace PBD;
void
+Session::add_post_transport_work (PostTransportWork ptw)
+{
+ PostTransportWork oldval;
+ PostTransportWork newval;
+ int tries = 0;
+
+ while (tries < 8) {
+ oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
+ newval = PostTransportWork (oldval | ptw);
+ if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
+ /* success */
+ return;
+ }
+ }
+
+ error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
+}
+
+void
Session::request_input_change_handling ()
{
if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
@@ -63,12 +82,21 @@ void
Session::request_slave_source (SlaveSource src)
{
Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, 0, 0.0);
+ bool seamless;
+
+ seamless = Config->get_seamless_loop ();
if (src == JACK) {
- /* could set_seamless_loop() be disposed of entirely?*/
+ /* JACK cannot support seamless looping at present */
Config->set_seamless_loop (false);
+ } else {
+ /* reset to whatever the value was before we last switched slaves */
+ Config->set_seamless_loop (_was_seamless);
}
+ /* save value of seamless from before the switch */
+ _was_seamless = seamless;
+
ev->slave = src;
queue_event (ev);
}
@@ -89,9 +117,9 @@ Session::request_diskstream_speed (Diskstream& ds, double speed)
}
void
-Session::request_stop (bool abort)
+Session::request_stop (bool abort, bool clear_state)
{
- Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
+ Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort, clear_state);
queue_event (ev);
}
@@ -103,7 +131,7 @@ Session::request_locate (nframes_t target_frame, bool with_roll)
}
void
-Session::force_locate (nframes_t target_frame, bool with_roll)
+Session::force_locate (nframes64_t target_frame, bool with_roll)
{
Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
queue_event (ev);
@@ -132,8 +160,22 @@ Session::request_play_loop (bool yn, bool leave_rolling)
}
void
-Session::realtime_stop (bool abort)
+Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
+{
+ Event* ev = new Event (Event::SetPlayAudioRange, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
+ if (range) {
+ ev->audio_range = *range;
+ } else {
+ ev->audio_range.clear ();
+ }
+ queue_event (ev);
+}
+
+void
+Session::realtime_stop (bool abort, bool clear_state)
{
+ PostTransportWork todo = PostTransportWork (0);
+
/* assume that when we start, we'll be moving forwards */
// FIXME: where should this really be? [DR]
@@ -142,9 +184,9 @@ Session::realtime_stop (bool abort)
deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
if (_transport_speed < 0.0f) {
- post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
+ todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
} else {
- post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
+ todo = PostTransportWork (todo | PostTransportStop);
}
if (actively_recording()) {
@@ -158,11 +200,19 @@ Session::realtime_stop (bool abort)
/* the duration change is not guaranteed to have happened, but is likely */
- post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
+ todo = PostTransportWork (todo | PostTransportDuration);
}
if (abort) {
- post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
+ todo = PostTransportWork (todo | PostTransportAbort);
+ }
+
+ if (clear_state) {
+ todo = PostTransportWork (todo | PostTransportClearSubstate);
+ }
+
+ if (todo) {
+ add_post_transport_work (todo);
}
_clear_event_type (Event::StopOnce);
@@ -188,29 +238,30 @@ Session::butler_transport_work ()
{
restart:
bool finished;
+ PostTransportWork ptw;
boost::shared_ptr<RouteList> r = routes.reader ();
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
finished = true;
-
- if (post_transport_work & PostTransportCurveRealloc) {
+ ptw = post_transport_work();
+ if (ptw & PostTransportCurveRealloc) {
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->curve_reallocate();
}
}
- if (post_transport_work & PostTransportInputChange) {
+ if (ptw & PostTransportInputChange) {
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->non_realtime_input_change ();
}
}
- if (post_transport_work & PostTransportSpeed) {
+ if (ptw & PostTransportSpeed) {
non_realtime_set_speed ();
}
- if (post_transport_work & PostTransportReverse) {
+ if (ptw & PostTransportReverse) {
clear_clicks();
cumulative_rf_motion = 0;
@@ -218,7 +269,7 @@ Session::butler_transport_work ()
/* don't seek if locate will take care of that in non_realtime_stop() */
- if (!(post_transport_work & PostTransportLocate)) {
+ if (!(ptw & PostTransportLocate)) {
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
@@ -233,19 +284,19 @@ Session::butler_transport_work ()
}
}
- if (post_transport_work & PostTransportLocate) {
+ if (ptw & PostTransportLocate) {
non_realtime_locate ();
}
- if (post_transport_work & PostTransportStop) {
- non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
+ if (ptw & PostTransportStop) {
+ non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
if (!finished) {
g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
goto restart;
}
}
- if (post_transport_work & PostTransportOverWrite) {
+ if (ptw & PostTransportOverWrite) {
non_realtime_overwrite (on_entry, finished);
if (!finished) {
g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
@@ -253,7 +304,7 @@ Session::butler_transport_work ()
}
}
- if (post_transport_work & PostTransportAudition) {
+ if (ptw & PostTransportAudition) {
non_realtime_set_audition ();
}
@@ -305,6 +356,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
time_t xnow;
bool did_record;
bool saved;
+ PostTransportWork ptw = post_transport_work();
did_record = false;
saved = false;
@@ -390,7 +442,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
(Config->get_slave_source() == None && config.get_auto_return());
if (auto_return_enabled ||
- (post_transport_work & PostTransportLocate) ||
+ (ptw & PostTransportLocate) ||
(_requested_return_frame >= 0) ||
synced_to_jack()) {
@@ -399,7 +451,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
}
if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
- !(post_transport_work & PostTransportLocate)) {
+ !(ptw & PostTransportLocate)) {
/* no explicit locate queued */
@@ -461,6 +513,14 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
}
+ /* do this before seeking, because otherwise the Diskstreams will do the wrong thing in seamless loop mode.
+ */
+
+ if (ptw & PostTransportClearSubstate) {
+ _play_range = false;
+ unset_play_loop ();
+ }
+
/* this for() block can be put inside the previous if() and has the effect of ... ??? what */
@@ -481,24 +541,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
deliver_mmc (MIDI::MachineControl::cmdStop, 0);
deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
- if (did_record) {
-
- /* XXX its a little odd that we're doing this here
- when realtime_stop(), which has already executed,
- will have done this.
- JLC - so let's not because it seems unnecessary and breaks loop record
- */
-#if 0
- if (!Config->get_latched_record_enable()) {
- g_atomic_int_set (&_record_status, Disabled);
- } else {
- g_atomic_int_set (&_record_status, Enabled);
- }
- RecordStateChanged (); /* emit signal */
-#endif
- }
-
- if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
+ if ((ptw & PostTransportLocate) && get_record_enabled()) {
/* capture start has been changed, so save pending state */
save_state ("", true);
saved = true;
@@ -514,23 +557,21 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
save_state (_current_snapshot_name);
}
- if (post_transport_work & PostTransportDuration) {
+ if (ptw & PostTransportDuration) {
DurationChanged (); /* EMIT SIGNAL */
}
- if (post_transport_work & PostTransportStop) {
+ if (ptw & PostTransportStop) {
_play_range = false;
play_loop = false;
}
- nframes_t tf = _transport_frame;
-
- PositionChanged (tf); /* EMIT SIGNAL */
+ PositionChanged ((nframes64_t) _transport_frame); /* EMIT SIGNAL */
TransportStateChange (); /* EMIT SIGNAL */
/* and start it up again if relevant */
- if ((post_transport_work & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
+ if ((ptw & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
request_transport_speed (1.0);
pending_locate_roll = false;
}
@@ -561,35 +602,48 @@ Session::check_declick_out ()
}
void
-Session::set_play_loop (bool yn, bool leave_rolling)
+Session::unset_play_loop ()
+{
+ play_loop = false;
+ clear_events (Event::AutoLoop);
+
+ // set all diskstreams to NOT use internal looping
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
+ if (!(*i)->hidden()) {
+ (*i)->set_loop (0);
+ }
+ }
+}
+
+void
+Session::set_play_loop (bool yn)
{
/* Called from event-handling context */
Location *loc;
- if (yn == play_loop) {
- return;
- }
-
- if ((actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
+ if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
+ /* nothing to do, or can't change loop status while recording */
return;
}
-
+
set_dirty();
-
+
if (yn && Config->get_seamless_loop() && synced_to_jack()) {
warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
"Recommend changing the configured options")
<< endmsg;
return;
}
+
+ if (yn) {
-
- if ((play_loop = yn)) {
+ play_loop = true;
if (loc) {
- set_play_range (false, true);
+ unset_play_range ();
if (Config->get_seamless_loop()) {
// set all diskstreams to use internal looping
@@ -609,34 +663,26 @@ Session::set_play_loop (bool yn, bool leave_rolling)
}
}
}
-
- /* stick in the loop event */
-
+
+ /* put the loop event into the event list */
+
Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
merge_event (event);
-
- // locate to start of loop and roll
- event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
- merge_event (event);
- }
+ /* locate to start of loop and roll. If doing seamless loop, force a
+ locate+buffer refill even if we are positioned there already.
+ */
+ start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
+ }
} else {
- clear_events (Event::AutoLoop);
-
- // set all diskstreams to NOT use internal looping
- boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
- if (!(*i)->hidden()) {
- (*i)->set_loop (0);
- }
- }
+ unset_play_loop ();
}
- TransportStateChange (); /* EMIT SIGNAL */
-}
+ TransportStateChange ();
+}
void
Session::flush_all_inserts ()
{
@@ -648,12 +694,12 @@ Session::flush_all_inserts ()
}
void
-Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
+Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
{
if (synced_to_jack()) {
double sp;
- nframes_t pos;
+ nframes64_t pos;
_slave->speed_and_position (sp, pos);
@@ -672,7 +718,7 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush,
}
} else {
- locate (target_frame, with_roll, with_flush, with_loop);
+ locate (target_frame, with_roll, with_flush, with_loop, force);
}
}
@@ -696,13 +742,13 @@ Session::micro_locate (nframes_t distance)
}
void
-Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
+Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
{
if (actively_recording() && !with_loop) {
return;
}
- if (_transport_frame == target_frame && !loop_changing && !with_loop) {
+ if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
if (with_roll) {
set_transport_speed (1.0, false);
}
@@ -730,17 +776,18 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
}
if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
- realtime_stop (false);
+ realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
}
- if ( !with_loop || loop_changing) {
+ if (force || !with_loop || loop_changing) {
- post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
+ PostTransportWork todo = PostTransportLocate;
if (with_roll) {
- post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
- }
+ todo = PostTransportWork (todo | PostTransportRoll);
+ }
+ add_post_transport_work (todo);
_butler->schedule_transport_work ();
} else {
@@ -792,7 +839,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
// cancel looping directly, this is called from event handling context
- set_play_loop (false, false);
+ set_play_loop (false);
}
else if (al && _transport_frame == al->start()) {
if (with_loop) {
@@ -824,7 +871,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
* @param abort
*/
void
-Session::set_transport_speed (double speed, bool abort)
+Session::set_transport_speed (double speed, bool abort, bool clear_state)
{
if (_transport_speed == speed) {
return;
@@ -859,6 +906,13 @@ Session::set_transport_speed (double speed, bool abort)
}
if (synced_to_jack ()) {
+ if (clear_state) {
+ /* do this here because our response to the slave won't
+ take care of it.
+ */
+ _play_range = false;
+ unset_play_loop ();
+ }
_engine.transport_stop ();
} else {
stop_transport (abort);
@@ -919,9 +973,11 @@ Session::set_transport_speed (double speed, bool abort)
/* if we are reversing relative to the current speed, or relative to the speed
before the last stop, then we have to do extra work.
*/
+
+ PostTransportWork todo = PostTransportWork (0);
if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
- post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
+ todo = PostTransportWork (todo | PostTransportReverse);
}
_last_transport_speed = _transport_speed;
@@ -930,11 +986,13 @@ Session::set_transport_speed (double speed, bool abort)
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
- post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
+ todo = PostTransportWork (todo | PostTransportSpeed);
+ break;
}
}
- if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
+ if (todo) {
+ add_post_transport_work (todo);
_butler->schedule_transport_work ();
}
}
@@ -943,7 +1001,7 @@ Session::set_transport_speed (double speed, bool abort)
/** Stop the transport. */
void
-Session::stop_transport (bool abort)
+Session::stop_transport (bool abort, bool clear_state)
{
if (_transport_speed == 0.0f) {
return;
@@ -979,7 +1037,7 @@ Session::stop_transport (bool abort)
return;
}
- realtime_stop (abort);
+ realtime_stop (abort, clear_state);
_butler->schedule_transport_work ();
}
@@ -1031,7 +1089,9 @@ Session::start_transport ()
void
Session::post_transport ()
{
- if (post_transport_work & PostTransportAudition) {
+ PostTransportWork ptw = post_transport_work ();
+
+ if (ptw & PostTransportAudition) {
if (auditioner && auditioner->active()) {
process_function = &Session::process_audition;
} else {
@@ -1039,14 +1099,14 @@ Session::post_transport ()
}
}
- if (post_transport_work & PostTransportStop) {
+ if (ptw & PostTransportStop) {
transport_sub_state = 0;
}
- if (post_transport_work & PostTransportLocate) {
+ if (ptw & PostTransportLocate) {
- if (((Config->get_slave_source() == None && (auto_play_legal && config.get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
+ if (((Config->get_slave_source() == None && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
start_transport ();
} else {
@@ -1055,8 +1115,10 @@ Session::post_transport ()
}
set_next_event ();
-
- post_transport_work = PostTransportWork (0);
+ /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
+ know were handled ?
+ */
+ set_post_transport_work (PostTransportWork (0));
}
void
@@ -1161,7 +1223,7 @@ Session::set_slave_source (SlaveSource src)
}
if (non_rt_required) {
- post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
+ add_post_transport_work (PostTransportSpeed);
_butler->schedule_transport_work ();
}
@@ -1171,7 +1233,7 @@ Session::set_slave_source (SlaveSource src)
void
Session::reverse_diskstream_buffers ()
{
- post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
+ add_post_transport_work (PostTransportReverse);
_butler->schedule_transport_work ();
}
@@ -1179,124 +1241,113 @@ void
Session::set_diskstream_speed (Diskstream* stream, double speed)
{
if (stream->realtime_set_speed (speed, false)) {
- post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
+ add_post_transport_work (PostTransportSpeed);
_butler->schedule_transport_work ();
set_dirty ();
}
}
void
-Session::set_audio_range (list<AudioRange>& range)
-{
- Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
- ev->audio_range = range;
- queue_event (ev);
-}
-
-void
-Session::request_play_range (bool yn, bool leave_rolling)
-{
- Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0f : 0.0f), yn);
- queue_event (ev);
-}
-
-void
-Session::set_play_range (bool yn, bool leave_rolling)
+Session::unset_play_range ()
{
- /* Called from event-processing context */
-
- if (yn) {
- /* cancel loop play */
- set_play_range (false, true);
- }
-
- _play_range = yn;
- setup_auto_play ();
-
-
- if (!_play_range && !leave_rolling) {
- /* stop transport */
- Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
- merge_event (ev);
- }
- TransportStateChange (); /* EMIT SIGNAL */
+ _play_range = false;
+ _clear_event_type (Event::RangeStop);
+ _clear_event_type (Event::RangeLocate);
}
void
-Session::setup_auto_play ()
+Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
{
- /* Called from event-processing context */
-
Event* ev;
- _clear_event_type (Event::RangeStop);
- _clear_event_type (Event::RangeLocate);
+ /* Called from event-processing context */
- if (!_play_range) {
+ unset_play_range ();
+
+ if (range.empty()) {
+ /* _play_range set to false in unset_play_range()
+ */
+ if (!leave_rolling) {
+ /* stop transport */
+ Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
+ merge_event (ev);
+ }
return;
}
- list<AudioRange>::size_type sz = current_audio_range.size();
+ _play_range = true;
- if (sz > 1) {
+ /* cancel loop play */
+ unset_play_loop ();
- list<AudioRange>::iterator i = current_audio_range.begin();
+ list<AudioRange>::size_type sz = range.size();
+
+ if (sz > 1) {
+
+ list<AudioRange>::iterator i = range.begin();
list<AudioRange>::iterator next;
-
- while (i != current_audio_range.end()) {
-
+
+ while (i != range.end()) {
+
next = i;
++next;
-
+
/* locating/stopping is subject to delays for declicking.
*/
-
+
nframes_t requested_frame = (*i).end;
-
+
if (requested_frame > current_block_size) {
requested_frame -= current_block_size;
} else {
requested_frame = 0;
}
-
- if (next == current_audio_range.end()) {
+
+ if (next == range.end()) {
ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
} else {
ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
}
-
+
merge_event (ev);
-
+
i = next;
}
-
+
} else if (sz == 1) {
- ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
+ ev = new Event (Event::RangeStop, Event::Add, range.front().end, 0, 0.0f);
merge_event (ev);
+
+ }
- }
+ /* save range so we can do auto-return etc. */
+
+ current_audio_range = range;
/* now start rolling at the right place */
- ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
+ ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, range.front().start, 0.0f, false);
merge_event (ev);
+
+ TransportStateChange ();
}
void
-Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
+Session::request_bounded_roll (nframes_t start, nframes_t end)
{
- Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0);
- ev->target2_frame = start;
- queue_event (ev);
-}
+ AudioRange ar (start, end, 0);
+ list<AudioRange> lar;
+ lar.push_back (ar);
+ request_play_range (&lar, true);
+}
void
-Session::request_bounded_roll (nframes_t start, nframes_t end)
+Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
{
- Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0);
+ Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0);
+ ev->target2_frame = start;
queue_event (ev);
- request_locate (start, true);
}
void
@@ -1312,10 +1363,10 @@ Session::engine_halted ()
*/
g_atomic_int_set (&_butler->should_do_transport_work, 0);
- post_transport_work = PostTransportWork (0);
+ set_post_transport_work (PostTransportWork (0));
_butler->stop ();
- realtime_stop (false);
+ realtime_stop (false, true);
non_realtime_stop (false, 0, ignored);
transport_sub_state = 0;
@@ -1326,7 +1377,7 @@ Session::engine_halted ()
void
Session::xrun_recovery ()
{
- Xrun (transport_frame()); //EMIT SIGNAL
+ Xrun ((nframes64_t)_transport_frame); //EMIT SIGNAL
if (Config->get_stop_recording_on_xrun() && actively_recording()) {
@@ -1342,12 +1393,14 @@ void
Session::update_latency_compensation (bool with_stop, bool abort)
{
bool update_jack = false;
+ PostTransportWork ptw;
if (_state_of_the_state & Deletion) {
return;
}
_worst_track_latency = 0;
+ ptw = post_transport_work();
#undef DEBUG_LATENCY
#ifdef DEBUG_LATENCY
@@ -1359,8 +1412,7 @@ Session::update_latency_compensation (bool with_stop, bool abort)
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (with_stop) {
- (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
- (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
+ (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
}
nframes_t old_latency = (*i)->output()->signal_latency ();
diff --git a/libs/ardour/slave.cc b/libs/ardour/slave.cc
index f07ea4c872..be88fe223c 100644
--- a/libs/ardour/slave.cc
+++ b/libs/ardour/slave.cc
@@ -35,13 +35,13 @@ SlaveSessionProxy::frame_rate() const
return session.frame_rate();
}
-nframes_t
+nframes64_t
SlaveSessionProxy::audible_frame() const
{
return session.audible_frame();
}
-nframes_t
+nframes64_t
SlaveSessionProxy::transport_frame() const
{
return session.transport_frame();
@@ -53,14 +53,14 @@ SlaveSessionProxy::frames_since_cycle_start() const
return session.engine().frames_since_cycle_start();
}
-nframes_t
+nframes64_t
SlaveSessionProxy::frame_time() const
{
return session.engine().frame_time();
}
void
-SlaveSessionProxy::request_locate(nframes_t frame, bool with_roll)
+SlaveSessionProxy::request_locate(nframes64_t frame, bool with_roll)
{
session.request_locate(frame, with_roll);
}