Advertisement
Guest User

JLayerPausable #2

a guest
Jan 21st, 2013
300
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.39 KB | None | 0 0
  1. /* *-----------------------------------------------------------------------
  2.  *   This program is free software; you can redistribute it and/or modify
  3.  *   it under the terms of the GNU Library General Public License as published
  4.  *   by the Free Software Foundation; either version 2 of the License, or
  5.  *   (at your option) any later version.
  6.  *
  7.  *   This program is distributed in the hope that it will be useful,
  8.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  *   GNU Library General Public License for more details.
  11.  *
  12.  *   You should have received a copy of the GNU Library General Public
  13.  *   License along with this program; if not, write to the Free Software
  14.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  *  
  16.  *   Original by: http://thiscouldbebetter.wordpress.com/2011/07/04/pausing-an-mp3-file-using-jlayer/
  17.  *   Modified: 21-jul-2012 by Arthur Assuncao
  18.  *   Last Modified by Maximilian Berger
  19.  *----------------------------------------------------------------------
  20.  */
  21.  
  22. import java.io.FileInputStream;
  23. import java.io.IOException;
  24. import java.io.InputStream;
  25. import java.net.URL;
  26.  
  27. import javazoom.jl.decoder.Bitstream;
  28. import javazoom.jl.decoder.Decoder;
  29. import javazoom.jl.decoder.Header;
  30. import javazoom.jl.decoder.JavaLayerException;
  31. import javazoom.jl.decoder.SampleBuffer;
  32. import javazoom.jl.player.AudioDevice;
  33. import javazoom.jl.player.FactoryRegistry;
  34.  
  35. public class JLayerPlayerPausable {
  36.     // This class is loosely based on javazoom.jl.player.AdvancedPlayer.
  37.  
  38.     private java.net.URL urlToStreamFrom;
  39.     private String audioPath;
  40.     private Bitstream bitstream;
  41.     private Decoder decoder;
  42.     private AudioDevice audioDevice;
  43.     private boolean closed;
  44.     private boolean complete;
  45.     private boolean paused;
  46.     private boolean stopped;
  47.     private PlaybackListener listener;
  48.     private int frameIndexCurrent;
  49.     private final int lostFrames = 20; // some fraction of a second of the sound
  50.                                         // gets "lost" after every pause. 52 in
  51.                                         // original code
  52.  
  53.     public JLayerPlayerPausable(URL urlToStreamFrom) throws JavaLayerException {
  54.         this.urlToStreamFrom = urlToStreamFrom;
  55.     }
  56.  
  57.     public JLayerPlayerPausable(String audioPath) throws JavaLayerException {
  58.         this.audioPath = audioPath;
  59.     }
  60.  
  61.     public void setPlaybackListener(PlaybackListener newPlaybackListener) {
  62.         if (newPlaybackListener != null) {
  63.             this.listener = newPlaybackListener;
  64.         } else {
  65.             throw new NullPointerException("PlaybackListener is null");
  66.         }
  67.     }
  68.  
  69.     private InputStream getAudioInputStream() throws IOException {
  70.         if (this.audioPath != null) {
  71.             return new FileInputStream(this.audioPath);
  72.         } else if (this.urlToStreamFrom != null) {
  73.             return this.urlToStreamFrom.openStream();
  74.         }
  75.         return null;
  76.     }
  77.  
  78.     public boolean play() throws JavaLayerException {
  79.         return this.play(0);
  80.     }
  81.  
  82.     public boolean play(int frameIndexStart) throws JavaLayerException {
  83.         return this.play(frameIndexStart, -1, lostFrames);
  84.     }
  85.  
  86.     public boolean play(int frameIndexStart, int frameIndexFinal,
  87.             int correctionFactorInFrames) throws JavaLayerException {
  88.         try {
  89.             this.bitstream = new Bitstream(this.getAudioInputStream());
  90.         } catch (IOException e) {
  91.             e.printStackTrace();
  92.         }
  93.         this.audioDevice = FactoryRegistry.systemRegistry().createAudioDevice();
  94.         this.decoder = new Decoder();
  95.         this.audioDevice.open(this.decoder);
  96.  
  97.         boolean shouldContinueReadingFrames = true;
  98.  
  99.         this.paused = false;
  100.         this.stopped = false;
  101.         this.frameIndexCurrent = 0;
  102.  
  103.         while (shouldContinueReadingFrames == true
  104.                 && this.frameIndexCurrent < frameIndexStart
  105.                         - correctionFactorInFrames) {
  106.             shouldContinueReadingFrames = this.skipFrame();
  107.             this.frameIndexCurrent++;
  108.         }
  109.  
  110.         if (this.listener != null) {
  111.             this.listener.playbackStarted(new PlaybackEvent(this,
  112.                     PlaybackEvent.EventType.Started, this.audioDevice
  113.                             .getPosition()));
  114.         }
  115.  
  116.         if (frameIndexFinal < 0) {
  117.             frameIndexFinal = Integer.MAX_VALUE;
  118.         }
  119.  
  120.         while (shouldContinueReadingFrames == true
  121.                 && this.frameIndexCurrent < frameIndexFinal) {
  122.             if (this.paused || this.stopped) {
  123.                 shouldContinueReadingFrames = false;
  124.                 try {
  125.                     Thread.sleep(1);
  126.                 } catch (Exception ex) {
  127.                     ex.printStackTrace();
  128.                 }
  129.             } else {
  130.                 shouldContinueReadingFrames = this.decodeFrame();
  131.                 this.frameIndexCurrent++;
  132.             }
  133.         }
  134.  
  135.         // last frame, ensure all data flushed to the audio device.
  136.         if (this.audioDevice != null && !this.paused) {
  137.             this.audioDevice.flush();
  138.  
  139.             synchronized (this) {
  140.                 this.complete = (this.closed == false);
  141.                 this.close();
  142.             }
  143.  
  144.             // report to listener
  145.             if (this.listener != null) {
  146.                 int audioDevicePosition = -1;
  147.                 if (this.audioDevice != null) {
  148.                     audioDevicePosition = this.audioDevice.getPosition();
  149.                 } else {
  150.                     // throw new
  151.                     // NullPointerException("attribute audioDevice in " +
  152.                     // this.getClass() + " is NULL");
  153.                 }
  154.                 PlaybackEvent playbackEvent = new PlaybackEvent(this,
  155.                         PlaybackEvent.EventType.Stopped,
  156.                         audioDevicePosition);
  157.                 this.listener.playbackFinished(playbackEvent);
  158.             }
  159.         }
  160.  
  161.         return shouldContinueReadingFrames;
  162.     }
  163.  
  164.     public boolean resume() throws JavaLayerException {
  165.         return this.play(this.frameIndexCurrent);
  166.     }
  167.  
  168.     public synchronized void close() {
  169.         if (this.audioDevice != null) {
  170.             this.closed = true;
  171.  
  172.             this.audioDevice.close();
  173.  
  174.             this.audioDevice = null;
  175.  
  176.             try {
  177.                 this.bitstream.close();
  178.             } catch (Exception ex) {
  179.                 ex.printStackTrace();
  180.             }
  181.         }
  182.     }
  183.  
  184.     protected boolean decodeFrame() throws JavaLayerException {
  185.         boolean returnValue = false;
  186.         if (this.stopped) { // nothing for decode
  187.             return false;
  188.         }
  189.  
  190.         /*
  191.          * Fix NullPointer
  192.          */
  193.        
  194.         if(bitstream == null)
  195.             throw new JavaLayerException("Could not open Stream");
  196.        
  197.         try {
  198.             if (this.audioDevice != null) {
  199.                 Header header = this.bitstream.readFrame();
  200.                 if (header != null) {
  201.                     // sample buffer set when decoder constructed
  202.                     SampleBuffer output = (SampleBuffer) this.decoder
  203.                             .decodeFrame(header, this.bitstream);
  204.  
  205.                     synchronized (this) {
  206.                         if (this.audioDevice != null) {
  207.                             this.audioDevice.write(output.getBuffer(), 0,
  208.                                     output.getBufferLength());
  209.                         }
  210.                     }
  211.  
  212.                     this.bitstream.closeFrame();
  213.                     if (listener != null)
  214.                         listener.frameDecoded(new PlaybackEvent(this, PlaybackEvent.EventType.FrameDecoded, audioDevice.getPosition()));
  215.                     returnValue = true;
  216.                 } else {
  217.                     System.out.println("End of file"); // end of file
  218.                     returnValue = false;
  219.                 }
  220.             }
  221.         } catch (RuntimeException ex) {
  222.             throw new JavaLayerException("Exception decoding audio frame", ex);
  223.         }
  224.         return returnValue;
  225.     }
  226.  
  227.     public void pause() {
  228.         if (!stopped) {
  229.             paused = true;
  230.             if (listener != null) {
  231.                 listener.playbackPaused(new PlaybackEvent(this,
  232.                         PlaybackEvent.EventType.Paused,
  233.                         this.audioDevice.getPosition()));
  234.             }
  235.             this.close();
  236.         }
  237.     }
  238.  
  239.     protected boolean skipFrame() throws JavaLayerException {
  240.         boolean returnValue = false;
  241.         Header header = this.bitstream.readFrame();
  242.  
  243.         if (header != null) {
  244.             this.bitstream.closeFrame();
  245.             returnValue = true;
  246.         }
  247.  
  248.         return returnValue;
  249.     }
  250.  
  251.     public void stop() {
  252.         if (!this.stopped) {
  253.             if (!this.closed) {
  254.                 this.listener.playbackFinished(new PlaybackEvent(this,
  255.                         PlaybackEvent.EventType.Stopped,
  256.                         this.audioDevice.getPosition()));
  257.                 this.close();
  258.             } else if (this.paused) {
  259.                 int audioDevicePosition = -1; // this.audioDevice.getPosition(),
  260.                                                 // audioDevice is null
  261.                 if(this.listener != null) //m.berger fix
  262.                     this.listener.playbackFinished(new PlaybackEvent(this,
  263.                         PlaybackEvent.EventType.Stopped,
  264.                         audioDevicePosition));
  265.             }
  266.             this.stopped = true;
  267.         }
  268.     }
  269.  
  270.     /**
  271.      * @return the closed
  272.      */
  273.     public boolean isClosed() {
  274.         return closed;
  275.     }
  276.  
  277.     /**
  278.      * @return the complete
  279.      */
  280.     public boolean isComplete() {
  281.         return complete;
  282.     }
  283.  
  284.     /**
  285.      * @return the paused
  286.      */
  287.     public boolean isPaused() {
  288.         return paused;
  289.     }
  290.  
  291.     /**
  292.      * @return the stopped
  293.      */
  294.     public boolean isStopped() {
  295.         return stopped;
  296.     }
  297.  
  298.  
  299.  
  300.     // inner classes
  301.     public static class PlaybackEvent {
  302.         public JLayerPlayerPausable source;
  303.         public EventType eventType;
  304.         public int frameIndex;
  305.         public static enum EventType{Started, Stopped, Paused, FrameDecoded};
  306.        
  307.         public PlaybackEvent(JLayerPlayerPausable source, EventType eventType, int frameIndex) {
  308.             this.source = source;
  309.             this.eventType = eventType;
  310.             this.frameIndex = frameIndex;
  311.         }
  312.     }
  313.  
  314.     public static class PlaybackAdapter implements PlaybackListener {
  315.         @Override
  316.         public void playbackStarted(PlaybackEvent event) {
  317.             System.err.println("Playback started");
  318.         }
  319.  
  320.         @Override
  321.         public void playbackPaused(PlaybackEvent event) {
  322.             System.err.println("Playback paused");
  323.         }
  324.  
  325.         @Override
  326.         public void playbackFinished(PlaybackEvent event) {
  327.             System.err.println("Playback stopped");
  328.         }
  329.  
  330.         @Override
  331.         public void frameDecoded(PlaybackEvent event) {
  332.             System.err.println("Frame Decoded: " + event.frameIndex);
  333.         }
  334.     }
  335.  
  336.     public static interface PlaybackListener {
  337.         public void playbackStarted(PlaybackEvent event);
  338.  
  339.         public void playbackPaused(PlaybackEvent event);
  340.  
  341.         public void playbackFinished(PlaybackEvent event);
  342.        
  343.         public void frameDecoded(PlaybackEvent event);
  344.     }
  345. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement