mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 14:43:33 +02:00
AudiListener interface angepasst
Die Listener Methoden haben nun sprechendere Namen. Sound und Mixer akzeptieren nun auch AudioListener.
This commit is contained in:
@@ -80,4 +80,19 @@ public interface Audio {
|
|||||||
*/
|
*/
|
||||||
void dispose();
|
void dispose();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fügt dem Medium das angegbene Objekt als {@code AudioListener} hinzu, der
|
||||||
|
* bei Start und Stopp der Wiedergabe informiert werden soll.
|
||||||
|
*
|
||||||
|
* @param listener Das zu informierende Objekt.
|
||||||
|
*/
|
||||||
|
void addAudioListener( AudioListener listener );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entfernt den angegebenen {@code AudioListener} vom Medium.
|
||||||
|
*
|
||||||
|
* @param listener Das Listener-Objekt.
|
||||||
|
*/
|
||||||
|
void removeAudioListener( AudioListener listener );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,33 @@ package schule.ngb.zm.media;
|
|||||||
|
|
||||||
import schule.ngb.zm.util.events.Listener;
|
import schule.ngb.zm.util.events.Listener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface für Klassen, die auf das starten und stoppen der Wiedergabe von
|
||||||
|
* {@link Audio}-Objekten reagieren möchten.
|
||||||
|
* <p>
|
||||||
|
* Implementierende Klassen können sich bei einem Auido-Objekt mittels
|
||||||
|
* {@link Audio#addAudioListener(AudioListener)} anmelden und werden über die
|
||||||
|
* jeweilige Methode informiert, sobald die Wiedergabe gestartet oder gestoppt
|
||||||
|
* wird.
|
||||||
|
*/
|
||||||
public interface AudioListener extends Listener<Audio> {
|
public interface AudioListener extends Listener<Audio> {
|
||||||
|
|
||||||
void start( Audio source );
|
/**
|
||||||
|
* Wird aufgerufen, sobald die Wiedergabe eines Audio-Objektes startet, dem
|
||||||
|
* dieses Objekt mittels {@link Audio#addAudioListener(AudioListener)}
|
||||||
|
* hinzugefügt wurde.
|
||||||
|
*
|
||||||
|
* @param source Das Audio-Objekt, dessen Wiedergabe gestartet wurde.
|
||||||
|
*/
|
||||||
|
void playbackStarted( Audio source );
|
||||||
|
|
||||||
void stop( Audio source );
|
/**
|
||||||
|
* Wird aufgerufen, sobald die Wiedergabe eines Audio-Objektes stoppt, dem
|
||||||
|
* dieses Objekt mittels {@link Audio#addAudioListener(AudioListener)}
|
||||||
|
* hinzugefügt wurde.
|
||||||
|
*
|
||||||
|
* @param source Das Audio-Objekt, dessen Wiedergabe gestoppt wurde.
|
||||||
|
*/
|
||||||
|
void playbackStopped( Audio source );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package schule.ngb.zm.media;
|
package schule.ngb.zm.media;
|
||||||
|
|
||||||
import schule.ngb.zm.Constants;
|
import schule.ngb.zm.Constants;
|
||||||
|
import schule.ngb.zm.util.events.EventDispatcher;
|
||||||
import schule.ngb.zm.util.tasks.TaskRunner;
|
import schule.ngb.zm.util.tasks.TaskRunner;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,24 +20,14 @@ import java.util.List;
|
|||||||
* Darüber hinaus kann ein Mixer Effekte wie einen
|
* Darüber hinaus kann ein Mixer Effekte wie einen
|
||||||
* {@link #fade(double, int) fadeIn} auf die Medien anwenden.
|
* {@link #fade(double, int) fadeIn} auf die Medien anwenden.
|
||||||
*/
|
*/
|
||||||
public class Mixer implements Audio {
|
@SuppressWarnings( "unused" )
|
||||||
|
public class Mixer implements Audio, AudioListener {
|
||||||
|
|
||||||
private List<AudioWrapper> audios;
|
private List<AudioWrapper> audios;
|
||||||
|
|
||||||
private float volume = 0.8f;
|
private float volume = 0.8f;
|
||||||
|
|
||||||
class AudioWrapper {
|
EventDispatcher<Audio, AudioListener> eventDispatcher;
|
||||||
|
|
||||||
Audio audio;
|
|
||||||
|
|
||||||
float volumeFactor;
|
|
||||||
|
|
||||||
public AudioWrapper( Audio audio, float volumeFactor ) {
|
|
||||||
this.audio = audio;
|
|
||||||
this.volumeFactor = volumeFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mixer() {
|
public Mixer() {
|
||||||
this.audios = new ArrayList<>(4);
|
this.audios = new ArrayList<>(4);
|
||||||
@@ -45,16 +37,61 @@ public class Mixer implements Audio {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add( Audio pAudio ) {
|
private AudioWrapper findWrapper( Audio pAudio ) {
|
||||||
add(pAudio, 1f);
|
for( AudioWrapper aw: audios ) {
|
||||||
|
if( aw.audio == pAudio ) {
|
||||||
|
return aw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean contains( Audio pAudio ) {
|
||||||
|
return findWrapper(pAudio) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add( Audio pAudio ) {
|
||||||
|
add(pAudio, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fügt ein Audio-Objekt dem Mixer mit dem angegebenen Lautstärke-Faktor
|
||||||
|
* hinzu.
|
||||||
|
* <p>
|
||||||
|
* Der Lautstärke-Faktor setzt die Lautstärke des Audio-Objektes relativ zur
|
||||||
|
* Lautstärke des Mixers. Bei einem Faktor von 1.0 wird die Lautstärke des
|
||||||
|
* Mixers übernommen. Bei einem Wert von 0.5 wird das Objekt halb so laut
|
||||||
|
* abgespielt. Auf diese Weise lässt sich die Lautstärke aller Audio-Objekte
|
||||||
|
* des Mixers gleichzeitig anpassen, während ihre relative Lautstärke
|
||||||
|
* zueinander gleich bleibt.
|
||||||
|
*
|
||||||
|
* @param pAudio Ein Audio-Objekt.
|
||||||
|
* @param pVolumeFactor Der Lautstärke-Faktor.
|
||||||
|
*/
|
||||||
public void add( Audio pAudio, double pVolumeFactor ) {
|
public void add( Audio pAudio, double pVolumeFactor ) {
|
||||||
audios.add(new AudioWrapper(pAudio, (float) pVolumeFactor));
|
if( !contains(pAudio) ) {
|
||||||
|
audios.add(new AudioWrapper(pAudio, (float) pVolumeFactor));
|
||||||
|
} else {
|
||||||
|
findWrapper(pAudio).volumeFactor = (float) pVolumeFactor;
|
||||||
|
}
|
||||||
pAudio.setVolume(pVolumeFactor * volume);
|
pAudio.setVolume(pVolumeFactor * volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entfernt die das angegebene Audio-Objekt aus dem Mixer. Ist das Objekt
|
||||||
|
* nicht Teil des Mixers, passiert nichts.
|
||||||
|
*
|
||||||
|
* @param pAudio Ein Audio-Objekt.
|
||||||
|
*/
|
||||||
public void remove( Audio pAudio ) {
|
public void remove( Audio pAudio ) {
|
||||||
|
Iterator<AudioWrapper> it = audios.listIterator();
|
||||||
|
while( it.hasNext() ) {
|
||||||
|
AudioWrapper aw = it.next();
|
||||||
|
if( aw.audio == pAudio ) {
|
||||||
|
it.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAll() {
|
public void removeAll() {
|
||||||
@@ -178,4 +215,57 @@ public class Mixer implements Audio {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playbackStarted( Audio source ) {
|
||||||
|
if( eventDispatcher != null ) {
|
||||||
|
eventDispatcher.dispatchEvent("start", Mixer.this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playbackStopped( Audio source ) {
|
||||||
|
if( !isPlaying() ) {
|
||||||
|
if( eventDispatcher != null ) {
|
||||||
|
eventDispatcher.dispatchEvent("stop", Mixer.this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAudioListener( AudioListener listener ) {
|
||||||
|
initializeEventDispatcher().addListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAudioListener( AudioListener listener ) {
|
||||||
|
initializeEventDispatcher().removeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interne Methode, um den Listener-Mechanismus zu initialisieren. Wird erst
|
||||||
|
* aufgerufen, soblad sich auch ein Listener registrieren möchte.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private EventDispatcher<Audio, AudioListener> initializeEventDispatcher() {
|
||||||
|
if( eventDispatcher == null ) {
|
||||||
|
eventDispatcher = new EventDispatcher<>();
|
||||||
|
eventDispatcher.registerEventType("start", (a,l) -> l.playbackStarted(a));
|
||||||
|
eventDispatcher.registerEventType("stop", (a,l) -> l.playbackStopped(a));
|
||||||
|
}
|
||||||
|
return eventDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AudioWrapper {
|
||||||
|
|
||||||
|
Audio audio;
|
||||||
|
|
||||||
|
float volumeFactor;
|
||||||
|
|
||||||
|
public AudioWrapper( Audio audio, float volumeFactor ) {
|
||||||
|
this.audio = audio;
|
||||||
|
this.volumeFactor = volumeFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import java.net.URL;
|
|||||||
* nicht komplett in den Speicher geladen, sondern direkt aus der Audioquelle
|
* nicht komplett in den Speicher geladen, sondern direkt aus der Audioquelle
|
||||||
* gestreamt und wiedergegeben.
|
* gestreamt und wiedergegeben.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public class Music implements Audio {
|
public class Music implements Audio {
|
||||||
|
|
||||||
// size of the byte buffer used to read/write the audio stream
|
// size of the byte buffer used to read/write the audio stream
|
||||||
@@ -276,11 +277,13 @@ public class Music implements Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addListener( AudioListener listener ) {
|
@Override
|
||||||
|
public void addAudioListener( AudioListener listener ) {
|
||||||
initializeEventDispatcher().addListener(listener);
|
initializeEventDispatcher().addListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeListener( AudioListener listener ) {
|
@Override
|
||||||
|
public void removeAudioListener( AudioListener listener ) {
|
||||||
initializeEventDispatcher().removeListener(listener);
|
initializeEventDispatcher().removeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,8 +295,8 @@ public class Music implements Audio {
|
|||||||
private EventDispatcher<Audio, AudioListener> initializeEventDispatcher() {
|
private EventDispatcher<Audio, AudioListener> initializeEventDispatcher() {
|
||||||
if( eventDispatcher == null ) {
|
if( eventDispatcher == null ) {
|
||||||
eventDispatcher = new EventDispatcher<>();
|
eventDispatcher = new EventDispatcher<>();
|
||||||
eventDispatcher.registerEventType("start", (a,l) -> l.start(a));
|
eventDispatcher.registerEventType("start", (a,l) -> l.playbackStarted(a));
|
||||||
eventDispatcher.registerEventType("stop", (a,l) -> l.stop(a));
|
eventDispatcher.registerEventType("stop", (a,l) -> l.playbackStopped(a));
|
||||||
}
|
}
|
||||||
return eventDispatcher;
|
return eventDispatcher;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package schule.ngb.zm.media;
|
|||||||
|
|
||||||
import schule.ngb.zm.util.Log;
|
import schule.ngb.zm.util.Log;
|
||||||
import schule.ngb.zm.util.Validator;
|
import schule.ngb.zm.util.Validator;
|
||||||
|
import schule.ngb.zm.util.events.EventDispatcher;
|
||||||
import schule.ngb.zm.util.io.ResourceStreamProvider;
|
import schule.ngb.zm.util.io.ResourceStreamProvider;
|
||||||
|
|
||||||
import javax.sound.sampled.*;
|
import javax.sound.sampled.*;
|
||||||
@@ -54,6 +55,8 @@ public class Sound implements Audio {
|
|||||||
*/
|
*/
|
||||||
private float volume = 0.8f;
|
private float volume = 0.8f;
|
||||||
|
|
||||||
|
EventDispatcher<Audio, AudioListener> eventDispatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erstellt einen Sound aus der angegebene Quelle.
|
* Erstellt einen Sound aus der angegebene Quelle.
|
||||||
*
|
*
|
||||||
@@ -235,7 +238,7 @@ public class Sound implements Audio {
|
|||||||
public synchronized void dispose() {
|
public synchronized void dispose() {
|
||||||
if( audioClip != null ) {
|
if( audioClip != null ) {
|
||||||
if( audioClip.isRunning() ) {
|
if( audioClip.isRunning() ) {
|
||||||
audioClip.stop();
|
stop();
|
||||||
}
|
}
|
||||||
audioClip.close();
|
audioClip.close();
|
||||||
audioClip = null;
|
audioClip = null;
|
||||||
@@ -259,8 +262,16 @@ public class Sound implements Audio {
|
|||||||
audioClip.addLineListener(new LineListener() {
|
audioClip.addLineListener(new LineListener() {
|
||||||
@Override
|
@Override
|
||||||
public void update( LineEvent event ) {
|
public void update( LineEvent event ) {
|
||||||
if( event.getType() == LineEvent.Type.STOP ) {
|
if( event.getType() == LineEvent.Type.START ) {
|
||||||
|
if( eventDispatcher != null ) {
|
||||||
|
eventDispatcher.dispatchEvent("start", Sound.this);
|
||||||
|
}
|
||||||
|
} else if( event.getType() == LineEvent.Type.STOP ) {
|
||||||
playbackStopped();
|
playbackStopped();
|
||||||
|
|
||||||
|
if( eventDispatcher != null ) {
|
||||||
|
eventDispatcher.dispatchEvent("stop", Sound.this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -302,12 +313,37 @@ public class Sound implements Audio {
|
|||||||
*/
|
*/
|
||||||
private void playbackStopped() {
|
private void playbackStopped() {
|
||||||
playing = false;
|
playing = false;
|
||||||
|
|
||||||
if( disposeAfterPlay ) {
|
if( disposeAfterPlay ) {
|
||||||
this.dispose();
|
this.dispose();
|
||||||
disposeAfterPlay = false;
|
disposeAfterPlay = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAudioListener( AudioListener listener ) {
|
||||||
|
initializeEventDispatcher().addListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAudioListener( AudioListener listener ) {
|
||||||
|
initializeEventDispatcher().removeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interne Methode, um den Listener-Mechanismus zu initialisieren. Wird erst
|
||||||
|
* aufgerufen, soblad sich auch ein Listener registrieren möchte.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private EventDispatcher<Audio, AudioListener> initializeEventDispatcher() {
|
||||||
|
if( eventDispatcher == null ) {
|
||||||
|
eventDispatcher = new EventDispatcher<>();
|
||||||
|
eventDispatcher.registerEventType("start", (a,l) -> l.playbackStarted(a));
|
||||||
|
eventDispatcher.registerEventType("stop", (a,l) -> l.playbackStopped(a));
|
||||||
|
}
|
||||||
|
return eventDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
private static final Log LOG = Log.getLogger(Sound.class);
|
private static final Log LOG = Log.getLogger(Sound.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user