~gryle-devel/gryle/trunk-deleted

« back to all changes in this revision

Viewing changes to src/javazoom/jl/player/Player.java

  • Committer: Richard Leo Marsh Warburton
  • Date: 2007-01-13 22:08:02 UTC
  • mto: (1.1.6 gryle)
  • mto: This revision was merged to the branch mainline in revision 9.
  • Revision ID: rlmw@viglab-28-20070113220802-6cjjur0hdk1rce47
added src files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * 11/19/04             1.0 moved to LGPL.
 
3
 * 29/01/00             Initial version. mdm@techie.com
 
4
 *-----------------------------------------------------------------------
 
5
 *   This program is free software; you can redistribute it and/or modify
 
6
 *   it under the terms of the GNU Library General Public License as published
 
7
 *   by the Free Software Foundation; either version 2 of the License, or
 
8
 *   (at your option) any later version.
 
9
 *
 
10
 *   This program is distributed in the hope that it will be useful,
 
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *   GNU Library General Public License for more details.
 
14
 *
 
15
 *   You should have received a copy of the GNU Library General Public
 
16
 *   License along with this program; if not, write to the Free Software
 
17
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
18
 *----------------------------------------------------------------------
 
19
 */
 
20
 
 
21
package javazoom.jl.player;
 
22
 
 
23
import java.io.InputStream;
 
24
 
 
25
import javazoom.jl.decoder.Bitstream;
 
26
import javazoom.jl.decoder.BitstreamException;
 
27
import javazoom.jl.decoder.Decoder;
 
28
import javazoom.jl.decoder.Header;
 
29
import javazoom.jl.decoder.JavaLayerException;
 
30
import javazoom.jl.decoder.SampleBuffer;
 
31
 
 
32
/**
 
33
 * The <code>Player</code> class implements a simple player for playback of an
 
34
 * MPEG audio stream.
 
35
 * 
 
36
 * @author Mat McGowan
 
37
 * @since 0.0.8
 
38
 */
 
39
 
 
40
// REVIEW: the audio device should not be opened until the
 
41
// first MPEG audio frame has been decoded.
 
42
public class Player {
 
43
        /**
 
44
         * The current frame number.
 
45
         */
 
46
        private int frame = 0;
 
47
 
 
48
        /**
 
49
         * The MPEG audio bitstream.
 
50
         */
 
51
        // javac blank final bug.
 
52
        /* final */private Bitstream bitstream;
 
53
 
 
54
        /**
 
55
         * The MPEG audio decoder.
 
56
         */
 
57
        /* final */private Decoder decoder;
 
58
 
 
59
        /**
 
60
         * The AudioDevice the audio samples are written to.
 
61
         */
 
62
        private AudioDevice audio;
 
63
 
 
64
        /**
 
65
         * Has the player been closed?
 
66
         */
 
67
        private boolean closed = false;
 
68
 
 
69
        /**
 
70
         * Has the player played back all frames from the stream?
 
71
         */
 
72
        private boolean complete = false;
 
73
 
 
74
        private int lastPosition = 0;
 
75
 
 
76
        /**
 
77
         * Creates a new <code>Player</code> instance.
 
78
         */
 
79
        public Player(InputStream stream) throws JavaLayerException {
 
80
                this(stream, null);
 
81
        }
 
82
 
 
83
        public Player(InputStream stream, AudioDevice device)
 
84
                        throws JavaLayerException {
 
85
                bitstream = new Bitstream(stream);
 
86
                decoder = new Decoder();
 
87
 
 
88
                if (device != null) {
 
89
                        audio = device;
 
90
                } else {
 
91
                        FactoryRegistry r = FactoryRegistry.systemRegistry();
 
92
                        audio = r.createAudioDevice();
 
93
                }
 
94
                audio.open(decoder);
 
95
        }
 
96
 
 
97
        public void play() throws JavaLayerException {
 
98
                play(Integer.MAX_VALUE);
 
99
        }
 
100
 
 
101
        /**
 
102
         * Plays a number of MPEG audio frames.
 
103
         * 
 
104
         * @param frames
 
105
         *            The number of frames to play.
 
106
         * @return true if the last frame was played, or false if there are more
 
107
         *         frames.
 
108
         */
 
109
        public boolean play(int frames) throws JavaLayerException {
 
110
                boolean ret = true;
 
111
 
 
112
                while (frames-- > 0 && ret) {
 
113
                        ret = decodeFrame();
 
114
                }
 
115
 
 
116
                if (!ret) {
 
117
                        // last frame, ensure all data flushed to the audio device.
 
118
                        AudioDevice out = audio;
 
119
                        if (out != null) {
 
120
                                out.flush();
 
121
                                synchronized (this) {
 
122
                                        complete = (!closed);
 
123
                                        close();
 
124
                                }
 
125
                        }
 
126
                }
 
127
                return ret;
 
128
        }
 
129
 
 
130
        /**
 
131
         * Cloases this player. Any audio currently playing is stopped immediately.
 
132
         */
 
133
        public synchronized void close() {
 
134
                AudioDevice out = audio;
 
135
                if (out != null) {
 
136
                        closed = true;
 
137
                        audio = null;
 
138
                        // this may fail, so ensure object state is set up before
 
139
                        // calling this method.
 
140
                        out.close();
 
141
                        lastPosition = out.getPosition();
 
142
                        try {
 
143
                                bitstream.close();
 
144
                        } catch (BitstreamException ex) {
 
145
                        }
 
146
                }
 
147
        }
 
148
 
 
149
        /**
 
150
         * Returns the completed status of this player.
 
151
         * 
 
152
         * @return true if all available MPEG audio frames have been decoded, or
 
153
         *         false otherwise.
 
154
         */
 
155
        public synchronized boolean isComplete() {
 
156
                return complete;
 
157
        }
 
158
 
 
159
        /**
 
160
         * Retrieves the position in milliseconds of the current audio sample being
 
161
         * played. This method delegates to the <code>
 
162
         * AudioDevice</code> that is
 
163
         * used by this player to sound the decoded audio samples.
 
164
         */
 
165
        public int getPosition() {
 
166
                int position = lastPosition;
 
167
 
 
168
                AudioDevice out = audio;
 
169
                if (out != null) {
 
170
                        position = out.getPosition();
 
171
                }
 
172
                return position;
 
173
        }
 
174
 
 
175
        /**
 
176
         * Decodes a single frame.
 
177
         * 
 
178
         * @return true if there are no more frames to decode, false otherwise.
 
179
         */
 
180
        protected boolean decodeFrame() throws JavaLayerException {
 
181
                try {
 
182
                        AudioDevice out = audio;
 
183
                        if (out == null)
 
184
                                return false;
 
185
 
 
186
                        Header h = bitstream.readFrame();
 
187
 
 
188
                        if (h == null)
 
189
                                return false;
 
190
 
 
191
                        // sample buffer set when decoder constructed
 
192
                        SampleBuffer output = (SampleBuffer) decoder.decodeFrame(h,
 
193
                                        bitstream);
 
194
 
 
195
                        synchronized (this) {
 
196
                                out = audio;
 
197
                                if (out != null) {
 
198
                                        out.write(output.getBuffer(), 0, output.getBufferLength());
 
199
                                }
 
200
                        }
 
201
 
 
202
                        bitstream.closeFrame();
 
203
                } catch (RuntimeException ex) {
 
204
                        throw new JavaLayerException("Exception decoding audio frame", ex);
 
205
                }
 
206
                /*
 
207
                 * catch (IOException ex) { System.out.println("exception decoding audio
 
208
                 * frame: "+ex); return false; } catch (BitstreamException bitex) {
 
209
                 * System.out.println("exception decoding audio frame: "+bitex); return
 
210
                 * false; } catch (DecoderException decex) {
 
211
                 * System.out.println("exception decoding audio frame: "+decex); return
 
212
                 * false; }
 
213
                 */
 
214
                return true;
 
215
        }
 
216
 
 
217
}