]> git.mxchange.org Git - flightgear.git/blob - src/Sound/voiceplayer.cxx
Fix rpmlint/Linux packager complaints
[flightgear.git] / src / Sound / voiceplayer.cxx
1 // voiceplayer.cxx -- voice/sound sample player
2 //
3 // Written by Jean-Yves Lefort, started September 2005.
4 //
5 // Copyright (C) 2005, 2006  Jean-Yves Lefort - jylefort@FreeBSD.org
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 ///////////////////////////////////////////////////////////////////////////////
22
23 #ifdef _MSC_VER
24 #  pragma warning( disable: 4355 )
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #  include <config.h>
29 #endif
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <math.h>
35
36 #include <string>
37 #include <sstream>
38
39 #include <simgear/debug/logstream.hxx>
40 #include <simgear/sound/soundmgr_openal.hxx>
41 #include <simgear/structure/exception.hxx>
42
43 using std::string;
44
45 #include "voiceplayer.hxx"
46
47 ///////////////////////////////////////////////////////////////////////////////
48 // constants //////////////////////////////////////////////////////////////////
49 ///////////////////////////////////////////////////////////////////////////////
50
51
52 ///////////////////////////////////////////////////////////////////////////////
53 // helpers ////////////////////////////////////////////////////////////////////
54 ///////////////////////////////////////////////////////////////////////////////
55 #define ADD_VOICE(Var,Sample,Twice) \
56     { make_voice(&Var);append(Var,Sample);\
57       if (Twice) append(Var,Sample); }
58
59 #define test_bits(_bits, _test) (((_bits) & (_test)) != 0)
60
61 ///////////////////////////////////////////////////////////////////////////////
62 // FGVoicePlayer //////////////////////////////////////////////////////////////
63 ///////////////////////////////////////////////////////////////////////////////
64
65 void
66 FGVoicePlayer::Speaker::bind (SGPropertyNode *node)
67 {
68     // uses xmlsound property names
69     tie(node, "volume", &volume);
70     tie(node, "pitch", &pitch);
71 }
72
73 void
74 FGVoicePlayer::Speaker::update_configuration ()
75 {
76     map< string, SGSharedPtr<SGSoundSample> >::iterator iter;
77     for (iter = player->samples.begin(); iter != player->samples.end(); iter++)
78     {
79         SGSoundSample *sample = (*iter).second;
80
81         sample->set_pitch(pitch);
82     }
83
84     if (player->voice)
85         player->voice->volume_changed();
86 }
87
88 FGVoicePlayer::Voice::~Voice ()
89 {
90     for (iter = elements.begin(); iter != elements.end(); iter++)
91         delete *iter;       // we owned the element
92     elements.clear();
93 }
94
95 void
96 FGVoicePlayer::Voice::play ()
97 {
98     iter = elements.begin();
99     element = *iter;
100
101     element->play(get_volume());
102 }
103
104 void
105 FGVoicePlayer::Voice::stop (bool now)
106 {
107     if (element)
108     {
109         if (now || element->silence)
110         {
111             element->stop();
112             element = NULL;
113         }
114         else
115             iter = elements.end() - 1; // stop after the current element finishes
116     }
117 }
118
119 void
120 FGVoicePlayer::Voice::set_volume (float _volume)
121 {
122     volume = _volume;
123     volume_changed();
124 }
125
126 void
127 FGVoicePlayer::Voice::volume_changed ()
128 {
129     if (element)
130         element->set_volume(get_volume());
131 }
132
133 void
134 FGVoicePlayer::Voice::update ()
135 {
136     if (element)
137     {
138         if (! element->is_playing())
139         {
140             if (++iter == elements.end())
141                 element = NULL;
142             else
143             {
144                 element = *iter;
145                 element->play(get_volume());
146             }
147         }
148     }
149 }
150
151 FGVoicePlayer::~FGVoicePlayer ()
152 {
153     vector<Voice *>::iterator iter1;
154     for (iter1 = _voices.begin(); iter1 != _voices.end(); iter1++)
155         delete *iter1;
156     _voices.clear();
157     samples.clear();
158 }
159
160 void
161 FGVoicePlayer::bind (SGPropertyNode *node, const char* default_dir_prefix)
162 {
163     dir_prefix = node->getStringValue("voice/file-prefix", default_dir_prefix);
164     speaker.bind(node);
165 }
166
167 void
168 FGVoicePlayer::init ()
169 {
170     SGSoundMgr *smgr = globals->get_soundmgr();
171     _sgr = smgr->find("avionics", true);
172     _sgr->tie_to_listener();
173     speaker.update_configuration();
174 }
175
176 void
177 FGVoicePlayer::pause()
178 {
179     if (paused)
180         return;
181
182     paused = true;
183     if (voice)
184     {
185         voice->stop(true);
186     }
187 }
188
189 void
190 FGVoicePlayer::resume()
191 {
192     if (!paused)
193         return;
194     paused = false;
195     if (voice)
196     {
197         voice->play();
198     }
199 }
200
201 SGSoundSample *
202 FGVoicePlayer::get_sample (const char *name)
203 {
204     string refname;
205     refname = dev_name + "/" + dir_prefix + name;
206
207     SGSoundSample *sample = _sgr->find(refname);
208     if (! sample)
209     {
210         string filename = dir_prefix + string(name) + ".wav";
211         try
212         {
213             sample = new SGSoundSample(filename.c_str(), SGPath());
214         }
215         catch (const sg_exception &e)
216         {
217             SG_LOG(SG_SOUND, SG_ALERT, "Error loading sound sample \"" + filename + "\": " + e.getFormattedMessage());
218             exit(1);
219         }
220
221         _sgr->add(sample, refname);
222         samples[refname] = sample;
223     }
224
225     return sample;
226 }
227
228 void
229 FGVoicePlayer::play (Voice *_voice, unsigned int flags)
230 {
231     if (!_voice)
232         return;
233     if (test_bits(flags, PLAY_NOW) || ! voice ||
234             (voice->element && voice->element->silence))
235     {
236         if (voice)
237             voice->stop(true);
238
239         voice = _voice;
240         looped = test_bits(flags, PLAY_LOOPED);
241
242         next_voice = NULL;
243         next_looped = false;
244
245         if (!paused)
246             voice->play();
247     }
248     else
249     {
250         next_voice = _voice;
251         next_looped = test_bits(flags, PLAY_LOOPED);
252     }
253 }
254
255 void
256 FGVoicePlayer::stop (unsigned int flags)
257 {
258     if (voice)
259     {
260         voice->stop(test_bits(flags, STOP_NOW));
261         if (voice->element)
262             looped = false;
263         else
264             voice = NULL;
265         next_voice = NULL;
266     }
267 }
268
269 void
270 FGVoicePlayer::set_volume (float _volume)
271 {
272     volume = _volume;
273     if (voice)
274         voice->volume_changed();
275 }
276
277 void
278 FGVoicePlayer::update ()
279 {
280     if (voice)
281     {
282         voice->update();
283
284         if (next_voice)
285         {
286             if (! voice->element || voice->element->silence)
287             {
288                 voice = next_voice;
289                 looped = next_looped;
290
291                 next_voice = NULL;
292                 next_looped = false;
293
294                 voice->play();
295             }
296         }
297         else
298         {
299             if (! voice->element)
300             {
301                 if (looped)
302                     voice->play();
303                 else
304                     voice = NULL;
305             }
306         }
307     }
308 }