X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsonitus%2Fdata%2Fsink%2FAudioSink.java;h=05253f37a03b6ee244b29d2aaf6591db9cbdc6f3;hb=f554e51504f7e39e658a84d79c041e0b0d8a6393;hp=fc4c60cd39e8b4bf058beffbfff881a6566dd7d2;hpb=a97335e5b42b4f3a9a7e3c8481675c117dffdd07;p=sonitus.git diff --git a/src/main/java/net/pterodactylus/sonitus/data/sink/AudioSink.java b/src/main/java/net/pterodactylus/sonitus/data/sink/AudioSink.java index fc4c60c..05253f3 100644 --- a/src/main/java/net/pterodactylus/sonitus/data/sink/AudioSink.java +++ b/src/main/java/net/pterodactylus/sonitus/data/sink/AudioSink.java @@ -17,16 +17,26 @@ package net.pterodactylus.sonitus.data.sink; +import static javax.sound.sampled.FloatControl.Type.VOLUME; + import java.io.IOException; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.List; import java.util.logging.Logger; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; +import net.pterodactylus.sonitus.data.Controller; import net.pterodactylus.sonitus.data.Metadata; import net.pterodactylus.sonitus.data.Sink; import net.pterodactylus.sonitus.data.Source; +import net.pterodactylus.sonitus.data.controller.Fader; +import net.pterodactylus.sonitus.data.controller.Switch; +import net.pterodactylus.sonitus.io.IntegralWriteOutputStream; import com.google.common.base.Preconditions; @@ -41,12 +51,92 @@ public class AudioSink implements Sink { /** The logger. */ private static final Logger logger = Logger.getLogger(AudioSink.class.getName()); + /** The volume fader. */ + private final Fader volumeFader; + + /** The “mute” switch. */ + private final Switch muteSwitch; + /** The current metadata. */ private Metadata metadata; /** The audio output. */ private SourceDataLine sourceDataLine; + /** A buffered output stream to ensure correct writing to the source data line. */ + private OutputStream sourceDataLineOutputStream = new IntegralWriteOutputStream(new OutputStream() { + + @Override + public void write(int b) throws IOException { + } + + @Override + public void write(byte[] b) throws IOException { + write(b, 0, b.length); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + if (sourceDataLine != null) { + sourceDataLine.write(b, off, len); + } + } + }, 1024); + + /** Creates a new audio sink. */ + public AudioSink() { + volumeFader = new Fader("Volume") { + + @Override + protected void valueSet(Double value) { + if (sourceDataLine != null) { + FloatControl volumeControl = (FloatControl) sourceDataLine.getControl(VOLUME); + volumeControl.setValue((float) (value * volumeControl.getMaximum())); + } + } + }; + muteSwitch = new Switch("Mute") { + + private float previousValue; + + @Override + protected void valueSet(Boolean value) { + if (sourceDataLine != null) { + FloatControl volumeControl = (FloatControl) sourceDataLine.getControl(VOLUME); + if (value) { + previousValue = volumeControl.getValue(); + volumeControl.setValue(0); + } else { + volumeControl.setValue(previousValue); + } + } + } + }; + } + + // + // CONTROLLED METHODS + // + + @Override + public String name() { + return "Audio Output"; + } + + @Override + public Metadata metadata() { + return metadata; + } + + @Override + public List> controllers() { + return Arrays.>asList(volumeFader, muteSwitch); + } + + // + // SINK METHODS + // + @Override public void open(Metadata metadata) throws IOException { Preconditions.checkArgument(metadata.encoding().equalsIgnoreCase("PCM"), "source must be PCM-encoded"); @@ -69,12 +159,13 @@ public class AudioSink implements Sink { @Override public void metadataUpdated(Metadata metadata) { - /* ignore. */ + logger.info(String.format("Now playing %s.", metadata)); + this.metadata = metadata; } @Override - public void process(byte[] buffer) { - sourceDataLine.write(buffer, 0, buffer.length); + public void process(byte[] buffer) throws IOException { + sourceDataLineOutputStream.write(buffer); logger.finest(String.format("AudioSink: Wrote %d Bytes.", buffer.length)); }