Skip to content

Commit cf06f37

Browse files
committed
Better support for ordered, re-entrant snapshot recall
1 parent c944458 commit cf06f37

File tree

1 file changed

+30
-5
lines changed

1 file changed

+30
-5
lines changed

src/main/java/heronarts/lx/snapshot/LXSnapshotEngine.java

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919

2020
package heronarts.lx.snapshot;
2121

22+
import java.util.ArrayDeque;
2223
import java.util.ArrayList;
2324
import java.util.Collections;
2425
import java.util.List;
2526
import java.util.Objects;
27+
import java.util.Queue;
2628

2729
import com.google.gson.JsonArray;
2830
import com.google.gson.JsonElement;
@@ -419,7 +421,7 @@ public LXGlobalSnapshot getCursorSnapshot() {
419421
return null;
420422
}
421423

422-
private List<LXSnapshot.View> recallViews = new ArrayList<>();
424+
private final List<LXSnapshot.View> recallViews = new ArrayList<>();
423425

424426
/**
425427
* Recall this snapshot, apply all of its values
@@ -431,20 +433,44 @@ public boolean recall(LXGlobalSnapshot snapshot) {
431433
return recall(snapshot, null);
432434
}
433435

436+
private boolean inRecall = false;
437+
438+
private final Queue<LXGlobalSnapshot> snapshotQueue = new ArrayDeque<>();
439+
434440
/**
435441
* Recall this snapshot, and populate an array of commands which
436442
* would need to be undone by this operation.
437443
*
438444
* @param snapshot Snapshot to recall
439445
* @param commands Array to populate with all the commands processed
440-
* @return True the snapshot was recalled, false if it was already mid-transition
446+
* @return True the snapshot was recalled, false if it was already mid-transition or another snapshot is mid-recall
441447
*/
442448
public boolean recall(LXGlobalSnapshot snapshot, List<LXCommand> commands) {
443449
if (this.inTransition == snapshot) {
444450
finishTransition();
445451
return false;
446452
}
447453

454+
// Snapshot recall may end up triggering the recall of *another* snapshot due
455+
// to modulation mappings based upon snapshot parameters values. If this occurs,
456+
// queue up the re-entrant snapshot recalls such that are all processed in the
457+
// order in which they were triggered.
458+
if (this.inRecall) {
459+
this.snapshotQueue.add(snapshot);
460+
return false;
461+
}
462+
463+
this.inRecall = true;
464+
_recall(snapshot, commands);
465+
while (!this.snapshotQueue.isEmpty()) {
466+
_recall(this.snapshotQueue.remove(), null);
467+
}
468+
this.inRecall = false;
469+
return true;
470+
}
471+
472+
private void _recall(LXGlobalSnapshot snapshot, List<LXCommand> commands) {
473+
448474
final boolean mixer = this.recallMixer.isOn();
449475
final boolean pattern = this.recallPattern.isOn();
450476
final boolean effect = this.recallEffect.isOn();
@@ -458,7 +484,8 @@ public boolean recall(LXGlobalSnapshot snapshot, List<LXCommand> commands) {
458484
commands.add(new LXCommand.Parameter.SetValue(this.autoCycleCursor, this.autoCycleCursor.getValuei()));
459485
}
460486
this.autoCycleCursor.setValue(snapshot.getIndex());
461-
this.recallViews = new ArrayList<>(snapshot.views);
487+
this.recallViews.clear();
488+
this.recallViews.addAll(snapshot.views);
462489
if (this.transitionEnabled.isOn()) {
463490
transition = true;
464491
this.inTransition = snapshot;
@@ -488,8 +515,6 @@ public boolean recall(LXGlobalSnapshot snapshot, List<LXCommand> commands) {
488515
if (transition) {
489516
this.transition.trigger();
490517
}
491-
492-
return true;
493518
}
494519

495520
private boolean isValidView(View view, boolean mixer, boolean pattern, boolean effect, boolean modulation, boolean output, boolean master) {

0 commit comments

Comments
 (0)