
berlin.yuna.tinkerforgesensor.model.AudioDevice Maven / Gradle / Ivy
package berlin.yuna.tinkerforgesensor.model;
import berlin.yuna.tinkerforgesensor.util.AudioControl;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.BooleanControl;
import javax.sound.sampled.Clip;
import javax.sound.sampled.CompoundControl;
import javax.sound.sampled.Control;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public class AudioDevice {
public final Mixer mixer;
public final Line line;
public final Line.Info lineInfo;
public final Mixer.Info mixerInfo;
public final boolean output;
public final boolean playback;
public long microsecondPosition;
public URL source;
public AudioDevice() {
try {
final AudioDevice audioDevice = createAudioDevice();
this.mixer = audioDevice.mixer;
this.line = audioDevice.line;
this.lineInfo = audioDevice.lineInfo;
this.mixerInfo = audioDevice.mixerInfo;
this.output = audioDevice.output;
this.playback = audioDevice.playback;
} catch (LineUnavailableException e) {
throw new RuntimeException(e);
}
}
public AudioDevice(final Line line, final Mixer mixer, final boolean output) {
this(mixer, line, line.getLineInfo(), mixer.getMixerInfo(), output, line instanceof Clip);
}
public AudioDevice(final Mixer mixer, final Line line, final Line.Info lineInfo, final Mixer.Info mixerInfo, final boolean output, final boolean playback) {
this.mixer = mixer;
this.line = line;
this.lineInfo = lineInfo;
this.mixerInfo = mixerInfo;
this.output = output;
this.playback = playback;
}
public int getVolume() {
final AtomicInteger volume = new AtomicInteger(-1);
openLine(open -> {
final FloatControl volCtrl = (FloatControl) findControl(FloatControl.Type.VOLUME);
if (volCtrl != null) {
volume.set((int) Math.round(volCtrl.getValue() * 100.0));
}
});
return volume.get();
}
public void setVolume(final int volume) {
openLine(open -> {
final FloatControl volCtrl = (FloatControl) findControl(FloatControl.Type.VOLUME);
if (volCtrl != null) {
volCtrl.setValue(volume / 100.0f);
}
});
}
public int getBalance() {
final AtomicInteger volume = new AtomicInteger(-1);
openLine(open -> {
final FloatControl volCtrl = (FloatControl) findControl(FloatControl.Type.BALANCE);
if (volCtrl != null) {
volume.set((int) Math.round(volCtrl.getValue() * 100.0));
}
});
return volume.get();
}
public void setBalance(final int volume) {
openLine(open -> {
final FloatControl volCtrl = (FloatControl) findControl(FloatControl.Type.BALANCE);
if (volCtrl != null) {
volCtrl.setValue(volume / 100.0f);
}
});
}
public boolean getMute() {
final AtomicBoolean mute = new AtomicBoolean(false);
openLine(open -> {
final BooleanControl muteCtrl = (BooleanControl) findControl(BooleanControl.Type.MUTE);
mute.set(muteCtrl != null && muteCtrl.getValue());
});
return mute.get();
}
public void setMute(final boolean mute) {
openLine(open -> {
if(open) {
final BooleanControl muteCtrl = (BooleanControl) findControl(BooleanControl.Type.MUTE);
if (muteCtrl != null) {
muteCtrl.setValue(mute);
}
}
});
}
public void setSource(final URL url) {
source = url;
microsecondPosition = 0;
}
public void play() {
if (playback && source != null) {
openClip(clip -> {
clip.setFramePosition(0);
clip.setMicrosecondPosition(microsecondPosition);
clip.start();
});
}
}
public void pause() {
if (playback && source != null) {
openLine(open -> {
final Clip clip = (Clip) line;
microsecondPosition = clip.getMicrosecondPosition();
clip.stop();
});
}
}
public void replay() {
if (playback && source != null) {
microsecondPosition = 0;
// clip.setFramePosition(0); // Must always rewind!
play();
}
}
public void stop() {
if (playback && source != null) {
openLine(open -> {
final Clip clip = (Clip) line;
clip.stop();
microsecondPosition = 0;
});
}
}
public boolean isRunning() {
final AtomicBoolean isRunning = new AtomicBoolean(false);
if (playback) {
openLine(open -> {
final Clip clip = (Clip) line;
isRunning.set(clip.isRunning());
});
}
return isRunning.get();
}
private void openClip(final Consumer consumer) {
final Clip clip = (Clip) this.line;
try {
final boolean opened = clip.isOpen();
if (!opened) {
clip.open(AudioSystem.getAudioInputStream(source));
}
} catch (LineUnavailableException | UnsupportedAudioFileException | IOException ignored) {
}
consumer.accept(clip);
}
private void openLine(final Consumer consumer) {
try {
final boolean opened = line.isOpen() || line instanceof Clip;
if (!opened) {
line.open();
}
} catch (LineUnavailableException ignored) {
}
consumer.accept(line.isOpen());
}
private Control findControl(final Control.Type type) {
if(line.isOpen()) {
return findControl(type, line.getControls());
}
return null;
}
private Control findControl(final Control.Type type, final Control... controls) {
if (controls == null || controls.length == 0) return null;
for (Control control : controls) {
if (control.getType().equals(type)) return control;
if (control instanceof CompoundControl) {
final CompoundControl compoundControl = (CompoundControl) control;
final Control member = findControl(type, compoundControl.getMemberControls());
if (member != null) return member;
}
}
return null;
}
private static AudioDevice createAudioDevice() throws LineUnavailableException {
final AudioDevice device = new AudioControl().getDefaultDevice();
final Mixer mixer = device != null ? device.mixer : AudioSystem.getMixer(AudioSystem.getMixerInfo()[0]);
return new AudioDevice(AudioSystem.getClip(), mixer, false);
}
@Override
public String toString() {
return "AudioDevice{" +
"lineInfo=" + (lineInfo != null ? lineInfo.toString() : mixer.getMixerInfo()) +
'}';
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy