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