Working state. Split AudioManager into 3 different branches for easier testing and srp

This commit is contained in:
lieght
2025-10-11 04:50:49 +02:00
parent 7f3d858320
commit 123ecc7d3a
12 changed files with 426 additions and 256 deletions

View File

@@ -1,12 +1,20 @@
package org.toop; package org.toop;
import javafx.scene.media.MediaPlayer;
import org.toop.app.App; import org.toop.app.App;
import org.toop.framework.audio.SoundManager; import org.toop.framework.audio.AudioEventListener;
import org.toop.framework.audio.AudioVolumeManager;
import org.toop.framework.audio.MusicManager;
import org.toop.framework.audio.SoundEffectManager;
import org.toop.framework.audio.interfaces.AudioManager;
import org.toop.framework.audio.interfaces.VolumeManager;
import org.toop.framework.networking.NetworkingClientManager; import org.toop.framework.networking.NetworkingClientManager;
import org.toop.framework.networking.NetworkingInitializationException; import org.toop.framework.networking.NetworkingInitializationException;
import org.toop.framework.resource.ResourceLoader; import org.toop.framework.resource.ResourceLoader;
import org.toop.framework.resource.ResourceManager; import org.toop.framework.resource.ResourceManager;
import javax.sound.sampled.Clip;
public final class Main { public final class Main {
static void main(String[] args) { static void main(String[] args) {
initSystems(); initSystems();
@@ -16,6 +24,13 @@ public final class Main {
private static void initSystems() throws NetworkingInitializationException { private static void initSystems() throws NetworkingInitializationException {
ResourceManager.loadAssets(new ResourceLoader("app/src/main/resources/assets")); ResourceManager.loadAssets(new ResourceLoader("app/src/main/resources/assets"));
new Thread(NetworkingClientManager::new).start(); new Thread(NetworkingClientManager::new).start();
new Thread(SoundManager::new).start(); new Thread(() -> {
AudioEventListener a =
new AudioEventListener(
new MusicManager(),
new SoundEffectManager(),
new AudioVolumeManager()
); a.initListeners();
}).start();
} }
} }

View File

@@ -6,6 +6,7 @@ import javafx.application.Platform;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import javafx.stage.Stage; import javafx.stage.Stage;
import jdk.jfr.Event;
import org.toop.app.layer.Layer; import org.toop.app.layer.Layer;
import org.toop.app.layer.layers.MainLayer; import org.toop.app.layer.layers.MainLayer;
import org.toop.app.layer.layers.QuitPopup; import org.toop.app.layer.layers.QuitPopup;
@@ -65,10 +66,11 @@ public final class App extends Application {
App.isQuitting = false; App.isQuitting = false;
new EventFlow().addPostEvent(new AudioEvents.StartBackgroundMusic()).postEvent();
final AppSettings settings = new AppSettings(); final AppSettings settings = new AppSettings();
settings.applySettings(); settings.applySettings();
new EventFlow().addPostEvent(new AudioEvents.StartBackgroundMusic()).asyncPostEvent();
activate(new MainLayer()); activate(new MainLayer());
} }

View File

@@ -54,9 +54,13 @@ public class AppSettings {
File settingsFile = File settingsFile =
new File(basePath + File.separator + "ISY1" + File.separator + "settings.json"); new File(basePath + File.separator + "ISY1" + File.separator + "settings.json");
// this.settingsAsset = new SettingsAsset(settingsFile);
ResourceManager.addAsset(new ResourceMeta<>("settings.json", new SettingsAsset(settingsFile))); return new SettingsAsset(settingsFile);
// this.settingsAsset = new SettingsAsset(settingsFile); // TODO
// ResourceManager.addAsset(new ResourceMeta<>("settings.json", new SettingsAsset(settingsFile))); // TODO
} }
return ResourceManager.get("settings.json");
return this.settingsAsset;
// return ResourceManager.get("settings.json"); // TODO
} }
} }

View File

