summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/session.h45
-rw-r--r--libs/ardour/audioengine.cc2
-rw-r--r--libs/ardour/mtc_slave.cc8
-rw-r--r--libs/ardour/session_events.cc4
-rw-r--r--libs/ardour/session_export.cc2
-rw-r--r--libs/ardour/session_midi.cc3
-rw-r--r--libs/ardour/session_process.cc3
-rw-r--r--libs/ardour/session_state.cc2
-rw-r--r--libs/ardour/session_transport.cc91
9 files changed, 97 insertions, 63 deletions
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 31a744383d..50ca7a91fe 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -160,24 +160,29 @@ class Session : public PBD::StatefulDestructible
float speed;
union {
- void* ptr;
- bool yes_or_no;
- nframes_t target2_frame;
- SlaveSource slave;
+ void* ptr;
+ bool yes_or_no;
+ nframes_t target2_frame;
+ SlaveSource slave;
};
+ union {
+ bool second_yes_or_no;
+ };
+
boost::shared_ptr<Region> region;
list<AudioRange> audio_range;
list<MusicRange> music_range;
- Event(Type t, Action a, nframes_t when, nframes_t where, float spd, bool yn = false)
- : type (t),
- action (a),
- action_frame (when),
- target_frame (where),
- speed (spd),
- yes_or_no (yn) {}
+ Event(Type t, Action a, nframes_t when, nframes_t where, float 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;
@@ -371,9 +376,9 @@ class Session : public PBD::StatefulDestructible
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 clear_state = true, bool abort = false);
void request_locate (nframes_t frame, bool with_roll = false);
-
+ void request_transport_speed (float speed);
void request_play_loop (bool yn, bool leave_rolling = false);
bool get_play_loop () const { return play_loop; }
@@ -384,7 +389,6 @@ class Session : public PBD::StatefulDestructible
void set_session_end (nframes_t end) { end_location->set_start(end); _end_location_is_free = false; }
void use_rf_shuttle_speed ();
void allow_auto_play (bool yn);
- void request_transport_speed (float speed);
void request_overwrite_buffer (Diskstream*);
void request_diskstream_speed (Diskstream&, float speed);
void request_input_change_handling ();
@@ -1179,6 +1183,7 @@ class Session : public PBD::StatefulDestructible
bool pending_locate_flush;
bool pending_abort;
+ bool pending_clear_substate;
bool pending_auto_loop;
pthread_t butler_thread;
@@ -1214,7 +1219,8 @@ class Session : public PBD::StatefulDestructible
PostTransportScrub = 0x8000,
PostTransportReverse = 0x10000,
PostTransportInputChange = 0x20000,
- PostTransportCurveRealloc = 0x40000
+ PostTransportCurveRealloc = 0x40000,
+ PostTransportClearSubstate = 0x80000
};
static const PostTransportWork ProcessCannotProceedMask =
@@ -1225,7 +1231,8 @@ class Session : public PBD::StatefulDestructible
PostTransportScrub|
PostTransportAudition|
PostTransportLocate|
- PostTransportStop);
+ PostTransportStop|
+ PostTransportClearSubstate);
PostTransportWork post_transport_work;
@@ -1457,10 +1464,10 @@ class Session : public PBD::StatefulDestructible
void start_locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false);
void force_locate (nframes_t frame, bool with_roll = false);
void set_diskstream_speed (Diskstream*, float speed);
- void set_transport_speed (float speed, bool abort = false);
- void stop_transport (bool abort = false);
+ void set_transport_speed (float 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_stop (bool abort, int entry_request_count, bool& finished);
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index ae8d7bf5f5..298eb8fa8d 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -962,6 +962,7 @@ void
AudioEngine::transport_stop ()
{
GET_PRIVATE_JACK_POINTER (_jack);
+ // cerr << "tell jack to stop\n";
jack_transport_stop (_priv_jack);
}
@@ -969,6 +970,7 @@ void
AudioEngine::transport_start ()
{
GET_PRIVATE_JACK_POINTER (_jack);
+ // cerr << "tell jack to roll\n";
jack_transport_start (_priv_jack);
}
diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc
index db7e1d5c84..9d54f847fc 100644
--- a/libs/ardour/mtc_slave.cc
+++ b/libs/ardour/mtc_slave.cc
@@ -143,7 +143,9 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
current.guard2++;
session.request_locate (mtc_frame, false);
- session.request_transport_speed (0);
+ // don't ask for "clear state on stop" because its not revelant when slaved to MTC - we can't
+ // be in looping/range play states anyway.
+ session.request_stop ();
update_mtc_status (MIDI::Parser::MTC_Stopped);
reset ();
@@ -279,7 +281,9 @@ MTC_Slave::speed_and_position (float& speed, nframes_t& pos)
mtc_speed = 0;
pos = last.position;
session.request_locate (pos, false);
- session.request_transport_speed (0);
+ // don't ask for "clear state on stop" because its not revelant when slaved to MTC - we can't
+ // be in looping/range play states anyway.
+ session.request_stop ();
update_mtc_status (MIDI::Parser::MTC_Stopped);
reset();
return false;
diff --git a/libs/ardour/session_events.cc b/libs/ardour/session_events.cc
index d818b0b254..fe5f08fa03 100644
--- a/libs/ardour/session_events.cc
+++ b/libs/ardour/session_events.cc
@@ -359,7 +359,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:
@@ -382,7 +382,7 @@ Session::process_event (Event* ev)
case Event::StopOnce:
if (!non_realtime_work_pending()) {
- stop_transport (ev->yes_or_no);
+ set_transport_speed (0.0, ev->yes_or_no, ev->second_yes_or_no);
_clear_event_type (Event::StopOnce);
}
remove = false;
diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc
index e7c2596fe1..15c778b2bd 100644
--- a/libs/ardour/session_export.cc
+++ b/libs/ardour/session_export.cc
@@ -677,7 +677,7 @@ Session::finalize_audio_export ()
stuff that stop_transport() implements.
*/
- realtime_stop (true);
+ realtime_stop (true, true);
schedule_butler_transport_work ();
/* restart slaving */
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index 1f0e08578f..8ad5896eba 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -994,7 +994,8 @@ Session::mmc_step_timeout ()
if (diff_usecs > 1000000.0 || fabs (_transport_speed) < 0.0000001) {
/* too long or too slow, stop transport */
- request_transport_speed (0.0);
+ // don't ask for "clear state on stop". We are just stationary, not stopped
+ request_stop ();
step_queued = false;
return false;
}
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 347356a7f4..a6b3b6dd4a 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -550,7 +550,8 @@ Session::follow_slave (nframes_t nframes)
Location* al = _locations.auto_loop_location();
if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
- // cancel looping
+ // master has moved outside the loop: stop looping
+ cerr << "Stop looping - master out of range\n";
request_play_loop(false);
}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index fe465462fb..0abe1b652e 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -142,6 +142,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
_tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
g_atomic_int_set (&processing_prohibited, 0);
+ post_transport_work = PostTransportWork (0);
insert_cnt = 0;
_transport_speed = 0;
_last_transport_speed = 0;
@@ -194,6 +195,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
_pan_automation_buffer = 0;
_npan_buffers = 0;
pending_abort = false;
+ pending_clear_substate = false;
destructive_index = 0;
current_trans = 0;
first_file_data_format_reset = true;
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 7c2eba1a61..41b4bcd0a6 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -97,9 +97,9 @@ Session::request_diskstream_speed (Diskstream& ds, float 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);
}
@@ -140,14 +140,23 @@ Session::request_play_loop (bool yn, bool leave_rolling)
}
void
-Session::realtime_stop (bool abort)
+Session::request_play_range (bool yn, bool leave_rolling)
+{
+ Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
+ 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 */
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()) {
@@ -163,13 +172,21 @@ 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) {
+ post_transport_work = PostTransportWork (post_transport_work | todo);
+ }
+
_clear_event_type (Event::StopOnce);
_clear_event_type (Event::RangeStop);
_clear_event_type (Event::RangeLocate);
@@ -451,11 +468,10 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
}
- /* unconditionally reset these flags. if play_loop is still true then Diskstream::seek() will do
- the wrong thing in seamless loop mode.
+ /* do this before seeking, because otherwise the Diskstreams will do the wrong thing in seamless loop mode.
*/
- if (post_transport_work & PostTransportStop) {
+ if (post_transport_work & PostTransportClearSubstate) {
_play_range = false;
unset_play_loop ();
}
@@ -552,7 +568,7 @@ Session::check_declick_out ()
start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
} else {
- stop_transport (pending_abort);
+ stop_transport (pending_abort, pending_clear_substate);
transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
}
}
@@ -580,11 +596,8 @@ Session::set_play_loop (bool yn)
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;
}
@@ -671,11 +684,10 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush,
*/
_engine.transport_locate (target_frame);
+ }
- if (sp != 1.0f && with_roll) {
- _engine.transport_start ();
- }
-
+ if (sp != 1.0f && with_roll) {
+ _engine.transport_start ();
}
} else {
@@ -737,7 +749,7 @@ 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 (force || !with_loop || loop_changing) {
@@ -825,7 +837,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
}
void
-Session::set_transport_speed (float speed, bool abort)
+Session::set_transport_speed (float speed, bool abort, bool clear_state)
{
if (_transport_speed == speed) {
return;
@@ -852,9 +864,16 @@ Session::set_transport_speed (float 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);
+ stop_transport (abort, clear_state);
}
} else if (transport_stopped() && speed == 1.0) {
@@ -911,8 +930,10 @@ Session::set_transport_speed (float speed, bool abort)
before the last stop, then we have to do extra work.
*/
+ PostTransportWork todo = PostTransportWork (0);
+
if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
- post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
+ todo = PostTransportWork (todo | PostTransportReverse);
last_stop_frame = _transport_frame;
}
@@ -922,18 +943,20 @@ Session::set_transport_speed (float 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) {
+ post_transport_work = PostTransportWork (post_transport_work | todo);
schedule_butler_transport_work ();
}
}
}
void
-Session::stop_transport (bool abort)
+Session::stop_transport (bool abort, bool clear_state)
{
if (_transport_speed == 0.0f) {
return;
@@ -958,18 +981,19 @@ Session::stop_transport (bool abort)
merge_event (ev);
transport_sub_state |= StopPendingCapture;
pending_abort = abort;
+ pending_clear_substate = clear_state;
return;
}
-
if ((transport_sub_state & PendingDeclickOut) == 0) {
transport_sub_state |= PendingDeclickOut;
/* we'll be called again after the declick */
pending_abort = abort;
+ pending_clear_substate = clear_state;
return;
}
- realtime_stop (abort);
+ realtime_stop (abort, clear_state);
schedule_butler_transport_work ();
}
@@ -1168,13 +1192,6 @@ Session::set_audio_range (list<AudioRange>& range)
}
void
-Session::request_play_range (bool yn, bool leave_rolling)
-{
- Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
- queue_event (ev);
-}
-
-void
Session::set_play_range (bool yn, bool leave_rolling)
{
/* Called from event-processing context */
@@ -1291,7 +1308,7 @@ Session::engine_halted ()
post_transport_work = PostTransportWork (0);
stop_butler ();
- realtime_stop (false);
+ realtime_stop (false, true);
non_realtime_stop (false, 0, ignored);
transport_sub_state = 0;