Warning: Can't use blame annotator:
svn blame failed on trunk/src/tmcsim/cadsimulator/SoundPlayer.java: ("Can't find a temporary directory: Internal error", 20014)

source: tmcsimulator/trunk/src/tmcsim/cadsimulator/SoundPlayer.java @ 51

Revision 51, 8.5 KB checked in by jdalbey, 10 years ago (diff)

SoundPlayer?.java modified to use Jaco mp3player instead of obsolete Sun libraries

RevLine 
1package tmcsim.cadsimulator;
2
3import jaco.mp3.player.MP3Player;
4import java.applet.*;
5import java.io.File;
6import java.util.Timer;
7import java.util.TimerTask;
8import java.util.Vector;
9import java.util.logging.Level;
10import java.util.logging.Logger;
11import tmcsim.client.cadclientgui.data.IncidentEvent;
12
13/**
14 * SoundPlayer is used to play audio files associated with IncidentEvents that
15 * occur during a simulation. When the SoundPlayer has been enabled audio clips
16 * are enqueued by calling the enqueueClip() method. The audio files are played
17 * in order of receipt and when finished, the IncidentEvent is notified. Audio
18 * playing may be disabled or enabled through the setAudioEnabled() method.
19 * Disabling audio will cause a currently playing audio clip to stop and be
20 * requeued at the front of the queue. Re-enabling the audio will then continue
21 * playing all queued clips. The deQueueAll() method is used to clear the list
22 * of audio clips that have been queued.
23 *
24 * @author Matthew Cechini (mcechini@calpoly.edu)
25 * @version Date: 2006/06/06 20:46:41
26 * @author Nicolas Russo modified to play mp3 audio.
27 * @version 2016.07.03
28 */
29public class SoundPlayer extends Thread
30{
31
32    /**
33     * Error Logger.
34     */
35    private Logger soundLogger = Logger.getLogger("tmcsim.cadsimulator");
36    /**
37     * The base location that wav files are referenced from
38     */
39    private String baseAudioDir = "";
40    /**
41     * The private vector of audioClips used during a simulation
42     */
43    private Vector<AudioClipInfo> enqueuedClips = null;
44    /**
45     * The audio clip that is currently being played by the AudioPlayer.
46     */
47    private AudioClipInfo currentClip = null;
48    /**
49     * Audio stream for playing audio files.
50     */
51    private AudioClip clip = null;
52    private MP3Player mp3Player = null;
53    /**
54     * Flag to designate when an audio file is playing. This prevents multiple
55     * audio files from being played simultaneously. Flag is initialized to
56     * false.
57     */
58    private boolean audioPlaying = false;
59    /**
60     * Flag to designate whether audio playing is enabled. If audio is disabled,
61     * then enquque events will be ignored. Flag is initialized to false.
62     */
63    private boolean audioEnabled = false;
64    /**
65     * Timer used to pause audio player during an audio file.
66     */
67    private Timer timer = null;
68
69    /**
70     * Inner class used to contain the audio file's name and duration.
71     */
72    private class AudioClipInfo
73    {
74
75        String fileName;
76        int duration;
77        IncidentEvent theEvent;
78
79        AudioClipInfo(IncidentEvent ie)
80        {
81            fileName = ie.waveFile;
82            duration = ie.waveLength;
83            theEvent = ie;
84        }
85
86        AudioClipInfo(String name, int dur)
87        {
88            fileName = name;
89            duration = dur;
90            theEvent = null;
91        }
92
93        public void wavePlayed()
94        {
95            if (theEvent != null)
96            {
97                theEvent.wavePlayed();
98            }
99        }
100    }
101
102    /**
103     * Constructor. Establish the base file path for wav file referencing.
104     *
105     * @param wavFilePath Pathname for where the simulation wav files will be
106     * referenced.
107     */
108    public SoundPlayer(String baseFilePath)
109    {
110        baseAudioDir = baseFilePath;
111        audioPlaying = false;
112        audioEnabled = true;
113        timer = new Timer();
114        enqueuedClips = new Vector<AudioClipInfo>();
115    }
116
117    /**
118     * Add a audioClipInfo object to the audioClips Vector. The enqueued audio
119     * file will play when all previously enqueued audio files have been played.
120     * If audio is not enabled, the clip will not be queued, and the incident
121     * event will be notified that the audio clip has finished playing to allow
122     * the simulation to continue.
123     *
124     * @param ie The Incident Event to enqueue to the current list of events.
125     */
126    public void enqueueClip(IncidentEvent ie)
127    {
128
129        if (audioEnabled)
130        {
131            synchronized (enqueuedClips)
132            {
133                enqueuedClips.add(new AudioClipInfo(ie));
134            }
135        }
136        else
137        {
138            ie.wavePlayed();
139        }
140    }
141
142    /**
143     * Method called when user presses reset in simulation. All queued events
144     * need to be deQueued.
145     */
146    public void deQueueAll()
147    {
148        synchronized (enqueuedClips)
149        {
150            enqueuedClips.clear();
151        }
152    }
153
154    /**
155     * Get the current audio enabled status.
156     *
157     * @return True if enabled, false if disabled.
158     */
159    public boolean getAudioEnabled()
160    {
161        return audioEnabled;
162    }
163
164    /**
165     * Set the current audio enabled status. A false value will cause all
166     * enqueue events to be ignored. A currently playing audio file will be
167     * stopped and requeued. All other queued events will remain in the queue.
168     *
169     * @param enable True if enabling, false if disabling.
170     */
171    public void setAudioEnabled(boolean enable)
172    {
173
174        if (!enable)
175        {
176            timer.cancel();
177            if (clip != null)
178            {
179                clip.stop();
180            }
181            if (mp3Player != null)
182            {
183                mp3Player.stop();
184            }
185
186            if (currentClip != null)
187            {
188                enqueuedClips.add(0, currentClip);
189            }
190
191            audioPlaying = false;
192        }
193
194        audioEnabled = enable;
195    }
196
197    /**
198     * Method declaration for the Thread.run() method. While this thread is not
199     * interrupted, check if there are enqueued audio files. If so, remove the
200     * first one(FIFO) create an AudioClip object, and play the audio file. A
201     * timer tis then started for the duration of the audio file. When the timer
202     * expires the audioPlaying flag is reset to false and the corresponding
203     * incident event is notified of the audio file's completion.
204     */
205    public void run()
206    {
207        AudioClipInfo theClip = null;
208
209        while (!isInterrupted())
210        {
211
212            synchronized (enqueuedClips)
213            {
214                if (enqueuedClips.size() > 0 && !audioPlaying && audioEnabled)
215                {
216                    theClip = enqueuedClips.remove(0);
217                }
218            }
219
220            //if nothing to play, wait a second
221            if (theClip == null)
222            {
223                try
224                {
225                    Thread.sleep(1000);
226                } catch (Exception e)
227                {
228                }
229            }
230            else
231            {
232
233                try
234                {
235
236                    if (theClip.duration > 0)
237                    {
238                        String filename = baseAudioDir + theClip.fileName;
239                        String fileExt = filename.substring(filename.lastIndexOf('.'));
240                        File audioFile = new File(filename);
241
242                        if (audioFile.exists() && fileExt.equals(".mp3"))
243                        {
244                            mp3Player = new MP3Player(audioFile);
245                            mp3Player.play();
246                        }
247                        else if (audioFile.exists() && fileExt.equals(".wav"))
248                        {
249                            clip = Applet.newAudioClip(audioFile.toURI().toURL());
250                            clip.play();
251                        }
252                        else
253                        {
254                            throw new Exception();
255                        }
256                    }
257
258                    currentClip = theClip;
259                    audioPlaying = true;
260
261                    timer = new Timer();
262                    timer.schedule(new TimerTask()
263                    {
264                        public void run()
265                        {
266                            clipPlayed();
267                            audioPlaying = false;
268                        }
269                    }, theClip.duration * 1000);
270
271                    theClip = null;
272                } catch (Exception e)
273                {
274                    soundLogger.logp(Level.WARNING, "SoundPlayer", "run",
275                            "Unable to play audio file: " + baseAudioDir + theClip.fileName, e);
276
277                    theClip.theEvent.wavePlayed();
278                    theClip = null;
279                    timer.cancel();
280                }
281            }
282        }
283    }
284
285    /**
286     * Called when audio file finishes playing. Notifies the corresponding
287     * Incident Event that its audio file has finished playing.
288     */
289    private void clipPlayed()
290    {
291        currentClip.wavePlayed();
292    }
293}
Note: See TracBrowser for help on using the repository browser.