@@ -0,0 +1,88 @@
package org.toop.framework.audio;
import org.toop.framework.audio.events.AudioEvents;
import org.toop.framework.audio.interfaces.MusicManager;
import org.toop.framework.audio.interfaces.SoundEffectManager;
import org.toop.framework.audio.interfaces.VolumeManager;
import org.toop.framework.eventbus.EventFlow;
public class AudioEventListener {
private final MusicManager<?> musicManager;
private final SoundEffectManager<?> soundEffectManager;
private final VolumeManager audioVolumeManager;
public AudioEventListener(
MusicManager<?> musicManager,
SoundEffectManager<?> soundEffectManager,
VolumeManager audioVolumeManager
) {
this.musicManager = musicManager;
this.soundEffectManager = soundEffectManager;
this.audioVolumeManager = audioVolumeManager;
}
public void initListeners() {
new EventFlow()
.listen(this::handlePlaySound)
.listen(this::handleStopSound)
.listen(this::handleMusicStart)
.listen(this::handleVolumeChange)
.listen(this::handleFxVolumeChange)
.listen(this::handleMusicVolumeChange)
.listen(this::handleGetVolume)
.listen(this::handleGetFxVolume)
.listen(this::handleGetMusicVolume);
}
private void handlePlaySound(AudioEvents.PlayEffect event) {
this.soundEffectManager.play(event.fileName(), event.loop());
}
private void handleStopSound(AudioEvents.StopEffect event) {
this.soundEffectManager.stop(event.clipId());
}
private void handleMusicStart(AudioEvents.StartBackgroundMusic event) {
this.musicManager.play();
}
private void handleVolumeChange(AudioEvents.ChangeVolume event) {
this.audioVolumeManager.setVolume(event.newVolume(), soundEffectManager, musicManager);
}
private void handleFxVolumeChange(AudioEvents.ChangeFxVolume event) {
this.audioVolumeManager.setFxVolume(event.newVolume(), soundEffectManager);
}
private void handleMusicVolumeChange(AudioEvents.ChangeMusicVolume event) {
this.audioVolumeManager.setMusicVolume(event.newVolume(), musicManager);
}
private void handleGetVolume(AudioEvents.GetCurrentVolume event) {
new EventFlow()
.addPostEvent(
new AudioEvents.GetCurrentVolumeResponse(
audioVolumeManager.getVolume(),
event.snowflakeId()))
.asyncPostEvent();
}
private void handleGetFxVolume(AudioEvents.GetCurrentFxVolume event) {
new EventFlow()
.addPostEvent(
new AudioEvents.GetCurrentFxVolumeResponse(
audioVolumeManager.getFxVolume(),
event.snowflakeId()))
.asyncPostEvent();
}
private void handleGetMusicVolume(AudioEvents.GetCurrentMusicVolume event) {
new EventFlow()
.addPostEvent(
new AudioEvents.GetCurrentMusicVolumeResponse(
audioVolumeManager.getMusicVolume(),
event.snowflakeId()))
.asyncPostEvent();
}
}

View File

