From 123abd494fcba1c12f65b1b4ed79013ee3e83b3c Mon Sep 17 00:00:00 2001 From: extio-de Date: Wed, 22 Jul 2026 20:42:36 +0200 Subject: [PATCH] fix(AudioController, OptionsAudioTab): optimize audio options handling and improve state management --- pom.xml | 2 +- .../game_engine/audio/AudioController.java | 30 +++++++++++++- .../audio/AudioStrategyJavaMixer.java | 1 - .../game_engine/menu/OptionsAudioTab.java | 40 +++++++++++++------ 4 files changed, 57 insertions(+), 16 deletions(-) diff --git a/pom.xml b/pom.xml index 6647f5e..09dfe84 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.extio game-engine - 1.0.26 + 1.0.27 25 diff --git a/src/main/java/de/extio/game_engine/audio/AudioController.java b/src/main/java/de/extio/game_engine/audio/AudioController.java index 54789ad..f3e2eff 100644 --- a/src/main/java/de/extio/game_engine/audio/AudioController.java +++ b/src/main/java/de/extio/game_engine/audio/AudioController.java @@ -9,6 +9,8 @@ import de.extio.game_engine.storage.StorageService; public final class AudioController implements AudioControl { + private static final long AUDIO_OPTIONS_STORE_DELAY_MS = 333; + private final StorageService storageService; private final AudioOptions audioOptions; // Passed as reference to strategies @@ -29,6 +31,8 @@ public final class AudioController implements AudioControl { private boolean useSoftwareMixing; + private long delayedAudioOptionsStoreAt = -1; + public AudioController(final StaticResourceService resourceService, final StorageService storageService) { this.storageService = storageService; this.audioOptions = new AudioOptions(); @@ -75,9 +79,15 @@ public final class AudioController implements AudioControl { if (this.audioStrategy != null) { this.audioStrategy.run(); } + if (this.consumeDelayedAudioOptionsStore()) { + this.storeAudioOptions(); + } } public void shutdown() { + if (this.consumePendingAudioOptionsStore()) { + this.storeAudioOptions(); + } this.audioControllerThread.interrupt(); this.stopStrategy(); } @@ -169,9 +179,25 @@ public final class AudioController implements AudioControl { } @Override - public void applyAudioOptions(final AudioOptions audioOptions) { + public synchronized void applyAudioOptions(final AudioOptions audioOptions) { this.audioOptions.apply(audioOptions); - this.storeAudioOptions(); + this.delayedAudioOptionsStoreAt = System.currentTimeMillis() + AUDIO_OPTIONS_STORE_DELAY_MS; + } + + private synchronized boolean consumeDelayedAudioOptionsStore() { + if (this.delayedAudioOptionsStoreAt < 0 || System.currentTimeMillis() < this.delayedAudioOptionsStoreAt) { + return false; + } + this.delayedAudioOptionsStoreAt = -1; + return true; + } + + private synchronized boolean consumePendingAudioOptionsStore() { + if (this.delayedAudioOptionsStoreAt < 0) { + return false; + } + this.delayedAudioOptionsStoreAt = -1; + return true; } private List wrapOpener(final StaticResource opener, final List audioFileNames) { diff --git a/src/main/java/de/extio/game_engine/audio/AudioStrategyJavaMixer.java b/src/main/java/de/extio/game_engine/audio/AudioStrategyJavaMixer.java index 0f5eae9..356a686 100644 --- a/src/main/java/de/extio/game_engine/audio/AudioStrategyJavaMixer.java +++ b/src/main/java/de/extio/game_engine/audio/AudioStrategyJavaMixer.java @@ -63,7 +63,6 @@ final class AudioStrategyJavaMixer implements AudioStrategy { .name("Audio Music") .daemon(true) .start(musicAudioPlayer); - musicThread.start(); this.musicAudioPlayer = new AudioThread(musicThread, musicAudioPlayer); } diff --git a/src/main/java/de/extio/game_engine/menu/OptionsAudioTab.java b/src/main/java/de/extio/game_engine/menu/OptionsAudioTab.java index 87b733e..c3a31e6 100644 --- a/src/main/java/de/extio/game_engine/menu/OptionsAudioTab.java +++ b/src/main/java/de/extio/game_engine/menu/OptionsAudioTab.java @@ -171,32 +171,48 @@ final class OptionsAudioTab extends AbstractOptionsTab implements OptionsTab { return false; } + final var options = this.audioControl().getAudioOptions(); + switch (controlId) { case "OptionsModule_Audio_SFX_Enable" -> { - final var currentValue = this.audioControl().getAudioOptions().getSfxOptions().isEnable(); - this.audioControl().getAudioOptions().getSfxOptions().setEnable(!currentValue); - this.audioControl().applyAudioOptions(this.audioControl().getAudioOptions()); + final var currentValue = options.getSfxOptions().isEnable(); + options.getSfxOptions().setEnable(!currentValue); + this.audioControl().applyAudioOptions(options); this.refreshContent(context); return true; } case "OptionsModule_Audio_Music_Enable" -> { - final var currentValue = this.audioControl().getAudioOptions().getMusicOptions().isEnable(); - this.audioControl().getAudioOptions().getMusicOptions().setEnable(!currentValue); - this.audioControl().applyAudioOptions(this.audioControl().getAudioOptions()); + final var currentValue = options.getMusicOptions().isEnable(); + options.getMusicOptions().setEnable(!currentValue); + this.audioControl().applyAudioOptions(options); this.refreshContent(context); return true; } case "OptionsModule_Audio_SFX_SoftwareMixing" -> { - final var currentValue = this.audioControl().getAudioOptions().getSfxOptions().isSoftwareMixing(); - this.audioControl().getAudioOptions().getSfxOptions().setSoftwareMixing(!currentValue); - this.audioControl().applyAudioOptions(this.audioControl().getAudioOptions()); + final var currentValue = options.getSfxOptions().isSoftwareMixing(); + options.getSfxOptions().setSoftwareMixing(!currentValue); + this.audioControl().applyAudioOptions(options); this.refreshContent(context); return true; } case "OptionsModule_Audio_Music_SoftwareMixing" -> { - final var currentValue = this.audioControl().getAudioOptions().getMusicOptions().isSoftwareMixing(); - this.audioControl().getAudioOptions().getMusicOptions().setSoftwareMixing(!currentValue); - this.audioControl().applyAudioOptions(this.audioControl().getAudioOptions()); + final var currentValue = options.getMusicOptions().isSoftwareMixing(); + options.getMusicOptions().setSoftwareMixing(!currentValue); + this.audioControl().applyAudioOptions(options); + this.refreshContent(context); + return true; + } + case "OptionsModule_Audio_SFX_Volume_Slider" -> { + final var newVolume = (double) event.getPayload(); + options.getSfxOptions().setVolume(newVolume); + this.audioControl().applyAudioOptions(options); + this.refreshContent(context); + return true; + } + case "OptionsModule_Audio_Music_Volume_Slider" -> { + final var newVolume = (double) event.getPayload(); + options.getMusicOptions().setVolume(newVolume); + this.audioControl().applyAudioOptions(options); this.refreshContent(context); return true; }