1 package fr.ifremer.tutti.ui.swing.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
41
42
43
44
45 public class SoundEngine implements Closeable {
46
47
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 }