2323
2424package  com .iluwatar .event .queue ;
2525
26+ import  org .slf4j .Logger ;
27+ import  org .slf4j .LoggerFactory ;
28+ 
2629import  java .io .File ;
2730import  java .io .IOException ;
2831
3841 * 
3942 */ 
4043public  class  Audio  {
44+   private  static  final  Logger  LOGGER  = LoggerFactory .getLogger (Audio .class );
45+   private  static  final  Audio  INSTANCE  = new  Audio ();
4146
4247  private  static  final  int  MAX_PENDING  = 16 ;
4348
44-   private  static  int  headIndex ;
49+   private  int  headIndex ;
50+ 
51+   private  int  tailIndex ;
4552
46-   private  static   int   tailIndex ;
53+   private  volatile   Thread   updateThread  =  null ;
4754
48-   private  static   Thread   updateThread  =  null ;
55+   private  PlayMessage []  pendingAudio  =  new   PlayMessage [ MAX_PENDING ] ;
4956
50-   private  static  PlayMessage [] pendingAudio  = new  PlayMessage [MAX_PENDING ];
57+   // Visible only for testing purposes 
58+   Audio () {
59+ 
60+   }
61+ 
62+   public  static  Audio  getInstance () {
63+     return  INSTANCE ;
64+   }
5165
5266  /** 
53-    * This method stops the Update Method's thread.   
67+    * This method stops the Update Method's thread and waits till service stops.  
5468   */ 
55-   public  static   synchronized  void  stopService () {
69+   public  synchronized  void  stopService ()  throws   InterruptedException  {
5670    if  (updateThread  != null ) {
5771      updateThread .interrupt ();
5872    }
73+     updateThread .join ();
74+     updateThread  = null ;
5975  }
6076
6177  /** 
6278   * This method check the Update Method's thread is started. 
6379   * @return boolean 
6480   */ 
65-   public  static  synchronized  boolean  isServiceRunning () {
66-     if  (updateThread  != null  && updateThread .isAlive () ) {
67-       return  true ;
68-     } else  {
69-       return  false ;
70-     }
81+   public  synchronized  boolean  isServiceRunning () {
82+     return  updateThread  != null  && updateThread .isAlive ();
7183  }
7284
7385  /** 
7486   * Starts the thread for the Update Method pattern if it was not started previously. 
7587   * Also when the thread is is ready initializes the indexes of the queue  
7688   */ 
77-   public  static   void  init () {
89+   public  void  init () {
7890    if  (updateThread  == null ) {
79-       updateThread  = new  Thread (new  Runnable () {
80-         public  void  run () {
81-           while  (!Thread .currentThread ().isInterrupted ()) {
82-             Audio .update ();
83-           }
91+       updateThread  = new  Thread (() -> {
92+         while  (!Thread .currentThread ().isInterrupted ()) {
93+           update ();
8494        }
8595      });
8696    }
@@ -90,7 +100,7 @@ public void run() {
90100  /** 
91101   * This is a synchronized thread starter 
92102   */ 
93-   public   static  synchronized  void  startThread () {
103+   private  synchronized  void  startThread () {
94104    if  (!updateThread .isAlive ()) {
95105      updateThread .start ();
96106      headIndex  = 0 ;
@@ -103,7 +113,7 @@ public static synchronized void startThread() {
103113   * @param stream is the AudioInputStream for the method 
104114   * @param volume is the level of the audio's volume  
105115   */ 
106-   public  static   void  playSound (AudioInputStream  stream , float  volume ) {
116+   public  void  playSound (AudioInputStream  stream , float  volume ) {
107117    init ();
108118    // Walk the pending requests. 
109119    for  (int  i  = headIndex ; i  != tailIndex ; i  = (i  + 1 ) % MAX_PENDING ) {
@@ -123,7 +133,7 @@ public static void playSound(AudioInputStream stream, float volume) {
123133   * This method uses the Update Method pattern. 
124134   * It takes the audio from the queue and plays it 
125135   */ 
126-   public   static  void  update () {
136+   private  void  update () {
127137    // If there are no pending requests, do nothing. 
128138    if  (headIndex  == tailIndex ) {
129139      return ;
@@ -136,13 +146,11 @@ public static void update() {
136146      clip .open (audioStream );
137147      clip .start ();
138148    } catch  (LineUnavailableException  e ) {
139-       System .err .println ("Error occoured while loading the audio: The line is unavailable" );
140-       e .printStackTrace ();
149+       LOGGER .trace ("Error occoured while loading the audio: The line is unavailable" , e );
141150    } catch  (IOException  e ) {
142-       System .err .println ("Input/Output error while loading the audio" );
143-       e .printStackTrace ();
151+       LOGGER .trace ("Input/Output error while loading the audio" , e );
144152    } catch  (IllegalArgumentException  e ) {
145-       System . err . println ("The system doesn't support the sound: "  + e .getMessage ());
153+       LOGGER . trace ("The system doesn't support the sound: "  + e .getMessage (),  e );
146154    }
147155  }
148156
@@ -153,7 +161,7 @@ public static void update() {
153161   * @throws UnsupportedAudioFileException when the audio file is not supported  
154162   * @throws IOException when the file is not readable 
155163   */ 
156-   public  static   AudioInputStream  getAudioStream (String  filePath )  
164+   public  AudioInputStream  getAudioStream (String  filePath )
157165      throws  UnsupportedAudioFileException , IOException  {
158166    return  AudioSystem .getAudioInputStream (new  File (filePath ).getAbsoluteFile ());
159167  }
@@ -162,7 +170,7 @@ public static AudioInputStream getAudioStream(String filePath)
162170   * Returns with the message array of the queue  
163171   * @return PlayMessage[] 
164172   */ 
165-   public  static   PlayMessage [] getPendingAudio () {
173+   public  PlayMessage [] getPendingAudio () {
166174    return  pendingAudio ;
167175  }
168176
0 commit comments