Index: /trunk/test/tmcsim/cadsimulator/SoundPlayerTest.java
===================================================================
--- /trunk/test/tmcsim/cadsimulator/SoundPlayerTest.java	(revision 16)
+++ /trunk/test/tmcsim/cadsimulator/SoundPlayerTest.java	(revision 51)
@@ -36,4 +36,7 @@
         System.out.println("run");
         Vector dummy = new Vector();
+        // the frog clip is actually 3 seconds long, but we specify clip duration of 2
+        // to demonstrate that the subsequent clip will start before the first one finishes.
+        // This shows that SoundPlayer assumes correct clip durations.
         IncidentEvent evt1 = new IncidentEvent(0, null, "frog-croak.mp3", 2, dummy, dummy);
         IncidentEvent evt2 = new IncidentEvent(0, null, "bikehorn.mp3", 1, dummy, dummy);
Index: /trunk/IDE_metadata/NetBeans/TMCSim/nbproject/project.properties
===================================================================
--- /trunk/IDE_metadata/NetBeans/TMCSim/nbproject/project.properties	(revision 43)
+++ /trunk/IDE_metadata/NetBeans/TMCSim/nbproject/project.properties	(revision 51)
@@ -28,6 +28,6 @@
 endorsed.classpath=
 excludes=
+file.reference.jaco-mp3-player-0.9.3.jar=../../../lib/jaco-mp3-player-0.9.3.jar
 file.reference.mockito-1.10.19.jar=../../../lib/mockito-1.10.19.jar
-file.reference.mp3plugin.jar=../../../lib/mp3plugin.jar
 file.reference.tmc-simulator-src=../../../src
 file.reference.tmc-simulator-test=../../../test
@@ -39,7 +39,7 @@
     ${file.reference.xercesImpl.jar}:\
     ${file.reference.uispec4j-jdk17.jar}:\
-    ${file.reference.mp3plugin.jar}:\
     ${file.reference.mockito-1.10.19.jar}:\
-    ${libs.junit_4.classpath}
+    ${libs.junit_4.classpath}:\
+    ${file.reference.jaco-mp3-player-0.9.3.jar}
 # Space-separated list of extra javac options
 javac.compilerargs=
Index: /trunk/src/tmcsim/cadsimulator/SoundPlayer.java
===================================================================
--- /trunk/src/tmcsim/cadsimulator/SoundPlayer.java	(revision 16)
+++ /trunk/src/tmcsim/cadsimulator/SoundPlayer.java	(revision 51)
@@ -1,6 +1,7 @@
 package tmcsim.cadsimulator;
 
+import jaco.mp3.player.MP3Player;
+import java.applet.*;
 import java.io.File;
-import java.io.FileInputStream;
 import java.util.Timer;
 import java.util.TimerTask;
@@ -8,228 +9,285 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
-
-import sun.audio.AudioPlayer;
-import sun.audio.AudioStream;
 import tmcsim.client.cadclientgui.data.IncidentEvent;
 
 /**
- * SoundPlayer is used to play audio files associated with IncidentEvents that 
- * occur during a simulation.  When the SoundPlayer has been enabled audio 
- * clips are enqueued by calling the enqueueClip() method.  The audio files 
- * are played in order of receipt and when finished, the IncidentEvent is 
- * notified.  Audio playing may be disabled or enabled through the 
- * setAudioEnabled() method.  Disabling audio will cause a currently
- * playing audio clip to stop and be requeued at the front of the queue.  
- * Re-enabling the audio will then continue playing all queued clips.  The
- * deQueueAll() method is used to clear the list of audio clips that have 
- * been queued.
+ * SoundPlayer is used to play audio files associated with IncidentEvents that
+ * occur during a simulation. When the SoundPlayer has been enabled audio clips
+ * are enqueued by calling the enqueueClip() method. The audio files are played
+ * in order of receipt and when finished, the IncidentEvent is notified. Audio
+ * playing may be disabled or enabled through the setAudioEnabled() method.
+ * Disabling audio will cause a currently playing audio clip to stop and be
+ * requeued at the front of the queue. Re-enabling the audio will then continue
+ * playing all queued clips. The deQueueAll() method is used to clear the list
+ * of audio clips that have been queued.
  *
  * @author Matthew Cechini (mcechini@calpoly.edu)
- * @version $Date: 2006/06/06 20:46:41 $ $Revision: 1.3 $
+ * @version Date: 2006/06/06 20:46:41
+ * @author Nicolas Russo modified to play mp3 audio.
+ * @version 2016.07.03
  */
