mk_node(vs) = fgGetNode("/velocities/vertical-speed-fps", true);
}
-void
-MK_VIII::PropertiesHandler::unbind ()
-{
- vector<SGPropertyNode_ptr>::iterator iter;
-
- for (iter = tied_properties.begin(); iter != tied_properties.end(); iter++)
- (*iter)->untie();
-
- tied_properties.clear();
-}
-
///////////////////////////////////////////////////////////////////////////////
// PowerHandler ///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool *input,
bool *feed)
{
- mk->properties_handler.tie(node, (string("inputs/discretes/") + name).c_str(), RawValueMethodsData<MK_VIII::IOHandler, bool, bool *>(*this, input, &MK_VIII::IOHandler::get_discrete_input, &MK_VIII::IOHandler::set_discrete_input));
+ mk->properties_handler.tie(node, (string("inputs/discretes/") + name).c_str(),
+ FGVoicePlayer::RawValueMethodsData<MK_VIII::IOHandler, bool, bool *>(*this, input, &MK_VIII::IOHandler::get_discrete_input, &MK_VIII::IOHandler::set_discrete_input));
if (feed)
mk->properties_handler.tie(node, (string("input-feeders/discretes/") + name).c_str(), SGRawValuePointer<bool>(feed));
}
///////////////////////////////////////////////////////////////////////////////
-// VoicePlayer ////////////////////////////////////////////////////////////////
+// FGVoicePlayer //////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void
-MK_VIII::VoicePlayer::Speaker::bind (SGPropertyNode *node)
+FGVoicePlayer::PropertiesHandler::unbind ()
+{
+ vector<SGPropertyNode_ptr>::iterator iter;
+
+ for (iter = tied_properties.begin(); iter != tied_properties.end(); iter++)
+ (*iter)->untie();
+
+ tied_properties.clear();
+}
+
+void
+FGVoicePlayer::Speaker::bind (SGPropertyNode *node)
{
// uses xmlsound property names
tie(node, "volume", &volume);
}
void
-MK_VIII::VoicePlayer::Speaker::update_configuration ()
+FGVoicePlayer::Speaker::update_configuration ()
{
map< string, SGSharedPtr<SGSoundSample> >::iterator iter;
for (iter = player->samples.begin(); iter != player->samples.end(); iter++)
player->voice->volume_changed();
}
-MK_VIII::VoicePlayer::Voice::~Voice ()
+FGVoicePlayer::Voice::~Voice ()
{
for (iter = elements.begin(); iter != elements.end(); iter++)
delete *iter; // we owned the element
}
void
-MK_VIII::VoicePlayer::Voice::play ()
+FGVoicePlayer::Voice::play ()
{
iter = elements.begin();
element = *iter;
}
void
-MK_VIII::VoicePlayer::Voice::stop (bool now)
+FGVoicePlayer::Voice::stop (bool now)
{
if (element)
{
}
void
-MK_VIII::VoicePlayer::Voice::set_volume (float _volume)
+FGVoicePlayer::Voice::set_volume (float _volume)
{
volume = _volume;
volume_changed();
}
void
-MK_VIII::VoicePlayer::Voice::volume_changed ()
+FGVoicePlayer::Voice::volume_changed ()
{
if (element)
element->set_volume(get_volume());
}
void
-MK_VIII::VoicePlayer::Voice::update ()
+FGVoicePlayer::Voice::update ()
{
if (element)
{
}
}
-MK_VIII::VoicePlayer::~VoicePlayer ()
+FGVoicePlayer::~FGVoicePlayer ()
{
vector<Voice *>::iterator iter1;
for (iter1 = _voices.begin(); iter1 != _voices.end(); iter1++)
}
void
-MK_VIII::VoicePlayer::init ()
+FGVoicePlayer::bind (SGPropertyNode *node, const char* default_dir_prefix)
{
-#define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay"
+ dir_prefix = node->getStringValue("voice/file-prefix", default_dir_prefix);
+ speaker.bind(node);
+}
+void
+FGVoicePlayer::init ()
+{
SGSoundMgr *smgr = globals->get_soundmgr();
_sgr = smgr->find("avionics", true);
_sgr->tie_to_listener();
+ speaker.update_configuration();
+}
- make_voice(&voices.application_data_base_failed, "application-data-base-failed");
- make_voice(&voices.bank_angle, "bank-angle");
- make_voice(&voices.bank_angle_bank_angle, "bank-angle", "bank-angle");
- make_voice(&voices.bank_angle_bank_angle_3, "bank-angle", "bank-angle", 3.0);
- make_voice(&voices.bank_angle_inop, "bank-angle-inop");
- make_voice(&voices.bank_angle_pause_bank_angle, "bank-angle", STDPAUSE, "bank-angle");
- make_voice(&voices.bank_angle_pause_bank_angle_3, "bank-angle", STDPAUSE, "bank-angle", 3.0);
- make_voice(&voices.callouts_inop, "callouts-inop");
- make_voice(&voices.configuration_type_invalid, "configuration-type-invalid");
- make_voice(&voices.dont_sink, "dont-sink");
- make_voice(&voices.dont_sink_pause_dont_sink, "dont-sink", STDPAUSE, "dont-sink");
- make_voice(&voices.five_hundred_above, "500-above");
- make_voice(&voices.glideslope, "glideslope");
- make_voice(&voices.glideslope_inop, "glideslope-inop");
- make_voice(&voices.gpws_inop, "gpws-inop");
- make_voice(&voices.hard_glideslope, "glideslope", "glideslope", 3.0);
- make_voice(&voices.minimums, "minimums");
- make_voice(&voices.minimums_minimums, "minimums", "minimums");
- make_voice(&voices.pull_up, "pull-up");
- make_voice(&voices.sink_rate, "sink-rate");
- make_voice(&voices.sink_rate_pause_sink_rate, "sink-rate", STDPAUSE, "sink-rate");
- make_voice(&voices.soft_glideslope, new Voice::SampleElement(get_sample("glideslope"), modify_amplitude(1.0, -6)));
- make_voice(&voices.terrain, "terrain");
- make_voice(&voices.terrain_pause_terrain, "terrain", STDPAUSE, "terrain");
- make_voice(&voices.too_low_flaps, "too-low-flaps");
- make_voice(&voices.too_low_gear, "too-low-gear");
- make_voice(&voices.too_low_terrain, "too-low-terrain");
+void
+FGVoicePlayer::pause()
+{
+ if (paused)
+ return;
- for (unsigned i = 0; i < n_altitude_callouts; i++)
+ paused = true;
+ if (voice)
{
- std::ostringstream name;
- name << "altitude-" << mk->mode6_handler.altitude_callout_definitions[i];
- make_voice(&voices.altitude_callouts[i], name.str().c_str());
+ voice->stop(true);
}
+}
- speaker.update_configuration();
+void
+FGVoicePlayer::resume()
+{
+ if (!paused)
+ return;
+ paused = false;
+ if (voice)
+ {
+ voice->play();
+ }
}
SGSoundSample *
-MK_VIII::VoicePlayer::get_sample (const char *name)
+FGVoicePlayer::get_sample (const char *name)
{
- std::ostringstream refname;
- refname << mk->name << "[" << mk->num << "]" << "/" << name;
+ string refname;
+ refname = dev_name + "/" + dir_prefix + name;
- SGSoundSample *sample = _sgr->find(refname.str());
+ SGSoundSample *sample = _sgr->find(refname);
if (! sample)
{
- string filename = "Sounds/mk-viii/" + string(name) + ".wav";
+ string filename = dir_prefix + string(name) + ".wav";
try
{
sample = new SGSoundSample(filename.c_str(), SGPath());
}
catch (const sg_exception &e)
{
- SG_LOG(SG_INSTR, SG_ALERT, "Error loading MK VIII sound sample \"" + filename + "\": " + e.getFormattedMessage());
+ SG_LOG(SG_INSTR, SG_ALERT, "Error loading sound sample \"" + filename + "\": " + e.getFormattedMessage());
exit(1);
}
- _sgr->add(sample, refname.str());
- samples[refname.str()] = sample;
+ _sgr->add(sample, refname);
+ samples[refname] = sample;
}
return sample;
}
void
-MK_VIII::VoicePlayer::play (Voice *_voice, unsigned int flags)
+FGVoicePlayer::play (Voice *_voice, unsigned int flags)
{
if (!_voice)
return;
- if (test_bits(flags, PLAY_NOW) || ! voice || voice->element->silence)
+ if (test_bits(flags, PLAY_NOW) || ! voice ||
+ (voice->element && voice->element->silence))
{
if (voice)
voice->stop(true);
next_voice = NULL;
next_looped = false;
- voice->play();
+ if (!paused)
+ voice->play();
}
else
{
}
void
-MK_VIII::VoicePlayer::stop (unsigned int flags)
+FGVoicePlayer::stop (unsigned int flags)
{
if (voice)
{
}
void
-MK_VIII::VoicePlayer::set_volume (float _volume)
+FGVoicePlayer::set_volume (float _volume)
{
volume = _volume;
if (voice)
}
void
-MK_VIII::VoicePlayer::update ()
+FGVoicePlayer::update ()
{
if (voice)
{
}
}
+///////////////////////////////////////////////////////////////////////////////
+// MK_VIII::VoicePlayer ///////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+void
+MK_VIII::VoicePlayer::init ()
+{
+ FGVoicePlayer::init();
+
+#define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay"
+ make_voice(&voices.application_data_base_failed, "application-data-base-failed");
+ make_voice(&voices.bank_angle, "bank-angle");
+ make_voice(&voices.bank_angle_bank_angle, "bank-angle", "bank-angle");
+ make_voice(&voices.bank_angle_bank_angle_3, "bank-angle", "bank-angle", 3.0);
+ make_voice(&voices.bank_angle_inop, "bank-angle-inop");
+ make_voice(&voices.bank_angle_pause_bank_angle, "bank-angle", STDPAUSE, "bank-angle");
+ make_voice(&voices.bank_angle_pause_bank_angle_3, "bank-angle", STDPAUSE, "bank-angle", 3.0);
+ make_voice(&voices.callouts_inop, "callouts-inop");
+ make_voice(&voices.configuration_type_invalid, "configuration-type-invalid");
+ make_voice(&voices.dont_sink, "dont-sink");
+ make_voice(&voices.dont_sink_pause_dont_sink, "dont-sink", STDPAUSE, "dont-sink");
+ make_voice(&voices.five_hundred_above, "500-above");
+ make_voice(&voices.glideslope, "glideslope");
+ make_voice(&voices.glideslope_inop, "glideslope-inop");
+ make_voice(&voices.gpws_inop, "gpws-inop");
+ make_voice(&voices.hard_glideslope, "glideslope", "glideslope", 3.0);
+ make_voice(&voices.minimums, "minimums");
+ make_voice(&voices.minimums_minimums, "minimums", "minimums");
+ make_voice(&voices.pull_up, "pull-up");
+ make_voice(&voices.sink_rate, "sink-rate");
+ make_voice(&voices.sink_rate_pause_sink_rate, "sink-rate", STDPAUSE, "sink-rate");
+ make_voice(&voices.soft_glideslope, new Voice::SampleElement(get_sample("glideslope"), modify_amplitude(1.0, -6)));
+ make_voice(&voices.terrain, "terrain");
+ make_voice(&voices.terrain_pause_terrain, "terrain", STDPAUSE, "terrain");
+ make_voice(&voices.too_low_flaps, "too-low-flaps");
+ make_voice(&voices.too_low_gear, "too-low-gear");
+ make_voice(&voices.too_low_terrain, "too-low-terrain");
+
+ for (unsigned i = 0; i < n_altitude_callouts; i++)
+ {
+ std::ostringstream name;
+ name << "altitude-" << MK_VIII::Mode6Handler::altitude_callout_definitions[i];
+ make_voice(&voices.altitude_callouts[i], name.str().c_str());
+ }
+ speaker.update_configuration();
+}
+
///////////////////////////////////////////////////////////////////////////////
// SelfTestHandler ////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
configuration_module.bind(node);
power_handler.bind(node);
io_handler.bind(node);
- voice_player.bind(node);
+ voice_player.bind(node, "Sounds/mk-viii/");
}
void
# pragma warning( disable: 4355 )
#endif
-///////////////////////////////////////////////////////////////////////////////
-// MK_VIII ////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// FGVoicePlayer /////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
-class MK_VIII : public SGSubsystem
+class FGVoicePlayer
{
- // keep in sync with Mode6Handler::altitude_callout_definitions[]
- static const unsigned n_altitude_callouts = 11;
+public:
- /////////////////////////////////////////////////////////////////////////////
- // MK_VIII::RawValueMethodsData /////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ // MK::RawValueMethodsData /////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class C, class VT, class DT>
+ class RawValueMethodsData : public SGRawValue<VT>
+ {
+ public:
+ typedef VT (C::*getter_t) (DT) const;
+ typedef void (C::*setter_t) (DT, VT);
+
+ RawValueMethodsData (C &obj, DT data, getter_t getter = 0, setter_t setter = 0)
+ : _obj(obj), _data(data), _getter(getter), _setter(setter) {}
+
+ virtual VT getValue () const
+ {
+ if (_getter)
+ return (_obj.*_getter)(_data);
+ else
+ return SGRawValue<VT>::DefaultValue();
+ }
+ virtual bool setValue (VT value)
+ {
+ if (_setter)
+ {
+ (_obj.*_setter)(_data, value);
+ return true;
+ }
+ else
+ return false;
+ }
+ virtual SGRawValue<VT> *clone () const
+ {
+ return new RawValueMethodsData<C,VT,DT>(_obj, _data, _getter, _setter);
+ }
+
+ private:
+ C &_obj;
+ DT _data;
+ getter_t _getter;
+ setter_t _setter;
+ };
+
+ class PropertiesHandler
+ {
+ public:
+ vector<SGPropertyNode_ptr> tied_properties;
+
+ template <class T>
+ inline void tie (SGPropertyNode *node, const SGRawValue<T> &raw_value)
+ {
+ node->tie(raw_value);
+ tied_properties.push_back(node);
+ }
+
+ template <class T>
+ inline void tie (SGPropertyNode *node,
+ const char *relative_path,
+ const SGRawValue<T> &raw_value)
+ {
+ tie(node->getNode(relative_path, true), raw_value);
+ }
- template <class C, class VT, class DT>
- class RawValueMethodsData : public SGRawValue<VT>
+ PropertiesHandler() {};
+
+ void unbind ();
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // FGVoicePlayer::Voice ////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
+
+ class Voice
{
public:
- typedef VT (C::*getter_t) (DT) const;
- typedef void (C::*setter_t) (DT, VT);
- RawValueMethodsData (C &obj, DT data, getter_t getter = 0, setter_t setter = 0)
- : _obj(obj), _data(data), _getter(getter), _setter(setter) {}
+ /////////////////////////////////////////////////////////////////////////
+ // FGVoicePlayer::Voice::Element ////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////
- virtual VT getValue () const
+ class Element
{
- if (_getter)
- return (_obj.*_getter)(_data);
- else
- return SGRawValue<VT>::DefaultValue();
- }
- virtual bool setValue (VT value)
+ public:
+ bool silence;
+
+ virtual inline void play (float volume) {}
+ virtual inline void stop () {}
+ virtual bool is_playing () = 0;
+ virtual inline void set_volume (float volume) {}
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+ // FGVoicePlayer::Voice::SampleElement ///////////////////////////
+ /////////////////////////////////////////////////////////////////////////
+
+ class SampleElement : public Element
{
- if (_setter)
- {
- (_obj.*_setter)(_data, value);
- return true;
- }
- else
- return false;
+ SGSharedPtr<SGSoundSample> _sample;
+ float _volume;
+
+ public:
+ inline SampleElement (SGSharedPtr<SGSoundSample> sample, float volume = 1.0)
+ : _sample(sample), _volume(volume) { silence = false; }
+
+ virtual inline void play (float volume) { if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); } }
+ virtual inline void stop () { if (_sample) _sample->stop(); }
+ virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; }
+ virtual inline void set_volume (float volume) { if (_sample) _sample->set_volume(volume * _volume); }
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+ // FGVoicePlayer::Voice::SilenceElement //////////////////////////
+ /////////////////////////////////////////////////////////////////////////
+
+ class SilenceElement : public Element
+ {
+ double _duration;
+ double start_time;
+
+ public:
+ inline SilenceElement (double duration)
+ : _duration(duration) { silence = true; }
+
+ virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); }
+ virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; }
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+ // FGVoicePlayer::Voice (continued) //////////////////////////////
+ /////////////////////////////////////////////////////////////////////////
+
+ Element *element;
+
+ inline Voice (FGVoicePlayer *_player)
+ : element(NULL), player(_player), volume(1.0) {}
+
+ ~Voice ();
+
+ inline void append (Element *_element) { elements.push_back(_element); }
+
+ void play ();
+ void stop (bool now);
+ void set_volume (float _volume);
+ void volume_changed ();
+ void update ();
+
+ private:
+ FGVoicePlayer *player;
+
+ float volume;
+
+ vector<Element *> elements;
+ vector<Element *>::iterator iter;
+
+ inline float get_volume () const { return player->volume * player->speaker.volume * volume; }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // FGVoicePlayer (continued) ///////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
+
+ struct
+ {
+ float volume;
+ } conf;
+
+ float volume;
+
+ Voice *voice;
+ Voice *next_voice;
+ bool paused;
+ string dev_name;
+ string dir_prefix;
+
+ inline FGVoicePlayer (PropertiesHandler* properties_handler, string _dev_name)
+ : volume(1.0), voice(NULL), next_voice(NULL), paused(false),
+ dev_name(_dev_name), dir_prefix(""),
+ speaker(this,properties_handler) {}
+
+ ~FGVoicePlayer ();
+
+ void init ();
+ void pause();
+ void resume();
+ bool is_playing() { return (voice!=NULL);}
+
+ enum
+ {
+ PLAY_NOW = 1 << 0,
+ PLAY_LOOPED = 1 << 1
+ };
+ void play (Voice *_voice, unsigned int flags = 0);
+
+ enum
+ {
+ STOP_NOW = 1 << 0
+ };
+ void stop (unsigned int flags = 0);
+
+ void set_volume (float _volume);
+ void update ();
+
+ void bind (SGPropertyNode *node, const char* default_dir_prefix);
+
+public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // FGVoicePlayer::Speaker //////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
+
+ class Speaker
+ {
+ FGVoicePlayer *player;
+ PropertiesHandler* properties_handler;
+
+ double pitch;
+
+ template <class T>
+ inline void tie (SGPropertyNode *node, const char *name, T *ptr)
+ {
+ properties_handler->tie
+ (node, (string("speaker/") + name).c_str(),
+ RawValueMethodsData<FGVoicePlayer::Speaker,T,T*>
+ (*this, ptr,
+ &FGVoicePlayer::Speaker::get_property,
+ &FGVoicePlayer::Speaker::set_property));
}
- virtual SGRawValue<VT> *clone () const
+
+ public:
+ template <class T>
+ inline void set_property (T *ptr, T value) { *ptr = value; update_configuration(); }
+
+ template <class T>
+ inline T get_property (T *ptr) const { return *ptr; }
+
+ float volume;
+
+ inline Speaker (FGVoicePlayer *_player,PropertiesHandler* _properties_handler)
+ : player(_player),
+ properties_handler(_properties_handler),
+ pitch(1),
+ volume(1)
{
- return new RawValueMethodsData<C,VT,DT>(_obj, _data, _getter, _setter);
}
- private:
- C &_obj;
- DT _data;
- getter_t _getter;
- setter_t _setter;
+ void bind (SGPropertyNode *node);
+ void update_configuration ();
};
+protected:
+ ///////////////////////////////////////////////////////////////////////////
+ // FGVoicePlayer (continued) ///////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
+
+ SGSharedPtr<SGSampleGroup> _sgr;
+ Speaker speaker;
+
+ map< string, SGSharedPtr<SGSoundSample> > samples;
+ vector<Voice *> _voices;
+
+ bool looped;
+ bool next_looped;
+
+ SGSoundSample *get_sample (const char *name);
+
+ inline void append (Voice *voice, Voice::Element *element) { voice->append(element); }
+ inline void append (Voice *voice, const char *sample_name) { voice->append(new Voice::SampleElement(get_sample(sample_name))); }
+ inline void append (Voice *voice, double silence) { voice->append(new Voice::SilenceElement(silence)); }
+
+ inline void make_voice (Voice **voice) { *voice = new Voice(this); _voices.push_back(*voice); }
+
+ template <class T1>
+ inline void make_voice (Voice **voice, T1 e1) { make_voice(voice); append(*voice, e1); }
+ template <class T1, class T2>
+ inline void make_voice (Voice **voice, T1 e1, T2 e2) { make_voice(voice, e1); append(*voice, e2); }
+ template <class T1, class T2, class T3>
+ inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3) { make_voice(voice, e1, e2); append(*voice, e3); }
+ template <class T1, class T2, class T3, class T4>
+ inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3, T4 e4) { make_voice(voice, e1, e2, e3); append(*voice, e4); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// MK_VIII ////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class MK_VIII : public SGSubsystem
+{
+ // keep in sync with Mode6Handler::altitude_callout_definitions[]
+ static const unsigned n_altitude_callouts = 11;
+
/////////////////////////////////////////////////////////////////////////////
// MK_VIII::Parameter ///////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// MK_VIII::PropertiesHandler ///////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
- class PropertiesHandler
+ class PropertiesHandler : public FGVoicePlayer::PropertiesHandler
{
MK_VIII *mk;
- vector<SGPropertyNode_ptr> tied_properties;
-
public:
struct
{
} external_properties;
inline PropertiesHandler (MK_VIII *device)
- : mk(device) {}
+ : FGVoicePlayer::PropertiesHandler(), mk(device) {}
- template <class T>
- inline void tie (SGPropertyNode *node, const SGRawValue<T> &raw_value)
- {
- node->tie(raw_value);
- tied_properties.push_back(node);
- }
-
- template <class T>
- inline void tie (SGPropertyNode *node,
- const char *relative_path,
- const SGRawValue<T> &raw_value)
- {
- tie(node->getNode(relative_path, true), raw_value);
- }
-
- PropertiesHandler() {};
+ PropertiesHandler() : FGVoicePlayer::PropertiesHandler() {}
void init ();
- void unbind ();
};
public:
bool *get_lamp_output (Lamp lamp);
};
-
- /////////////////////////////////////////////////////////////////////////////
- // MK_VIII::VoicePlayer /////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
-
- class VoicePlayer
+
+ class VoicePlayer : public FGVoicePlayer
{
public:
+ VoicePlayer (MK_VIII *device) :
+ FGVoicePlayer(&device->properties_handler, "mk-viii")
+ {}
- ///////////////////////////////////////////////////////////////////////////
- // MK_VIII::VoicePlayer::Voice ////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- class Voice
- {
- public:
-
- /////////////////////////////////////////////////////////////////////////
- // MK_VIII::VoicePlayer::Voice::Element ////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////
-
- class Element
- {
- public:
- bool silence;
-
- virtual inline void play (float volume) {}
- virtual inline void stop () {}
- virtual bool is_playing () = 0;
- virtual inline void set_volume (float volume) {}
- };
-
- /////////////////////////////////////////////////////////////////////////
- // MK_VIII::VoicePlayer::Voice::SampleElement ///////////////////////////
- /////////////////////////////////////////////////////////////////////////
-
- class SampleElement : public Element
- {
- SGSharedPtr<SGSoundSample> _sample;
- float _volume;
-
- public:
- inline SampleElement (SGSharedPtr<SGSoundSample> sample, float volume = 1.0)
- : _sample(sample), _volume(volume) { silence = false; }
-
- virtual inline void play (float volume) { if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); } }
- virtual inline void stop () { if (_sample) _sample->stop(); }
- virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; }
- virtual inline void set_volume (float volume) { if (_sample) _sample->set_volume(volume * _volume); }
- };
-
- /////////////////////////////////////////////////////////////////////////
- // MK_VIII::VoicePlayer::Voice::SilenceElement //////////////////////////
- /////////////////////////////////////////////////////////////////////////
-
- class SilenceElement : public Element
- {
- double _duration;
- double start_time;
-
- public:
- inline SilenceElement (double duration)
- : _duration(duration) { silence = true; }
-
- virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); }
- virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; }
- };
-
- /////////////////////////////////////////////////////////////////////////
- // MK_VIII::VoicePlayer::Voice (continued) //////////////////////////////
- /////////////////////////////////////////////////////////////////////////
-
- Element *element;
-
- inline Voice (VoicePlayer *_player)
- : element(NULL), player(_player), volume(1.0) {}
-
- ~Voice ();
-
- inline void append (Element *_element) { elements.push_back(_element); }
-
- void play ();
- void stop (bool now);
- void set_volume (float _volume);
- void volume_changed ();
- void update ();
-
- private:
- VoicePlayer *player;
-
- float volume;
-
- vector<Element *> elements;
- vector<Element *>::iterator iter;
-
- inline float get_volume () const { return player->volume * player->speaker.volume * volume; }
- };
-
- ///////////////////////////////////////////////////////////////////////////
- // MK_VIII::VoicePlayer (continued) ///////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- struct
- {
- float volume;
- } conf;
-
- float volume;
-
- Voice *voice;
- Voice *next_voice;
-
- struct
- {
- Voice *application_data_base_failed;
- Voice *bank_angle;
- Voice *bank_angle_bank_angle;
- Voice *bank_angle_bank_angle_3;
- Voice *bank_angle_inop;
- Voice *bank_angle_pause_bank_angle;
- Voice *bank_angle_pause_bank_angle_3;
- Voice *callouts_inop;
- Voice *configuration_type_invalid;
- Voice *dont_sink;
- Voice *dont_sink_pause_dont_sink;
- Voice *five_hundred_above;
- Voice *glideslope;
- Voice *glideslope_inop;
- Voice *gpws_inop;
- Voice *hard_glideslope;
- Voice *minimums;
- Voice *minimums_minimums;
- Voice *pull_up;
- Voice *sink_rate;
- Voice *sink_rate_pause_sink_rate;
- Voice *soft_glideslope;
- Voice *terrain;
- Voice *terrain_pause_terrain;
- Voice *too_low_flaps;
- Voice *too_low_gear;
- Voice *too_low_terrain;
- Voice *altitude_callouts[n_altitude_callouts];
- } voices;
-
- inline VoicePlayer (MK_VIII *device)
- : voice(NULL), next_voice(NULL), mk(device), speaker(this) {}
-
- ~VoicePlayer ();
-
- void init ();
-
- enum
- {
- PLAY_NOW = 1 << 0,
- PLAY_LOOPED = 1 << 1
- };
- void play (Voice *_voice, unsigned int flags = 0);
-
- enum
- {
- STOP_NOW = 1 << 0
- };
- void stop (unsigned int flags = 0);
-
- void set_volume (float _volume);
- void update ();
-
- inline void bind (SGPropertyNode *node) { speaker.bind(node); }
-
- public:
-
- ///////////////////////////////////////////////////////////////////////////
- // MK_VIII::VoicePlayer::Speaker //////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- class Speaker
- {
- VoicePlayer *player;
-
- double pitch;
-
- template <class T>
- inline void tie (SGPropertyNode *node, const char *name, T *ptr)
- {
- player->mk->properties_handler.tie
- (node, (string("speaker/") + name).c_str(),
- RawValueMethodsData<MK_VIII::VoicePlayer::Speaker,T,T*>
- (*this, ptr,
- &MK_VIII::VoicePlayer::Speaker::get_property,
- &MK_VIII::VoicePlayer::Speaker::set_property));
- }
-
- public:
- template <class T>
- inline void set_property (T *ptr, T value) { *ptr = value; update_configuration(); }
-
- template <class T>
- inline T get_property (T *ptr) const { return *ptr; }
-
- float volume;
+ ~VoicePlayer() {}
+ void init ();
- inline Speaker (VoicePlayer *_player)
- : player(_player),
- pitch(1),
- volume(1)
+ struct
{
- }
-
- void bind (SGPropertyNode *node);
- void update_configuration ();
- };
-
- private:
- ///////////////////////////////////////////////////////////////////////////
- // MK_VIII::VoicePlayer (continued) ///////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- MK_VIII *mk;
-
- SGSharedPtr<SGSampleGroup> _sgr;
- Speaker speaker;
-
- map< string, SGSharedPtr<SGSoundSample> > samples;
- vector<Voice *> _voices;
-
- bool looped;
- bool next_looped;
-
- SGSoundSample *get_sample (const char *name);
-
- inline void append (Voice *voice, Voice::Element *element) { voice->append(element); }
- inline void append (Voice *voice, const char *sample_name) { voice->append(new Voice::SampleElement(get_sample(sample_name))); }
- inline void append (Voice *voice, double silence) { voice->append(new Voice::SilenceElement(silence)); }
-
- inline void make_voice (Voice **voice) { *voice = new Voice(this); _voices.push_back(*voice); }
-
- template <class T1>
- inline void make_voice (Voice **voice, T1 e1) { make_voice(voice); append(*voice, e1); }
- template <class T1, class T2>
- inline void make_voice (Voice **voice, T1 e1, T2 e2) { make_voice(voice, e1); append(*voice, e2); }
- template <class T1, class T2, class T3>
- inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3) { make_voice(voice, e1, e2); append(*voice, e3); }
- template <class T1, class T2, class T3, class T4>
- inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3, T4 e4) { make_voice(voice, e1, e2, e3); append(*voice, e4); }
+ Voice *application_data_base_failed;
+ Voice *bank_angle;
+ Voice *bank_angle_bank_angle;
+ Voice *bank_angle_bank_angle_3;
+ Voice *bank_angle_inop;
+ Voice *bank_angle_pause_bank_angle;
+ Voice *bank_angle_pause_bank_angle_3;
+ Voice *callouts_inop;
+ Voice *configuration_type_invalid;
+ Voice *dont_sink;
+ Voice *dont_sink_pause_dont_sink;
+ Voice *five_hundred_above;
+ Voice *glideslope;
+ Voice *glideslope_inop;
+ Voice *gpws_inop;
+ Voice *hard_glideslope;
+ Voice *minimums;
+ Voice *minimums_minimums;
+ Voice *pull_up;
+ Voice *sink_rate;
+ Voice *sink_rate_pause_sink_rate;
+ Voice *soft_glideslope;
+ Voice *terrain;
+ Voice *terrain_pause_terrain;
+ Voice *too_low_flaps;
+ Voice *too_low_gear;
+ Voice *too_low_terrain;
+ Voice *altitude_callouts[n_altitude_callouts];
+ } voices;
+
};
private: