aboutsummaryrefslogtreecommitdiff
path: root/subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/AudioPlayer.java
diff options
context:
space:
mode:
Diffstat (limited to 'subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/AudioPlayer.java')
-rw-r--r--subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/AudioPlayer.java207
1 files changed, 0 insertions, 207 deletions
diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/AudioPlayer.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/AudioPlayer.java
deleted file mode 100644
index 902387be..00000000
--- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/AudioPlayer.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.service.jukebox;
-
-import java.io.BufferedInputStream;
-import java.io.InputStream;
-import java.util.concurrent.atomic.AtomicReference;
-
-import javax.sound.sampled.AudioFormat;
-import javax.sound.sampled.AudioSystem;
-import javax.sound.sampled.FloatControl;
-import javax.sound.sampled.SourceDataLine;
-
-import org.apache.commons.io.IOUtils;
-
-import net.sourceforge.subsonic.Logger;
-import net.sourceforge.subsonic.service.JukeboxService;
-
-import static net.sourceforge.subsonic.service.jukebox.AudioPlayer.State.*;
-
-/**
- * A simple wrapper for playing sound from an input stream.
- * <p/>
- * Supports pause and resume, but not restarting.
- *
- * @author Sindre Mehus
- * @version $Id$
- */
-public class AudioPlayer {
-
- private static final Logger LOG = Logger.getLogger(JukeboxService.class);
-
- private final InputStream in;
- private final Listener listener;
- private final SourceDataLine line;
- private final AtomicReference<State> state = new AtomicReference<State>(PAUSED);
- private FloatControl gainControl;
-
- public AudioPlayer(InputStream in, Listener listener) throws Exception {
- this.in = new BufferedInputStream(in);
- this.listener = listener;
-
- AudioFormat format = AudioSystem.getAudioFileFormat(this.in).getFormat();
- line = AudioSystem.getSourceDataLine(format);
- line.open(format);
- LOG.debug("Opened line " + line);
-
- if (line.isControlSupported(FloatControl.Type.MASTER_GAIN)) {
- gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN);
- setGain(0.5f);
- }
- new AudioDataWriter();
- }
-
- /**
- * Starts (or resumes) the player. This only has effect if the current state is
- * {@link State#PAUSED}.
- */
- public synchronized void play() {
- if (state.get() == PAUSED) {
- line.start();
- setState(PLAYING);
- }
- }
-
- /**
- * Pauses the player. This only has effect if the current state is
- * {@link State#PLAYING}.
- */
- public synchronized void pause() {
- if (state.get() == PLAYING) {
- setState(PAUSED);
- line.stop();
- line.flush();
- }
- }
-
- /**
- * Closes the player, releasing all resources. After this the player state is
- * {@link State#CLOSED} (unless the current state is {@link State#EOM}).
- */
- public synchronized void close() {
- if (state.get() != CLOSED && state.get() != EOM) {
- setState(CLOSED);
- }
-
- try {
- line.stop();
- } catch (Throwable x) {
- LOG.warn("Failed to stop player: " + x, x);
- }
- try {
- if (line.isOpen()) {
- line.close();
- LOG.debug("Closed line " + line);
- }
- } catch (Throwable x) {
- LOG.warn("Failed to close player: " + x, x);
- }
- IOUtils.closeQuietly(in);
- }
-
- /**
- * Returns the player state.
- */
- public State getState() {
- return state.get();
- }
-
- /**
- * Sets the gain.
- *
- * @param gain The gain between 0.0 and 1.0.
- */
- public void setGain(float gain) {
- if (gainControl != null) {
-
- double minGainDB = gainControl.getMinimum();
- double maxGainDB = gainControl.getMaximum();
- double ampGainDB = 0.5f * maxGainDB - minGainDB;
- double cste = Math.log(10.0) / 20;
- double valueDB = minGainDB + (1 / cste) * Math.log(1 + (Math.exp(cste * ampGainDB) - 1) * gain);
-
- valueDB = Math.min(valueDB, maxGainDB);
- valueDB = Math.max(valueDB, minGainDB);
-
- gainControl.setValue((float) valueDB);
- }
- }
-
- /**
- * Returns the position in seconds.
- */
- public int getPosition() {
- return (int) (line.getMicrosecondPosition() / 1000000L);
- }
-
- private void setState(State state) {
- if (this.state.getAndSet(state) != state && listener != null) {
- listener.stateChanged(this, state);
- }
- }
-
- private class AudioDataWriter implements Runnable {
-
- public AudioDataWriter() {
- new Thread(this).start();
- }
-
- public void run() {
- try {
- byte[] buffer = new byte[8192];
-
- while (true) {
-
- switch (state.get()) {
- case CLOSED:
- case EOM:
- return;
- case PAUSED:
- Thread.sleep(250);
- break;
- case PLAYING:
- int n = in.read(buffer);
- if (n == -1) {
- setState(EOM);
- return;
- }
- line.write(buffer, 0, n);
- break;
- }
- }
- } catch (Throwable x) {
- LOG.warn("Error when copying audio data: " + x, x);
- } finally {
- close();
- }
- }
- }
-
- public interface Listener {
- void stateChanged(AudioPlayer player, State state);
- }
-
- public static enum State {
- PAUSED,
- PLAYING,
- CLOSED,
- EOM
- }
-}