package fr.edmhouse.audio; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import fr.edmhouse.main.EDMHouse; import javazoom.jl.decoder.Bitstream; import javazoom.jl.decoder.BitstreamException; import javazoom.jl.decoder.Decoder; import javazoom.jl.decoder.JavaLayerException; import javazoom.jl.player.AudioDevice; import javazoom.jl.player.FactoryRegistry; import javazoom.jl.player.advenced.AdvancedPlayer; import javazoom.jl.player.advenced.PlaybackEvent; /** * A custom recursive version of JLayer's AdvancedPlayer that skip to desired * location when it should. Used to be able to pause but not anymore. */ public class CustomPlayer extends AdvancedPlayer { /** * A backup of the FilePath used when constructing the player. Comes handy * when you need to reset the Bitstream of the player. */ private String pathBackup; /** * Is true if the player created a new player inside of him to play an other * part of the song for him. In this case the * <code>inceptionnedPlayer</code> var will point to the player playing. * Keep in mind that this player can also be inceptionned any number of * times. */ private boolean isinceptionned = false; /** COntains the inceptionnedPlayer of the current one if it exists. */ private CustomPlayer inceptionnedPlayer; /** * Creates a new <code>Player</code> instance. */ public CustomPlayer(String path) throws JavaLayerException { this.pathBackup = path; try { FileInputStream fis = new FileInputStream(path); super.bitstream = new Bitstream(fis); } catch (FileNotFoundException e) { } super.audio = FactoryRegistry.systemRegistry().createAudioDevice(); super.audio.open(super.decoder = new Decoder()); } /** * Creates a new <code>Player</code> instance. */ public CustomPlayer(InputStream stream) throws JavaLayerException { this(stream, null); } /** * Creates a new <code>Player</code> instance. */ public CustomPlayer(InputStream stream, AudioDevice device) throws JavaLayerException { super.bitstream = new Bitstream(stream); if (device != null) super.audio = device; else super.audio = FactoryRegistry.systemRegistry().createAudioDevice(); super.audio.open(super.decoder = new Decoder()); } @Override public void play() throws JavaLayerException { play(Integer.MAX_VALUE); } /** * Plays a number of MPEG audio frames. * * @param frames * The number of frames to play. * @return true if the last frame was played, or false if there are more * frames. */ @Override public boolean play(int frames) throws JavaLayerException { boolean ret = true, shouldendfunction = true; if (listener != null) listener.playbackStarted(createEvent(PlaybackEvent.STARTED)); for (; frames > 0 && ret && shouldendfunction;) { if (EDMHouse.BGM.needjump) { shouldendfunction = false; EDMHouse.BGM.needjump = false; this.isinceptionned = true; this.inceptionnedPlayer = new CustomPlayer(this.pathBackup); int position = (int) ((((float) EDMHouse.frame.canvas.progression)) / 26); // Because a mp3 frame length is always 0.026 sec. this.inceptionnedPlayer.play(position, Integer.MAX_VALUE); complete = true; } else { ret = decodeFrame(); frames--; } } if (shouldendfunction) { AudioDevice out = audio; if (out != null) { out.flush(); synchronized (this) { complete = (!closed); close(); } if (listener != null) listener.playbackFinished(createEvent(out, PlaybackEvent.STOPPED)); } } return ret; } /** * Plays a range of MPEG audio frames * * @param start * The first frame to play * @param end * The last frame to play * @return true if the last frame was played, or false if there are more * frames. */ @Override public boolean play(final int start, final int end) throws JavaLayerException { boolean ret = true; int offset = start; while (offset-- > 0 && ret) ret = skipFrame(); return play(end - start); } /** * Cloases this player. Any audio currently playing is stopped immediately. */ public synchronized void close() { AudioDevice out = audio; if (out != null) { closed = true; audio = null; out.close(); try { bitstream.close(); } catch (BitstreamException ex) { } if (this.isinceptionned) this.inceptionnedPlayer.close(); } } }