1 // voiceplayer.hxx -- voice/sound sample player
3 // Written by Jean-Yves Lefort, started September 2005.
5 // Copyright (C) 2005, 2006 Jean-Yves Lefort - jylefort@FreeBSD.org
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #ifndef __SOUND_VOICEPLAYER_HXX
23 #define __SOUND_VOICEPLAYER_HXX
31 #include <simgear/props/props.hxx>
32 #include <simgear/props/tiedpropertylist.hxx>
33 #include <simgear/sound/sample_openal.hxx>
40 #include <Main/globals.hxx>
43 # pragma warning( push )
44 # pragma warning( disable: 4355 )
47 /////////////////////////////////////////////////////////////////////////////
48 // FGVoicePlayer /////////////////////////////////////////////////////
49 /////////////////////////////////////////////////////////////////////////////
55 /////////////////////////////////////////////////////////////////////////////
56 // MK::RawValueMethodsData /////////////////////////////////////////////
57 /////////////////////////////////////////////////////////////////////////////
59 template <class C, class VT, class DT>
60 class RawValueMethodsData : public SGRawValue<VT>
63 typedef VT (C::*getter_t) (DT) const;
64 typedef void (C::*setter_t) (DT, VT);
66 RawValueMethodsData (C &obj, DT data, getter_t getter = 0, setter_t setter = 0)
67 : _obj(obj), _data(data), _getter(getter), _setter(setter) {}
69 virtual VT getValue () const
72 return (_obj.*_getter)(_data);
74 return SGRawValue<VT>::DefaultValue();
76 virtual bool setValue (VT value)
80 (_obj.*_setter)(_data, value);
86 virtual SGRawValue<VT> *clone () const
88 return new RawValueMethodsData<C,VT,DT>(_obj, _data, _getter, _setter);
98 class PropertiesHandler : public simgear::TiedPropertyList
103 inline void tie (SGPropertyNode *node, const SGRawValue<T> &raw_value)
109 inline void tie (SGPropertyNode *node,
110 const char *relative_path,
111 const SGRawValue<T> &raw_value)
113 Tie(node->getNode(relative_path, true),raw_value);
116 PropertiesHandler() {};
118 void unbind () {Untie();}
121 ///////////////////////////////////////////////////////////////////////////
122 // FGVoicePlayer::Voice ////////////////////////////////////////////
123 ///////////////////////////////////////////////////////////////////////////
129 /////////////////////////////////////////////////////////////////////////
130 // FGVoicePlayer::Voice::Element ////////////////////////////////////////
131 /////////////////////////////////////////////////////////////////////////
138 virtual ~Element() {}
139 virtual inline void play (float volume) {}
140 virtual inline void stop () {}
141 virtual bool is_playing () = 0;
142 virtual inline void set_volume (float volume) {}
145 /////////////////////////////////////////////////////////////////////////
146 // FGVoicePlayer::Voice::SampleElement ///////////////////////////
147 /////////////////////////////////////////////////////////////////////////
149 class SampleElement : public Element
151 SGSharedPtr<SGSoundSample> _sample;
155 inline SampleElement (SGSharedPtr<SGSoundSample> sample, float volume = 1.0)
156 : _sample(sample), _volume(volume) { silence = false; }
158 virtual inline void play (float volume) { if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); } }
159 virtual inline void stop () { if (_sample) _sample->stop(); }
160 virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; }
161 virtual inline void set_volume (float volume) { if (_sample) _sample->set_volume(volume * _volume); }
164 /////////////////////////////////////////////////////////////////////////
165 // FGVoicePlayer::Voice::SilenceElement //////////////////////////
166 /////////////////////////////////////////////////////////////////////////
168 class SilenceElement : public Element
174 inline SilenceElement (double duration)
175 : _duration(duration) { silence = true; }
177 virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); }
178 virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; }
181 /////////////////////////////////////////////////////////////////////////
182 // FGVoicePlayer::Voice (continued) //////////////////////////////
183 /////////////////////////////////////////////////////////////////////////
187 inline Voice (FGVoicePlayer *_player)
188 : element(NULL), player(_player), volume(1.0) {}
192 inline void append (Element *_element) { elements.push_back(_element); }
195 void stop (bool now);
196 void set_volume (float _volume);
197 void volume_changed ();
201 FGVoicePlayer *player;
205 vector<Element *> elements;
206 vector<Element *>::iterator iter;
208 inline float get_volume () const { return player->volume * player->speaker.volume * volume; }
211 ///////////////////////////////////////////////////////////////////////////
212 // FGVoicePlayer (continued) ///////////////////////////////////////
213 ///////////////////////////////////////////////////////////////////////////
228 inline FGVoicePlayer (PropertiesHandler* properties_handler, string _dev_name)
229 : volume(1.0), voice(NULL), next_voice(NULL), paused(false),
230 dev_name(_dev_name), dir_prefix(""),
231 speaker(this,properties_handler) {}
233 virtual ~FGVoicePlayer ();
238 bool is_playing() { return (voice!=NULL);}
245 void play (Voice *_voice, unsigned int flags = 0);
251 void stop (unsigned int flags = 0);
253 void set_volume (float _volume);
256 void bind (SGPropertyNode *node, const char* default_dir_prefix);
260 ///////////////////////////////////////////////////////////////////////////
261 // FGVoicePlayer::Speaker //////////////////////////////////////////
262 ///////////////////////////////////////////////////////////////////////////
266 FGVoicePlayer *player;
267 PropertiesHandler* properties_handler;
272 inline void tie (SGPropertyNode *node, const char *name, T *ptr)
274 properties_handler->tie
275 (node, (string("speaker/") + name).c_str(),
276 RawValueMethodsData<FGVoicePlayer::Speaker,T,T*>
278 &FGVoicePlayer::Speaker::get_property,
279 &FGVoicePlayer::Speaker::set_property));
284 inline void set_property (T *ptr, T value) { *ptr = value; update_configuration(); }
287 inline T get_property (T *ptr) const { return *ptr; }
291 inline Speaker (FGVoicePlayer *_player,PropertiesHandler* _properties_handler)
293 properties_handler(_properties_handler),
299 void bind (SGPropertyNode *node);
300 void update_configuration ();
304 ///////////////////////////////////////////////////////////////////////////
305 // FGVoicePlayer (continued) ///////////////////////////////////////
306 ///////////////////////////////////////////////////////////////////////////
308 SGSharedPtr<SGSampleGroup> _sgr;
311 map< string, SGSharedPtr<SGSoundSample> > samples;
312 vector<Voice *> _voices;
317 SGSoundSample *get_sample (const char *name);
319 inline void append (Voice *voice, Voice::Element *element) { voice->append(element); }
320 inline void append (Voice *voice, const char *sample_name) { voice->append(new Voice::SampleElement(get_sample(sample_name))); }
321 inline void append (Voice *voice, double silence) { voice->append(new Voice::SilenceElement(silence)); }
323 inline void make_voice (Voice **voice) { *voice = new Voice(this); _voices.push_back(*voice); }
326 inline void make_voice (Voice **voice, T1 e1) { make_voice(voice); append(*voice, e1); }
327 template <class T1, class T2>
328 inline void make_voice (Voice **voice, T1 e1, T2 e2) { make_voice(voice, e1); append(*voice, e2); }
329 template <class T1, class T2, class T3>
330 inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3) { make_voice(voice, e1, e2); append(*voice, e3); }
331 template <class T1, class T2, class T3, class T4>
332 inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3, T4 e4) { make_voice(voice, e1, e2, e3); append(*voice, e4); }
335 #endif // __SOUND_VOICEPLAYER_HXX