// Implementation of FGATC - ATC subsystem base class. // // Written by David Luff, started February 2002. // // Copyright (C) 2002 David C Luff - david.luff@nottingham.ac.uk // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifdef HAVE_CONFIG_H # include #endif #include #include
#include "ATC.hxx" #include "ATCdisplay.hxx" FGATC::FGATC() { freqClear = true; receiving = false; respond = false; runResponseCounter = false; _runReleaseCounter = false; responseID = ""; responseReqd = false; _type = INVALID; } FGATC::~FGATC() { } // 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'; if(responseCounter >= responseTime) { runResponseCounter = false; respond = true; //cout << "RESPOND\n"; } else { responseCounter += dt; } } if(_runReleaseCounter) { if(_releaseCounter >= _releaseTime) { freqClear = true; _runReleaseCounter = false; } else { _releaseCounter += dt; } } } void FGATC::ReceiveUserCallback(int code) { SG_LOG(SG_ATC, SG_WARN, "WARNING - whichever ATC class was intended to receive callback code " << code << " didn't get it!!!"); } void FGATC::SetResponseReqd(string rid) { receiving = false; responseReqd = true; respond = false; // TODO - this ignores the fact that more than one plane could call this before response // Shouldn't happen with AI only, but user could confuse things?? responseID = rid; runResponseCounter = true; responseCounter = 0.0; responseTime = 1.8; // TODO - randomize this slightly. } void FGATC::NotifyTransmissionFinished(string rid) { //cout << "Transmission finished, callsign = " << rid << '\n'; receiving = false; responseID = rid; if(responseReqd) { runResponseCounter = true; responseCounter = 0.0; responseTime = 1.2; // TODO - randomize this slightly, and allow it to be dependent on the transmission and how busy the ATC is. respond = false; // TODO - this ignores the fact that more than one plane could call this before response // Shouldn't happen with AI only, but user could confuse things?? } else { freqClear = true; } } void FGATC::AddPlane(string pid) { } int FGATC::RemovePlane() { return 0; } void FGATC::SetDisplay() { } void FGATC::SetNoDisplay() { } void FGATC::SetData(ATCData* d) { lon = d->lon; lat = d->lat; elev = d->elev; x = d->x; y = d->y; z = d->z; range = d->range; ident = d->ident; name = d->name; freq = d->freq; } // Render a transmission // 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, string refname, bool repeating) { #ifdef ENABLE_AUDIO_SUPPORT voice = (voiceOK && fgGetBool("/sim/sound/audible") && fgGetBool("/sim/sound/voice")); if(voice) { int len; unsigned char* buf = vPtr->WriteMessage((char*)msg.c_str(), len, voice); if(voice) { SGSimpleSound* simple = new SGSimpleSound(buf, len); // 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("/radios/comm[0]/volume")); globals->get_soundmgr()->add(simple, refname); if(repeating) { globals->get_soundmgr()->play_looped(refname); } else { globals->get_soundmgr()->play_once(refname); } } delete[] buf; } #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) { if((msg.substr(i,1) == "_") || (msg.substr(i,1) == "/")) { msg[i] = ' '; } } globals->get_ATC_display()->RegisterRepeatingMessage(msg); } playing = true; } // Cease rendering a transmission. void FGATC::NoRender(string refname) { if(playing) { if(voice) { #ifdef ENABLE_AUDIO_SUPPORT globals->get_soundmgr()->stop(refname); globals->get_soundmgr()->remove(refname); #endif } else { globals->get_ATC_display()->CancelRepeatingMessage(); } playing = false; } } // Generate the text of a message from its parameters and the current context. string FGATC::GenText(const string& m, int c) { return(""); } 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(APPROACH): return(os << "APPROACH"); case(DEPARTURE): return(os << "DEPARTURE"); case(ENROUTE): return(os << "ENROUTE"); } return(os << "ERROR - Unknown switch in atc_type operator << "); }