summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-11-06 22:43:47 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-11-06 22:43:47 +0000
commit8bb5605dfc48a9578164e820fb866f0e7881d899 (patch)
tree29171e531c26a0a79513f0b6f06d95d9ce05c494
parentc3e7746e367b5b461f0577b548c9e29854bdde06 (diff)
deep, somewhat subtle changes for transport control. Everything should use Session::request_stop(), which nows takes an additional argument indicating whether or not to clear play range/loop state. UI threads will generally do so, other things, like slave sync objects, generally will not. also fixed stupid delay on exit, caused by unconditional usleep (2.5 seconds) ...
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@6027 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/ardour_ui.cc20
-rw-r--r--gtk2_ardour/ardour_ui2.cc2
-rw-r--r--gtk2_ardour/editor_mouse.cc4
-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
12 files changed, 111 insertions, 75 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 4bbd7c5429..834c329793 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -729,9 +729,11 @@ ARDOUR_UI::finish()
{
if (session) {
- if (session->transport_rolling()) {
- session->request_stop ();
- usleep (2500000);
+ int tries = 0;
+
+ while (session->transport_rolling() && (++tries < 8)) {
+ session->request_stop (true, false);
+ usleep (10000);
}
if (session->dirty()) {
@@ -1398,14 +1400,14 @@ ARDOUR_UI::transport_stop ()
return;
}
- session->request_stop ();
+ session->request_stop (false, true);
}
void
ARDOUR_UI::transport_stop_and_forget_capture ()
{
if (session) {
- session->request_stop (true);
+ session->request_stop (true, true);
}
}
@@ -1473,9 +1475,10 @@ ARDOUR_UI::transport_roll ()
if (session->get_play_loop()) {
/* XXX it is not possible to just leave seamless loop and keep
- playing at present (nov 4th 2009
+ playing at present (nov 4th 2009)
*/
if (!Config->get_seamless_loop()) {
+ /* off, and stop */
session->request_play_loop (false, true);
} else {
return;
@@ -1534,12 +1537,11 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
affect_transport = false;
session->request_play_range (false, true);
}
- }
+ }
if (affect_transport) {
-
if (rolling) {
- session->request_stop (with_abort);
+ session->request_stop (with_abort, true);
} else {
session->request_transport_speed (1.0f);
}
diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc
index e58b9d6a09..ac6f3e7413 100644
--- a/gtk2_ardour/ardour_ui2.cc
+++ b/gtk2_ardour/ardour_ui2.cc
@@ -637,7 +637,7 @@ ARDOUR_UI::shuttle_box_button_release (GdkEventButton* ev)
roll_button.set_visual_state (1);
} else {
shuttle_fract = 0;
- session->request_transport_speed (0.0);
+ session->request_stop ();
}
shuttle_box.queue_draw ();
}
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index 490112d430..3fd7e09afc 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -1191,7 +1191,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
}
} else {
/* make sure we stop */
- session->request_transport_speed (0.0);
+ session->request_stop ();
}
break;
@@ -2247,7 +2247,7 @@ Editor::start_cursor_grab (ArdourCanvas::Item* item, GdkEvent* event)
_dragging_playhead = true;
if (session && drag_info.was_rolling) {
- session->request_stop ();
+ session->request_stop (false, true);
}
if (session && session->is_auditioning()) {
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;