summaryrefslogtreecommitdiff
path: root/libs/ardour/transport_fsm.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2019-10-29 16:15:38 -0600
committerPaul Davis <paul@linuxaudiosystems.com>2019-10-29 16:20:04 -0600
commitc368c26519d05815e9bfadbd02f9de5f5d84321c (patch)
tree8a5ddd08e2de433332cb1c68a9d8bb864c21e807 /libs/ardour/transport_fsm.cc
parent78cf0e5235a4138cc1c118dd4c2e202320d74b21 (diff)
fix handling of deferred events in transportFSM
tfsm events live on intrusive lists, with only 1 hook, which means they can only be on one list at a time, and cannot be deleted while part of the list. This wasn't being addressed properly when deferring (and undeferring) events.
Diffstat (limited to 'libs/ardour/transport_fsm.cc')
-rw-r--r--libs/ardour/transport_fsm.cc48
1 files changed, 39 insertions, 9 deletions
diff --git a/libs/ardour/transport_fsm.cc b/libs/ardour/transport_fsm.cc
index 2fd61a3d00..c8b5c65035 100644
--- a/libs/ardour/transport_fsm.cc
+++ b/libs/ardour/transport_fsm.cc
@@ -80,7 +80,19 @@ TransportFSM::process_events ()
MotionState oms = _motion_state;
ButlerState obs = _butler_state;
- if (process_event (queued_events.front())) { /* event processed successfully */
+ Event* ev = &queued_events.front();
+ bool deferred;
+
+ /* must remove from the queued_events list now, because
+ * process_event() may defer the event. This will lead to
+ * insertion into the deferred_events list, and its not possible
+ * with intrusive lists to be present in two lists at once
+ * (without additional hooks).
+ */
+
+ queued_events.pop_front ();
+
+ if (process_event (*ev, false, deferred)) { /* event processed successfully */
if (oms != _motion_state || obs != _butler_state) {
@@ -93,7 +105,8 @@ TransportFSM::process_events ()
for (EventList::iterator e = deferred_events.begin(); e != deferred_events.end(); ) {
Event* deferred_ev = &(*e);
- if (process_event (*e)) { /* event processed, remove from deferred */
+ bool deferred2;
+ if (process_event (*e, true, deferred2)) { /* event processed, remove from deferred */
e = deferred_events.erase (e);
delete deferred_ev;
} else {
@@ -104,9 +117,9 @@ TransportFSM::process_events ()
}
}
- Event* ev = &queued_events.front();
- queued_events.pop_front ();
- delete ev;
+ if (!deferred) {
+ delete ev;
+ }
}
processing--;
@@ -178,10 +191,12 @@ TransportFSM::bad_transition (Event const & ev)
}
bool
-TransportFSM::process_event (Event& ev)
+TransportFSM::process_event (Event& ev, bool already_deferred, bool& deferred)
{
DEBUG_TRACE (DEBUG::TFSMEvents, string_compose ("process %1\n", enum_2_string (ev.type)));
+ deferred = false;
+
switch (ev.type) {
case StartTransport:
@@ -194,10 +209,16 @@ TransportFSM::process_event (Event& ev)
break;
case DeclickToLocate:
case WaitingForLocate:
- defer (ev);
+ if (!already_deferred) {
+ defer (ev);
+ deferred = true;
+ }
break;
case DeclickToStop:
- defer (ev);
+ if (!already_deferred) {
+ defer (ev);
+ deferred = true;
+ }
break;
default:
bad_transition (ev); return false;
@@ -215,7 +236,10 @@ TransportFSM::process_event (Event& ev)
break;
case DeclickToLocate:
case WaitingForLocate:
- defer (ev);
+ if (!already_deferred) {
+ defer (ev);
+ deferred = true;
+ }
break;
default:
bad_transition (ev); return false;
@@ -224,6 +248,12 @@ TransportFSM::process_event (Event& ev)
break;
case Locate:
+ DEBUG_TRACE (DEBUG::TFSMEvents, string_compose ("locate, with roll = %1 flush = %2 target = %3 loop %4 force %5\n",
+ ev.with_roll,
+ ev.with_flush,
+ ev.target,
+ ev.with_loop,
+ ev.force));
switch (_motion_state) {
case Stopped:
transition (WaitingForLocate);