Logo Search packages:      
Sourcecode: libjlayer-java version File versions  Download package

AdvancedPlayer.java

/*
 * 11/19/04       1.0 moved to LGPL. 
 *-----------------------------------------------------------------------
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as published
 *   by the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program 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 Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *----------------------------------------------------------------------
 */

package javazoom.jl.player.advanced;

import java.io.InputStream;

import javazoom.jl.decoder.Bitstream;
import javazoom.jl.decoder.BitstreamException;
import javazoom.jl.decoder.Decoder;
import javazoom.jl.decoder.Header;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.decoder.SampleBuffer;
import javazoom.jl.player.AudioDevice;
import javazoom.jl.player.FactoryRegistry;

/**
 * a hybrid of javazoom.jl.player.Player tweeked to include <code>play(startFrame, endFrame)</code>
 * hopefully this will be included in the api
 */
00037 public class AdvancedPlayer
{
      /** The MPEG audio bitstream.*/
00040       private Bitstream bitstream;
      /** The MPEG audio decoder. */
00042       private Decoder decoder;
      /** The AudioDevice the audio samples are written to. */
00044       private AudioDevice audio;
      /** Has the player been closed? */
00046       private boolean closed = false;
      /** Has the player played back all frames from the stream? */
00048       private boolean complete = false;
      private int lastPosition = 0;
      /** Listener for the playback process */
00051       private PlaybackListener listener;

      /**
       * Creates a new <code>Player</code> instance.
       */
00056       public AdvancedPlayer(InputStream stream) throws JavaLayerException
      {
            this(stream, null);
      }

      public AdvancedPlayer(InputStream stream, AudioDevice device) throws JavaLayerException
      {
            bitstream = new Bitstream(stream);

            if (device!=null) audio = device;
            else audio = FactoryRegistry.systemRegistry().createAudioDevice();
            audio.open(decoder = new Decoder());
      }

      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.
       */
00082       public boolean play(int frames) throws JavaLayerException
      {
            boolean ret = true;

            // report to listener
            if(listener != null) listener.playbackStarted(createEvent(PlaybackEvent.STARTED));

            while (frames-- > 0 && ret)
            {
                  ret = decodeFrame();
            }

//          if (!ret)
            {
                  // last frame, ensure all data flushed to the audio device.
                  AudioDevice out = audio;
                  if (out != null)
                  {
//                      System.out.println(audio.getPosition());
                        out.flush();
//                      System.out.println(audio.getPosition());
                        synchronized (this)
                        {
                              complete = (!closed);
                              close();
                        }

                        // report to listener
                        if(listener != null) listener.playbackFinished(createEvent(out, PlaybackEvent.STOPPED));
                  }
            }
            return ret;
      }

      /**
       * Cloases this player. Any audio currently playing is stopped
       * immediately.
       */
00120       public synchronized void close()
      {
            AudioDevice out = audio;
            if (out != null)
            {
                  closed = true;
                  audio = null;
                  // this may fail, so ensure object state is set up before
                  // calling this method.
                  out.close();
                  lastPosition = out.getPosition();
                  try
                  {
                        bitstream.close();
                  }
                  catch (BitstreamException ex)
                  {}
            }
      }

      /**
       * Decodes a single frame.
       *
       * @return true if there are no more frames to decode, false otherwise.
       */
00145       protected boolean decodeFrame() throws JavaLayerException
      {
            try
            {
                  AudioDevice out = audio;
                  if (out == null) return false;

                  Header h = bitstream.readFrame();
                  if (h == null) return false;

                  // sample buffer set when decoder constructed
                  SampleBuffer output = (SampleBuffer) decoder.decodeFrame(h, bitstream);

                  synchronized (this)
                  {
                        out = audio;
                        if(out != null)
                        {
                              out.write(output.getBuffer(), 0, output.getBufferLength());
                        }
                  }

                  bitstream.closeFrame();
            }
            catch (RuntimeException ex)
            {
                  throw new JavaLayerException("Exception decoding audio frame", ex);
            }
            return true;
      }

      /**
       * skips over a single frame
       * @return false  if there are no more frames to decode, true otherwise.
       */
00180       protected boolean skipFrame() throws JavaLayerException
      {
            Header h = bitstream.readFrame();
            if (h == null) return false;
            bitstream.closeFrame();
            return true;
      }

      /**
       * 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.
       */
00194       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);
      }

      /**
       * Constructs a <code>PlaybackEvent</code>
       */
00205       private PlaybackEvent createEvent(int id)
      {
            return createEvent(audio, id);
      }

      /**
       * Constructs a <code>PlaybackEvent</code>
       */
00213       private PlaybackEvent createEvent(AudioDevice dev, int id)
      {
            return new PlaybackEvent(this, id, dev.getPosition());
      }

      /**
       * sets the <code>PlaybackListener</code>
       */
00221       public void setPlayBackListener(PlaybackListener listener)
      {
            this.listener = listener;
      }

      /**
       * gets the <code>PlaybackListener</code>
       */
00229       public PlaybackListener getPlayBackListener()
      {
            return listener;
      }

      /**
       * closes the player and notifies <code>PlaybackListener</code>
       */
00237       public void stop()
      {
            listener.playbackFinished(createEvent(PlaybackEvent.STOPPED));
            close();
      }
}

Generated by  Doxygen 1.6.0   Back to index