]> git.mxchange.org Git - flightgear.git/blobdiff - src/ATCDCL/ATC.cxx
Merge branch 'topic/pu-crash'
[flightgear.git] / src / ATCDCL / ATC.cxx
index 2bc321805619481bed8f0698fdeb42cdfd700693..41c56e64844998beb1db3d754b6fdedbc169d315 100644 (file)
 #  include <config.h>
 #endif
 
+#include "ATC.hxx"
+
+#include <iostream>
+
 #include <simgear/sound/soundmgr_openal.hxx>
 #include <simgear/structure/exception.hxx>
 
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 
-#include "ATC.hxx"
 
-FGATC::FGATC() {
-       freqClear = true;
-       receiving = false;
-       respond = false;
-       runResponseCounter = false;
-       _runReleaseCounter = false;
-       responseID = "";
-       responseReqd = false;
-       _type = INVALID;
-       _display = false;
-       _displaying = false;
-       
+
+FGATC::FGATC() :
+       _voiceOK(false),
+       _playing(false),
+       _sgr(NULL),
+       freqClear(true),
+       receiving(false),
+       respond(false),
+       responseID(""),
+       runResponseCounter(false),
+       _runReleaseCounter(false),
+       responseReqd(false),
+       _type(INVALID),
+       _display(false),
        // Transmission timing stuff
-       pending_transmission = "";
-       _timeout = 0;
-       _pending = false;
-       _callback_code = 0;
-       _transmit = false;
-       _transmitting = false;
-       _counter = 0.0;
-       _max_count = 5.0;
-       
-       _voiceOK = false;
+       pending_transmission(""),
+       _timeout(0),
+       _pending(false),
+       _callback_code(0),
+       _transmit(false),
+       _transmitting(false),
+       _counter(0.0),
+       _max_count(5.0)
+{
+       SGSoundMgr *smgr = globals->get_soundmgr();
+       _sgr = smgr->find("atc", true);
+
+       _volume = fgGetNode("/sim/sound/atc/volume", true);
+       _enabled = fgGetNode("/sim/sound/atc/enabled", true);
+       _atc_external = fgGetNode("/sim/sound/atc/external-view", true);
+       _internal = fgGetNode("/sim/current-view/internal", true);
 }
 
 FGATC::~FGATC() {
 }
 
-// Derived classes wishing to use the response counter should call this from their own Update(...).
+// Derived classes wishing to use the response counter should 
+// call this from their own Update(...).
 void FGATC::Update(double dt) {
        if(runResponseCounter) {
                //cout << responseCounter << '\t' << responseTime << '\n';
@@ -100,6 +112,18 @@ void FGATC::Update(double dt) {
                }
        }
 
+#ifdef ENABLE_AUDIO_SUPPORT
+       bool active = _atc_external->getBoolValue() ||
+                     _internal->getBoolValue();
+
+       if ( active && _enabled->getBoolValue() ) {
+               _sgr->set_volume( _volume->getFloatValue() );
+               _sgr->resume(); // no-op if already in resumed state
+       } else {
+               _sgr->suspend();
+       }
+#endif
+
        if(_transmit) {
                _counter = 0.0;
                _max_count = 5.0;               // FIXME - hardwired length of message - need to calculate it!
@@ -200,12 +224,9 @@ int FGATC::RemovePlane() {
 }
 
 void FGATC::SetData(ATCData* d) {
-       lon = d->lon;
-       lat = d->lat;
-       elev = d->elev;
-       x = d->x;
-       y = d->y;
-       z = d->z;
+       _type = d->type;
+       _geod = d->geod;
+       _cart = d->cart;
        range = d->range;
        ident = d->ident;
        name = d->name;
@@ -216,37 +237,36 @@ void FGATC::SetData(ATCData* d) {
 // Outputs the transmission either on screen or as audio depending on user preference
 // The refname is a string to identify this sample to the sound manager
 // The repeating flag indicates whether the message should be repeated continuously or played once.
-void FGATC::Render(string& msg, const string& refname, bool repeating) {
+void FGATC::Render(string& msg, const float volume, 
+                                  const string& refname, const bool repeating) {
+       if (volume < 0.05) return;
+
        if (repeating)
                fgSetString("/sim/messages/atis", msg.c_str());
        else
                fgSetString("/sim/messages/atc", msg.c_str());
 
-       #ifdef ENABLE_AUDIO_SUPPORT
+#ifdef ENABLE_AUDIO_SUPPORT
        _voice = (_voiceOK && fgGetBool("/sim/sound/voice"));
        if(_voice) {
-               int len;
-               unsigned char* buf = _vPtr->WriteMessage((char*)msg.c_str(), len, _voice);
-               if(_voice) {
+               size_t len;
+               void* buf = _vPtr->WriteMessage((char*)msg.c_str(), &len);
+               if(buf) {
+                       NoRender(refname);
                        try {
-                               SGSoundSample *simple
-                                                               = new SGSoundSample(buf, len, 8000);
-                               // TODO - at the moment the volume is always set off comm1 
-                               // and can't be changed after the transmission has started.
-                               simple->set_volume(5.0 * fgGetDouble("/instrumentation/comm[0]/volume"));
-                               globals->get_soundmgr()->add(simple, refname);
-                               if(repeating) {
-                                       globals->get_soundmgr()->play_looped(refname);
-                               } else {
-                                       globals->get_soundmgr()->play_once(refname);
-                               }
+// >>> Beware: must pass a (new) object to the (add) method,
+// >>> because the (remove) method is going to do a (delete)
+// >>> whether that's what you want or not.
+                               SGSoundSample *simple = new SGSoundSample(&buf, len, 8000);
+                               simple->set_volume(volume);
+                               _sgr->add(simple, refname);
+                               _sgr->play(refname, repeating);
                        } catch ( sg_io_exception &e ) {
                                SG_LOG(SG_GENERAL, SG_ALERT, e.getFormattedMessage());
                        }
                }
-               delete[] buf;
        }
-       #endif  // ENABLE_AUDIO_SUPPORT
+#endif // ENABLE_AUDIO_SUPPORT
        if(!_voice) {
                // first rip the underscores and the pause hints out of the string - these are for the convienience of the voice parser
                for(unsigned int i = 0; i < msg.length(); ++i) {
@@ -264,8 +284,8 @@ void FGATC::NoRender(const string& refname) {
        if(_playing) {
                if(_voice) {
 #ifdef ENABLE_AUDIO_SUPPORT            
-                       globals->get_soundmgr()->stop(refname);
-                       globals->get_soundmgr()->remove(refname);
+                       _sgr->stop(refname);
+                       _sgr->remove(refname);
 #endif
                }
                _playing = false;
@@ -279,13 +299,73 @@ string FGATC::GenText(const string& m, int c) {
 
 ostream& operator << (ostream& os, atc_type atc) {
        switch(atc) {
-               case(INVALID):    return(os << "INVALID");
-               case(ATIS):       return(os << "ATIS");
-               case(GROUND):     return(os << "GROUND");
-               case(TOWER):      return(os << "TOWER");
+               case(AWOS):        return(os << "AWOS");
+               case(ATIS):        return(os << "ATIS");
+               case(GROUND):    return(os << "GROUND");
+               case(TOWER):      return(os << "TOWER");
                case(APPROACH):   return(os << "APPROACH");
                case(DEPARTURE):  return(os << "DEPARTURE");
-               case(ENROUTE):    return(os << "ENROUTE");
+               case(ENROUTE):  return(os << "ENROUTE");
+               case(INVALID):  return(os << "INVALID");
        }
        return(os << "ERROR - Unknown switch in atc_type operator << ");
 }
+
+std::istream& operator >> ( std::istream& fin, ATCData& a )
+{
+       double f;
+       char ch;
+       char tp;
+       
+       fin >> tp;
+       
+       switch(tp) {
+       case 'I':
+               a.type = ATIS;
+               break;
+       case 'T':
+               a.type = TOWER;
+               break;
+       case 'G':
+               a.type = GROUND;
+               break;
+       case 'A':
+               a.type = APPROACH;
+               break;
+       case '[':
+               a.type = INVALID;
+               return fin >> skipeol;
+       default:
+               SG_LOG(SG_GENERAL, SG_ALERT, "Warning - unknown type \'" << tp << "\' found whilst reading ATC frequency data!\n");
+               a.type = INVALID;
+               return fin >> skipeol;
+       }
+       
+       double lat, lon, elev;
+
+       fin >> lat >> lon >> elev >> f >> a.range >> a.ident;
+       a.geod = SGGeod::fromDegM(lon, lat, elev);
+       a.name = "";
+       fin >> ch;
+       if(ch != '"') a.name += ch;
+       while(1) {
+               //in >> noskipws
+               fin.unsetf(std::ios::skipws);
+               fin >> ch;
+               if((ch == '"') || (ch == 0x0A)) {
+                       break;
+               }   // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the "
+               a.name += ch;
+       }
+       fin.setf(std::ios::skipws);
+       //cout << "Comm name = " << a.name << '\n';
+       
+       a.freq = (int)(f*100.0 + 0.5);
+       
+       // cout << a.ident << endl;
+       
+       // generate cartesian coordinates
+       a.cart = SGVec3d::fromGeod(a.geod);     
+       return fin >> skipeol;
+}
+