View Javadoc
1   package fr.ifremer.tutti.ui.swing.util;
2   
3   /*
4    * #%L
5    * Tutti :: UI
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2012 - 2016 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU General Public License as
13   * published by the Free Software Foundation, either version 3 of the
14   * License, or (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public
22   * License along with this program.  If not, see
23   * <http://www.gnu.org/licenses/gpl-3.0.html>.
24   * #L%
25   */
26  
27  import com.google.common.base.MoreObjects;
28  import com.google.common.base.Optional;
29  import fr.ifremer.tutti.TuttiConfiguration;
30  import fr.ifremer.tutti.util.BeepFrequency;
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.nuiton.jaxx.application.ApplicationTechnicalException;
34  
35  import java.io.Closeable;
36  import java.util.concurrent.LinkedBlockingQueue;
37  import java.util.concurrent.TimeUnit;
38  
39  /**
40   * Created on 20/01/16.
41   *
42   * @author Tony Chemit - chemit@codelutin.com
43   * @since 4.4
44   */
45  public class SoundEngine implements Closeable {
46  
47      /** Logger. */
48      private static final Log log = LogFactory.getLog(SoundEngine.class);
49  
50      protected final TuttiConfiguration configuration;
51      protected final Thread thread;
52      protected final LinkedBlockingQueue<Object> soundsToPlay;
53      protected boolean stop;
54  
55      public SoundEngine(TuttiConfiguration configuration) {
56          this.configuration = configuration;
57          this.thread = new Thread(new SoundEngineRunnable(), toString());
58          this.soundsToPlay = new LinkedBlockingQueue<>();
59          if (log.isInfoEnabled()) {
60              log.info("Starting sound engine thread: " + thread);
61          }
62      }
63  
64      public void open() {
65          thread.start();
66      }
67  
68      public synchronized void beepOnExternalDeviceDataReception(String unit, float aroundLengthStep) {
69  
70          if (configuration.isExternalDevicesDataReceptionBeepEnabled()) {
71              soundsToPlay.add(configuration.getExternalDevicesDataReceptionBeepFrequency());
72          }
73  
74          if (configuration.isExternalDevicesVoiceEnabled()) {
75              soundsToPlay.add(new Measure(unit, aroundLengthStep));
76          }
77  
78      }
79  
80      public synchronized void beepOnExternalDeviceErrorReception() {
81  
82          if (configuration.isExternalDevicesErrorReceptionBeepEnabled()) {
83              for (int i = 0; i < 3; i++) {
84                  soundsToPlay.add(configuration.getExternalDevicesDataReceptionBeepFrequency());
85              }
86          }
87  
88      }
89  
90      @Override
91      public synchronized void close() {
92  
93          if (log.isInfoEnabled()) {
94              log.info("Stopping sound engine thread: " + thread);
95          }
96          stop = true;
97          thread.interrupt();
98      }
99  
100     protected class Measure {
101 
102         protected final String unit;
103         protected final float aroundLengthStep;
104 
105         protected Measure(String unit, float aroundLengthStep) {
106             this.unit = unit;
107             this.aroundLengthStep = aroundLengthStep;
108         }
109 
110         @Override
111         public String toString() {
112             return MoreObjects.toStringHelper(this)
113                     .add("unit", unit)
114                     .add("aroundLengthStep", aroundLengthStep)
115                     .toString();
116         }
117     }
118 
119     protected class SoundEngineRunnable implements Runnable {
120 
121         @Override
122         public void run() {
123 
124             while (true) {
125 
126                 try {
127                     Object sound = soundsToPlay.poll(1, TimeUnit.SECONDS);
128 
129                     if (sound != null) {
130 
131                         if (sound instanceof Measure) {
132 
133                             Measure measure = (Measure) sound;
134 
135                             if (log.isInfoEnabled()) {
136                                 log.info("New Measure to say: " + measure);
137                             }
138                             String unit;
139                             if (configuration.isExternalDevicesReadsUnit()) {
140                                 unit = measure.unit;
141                             } else {
142                                 unit = null;
143                             }
144                             SoundUtil.readNumber(measure.aroundLengthStep, Optional.fromNullable(unit));
145 
146                         } else if (sound instanceof BeepFrequency) {
147                             SoundUtil.beep(configuration.getExternalDevicesErrorReceptionBeepFrequency());
148                         }
149 
150                     }
151 
152                     if (stop) {
153                         break;
154                     }
155 
156                 } catch (InterruptedException e) {
157 
158                     if (!stop) {
159                         throw new ApplicationTechnicalException("Could not get measure to say", e);
160                     }
161 
162                 }
163 
164 
165             }
166 
167         }
168     }
169 
170 }