@@ -3,33 +3,21 @@ package org.toop.framework.audio;
import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaPlayer;
import javax.sound.sampled.Clip; import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl; import javax.sound.sampled.FloatControl;
import org.toop.framework.audio.events.AudioEvents; import org.toop.framework.audio.interfaces.AudioManager;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.audio.interfaces.VolumeManager;
public class AudioVolumeManager { public class AudioVolumeManager implements VolumeManager {
private final SoundManager sM; private double volume = 0.0;
private double fxVolume = 0.0;
private double musicVolume = 0.0;
private double volume = 1.0; public AudioVolumeManager() {}
private double fxVolume = 1.0;
private double musicVolume = 1.0;
public AudioVolumeManager(SoundManager soundManager) { private <T extends MediaPlayer> void updateMusicVolume(T mediaPlayer) {
this.sM = soundManager;
new EventFlow()
.listen(this::handleVolumeChange)
.listen(this::handleFxVolumeChange)
.listen(this::handleMusicVolumeChange)
.listen(this::handleGetCurrentVolume)
.listen(this::handleGetCurrentFxVolume)
.listen(this::handleGetCurrentMusicVolume);
}
public void updateMusicVolume(MediaPlayer mediaPlayer) {
mediaPlayer.setVolume(this.musicVolume * this.volume); mediaPlayer.setVolume(this.musicVolume * this.volume);
} }
public void updateSoundEffectVolume(Clip clip) { private <T extends Clip> void updateSoundEffectVolume(T clip) {
if (clip.isControlSupported(FloatControl.Type.MASTER_GAIN)) { if (clip.isControlSupported(FloatControl.Type.MASTER_GAIN)) {
FloatControl volumeControl = FloatControl volumeControl =
(FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
@@ -49,50 +37,45 @@ public class AudioVolumeManager {
else return Math.max(volume, 0.0); else return Math.max(volume, 0.0);
} }
private void handleFxVolumeChange(AudioEvents.ChangeFxVolume event) { @Override
this.fxVolume = limitVolume(event.newVolume() / 100); public void setVolume(double newVolume, AudioManager<?> sm, AudioManager<?> mm) {
for (Clip clip : sM.getActiveSoundEffects().values()) { this.volume = limitVolume(newVolume / 100);
updateSoundEffectVolume(clip); for (var clip : sm.getActiveAudio()) {
this.updateSoundEffectVolume((Clip) clip);
}
for (var mediaPlayer : mm.getActiveAudio()) {
this.updateMusicVolume((MediaPlayer) mediaPlayer);
} }
} }
private void handleVolumeChange(AudioEvents.ChangeVolume event) { @Override
this.volume = limitVolume(event.newVolume() / 100); public void setFxVolume(double newVolume, AudioManager<?> sm) {
for (MediaPlayer mediaPlayer : sM.getActiveMusic()) { this.fxVolume = limitVolume(newVolume / 100);
this.updateMusicVolume(mediaPlayer); for (var clip : sm.getActiveAudio()) {
} this.updateSoundEffectVolume((Clip) clip); // TODO: What if not clip
for (Clip clip : sM.getActiveSoundEffects().values()) {
updateSoundEffectVolume(clip);
} }
} }
private void handleMusicVolumeChange(AudioEvents.ChangeMusicVolume event) { @Override
this.musicVolume = limitVolume(event.newVolume() / 100); public void setMusicVolume(double newVolume, AudioManager<?> mm) {
for (MediaPlayer mediaPlayer : sM.getActiveMusic()) { this.musicVolume = limitVolume(newVolume / 100);
this.updateMusicVolume(mediaPlayer); for (var mediaPlayer : mm.getActiveAudio()) {
this.updateMusicVolume((MediaPlayer) mediaPlayer); // TODO; What if not MediaPlayer
} }
} }
private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) { @Override
new EventFlow() public double getVolume() {
.addPostEvent( return volume * 100;
new AudioEvents.GetCurrentVolumeResponse(volume * 100, event.snowflakeId()))
.asyncPostEvent();
} }
private void handleGetCurrentFxVolume(AudioEvents.GetCurrentFxVolume event) { @Override
new EventFlow() public double getFxVolume() {
.addPostEvent( return fxVolume * 100;
new AudioEvents.GetCurrentFxVolumeResponse(
fxVolume * 100, event.snowflakeId()))
.asyncPostEvent();
} }
private void handleGetCurrentMusicVolume(AudioEvents.GetCurrentMusicVolume event) { @Override
new EventFlow() public double getMusicVolume() {
.addPostEvent( return musicVolume * 100;
new AudioEvents.GetCurrentMusicVolumeResponse(
musicVolume * 100, event.snowflakeId()))
.asyncPostEvent();
} }
} }

View File

@@ -0,0 +1,84 @@
package org.toop.framework.audio;
import javafx.scene.media.MediaPlayer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.toop.framework.resource.ResourceManager;
import org.toop.framework.resource.resources.MusicAsset;
import java.util.*;
public class MusicManager implements org.toop.framework.audio.interfaces.MusicManager<MediaPlayer> {
private static final Logger logger = LogManager.getLogger(MusicManager.class);
// private final List<MusicAsset> musicAssets = new ArrayList<>(); // TODO
private final List<MediaPlayer> backgroundMusic = new LinkedList<>();
private int playingIndex = 0;
private boolean playing = false;
public MusicManager() {}
@Override
public Collection<MediaPlayer> getActiveAudio() {
return backgroundMusic;
}
private void addBackgroundMusic(MusicAsset musicAsset) {
backgroundMusic.add(new MediaPlayer(musicAsset.getMedia()));
}
private void addBackgroundMusic(MediaPlayer mediaPlayer) {
backgroundMusic.add(mediaPlayer);
}
public void play() { // TODO maybe remove VolumeManager from input
backgroundMusic.clear();
List<MediaPlayer> shuffledArray =
new ArrayList<>(
ResourceManager.getAllOfType(MusicAsset.class).stream()
.map(ma ->
initMediaPlayer(new MediaPlayer(ma.getResource().getMedia())))
.toList());
Collections.shuffle(shuffledArray);
backgroundMusic.addAll(shuffledArray);
backgroundMusicPlayer();
}
private void backgroundMusicPlayer() {
if (playingIndex >= backgroundMusic.size()) {
playingIndex = 0;
}
MediaPlayer ma = backgroundMusic.get(playingIndex);
if (ma == null) {
logger.error("Background music player is null. Queue: {}",
backgroundMusic.stream().map(e -> e.getMedia().getSource()));
return;
}
logger.info("Background music player is playing: {}", ma.getMedia().getSource()); //TODO shorten to name
ma.play();
this.playing = true;
}
private MediaPlayer initMediaPlayer(MediaPlayer mediaPlayer) {
mediaPlayer.setOnEndOfMedia(mediaPlayer::stop);
mediaPlayer.setOnError( () -> {
logger.error("Error playing music: {}", mediaPlayer.getMedia().getSource());
backgroundMusic.remove(mediaPlayer);
mediaPlayer.stop();
});
mediaPlayer.setOnStopped( () -> {
mediaPlayer.stop();
playingIndex++;
this.playing = false;
backgroundMusicPlayer();
});
return mediaPlayer;
}
}

View File

@@ -0,0 +1,28 @@
package org.toop.framework.audio;
import org.toop.framework.resource.resources.SoundEffectAsset;
import javax.sound.sampled.Clip;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class SoundEffectManager implements org.toop.framework.audio.interfaces.SoundEffectManager<Clip> {
private final Map<Long, Clip> activeSoundEffects = new HashMap<>();
private final HashMap<String, SoundEffectAsset> audioResources = new HashMap<>();
public Collection<Clip> getActiveAudio() {
return this.activeSoundEffects.values();
}
@Override
public void play(String name, boolean loop) {
}
@Override
public void stop(long clipId) {
}
}

View File

@@ -1,197 +1,135 @@
package org.toop.framework.audio; //package org.toop.framework.audio;
//
import java.io.*; //import java.io.*;
import java.util.*; //import java.util.*;
import javafx.scene.media.MediaPlayer; //import javafx.scene.media.MediaPlayer;
import javax.sound.sampled.*; //import javax.sound.sampled.*;
import org.apache.logging.log4j.LogManager; //import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; //import org.apache.logging.log4j.Logger;
import org.toop.framework.SnowflakeGenerator; //import org.toop.framework.SnowflakeGenerator;
import org.toop.framework.audio.events.AudioEvents; //import org.toop.framework.audio.events.AudioEvents;
import org.toop.framework.eventbus.EventFlow; //import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.resource.ResourceManager; //import org.toop.framework.resource.ResourceManager;
import org.toop.framework.resource.ResourceMeta; //import org.toop.framework.resource.ResourceMeta;
import org.toop.framework.resource.resources.MusicAsset; //import org.toop.framework.resource.resources.MusicAsset;
import org.toop.framework.resource.resources.SoundEffectAsset; //import org.toop.framework.resource.resources.SoundEffectAsset;
//
public class SoundManager { //public class SoundManager {
private static final Logger logger = LogManager.getLogger(SoundManager.class); // private static final Logger logger = LogManager.getLogger(SoundManager.class);
private final List<MediaPlayer> activeMusic = new ArrayList<>(); // private final Map<Long, Clip> activeSoundEffects = new HashMap<>();
private final Queue<MusicAsset> backgroundMusicQueue = new LinkedList<>(); // private final HashMap<String, SoundEffectAsset> audioResources = new HashMap<>();
private final Map<Long, Clip> activeSoundEffects = new HashMap<>(); //// private final AudioVolumeManager audioVolumeManager = new AudioVolumeManager(this);
private final HashMap<String, SoundEffectAsset> audioResources = new HashMap<>(); //
private final AudioVolumeManager audioVolumeManager = new AudioVolumeManager(this); // public SoundManager() {
// // Get all Audio Resources and add them to a list.
public SoundManager() { // for (ResourceMeta<SoundEffectAsset> asset :
// Get all Audio Resources and add them to a list. // ResourceManager.getAllOfType(SoundEffectAsset.class)) {
for (ResourceMeta<SoundEffectAsset> asset : // try {
ResourceManager.getAllOfType(SoundEffectAsset.class)) { // this.addAudioResource(asset);
try { // } catch (IOException | LineUnavailableException | UnsupportedAudioFileException e) {
this.addAudioResource(asset); // throw new RuntimeException(e);
} catch (IOException | LineUnavailableException | UnsupportedAudioFileException e) { // }
throw new RuntimeException(e); // }
} // new EventFlow()
} // .listen(this::handlePlaySound)
new EventFlow() // .listen(this::handleStopSound)
.listen(this::handlePlaySound) // .listen(
.listen(this::handleStopSound) // AudioEvents.ClickButton.class,
.listen(this::handleMusicStart) // _ -> {
.listen( // try {
AudioEvents.ClickButton.class, // playSound("medium-button-click.wav", false);
_ -> { // } catch (UnsupportedAudioFileException
try { // | LineUnavailableException
playSound("medium-button-click.wav", false); // | IOException e) {
} catch (UnsupportedAudioFileException // logger.error(e);
| LineUnavailableException // }
| IOException e) { // });
logger.error(e); // }
} //
}); // private void handlePlaySound(AudioEvents.PlayEffect event) {
} // try {
// this.playSound(event.fileName(), event.loop());
private void handlePlaySound(AudioEvents.PlayEffect event) { // } catch (UnsupportedAudioFileException | LineUnavailableException | IOException e) {
try { // throw new RuntimeException(e);
this.playSound(event.fileName(), event.loop()); // }
} catch (UnsupportedAudioFileException | LineUnavailableException | IOException e) { // }
throw new RuntimeException(e); //
} // private void handleStopSound(AudioEvents.StopEffect event) {
} // this.stopSound(event.clipId());
// }
private void handleStopSound(AudioEvents.StopEffect event) { //
this.stopSound(event.clipId()); // private void addAudioResource(ResourceMeta<SoundEffectAsset> audioAsset)
} // throws IOException, UnsupportedAudioFileException, LineUnavailableException {
//
private void addAudioResource(ResourceMeta<SoundEffectAsset> audioAsset) // this.audioResources.put(audioAsset.getName(), audioAsset.getResource());
throws IOException, UnsupportedAudioFileException, LineUnavailableException { // }
//
this.audioResources.put(audioAsset.getName(), audioAsset.getResource()); // private long playSound(String audioFileName, boolean loop)
} // throws UnsupportedAudioFileException, LineUnavailableException, IOException {
// SoundEffectAsset asset = audioResources.get(audioFileName);
private void handleMusicStart(AudioEvents.StartBackgroundMusic e) { //
backgroundMusicQueue.clear(); // // Return -1 which indicates resource wasn't available
List<MusicAsset> shuffledArray = // if (asset == null) {
new ArrayList<>( // logger.warn("Unable to load audio asset: {}", audioFileName);
ResourceManager.getAllOfType(MusicAsset.class).stream() // return -1;
.map(ResourceMeta::getResource) // }
.toList()); //
Collections.shuffle(shuffledArray); // // Get a new clip from resource
backgroundMusicQueue.addAll(shuffledArray); // Clip clip = asset.getNewClip();
backgroundMusicPlayer(); //
} // // Set volume of clip
//// audioVolumeManager.updateSoundEffectVolume(clip);
private void addBackgroundMusic(MusicAsset musicAsset) { //
backgroundMusicQueue.add(musicAsset); // // If supposed to loop make it loop, else just start it once
} // if (loop) {
// clip.loop(Clip.LOOP_CONTINUOUSLY);
private void backgroundMusicPlayer() { // } else {
MusicAsset ma = backgroundMusicQueue.poll(); // clip.start();
if (ma == null) return; // }
//
MediaPlayer mediaPlayer = new MediaPlayer(ma.getMedia()); // logger.debug("Playing sound: {}", asset.getFile().getName());
//
mediaPlayer.setOnEndOfMedia( // // Generate id for clip
() -> { // long clipId = new SnowflakeGenerator().nextId();
addBackgroundMusic(ma); //
activeMusic.remove(mediaPlayer); // // store it so we can stop it later
mediaPlayer.dispose(); // activeSoundEffects.put(clipId, clip);
ma.unload(); //
backgroundMusicPlayer(); // play next // // remove when finished (only for non-looping sounds)
}); // clip.addLineListener(
// event -> {
mediaPlayer.setOnStopped( // if (event.getType() == LineEvent.Type.STOP && !clip.isRunning()) {
() -> { // activeSoundEffects.remove(clipId);
addBackgroundMusic(ma); // clip.close();
activeMusic.remove(mediaPlayer); // }
ma.unload(); // });
}); //
// // Return id so it can be stopped
mediaPlayer.setOnError( // return clipId;
() -> { // }
addBackgroundMusic(ma); //
activeMusic.remove(mediaPlayer); // public void stopSound(long clipId) {
ma.unload(); // Clip clip = activeSoundEffects.get(clipId);
}); //
// if (clip == null) {
audioVolumeManager.updateMusicVolume(mediaPlayer); // return;
mediaPlayer.play(); // }
activeMusic.add(mediaPlayer); //
logger.info("Playing background music: {}", ma.getFile().getName()); // clip.stop();
logger.info( // clip.close();
"Background music next in line: {}", // activeSoundEffects.remove(clipId);
backgroundMusicQueue.peek() != null // }
? backgroundMusicQueue.peek().getFile().getName() //
: null); // public void stopAllSounds() {
} // for (Clip clip : activeSoundEffects.values()) {
// clip.stop();
private long playSound(String audioFileName, boolean loop) // clip.close();
throws UnsupportedAudioFileException, LineUnavailableException, IOException { // }
SoundEffectAsset asset = audioResources.get(audioFileName); // activeSoundEffects.clear();
// }
// Return -1 which indicates resource wasn't available //
if (asset == null) { // public Map<Long, Clip> getActiveSoundEffects() {
logger.warn("Unable to load audio asset: {}", audioFileName); // return this.activeSoundEffects;
return -1; // }
} //
//}
// Get a new clip from resource
Clip clip = asset.getNewClip();
// Set volume of clip
audioVolumeManager.updateSoundEffectVolume(clip);
// If supposed to loop make it loop, else just start it once
if (loop) {
clip.loop(Clip.LOOP_CONTINUOUSLY);
} else {
clip.start();
}
logger.debug("Playing sound: {}", asset.getFile().getName());
// Generate id for clip
long clipId = new SnowflakeGenerator().nextId();
// store it so we can stop it later
activeSoundEffects.put(clipId, clip);
// remove when finished (only for non-looping sounds)
clip.addLineListener(
event -> {
if (event.getType() == LineEvent.Type.STOP && !clip.isRunning()) {
activeSoundEffects.remove(clipId);
clip.close();
}
});
// Return id so it can be stopped
return clipId;
}
public void stopSound(long clipId) {
Clip clip = activeSoundEffects.get(clipId);
if (clip == null) {
return;
}
clip.stop();
clip.close();
activeSoundEffects.remove(clipId);
}
public void stopAllSounds() {
for (Clip clip : activeSoundEffects.values()) {
clip.stop();
clip.close();
}
activeSoundEffects.clear();
}
public Map<Long, Clip> getActiveSoundEffects() {
return this.activeSoundEffects;
}
public List<MediaPlayer> getActiveMusic() {
return activeMusic;
}
}

View File

@@ -0,0 +1,7 @@
package org.toop.framework.audio.interfaces;
import java.util.Collection;
public interface AudioManager<T> {
Collection<T> getActiveAudio();
}

View File

@@ -0,0 +1,5 @@
package org.toop.framework.audio.interfaces;
public interface MusicManager<T> extends AudioManager<T> {
void play();
}

View File

@@ -0,0 +1,6 @@
package org.toop.framework.audio.interfaces;
public interface SoundEffectManager<T> extends AudioManager<T> {
void play(String name, boolean loop);
void stop(long clipId);
}

View File

@@ -0,0 +1,10 @@
package org.toop.framework.audio.interfaces;
public interface VolumeManager {
void setVolume(double newVolume, AudioManager<?> sm, AudioManager<?> mm);
void setFxVolume(double newVolume, AudioManager<?> sm);
void setMusicVolume(double newVolume, AudioManager<?> mm);
double getVolume();
double getFxVolume();
double getMusicVolume();
}