From 55cedc95665ef3427776e55d01553fa754788d5f Mon Sep 17 00:00:00 2001
From: tobias <thinkdifferent055@gmail.com>
Date: Sun, 8 Oct 2023 10:51:45 +0200
Subject: [PATCH] #191 - Use last volume trigger target value as start value
 for next trigger in the same play session. Cache the last volume change in
 VolumeTriggerVolumeFilter and reset it on pad ready status

---
 .../java/de/tobias/playpad/PlayPadImpl.java   |  1 +
 .../playpad/pad/content/AudioContent.java     |  4 +-
 .../playpad/trigger/VolumeTriggerItem.java    | 16 ++++--
 .../trigger/VolumeTriggerVolumeFilter.java    | 52 +++++++++++++++++++
 .../initialize/ListenerRegistrationTask.scala | 13 +++++
 .../pad/fade/AbstractFadeController.java      |  3 ++
 6 files changed, 82 insertions(+), 7 deletions(-)
 create mode 100644 PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerVolumeFilter.java
 create mode 100644 PlayWall/src/main/scala/de/tobias/playpad/initialize/ListenerRegistrationTask.scala

diff --git a/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java b/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java
index c49bbd13..d393c5fa 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java
@@ -212,6 +212,7 @@ public class PlayPadImpl implements PlayPad {
 		initializer.submit(new KeyboardDefaultMappingTask());
 
 		initializer.submit(new ServiceInitializationTask());
+		initializer.submit(new ListenerRegistrationTask());
 
 		initializer.submit(new VersionizerSetupTask());
 		initializer.submit(new ComponentLoadingTask());
diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java
index 3e3d0639..9ac9d7d9 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java
@@ -134,8 +134,8 @@ public class AudioContent extends PadContent implements Pauseable, Durationable,
 
 	@Override
 	public void onFadeLevelChange(double level) {
-		Pad pad = getPad();
-		audioHandler.setVolume(level * VolumeManager.getInstance().computeVolume(pad));
+		final double newVolume = VolumeManager.getInstance().computeVolume(getPad()) * level;
+		audioHandler.setVolume(newVolume);
 	}
 
 	@Override
diff --git a/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItem.java b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItem.java
index 96c9ca10..88fb85bc 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItem.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItem.java
@@ -21,7 +21,7 @@ public class VolumeTriggerItem extends TriggerItem {
 	private Duration duration = new Duration(2000);
 	private List<UUID> uuids;
 
-	private String type;
+	private final String type;
 
 	VolumeTriggerItem(String type) {
 		super();
@@ -58,11 +58,17 @@ public class VolumeTriggerItem extends TriggerItem {
 	public void performAction(Pad pad, Project project, IMainViewController controller, Profile profile) {
 		uuids.stream().map(project::getPad)
 				.filter(i -> i.getContent() instanceof Fadeable)
-				.forEach(destination -> {
-					Fadeable fadeable = (Fadeable) destination.getContent();
+				.forEach(targetPad -> {
+					final Fadeable fadeable = (Fadeable) targetPad.getContent();
 
-					final double start = VolumeManager.getInstance().computeVolume(destination);
-					fadeable.fade(start, volume, duration, null);
+					// Use pad * last VolumeTrigger
+					final double start = VolumeManager.getInstance().computeVolume(targetPad) * VolumeTriggerVolumeFilter.getInstance().getVolume(pad);
+					// Use pad * target VolumeTrigger
+					final double destination = VolumeManager.getInstance().computeVolume(targetPad) * volume;
+					// Update VolumeTrigger
+					VolumeTriggerVolumeFilter.getInstance().setVolume(pad, volume);
+
+					fadeable.fade(start, destination, duration, null);
 				});
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerVolumeFilter.java b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerVolumeFilter.java
new file mode 100644
index 00000000..b8dad1b7
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerVolumeFilter.java
@@ -0,0 +1,52 @@
+package de.tobias.playpad.trigger;
+
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadStatus;
+import de.tobias.playpad.plugin.PadListener;
+import de.tobias.playpad.volume.VolumeFilter;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class VolumeTriggerVolumeFilter implements VolumeFilter, PadListener {
+
+	private static VolumeTriggerVolumeFilter instance;
+
+	public static VolumeTriggerVolumeFilter getInstance() {
+		if (instance == null) {
+			instance = new VolumeTriggerVolumeFilter();
+		}
+		return instance;
+	}
+
+	private VolumeTriggerVolumeFilter() {
+		// nothing to do
+	}
+
+	private final Map<UUID, Double> volumes = new HashMap<>();
+
+	@Override
+	public double getVolume(Pad pad) {
+		return volumes.getOrDefault(pad.getUuid(), 1.0);
+	}
+
+	public void setVolume(Pad pad, double newVolume) {
+		volumes.put(pad.getUuid(), newVolume);
+	}
+
+	// Pad Listener
+
+
+	@Override
+	public void onNameChanged(Pad pad, String oldValue, String newValue) {
+		// nothing to do
+	}
+
+	@Override
+	public void onStatusChange(Pad pad, PadStatus newValue) {
+		if (newValue == PadStatus.READY) {
+			volumes.remove(pad.getUuid());
+		}
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/ListenerRegistrationTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ListenerRegistrationTask.scala
new file mode 100644
index 00000000..5ab0117d
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ListenerRegistrationTask.scala
@@ -0,0 +1,13 @@
+package de.tobias.playpad.initialize
+
+import de.thecodelabs.utils.application
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.trigger.VolumeTriggerVolumeFilter
+
+class ListenerRegistrationTask extends PlayPadInitializeTask {
+	override def name(): String = "ListenerRegistration"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		instance.addPadListener(VolumeTriggerVolumeFilter.getInstance())
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/AbstractFadeController.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/AbstractFadeController.java
index 3923a9e0..21eb241d 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/AbstractFadeController.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/AbstractFadeController.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.pad.fade;
 
+import de.thecodelabs.logger.Logger;
 import javafx.animation.Transition;
 import javafx.util.Duration;
 
@@ -42,6 +43,8 @@ public abstract class AbstractFadeController {
 	}
 
 	public void fade(double from, double to, Duration duration, Runnable onFinish) {
+		Logger.debug("Fading from {0} to {1} in {2}", from, to, duration);
+
 		if (currentFadeTransition != null) {
 			currentFadeTransition.stop();
 		}
-- 
GitLab