-public class SoundPlayer extends Thread {
-    
-    /** Error Logger. */
+public class SoundPlayer extends Thread
+{
+
+    /**
+     * Error Logger.
+     */
     private Logger soundLogger = Logger.getLogger("tmcsim.cadsimulator");
-                                
-    /** The base location that wav files are referenced from */             
+    /**
+     * The base location that wav files are referenced from
+     */
     private String baseAudioDir = "";
-                                
-    /** The private vector of audioClips used during a simulation */
+    /**
+     * The private vector of audioClips used during a simulation
+     */
     private Vector<AudioClipInfo> enqueuedClips = null;
-    
-    /** The audio clip that is currently being played by the AudioPlayer. */
+    /**
+     * The audio clip that is currently being played by the AudioPlayer.
+     */
     private AudioClipInfo currentClip = null;
-    
-    /** Audio stream for playing audio files. */
-    private AudioStream audioStream = null;
-    
-    /**
-     * Flag to designate when an audio file is playing. This prevents 
-     * multiple audio files from being played simultaneously. 
-     * Flag is initialized to false.
-     */
-    private boolean audioPlaying = false;   
-    
-    /** Flag to designate whether audio playing is enabled.  If audio is disabled,
-     *  then enquque events will be ignored.  Flag is initialized to false.
+    /**
+     * Audio stream for playing audio files.
+     */
+    private AudioClip clip = null;
+    private MP3Player mp3Player = null;
+    /**
+     * Flag to designate when an audio file is playing. This prevents multiple
+     * audio files from being played simultaneously. Flag is initialized to
+     * false.
+     */
+    private boolean audioPlaying = false;
+    /**
+     * Flag to designate whether audio playing is enabled. If audio is disabled,
+     * then enquque events will be ignored. Flag is initialized to false.
      */
     private boolean audioEnabled = false;
-    
-    /** Timer used to pause audio player during an audio file. */
+    /**
+     * Timer used to pause audio player during an audio file.
+     */
     private Timer timer = null;
-    
-    /** Inner class used to contain the audio file's name and duration. */
-    private class AudioClipInfo {
+
+    /**
+     * Inner class used to contain the audio file's name and duration.
+     */
+    private class AudioClipInfo
+    {
+
         String fileName;
         int duration;
         IncidentEvent theEvent;
-        
-        AudioClipInfo(IncidentEvent ie) {
+
+        AudioClipInfo(IncidentEvent ie)
+        {
             fileName = ie.waveFile;
-            duration = ie.waveLength;   
+            duration = ie.waveLength;
             theEvent = ie;
-        }       
-                
-        AudioClipInfo(String name, int dur) {
+        }
+
+        AudioClipInfo(String name, int dur)
+        {
             fileName = name;
-            duration = dur; 
+            duration = dur;
             theEvent = null;
-        }   
-        
-        public void wavePlayed() {
-            if(theEvent != null)
+        }
+
+        public void wavePlayed()
+        {
+            if (theEvent != null)
+            {
                 theEvent.wavePlayed();
-        }   
-    }
- 
-    /**
-     * Constructor.  Establish the base file path for wav file referencing.
-     *
-     * @param wavFilePath Pathname for where the simulation wav files will be referenced.
-     */
-    public SoundPlayer(String baseFilePath) {
-        
-        baseAudioDir  = baseFilePath;
-        audioPlaying  = false;
-        audioEnabled  = true;
-        timer         = new Timer();                        
+            }
+        }
+    }
+
+    /**
+     * Constructor. Establish the base file path for wav file referencing.
+     *
+     * @param wavFilePath Pathname for where the simulation wav files will be
+     * referenced.
+     */
+    public SoundPlayer(String baseFilePath)
+    {
+        baseAudioDir = baseFilePath;
+        audioPlaying = false;
+        audioEnabled = true;
+        timer = new Timer();
         enqueuedClips = new Vector<AudioClipInfo>();
     }
 
     /**
-     * Add a audioClipInfo object to the audioClips Vector.  The enqueued audio file will play
-     * when all previously enqueued audio files have been played.  If audio is not enabled, the
-     * clip will not be queued, and the incident event will be notified that the audio clip 
-     * has finished playing to allow the simulation to continue.
+     * Add a audioClipInfo object to the audioClips Vector. The enqueued audio
+     * file will play when all previously enqueued audio files have been played.
+     * If audio is not enabled, the clip will not be queued, and the incident
+     * event will be notified that the audio clip has finished playing to allow
+     * the simulation to continue.
      *
      * @param ie The Incident Event to enqueue to the current list of events.
      */
-    public void enqueueClip (IncidentEvent ie) {
-
-        if(audioEnabled) {
-            synchronized(enqueuedClips)  {
+    public void enqueueClip(IncidentEvent ie)
+    {
+
+        if (audioEnabled)
+        {
+            synchronized (enqueuedClips)
+            {
                 enqueuedClips.add(new AudioClipInfo(ie));
             }
         }
-        else {
+        else
+        {
             ie.wavePlayed();
         }
-    } 
-    
-    /**
-     * Method called when user presses reset in simulation.  All queued events need
-     * to be deQueued.
-     */
-    public void deQueueAll() {
-        synchronized(enqueuedClips) {
+    }
+
+    /**
+     * Method called when user presses reset in simulation. All queued events
+     * need to be deQueued.
+     */
+    public void deQueueAll()
+    {
+        synchronized (enqueuedClips)
+        {
             enqueuedClips.clear();
-        }       
-    }  
-    
-    /** 
+        }
+    }
+
+    /**
      * Get the current audio enabled status.
      *
      * @return True if enabled, false if disabled.
      */
-    public boolean getAudioEnabled() {
+    public boolean getAudioEnabled()
+    {
         return audioEnabled;
-    }   
-    
-    /**
-     * Set the current audio enabled status.  A false value will cause all
-     * enqueue events to be ignored.  A currently playing audio file will be 
-     * stopped and requeued.  All other queued events will remain in the queue.
+    }
+
+    /**
+     * Set the current audio enabled status. A false value will cause all
+     * enqueue events to be ignored. A currently playing audio file will be
+     * stopped and requeued. All other queued events will remain in the queue.
      *
      * @param enable True if enabling, false if disabling.
      */
-    public void setAudioEnabled(boolean enable) {
-        
-        if(!enable) {           
+    public void setAudioEnabled(boolean enable)
+    {
+
+        if (!enable)
+        {
             timer.cancel();
-            AudioPlayer.player.stop(audioStream);
-            
-            if(currentClip != null) {
+            if (clip != null)
+            {
+                clip.stop();
+            }
+            if (mp3Player != null)
+            {
+                mp3Player.stop();
+            }
+
+            if (currentClip != null)
+            {
                 enqueuedClips.add(0, currentClip);
-            }           
-            
+            }
+
             audioPlaying = false;
         }
-        
+
         audioEnabled = enable;
     }
-    
-        
-    /**
-     * Method declaration for the Thread.run() method.  While this thread is not 
-     * interrupted, check if there are enqueued audio files.  If so, remove the 
-     * first one(FIFO) create an AudioClip object, and play the audio file.
-     * A timer tis then started for the duration of the audio file.  When the
-     * timer expires the audioPlaying flag is reset to false and the corresponding
+
+    /**
+     * Method declaration for the Thread.run() method. While this thread is not
+     * interrupted, check if there are enqueued audio files. If so, remove the
+     * first one(FIFO) create an AudioClip object, and play the audio file. A
+     * timer tis then started for the duration of the audio file. When the timer
+     * expires the audioPlaying flag is reset to false and the corresponding
      * incident event is notified of the audio file's completion.
      */
-    public void run() {
+    public void run()
+    {
         AudioClipInfo theClip = null;
-        
-        while(!isInterrupted()) {
-            
-            synchronized(enqueuedClips) {
-                if(enqueuedClips.size() > 0 && !audioPlaying && audioEnabled)
-                    theClip = enqueuedClips.remove(0);                  
-            }
-                
+
+        while (!isInterrupted())
+        {
+
+            synchronized (enqueuedClips)
+            {
+                if (enqueuedClips.size() > 0 && !audioPlaying && audioEnabled)
+                {
+                    theClip = enqueuedClips.remove(0);
+                }
+            }
+
             //if nothing to play, wait a second
-            if(theClip == null) {
-                try { Thread.sleep(1000);} catch (Exception e) {}
-            }
-            else {
-                        
-                try{
-                    
-                    if(theClip.duration > 0) {              
-                        
-                        File audioFile = new File(baseAudioDir + theClip.fileName);
-                        
-                        if(audioFile.exists()) {
-                            audioStream = new AudioStream (new FileInputStream(audioFile));      
-                            AudioPlayer.player.start(audioStream);  
-                        }
-                        else {
+            if (theClip == null)
+            {
+                try
+                {
+                    Thread.sleep(1000);
+                } catch (Exception e)
+                {
+                }
+            }
+            else
+            {
+
+                try
+                {
+
+                    if (theClip.duration > 0)
+                    {
+                        String filename = baseAudioDir + theClip.fileName;
+                        String fileExt = filename.substring(filename.lastIndexOf('.'));
+                        File audioFile = new File(filename);
+
+                        if (audioFile.exists() && fileExt.equals(".mp3"))
+                        {
+                            mp3Player = new MP3Player(audioFile);
+                            mp3Player.play();
+                        }
+                        else if (audioFile.exists() && fileExt.equals(".wav"))
+                        {
+                            clip = Applet.newAudioClip(audioFile.toURI().toURL());
+                            clip.play();
+                        }
+                        else
+                        {
                             throw new Exception();
-                        } 
+                        }
                     }
-                    
-                    currentClip  = theClip;                                             
+
+                    currentClip = theClip;
                     audioPlaying = true;
-                    
+
                     timer = new Timer();
-                    timer.schedule(new TimerTask () {
-                        public void run() {
+                    timer.schedule(new TimerTask()
+                    {
+                        public void run()
+                        {
                             clipPlayed();
-                            audioPlaying = false;                       
+                            audioPlaying = false;
                         }
                     }, theClip.duration * 1000);
-                    
-                    theClip = null;                     
-                } 
-                catch (Exception e) {
-                    soundLogger.logp(Level.WARNING, "SoundPlayer", "run", 
+
+                    theClip = null;
+                } catch (Exception e)
+                {
+                    soundLogger.logp(Level.WARNING, "SoundPlayer", "run",
                             "Unable to play audio file: " + baseAudioDir + theClip.fileName, e);
-    
+
                     theClip.theEvent.wavePlayed();
                     theClip = null;
                     timer.cancel();
-                }   
-            }                               
-        }                       
-    }
-    
-        
-    /**
-     * Called when audio file finishes playing.  Notifies the corresponding 
+                }
+            }
+        }
+    }
+
+    /**
+     * Called when audio file finishes playing. Notifies the corresponding
      * Incident Event that its audio file has finished playing.
      */
-    private void clipPlayed() {
+    private void clipPlayed()
+    {
         currentClip.wavePlayed();
-    }  
+    }
 }
Index: /trunk/src/tmcsim/application.properties
===================================================================
--- /trunk/src/tmcsim/application.properties	(revision 50)
+++ /trunk/src/tmcsim/application.properties	(revision 51)
@@ -1,5 +1,5 @@
-#Sat, 02 Jul 2016 16:19:54 -0700
+#Sun, 03 Jul 2016 06:56:35 -0700
 
 Application.revision=49
 
-Application.buildnumber=19
+Application.buildnumber=20
