1
0
Fork 0

ATCDCL cleanup, part II.

Remove/comment out obsolete code.
Refactor ATCmgr(-old) into ATISmgr(-new), only keeping the COM radio / ATIS
support.
This commit is contained in:
ThorstenB 2012-05-12 23:27:57 +02:00
parent d6ef7bb091
commit a2922e2e23
12 changed files with 425 additions and 513 deletions

View file

@ -35,9 +35,13 @@
#include <Airports/simple.hxx>
FGATC::FGATC() :
freq(0),
_currentStation(NULL),
range(0),
_voice(true),
_playing(false),
_voiceOK(false),
_sgr(NULL),
#ifdef OLD_ATC_MGR
freqClear(true),
receiving(false),
respond(false),
@ -45,22 +49,25 @@ FGATC::FGATC() :
runResponseCounter(false),
_runReleaseCounter(false),
responseReqd(false),
_type(INVALID),
_display(false),
// Transmission timing stuff
pending_transmission(""),
_timeout(0),
#endif
_type(INVALID),
_display(false)
#ifdef OLD_ATC_MGR
,_timeout(0),
_pending(false),
_transmit(false),
_transmitting(false),
_counter(0.0),
_max_count(5.0)
#endif
{
SGSoundMgr *smgr = globals->get_soundmgr();
_sgr = smgr->find("atc", true);
_sgr->tie_to_listener();
_sgr->tie_to_listener();
_volume = fgGetNode("/sim/sound/atc/volume", true);
_masterVolume = 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);
@ -72,6 +79,20 @@ FGATC::~FGATC() {
// Derived classes wishing to use the response counter should
// call this from their own Update(...).
void FGATC::Update(double dt) {
#ifdef ENABLE_AUDIO_SUPPORT
bool active = _atc_external->getBoolValue() ||
_internal->getBoolValue();
if ( active && _enabled->getBoolValue() ) {
_sgr->set_volume( _masterVolume->getFloatValue() );
_sgr->resume(); // no-op if already in resumed state
} else {
_sgr->suspend();
}
#endif
#ifdef OLD_ATC_MGR
if(runResponseCounter) {
//cout << responseCounter << '\t' << responseTime << '\n';
if(responseCounter >= responseTime) {
@ -112,18 +133,6 @@ 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!
@ -149,8 +158,10 @@ void FGATC::Update(double dt) {
}
_counter += dt;
}
#endif
}
#ifdef OLD_ATC_MGR
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!!!");
}
@ -180,21 +191,45 @@ void FGATC::NotifyTransmissionFinished(const string& rid) {
freqClear = true;
}
}
#endif
void FGATC::SetStation(flightgear::CommStation* sta) {
switch (sta->type()) {
case FGPositioned::FREQ_ATIS: _type = ATIS; break;
case FGPositioned::FREQ_AWOS: _type = AWOS; break;
default:
throw sg_exception("unsupported comm station type");
if (_currentStation == sta)
return;
_currentStation = sta;
if (sta)
{
switch (sta->type()) {
case FGPositioned::FREQ_ATIS: _type = ATIS; break;
case FGPositioned::FREQ_AWOS: _type = AWOS; break;
default:
sta = NULL;
break;
}
}
if (sta == NULL)
{
range = 0;
ident = "";
name = "";
freq = 0;
SetNoDisplay();
Update(0); // one last update
}
else
{
_geod = sta->geod();
_cart = sta->cart();
range = sta->rangeNm();
ident = sta->airport()->ident();
name = sta->airport()->name();
freq = sta->freqKHz();
SetDisplay();
}
_geod = sta->geod();
_cart = sta->cart();
range = sta->rangeNm();
ident = sta->airport()->ident();
name = sta->airport()->name();
freq = sta->freqKHz();
}
// Render a transmission
@ -203,7 +238,7 @@ void FGATC::SetStation(flightgear::CommStation* sta) {
// The repeating flag indicates whether the message should be repeated continuously or played once.
void FGATC::Render(string& msg, const float volume,
const string& refname, const bool repeating) {
if (volume < 0.05)
if ((!_display) ||(volume < 0.05))
{
NoRender(refname);
return;
@ -215,35 +250,55 @@ void FGATC::Render(string& msg, const float volume,
fgSetString("/sim/messages/atc", msg.c_str());
#ifdef ENABLE_AUDIO_SUPPORT
_voice = (_voiceOK && fgGetBool("/sim/sound/voice"));
if(_voice) {
size_t len;
void* buf = _vPtr->WriteMessage((char*)msg.c_str(), &len);
NoRender(refname);
if(buf) {
try {
bool useVoice = _voice && fgGetBool("/sim/sound/voice") && fgGetBool("/sim/sound/atc/enabled");
SGSoundSample *simple = _sgr->find(refname);
if(useVoice) {
if (simple && (_currentMsg == msg))
{
simple->set_volume(volume);
}
else
{
_currentMsg = msg;
size_t len;
void* buf = NULL;
if (!_vPtr)
_vPtr = GetVoicePointer();
if (_vPtr)
buf = _vPtr->WriteMessage((char*)msg.c_str(), &len);
NoRender(refname);
if(buf) {
try {
// >>> 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_ATC, SG_ALERT, e.getFormattedMessage());
}
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_ATC, SG_ALERT, e.getFormattedMessage());
}
}
}
}
else
if (simple)
{
NoRender(refname);
}
#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
if (!useVoice)
{
// first rip the underscores and the pause hints out of the string - these are for the convenience of the voice parser
for(unsigned int i = 0; i < msg.length(); ++i) {
if((msg.substr(i,1) == "_") || (msg.substr(i,1) == "/")) {
msg[i] = ' ';
}
}
}
_playing = true;
_playing = true;
}
@ -251,7 +306,7 @@ void FGATC::Render(string& msg, const float volume,
void FGATC::NoRender(const string& refname) {
if(_playing) {
if(_voice) {
#ifdef ENABLE_AUDIO_SUPPORT
#ifdef ENABLE_AUDIO_SUPPORT
_sgr->stop(refname);
_sgr->remove(refname);
#endif
@ -260,6 +315,7 @@ void FGATC::NoRender(const string& refname) {
}
}
#ifdef OLD_ATC_MGR
// Generate the text of a message from its parameters and the current context.
string FGATC::GenText(const string& m, int c) {
return("");
@ -336,4 +392,4 @@ std::istream& operator >> ( std::istream& fin, ATCData& a )
a.cart = SGVec3d::fromGeod(a.geod);
return fin >> skipeol;
}
#endif

View file

@ -42,20 +42,6 @@ namespace flightgear
class CommStation;
}
// Convert a frequency in MHz to tens of kHz
// so we can use it e.g. as an index into commlist_freq
//
// If freq > 1000 assume it's already in tens of KHz;
// otherwise assume MHz.
//
// Note: 122.375 must be rounded DOWN to 12237
// in order to be consistent with apt.dat et cetera.
inline int kHz10(double freq)
{
if (freq > 1000.) return int(freq);
return int(freq*100.0 + 0.25);
}
// Possible types of ATC type that the radios may be tuned to.
// INVALID implies not tuned in to anything.
enum atc_type {
@ -69,6 +55,7 @@ enum atc_type {
INVALID /* must be last element; see ATC_NUM_TYPES */
};
#ifdef OLD_ATC_MGR
const int ATC_NUM_TYPES = 1 + INVALID;
// DCL - new experimental ATC data store
@ -98,9 +85,10 @@ struct RunwayDetails {
};
std::ostream& operator << (std::ostream& os, atc_type atc);
#endif
class FGATC {
friend class FGATCMgr;
friend class FGATISMgr;
public:
FGATC();
@ -113,15 +101,16 @@ public:
// wish to use the response timer functionality.
virtual void Update(double dt);
// Recieve a coded callback from the ATC menu system based on the user's selection
virtual void ReceiveUserCallback(int code);
// Indicate that this instance should output to the display if appropriate
inline void SetDisplay() { _display = true; }
// Indicate that this instance should not output to the display
inline void SetNoDisplay() { _display = false; }
#ifdef OLD_ATC_MGR
// Receive a coded callback from the ATC menu system based on the user's selection
virtual void ReceiveUserCallback(int code);
// Generate the text of a message from its parameters and the current context.
virtual std::string GenText(const std::string& m, int c);
@ -141,21 +130,24 @@ public:
// AI traffic should check FreqClear() is true prior to transmitting.
// The user will just have to wait for a gap in dialog as in real life.
// Return the type of ATC station that the class represents
inline atc_type GetType() { return _type; }
// Set the core ATC data
void SetStation(flightgear::CommStation* sta);
inline int get_freq() const { return freq; }
inline void set_freq(const int fq) {freq = fq;}
inline int get_range() const { return range; }
inline void set_range(const int rg) {range = rg;}
#endif
// Return the type of ATC station that the class represents
inline atc_type GetType() { return _type; }
// Set the core ATC data
void SetStation(flightgear::CommStation* sta);
inline const std::string& get_ident() { return ident; }
inline void set_ident(const std::string& id) { ident = id; }
inline const std::string& get_name() { return name; }
inline void set_name(const std::string& nm) { name = nm; }
protected:
// Render a transmission
@ -169,25 +161,26 @@ protected:
// Requires the sound manager refname if audio, else "".
void NoRender(const std::string& refname);
virtual FGATCVoice* GetVoicePointer() = 0;
SGGeod _geod;
SGVec3d _cart;
int freq;
std::map<std::string,int> active_on;
flightgear::CommStation* _currentStation;
int range;
std::string ident; // Code of the airport its at.
std::string name; // Name transmitted in the broadcast.
std::string _currentMsg; // Current message being transmitted
// Rendering related stuff
bool _voice; // Flag - true if we are using voice
bool _playing; // Indicates a message in progress
bool _voiceOK; // Flag - true if at least one voice has loaded OK
bool _playing; // Indicates a message in progress
FGATCVoice* _vPtr;
SGSharedPtr<SGSampleGroup> _sgr; // default sample group;
#ifdef OLD_ATC_MGR
bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog
bool receiving; // Flag to indicate we are receiving a transmission
@ -204,11 +197,14 @@ protected:
bool responseReqd; // Flag to indicate we should be responding to a request/report
double _releaseTime;
double _releaseCounter;
std::string pending_transmission; // derived classes set this string before calling Transmit(...)
#endif
atc_type _type;
bool _display; // Flag to indicate whether we should be outputting to the ATC display.
std::string pending_transmission; // derived classes set this string before calling Transmit(...)
private:
#ifdef OLD_ATC_MGR
// Transmission timing stuff.
double _timeout;
bool _pending;
@ -216,13 +212,16 @@ private:
bool _transmitting; // we are transmitting
double _counter;
double _max_count;
#endif
SGPropertyNode_ptr _volume;
SGPropertyNode_ptr _masterVolume;
SGPropertyNode_ptr _enabled;
SGPropertyNode_ptr _atc_external;
SGPropertyNode_ptr _internal;
};
#ifdef OLD_ATC_MGR
std::istream& operator>> ( std::istream& fin, ATCData& a );
#endif
#endif // _FG_ATC_HXX

View file

@ -1,308 +0,0 @@
// ATCmgr.cxx - Implementation of FGATCMgr - a global Flightgear ATC manager.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/structure/exception.hxx>
#include <Airports/simple.hxx>
#include <ATC/CommStation.hxx>
#include <Main/fg_props.hxx>
#include "ATCmgr.hxx"
#include "ATCutils.hxx"
#include "atis.hxx"
using flightgear::CommStation;
FGATCMgr::FGATCMgr() :
initDone(false),
atc_list(new atc_list_type),
#ifdef ENABLE_AUDIO_SUPPORT
voice(true),
voiceOK(false),
v1(0)
#else
voice(false),
#endif
{
globals->set_ATC_mgr(this);
}
FGATCMgr::~FGATCMgr() {
globals->set_ATC_mgr(NULL);
delete v1;
}
void FGATCMgr::bind() {
}
void FGATCMgr::unbind() {
}
void FGATCMgr::init() {
//cout << "ATCMgr::init called..." << endl;
lon_node = fgGetNode("/position/longitude-deg", true);
lat_node = fgGetNode("/position/latitude-deg", true);
elev_node = fgGetNode("/position/altitude-ft", true);
atc_list_itr = atc_list->begin();
// Search for connected ATC stations once per 0.8 seconds or so
// globals->get_event_mgr()->add( "fgATCSearch()", fgATCSearch,
// FGEvent::FG_EVENT_READY, 800);
//
// For some reason the above doesn't compile - including Time/event.hxx stops compilation.
// Is this still true after the reorganization of the event managar??
// -EMH-
initDone = true;
//cout << "ATCmgr::init done!" << endl;
}
void FGATCMgr::update(double dt) {
if(!initDone) {
init();
SG_LOG(SG_ATC, SG_WARN, "Warning - ATCMgr::update(...) called before ATCMgr::init()");
}
//cout << "Entering update..." << endl;
//Traverse the list of active stations.
//Only update one class per update step to avoid the whole ATC system having to calculate between frames.
//Eventually we should only update every so many steps.
//cout << "In FGATCMgr::update - atc_list.size = " << atc_list->size() << endl;
if(atc_list->size()) {
if(atc_list_itr == atc_list->end()) {
atc_list_itr = atc_list->begin();
}
//cout << "Updating " << (*atc_list_itr)->get_ident() << ' ' << (*atc_list_itr)->GetType() << '\n';
//cout << "Freq = " << (*atc_list_itr)->get_freq() << '\n';
//cout << "Updating...\n";
(*atc_list_itr).second->Update(dt * atc_list->size());
//cout << "Done ATC update..." << endl;
++atc_list_itr;
}
#ifdef ATC_TEST
//cout << "ATC_LIST: " << atc_list->size() << ' ';
for(atc_list_iterator it = atc_list->begin(); it != atc_list->end(); it++) {
cout << (*it)->get_ident() << ' ';
}
//cout << '\n';
#endif
// Search the tuned frequencies every now and then - this should be done with the event scheduler
static int i = 0; // Very ugly - but there should only ever be one instance of FGATCMgr.
if(i == 15) {
//cout << "About to search navcomm1" << endl;
FreqSearch("comm", 0);
FreqSearch("nav", 0);
}
if(i == 30) {
//cout << "About to search navcomm2" << endl;
FreqSearch("comm", 1);
FreqSearch("nav", 1);
i = 0;
}
++i;
//cout << "comm1 type = " << comm_type[0] << '\n';
//cout << "Leaving update..." << endl;
}
typedef map<string,int> MSI;
void FGATCMgr::ZapOtherService(const string ncunit, const string svc_name){
for (atc_list_iterator svc = atc_list->begin(); svc != atc_list->end(); svc++) {
if (svc->first != svc_name) {
MSI &actv = svc->second->active_on;
// OK, we have found some OTHER service;
// see if it is (was) active on our unit:
if (!actv.count(ncunit)) continue;
//cout << "Eradicating '" << svc->first << "' from: " << ncunit << endl;
actv.erase(ncunit);
if (!actv.size()) {
//cout << "Eradicating service: '" << svc->first << "'" << endl;
svc->second->SetNoDisplay();
svc->second->Update(0); // one last update
SG_LOG(SG_ATC, SG_INFO, "would have erased ATC service:" << svc->second->get_name()<< "/"
<< svc->second->get_ident());
// delete svc->second;
atc_list->erase(svc);
// ALL pointers into the ATC list are now invalid,
// so let's reset them:
atc_list_itr = atc_list->begin();
}
break; // cannot be duplicates in the active list
}
}
}
// Find in list - return a currently active ATC pointer given ICAO code and type
// Return NULL if the given service is not in the list
// - *** THE CALLING FUNCTION MUST CHECK FOR THIS ***
FGATC* FGATCMgr::FindInList(const string& id, const atc_type& tp) {
string ndx = id + decimalNumeral(tp);
if (!atc_list->count(ndx)) return 0;
return (*atc_list)[ndx];
}
// Return a pointer to an appropriate voice for a given type of ATC
// creating the voice if necessary - ie. make sure exactly one copy
// of every voice in use exists in memory.
//
// TODO - in the future this will get more complex and dole out country/airport
// specific voices, and possible make sure that the same voice doesn't get used
// at different airports in quick succession if a large enough selection are available.
FGATCVoice* FGATCMgr::GetVoicePointer(const atc_type& type) {
// TODO - implement me better - maintain a list of loaded voices and other voices!!
if(voice) {
switch(type) {
case ATIS: case AWOS:
#ifdef ENABLE_AUDIO_SUPPORT
// Delayed loading fo all available voices, needed because the
// soundmanager might not be initialized (at all) at this point.
// For now we'll do one hardwired one
/* I've loaded the voice even if /sim/sound/pause is true
* since I know no way of forcing load of the voice if the user
* subsequently switches /sim/sound/audible to true.
* (which is the right thing to do -- CLO) :-)
*/
if (!voiceOK && fgGetBool("/sim/sound/working")) {
v1 = new FGATCVoice;
try {
voiceOK = v1->LoadVoice("default");
voice = voiceOK;
} catch ( sg_io_exception & e) {
voiceOK = false;
SG_LOG(SG_ATC, SG_ALERT, "Unable to load default voice : "
<< e.getFormattedMessage().c_str());
voice = false;
delete v1;
v1 = 0;
}
}
#endif
if(voiceOK) {
return(v1);
}
case TOWER:
return(NULL);
case APPROACH:
return(NULL);
case GROUND:
return(NULL);
default:
return(NULL);
}
return(NULL);
} else {
return(NULL);
}
}
// Search for ATC stations by frequency
void FGATCMgr::FreqSearch(const string navcomm, const int unit) {
string ncunit = navcomm + "[" + decimalNumeral(unit) + "]";
string commbase = "/instrumentation/" + ncunit;
string commfreq = commbase + "/frequencies/selected-mhz";
SGPropertyNode_ptr comm_node = fgGetNode(commfreq.c_str(), false);
//cout << "FreqSearch: " << ncunit
// << " node: " << comm_node << endl;
if (!comm_node) return; // no such radio unit
ATCData data;
// Note: 122.375 must be rounded DOWN to 12237
// in order to be consistent with apt.dat et cetera.
int freqKhz = static_cast<int>(comm_node->getDoubleValue() * 100.0 + 0.25);
_aircraftPos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
lat_node->getDoubleValue(), elev_node->getDoubleValue());
class RangeFilter : public CommStation::Filter {
public:
RangeFilter( const SGGeod & pos ) :
CommStation::Filter(),
_cart(SGVec3d::fromGeod(pos)),
_pos(pos)
{}
virtual bool pass(FGPositioned* aPos) const
{
flightgear::CommStation * stn = dynamic_cast<flightgear::CommStation*>(aPos);
if( NULL == stn ) return false;
// do the range check in cartesian space, since the distances are potentially
// large enough that the geodetic functions become unstable
// (eg, station on opposite side of the planet)
double rangeM = SGMiscd::max( stn->rangeNm(), 10.0 ) * SG_NM_TO_METER;
double d2 = distSqr( aPos->cart(), _cart);
return d2 <= (rangeM * rangeM);
}
private:
SGVec3d _cart;
SGGeod _pos;
};
RangeFilter rangeFilter(_aircraftPos );
CommStation* sta = CommStation::findByFreq(freqKhz, _aircraftPos, &rangeFilter );
if (!sta) {
ZapOtherService(ncunit, "x x x");
return;
}
// Get rid of any *other* service that was on this radio unit:
FGPositioned::Type ty = sta->type();
string svc_name = sta->ident() + FGPositioned::nameForType(ty);
ZapOtherService(ncunit, svc_name);
// See if the service already exists, possibly connected to
// some other radio unit:
if (atc_list->count(svc_name)) {
// make sure the service knows it's tuned on this radio:
FGATC* svc = (*atc_list)[svc_name];
svc->active_on[ncunit] = 1;
svc->SetDisplay();
return;
}
// This was a switch-case statement but the compiler didn't like
// the new variable creation with it.
if(ty == FGPositioned::FREQ_ATIS || ty == FGPositioned::FREQ_AWOS) {
(*atc_list)[svc_name] = new FGATIS;
FGATC* svc = (*atc_list)[svc_name];
if(svc != NULL) {
svc->SetStation(sta);
svc->active_on[ncunit] = 1;
svc->SetDisplay();
svc->Init();
}
}
}

208
src/ATCDCL/ATISmgr.cxx Normal file
View file

@ -0,0 +1,208 @@
// ATISmgr.cxx - Implementation of FGATISMgr - a global Flightgear ATIS manager.
//
// Written by David Luff, started February 2002.
//
// Copyright (C) 2002 David C Luff - david.luff@nottingham.ac.uk
// Copyright (C) 2012 Thorsten Brehm
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/structure/exception.hxx>
#include <Airports/simple.hxx>
#include <ATC/CommStation.hxx>
#include <Main/fg_props.hxx>
#include "ATISmgr.hxx"
#include "ATCutils.hxx"
#include "atis.hxx"
using flightgear::CommStation;
FGATISMgr::FGATISMgr() :
_currentUnit(0),
_maxCommRadios(2),
#ifdef ENABLE_AUDIO_SUPPORT
voice(true),
voice1(0)
#else
voice(false)
#endif
{
globals->set_ATIS_mgr(this);
}
FGATISMgr::~FGATISMgr()
{
globals->set_ATIS_mgr(NULL);
for (unsigned int unit = 0;unit < _maxCommRadios; ++unit)
{
delete radios[unit].station;
radios[unit].station = NULL;
}
#ifdef ENABLE_AUDIO_SUPPORT
delete voice1;
#endif
}
void FGATISMgr::bind()
{
}
void FGATISMgr::unbind()
{
}
void FGATISMgr::init()
{
lon_node = fgGetNode("/position/longitude-deg", true);
lat_node = fgGetNode("/position/latitude-deg", true);
elev_node = fgGetNode("/position/altitude-ft", true);
for (unsigned int unit = 0;unit < _maxCommRadios; ++unit)
{
CommRadioData data;
string ncunit = "comm[" + decimalNumeral(unit) + "]";
string commbase = "/instrumentation/" + ncunit;
string commfreq = commbase + "/frequencies/selected-mhz";
data.freq = fgGetNode(commfreq.c_str(), true);
data.station = new FGATIS(commbase);
radios.push_back(data);
}
}
void FGATISMgr::update(double dt)
{
// update only runs every now and then (1-2 per second)
if (++_currentUnit >= _maxCommRadios)
_currentUnit = 0;
FGATC* pStation = radios[_currentUnit].station;
if (pStation)
pStation->Update(dt * _maxCommRadios);
// Search the tuned frequencies
FreqSearch(_currentUnit);
}
// Return a pointer to an appropriate voice for a given type of ATC
// creating the voice if necessary - i.e. make sure exactly one copy
// of every voice in use exists in memory.
//
// TODO - in the future this will get more complex and dole out country/airport
// specific voices, and possible make sure that the same voice doesn't get used
// at different airports in quick succession if a large enough selection are available.
FGATCVoice* FGATISMgr::GetVoicePointer(const atc_type& type)
{
// TODO - implement me better - maintain a list of loaded voices and other voices!!
if(voice)
{
switch(type)
{
case ATIS: case AWOS:
#ifdef ENABLE_AUDIO_SUPPORT
// Delayed loading for all available voices, needed because the
// sound manager might not be initialized (at all) at this point.
// For now we'll do one hard-wired one
/* I've loaded the voice even if /sim/sound/pause is true
* since I know no way of forcing load of the voice if the user
* subsequently switches /sim/sound/audible to true.
* (which is the right thing to do -- CLO) :-)
*/
if (!voice1 && fgGetBool("/sim/sound/working")) {
voice1 = new FGATCVoice;
try {
voice = voice1->LoadVoice("default");
} catch ( sg_io_exception & e) {
SG_LOG(SG_ATC, SG_ALERT, "Unable to load default voice : "
<< e.getFormattedMessage().c_str());
voice = false;
delete voice1;
voice1 = 0;
}
}
if (voice)
return voice1;
#endif
return NULL;
case TOWER:
return NULL;
case APPROACH:
return NULL;
case GROUND:
return NULL;
default:
return NULL;
}
}
return NULL;
}
class RangeFilter : public CommStation::Filter
{
public:
RangeFilter( const SGGeod & pos ) :
CommStation::Filter(),
_cart(SGVec3d::fromGeod(pos)),
_pos(pos)
{
}
virtual bool pass(FGPositioned* aPos) const
{
flightgear::CommStation * stn = dynamic_cast<flightgear::CommStation*>(aPos);
if( NULL == stn )
return false;
// do the range check in cartesian space, since the distances are potentially
// large enough that the geodetic functions become unstable
// (eg, station on opposite side of the planet)
double rangeM = SGMiscd::max( stn->rangeNm(), 10.0 ) * SG_NM_TO_METER;
double d2 = distSqr( aPos->cart(), _cart);
return d2 <= (rangeM * rangeM);
}
private:
SGVec3d _cart;
SGGeod _pos;
};
// Search for ATC stations by frequency
void FGATISMgr::FreqSearch(const unsigned int unit)
{
double frequency = radios[unit].freq->getDoubleValue();
// Note: 122.375 must be rounded DOWN to 12237
// in order to be consistent with apt.dat et cetera.
int freqKhz = static_cast<int>(frequency * 100.0 + 0.25);
_aircraftPos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
lat_node->getDoubleValue(), elev_node->getDoubleValue());
RangeFilter rangeFilter(_aircraftPos );
CommStation* sta = CommStation::findByFreq(freqKhz, _aircraftPos, &rangeFilter );
radios[unit].station->SetStation(sta);
}

View file

@ -1,5 +1,5 @@
// ATCMgr.hxx - definition of FGATCMgr
// - a global management class for FlightGear generated ATC
// ATISmgr.hxx - definition of FGATISMgr
// - a global management class for FlightGear generated ATIS
//
// Written by David Luff, started February 2002.
//
@ -30,23 +30,26 @@
#include "ATC.hxx"
class FGATCMgr : public SGSubsystem
namespace flightgear
{
class CommStation;
}
typedef struct
{
SGPropertyNode_ptr freq;
FGATC* station;
} CommRadioData;
class FGATISMgr : public SGSubsystem
{
private:
// A vector containing all comm radios
typedef std::vector<CommRadioData> radio_list_type;
radio_list_type radios;
bool initDone; // Hack - guard against update getting called before init
// A list of pointers to all currently active ATC classes
typedef std::map<std::string,FGATC*> atc_list_type;
typedef atc_list_type::iterator atc_list_iterator;
typedef atc_list_type::const_iterator atc_list_const_iterator;
// Everything put in this list should be created dynamically
// on the heap and ***DELETED WHEN REMOVED!!!!!***
atc_list_type* atc_list;
atc_list_iterator atc_list_itr;
// Any member function of FGATCMgr is permitted to leave this iterator pointing
// Any member function of FGATISMgr is permitted to leave this iterator pointing
// at any point in or at the end of the list.
// Hence any new access must explicitly first check for atc_list.end() before dereferencing.
@ -58,19 +61,18 @@ private:
SGPropertyNode_ptr lat_node;
SGPropertyNode_ptr elev_node;
//FGATIS atis;
unsigned int _currentUnit;
unsigned int _maxCommRadios;
// Voice related stuff
bool voice; // Flag - true if we are using voice
#ifdef ENABLE_AUDIO_SUPPORT
bool voiceOK; // Flag - true if at least one voice has loaded OK
FGATCVoice* v1;
FGATCVoice* voice1;
#endif
public:
FGATCMgr();
~FGATCMgr();
FGATISMgr();
~FGATISMgr();
void init();
@ -80,35 +82,18 @@ public:
void update(double dt);
// Return a pointer to an appropriate voice for a given type of ATC
// creating the voice if necessary - ie. make sure exactly one copy
// creating the voice if necessary - i.e. make sure exactly one copy
// of every voice in use exists in memory.
//
// TODO - in the future this will get more complex and dole out country/airport
// specific voices, and possible make sure that the same voice doesn't get used
// at different airports in quick succession if a large enough selection are available.
FGATCVoice* GetVoicePointer(const atc_type& type);
atc_type GetComm1ATCType() { return(INVALID/* kludge */); }
FGATC* GetComm1ATCPointer() { return(0/* kludge */); }
atc_type GetComm2ATCType() { return(INVALID); }
FGATC* GetComm2ATCPointer() { return(0/* kludge */); }
private:
// Remove a class from the atc_list and delete it from memory
// *if* no other comm channel or AI plane is using it.
void ZapOtherService(const std::string ncunit, const std::string svc_name);
// Return a pointer to a class in the list given ICAO code and type
// Return NULL if the given service is not in the list
// - *** THE CALLING FUNCTION MUST CHECK FOR THIS ***
FGATC* FindInList(const std::string& id, const atc_type& tp);
// Search the specified radio for stations on the same frequency and in range.
void FreqSearch(const std::string navcomm, const int unit);
void FreqSearch(const unsigned int unit);
};
#endif // _FG_ATCMGR_HXX

View file

@ -4,7 +4,7 @@ set(SOURCES
ATC.cxx
atis.cxx
ATCVoice.cxx
ATCmgr.cxx
ATISmgr.cxx
ATCutils.cxx
ATCProjection.cxx
)
@ -13,7 +13,7 @@ set(HEADERS
ATC.hxx
atis.hxx
ATCVoice.hxx
ATCmgr.hxx
ATISmgr.hxx
ATCutils.hxx
ATCProjection.hxx
atis_lexicon.hxx

View file

@ -57,7 +57,7 @@
#include "ATCutils.hxx"
#include "ATCmgr.hxx"
#include "ATISmgr.hxx"
using std::string;
using std::map;
@ -66,7 +66,7 @@ using std::cout;
using boost::ref;
using boost::tie;
FGATIS::FGATIS() :
FGATIS::FGATIS(const string& commbase) :
transmission(""),
trans_ident(""),
old_volume(0),
@ -74,20 +74,8 @@ FGATIS::FGATIS() :
msg_OK(0),
attention(0),
_prev_display(0),
refname("atis")
_commbase(commbase)
{
FGATCMgr* pAtcMgr = globals->get_ATC_mgr();
if (!pAtcMgr)
{
SG_LOG(SG_ATC, SG_ALERT, "ERROR! No ATC manager! Oops...");
_vPtr = NULL;
}
else
_vPtr = pAtcMgr->GetVoicePointer(ATIS);
_voiceOK = (_vPtr == NULL ? false : true);
if (!(_type != ATIS || _type == AWOS)) {
SG_LOG(SG_ATC, SG_ALERT, "ERROR - _type not ATIS or AWOS in atis.cxx");
}
fgTie("/environment/attention", this, (int_getter)0, &FGATIS::attend);
///////////////
@ -115,6 +103,18 @@ FGATIS::~FGATIS() {
fgUntie("/environment/attention");
}
FGATCVoice* FGATIS::GetVoicePointer()
{
FGATISMgr* pAtisMgr = globals->get_ATIS_mgr();
if (!pAtisMgr)
{
SG_LOG(SG_ATC, SG_ALERT, "ERROR! No ATIS manager! Oops...");
return NULL;
}
return pAtisMgr->GetVoicePointer(ATIS);
}
void FGATIS::Init() {
// Nothing to see here. Move along.
}
@ -137,6 +137,7 @@ FGATIS::attend (int attn)
void FGATIS::Update(double dt) {
cur_time = globals->get_time_params()->get_cur_time();
msg_OK = (msg_time < cur_time);
#ifdef ATIS_TEST
if (msg_OK || _display != _prev_display) {
cout << "ATIS Update: " << _display << " " << _prev_display
@ -146,29 +147,27 @@ void FGATIS::Update(double dt) {
msg_time = cur_time;
}
#endif
if(_display) {
double volume(0);
for (map<string,int>::iterator act = active_on.begin();
act != active_on.end(); act++) {
string prop = "/instrumentation/" + act->first + "/volume";
volume += globals->get_props()->getDoubleValue(prop.c_str());
}
if(_display)
{
string prop = _commbase + "/volume";
double volume = globals->get_props()->getDoubleValue(prop.c_str());
// Check if we need to update the message
// - basically every hour and if the weather changes significantly at the station
// If !_prev_display, the radio had been detuned for a while and our
// "transmission" variable was lost when we were de-instantiated.
int rslt = GenTransmission(!_prev_display, attention);
int changed = GenTransmission(!_prev_display, attention);
TreeOut(msg_OK);
if (rslt || volume != old_volume) {
if (changed || volume != old_volume) {
//cout << "ATIS calling ATC::render volume: " << volume << endl;
Render(transmission, volume, refname, true);
Render(transmission, volume, _commbase, true);
old_volume = volume;
}
} else {
// We shouldn't be displaying
//cout << "ATIS.CXX - calling NoRender()..." << endl;
NoRender(refname);
NoRender(_commbase);
}
_prev_display = _display;
attention = 0;
@ -517,26 +516,16 @@ int FGATIS::GenTransmission(const int regen, const int special) {
return 1;
}
// Put the transmission into the property tree,
// possibly in multiple places if multiple radios
// are tuned to the same ATIS.
// Put the transmission into the property tree.
// You can see it by pointing a web browser
// at the property tree. The second comm radio is:
// http://localhost:5400/instrumentation/comm[1]
//
// (Also, if in debug mode, dump it to the console.)
void FGATIS::TreeOut(int msg_OK){
for (map<string,int>::iterator act = active_on.begin();
act != active_on.end();
act++){
string prop = "/instrumentation/" + act->first + "/atis";
string prop = _commbase + "/atis";
globals->get_props()->setStringValue(prop.c_str(),
("<pre>\n" + transmission_readable + "</pre>\n").c_str());
#ifdef ATIS_TEST
if (msg_OK) cout << "**** ATIS active on: " << prop << endl;
#endif
}
#ifdef ATIS_TEST
if (msg_OK) cout << transmission_readable << endl;
#endif
SG_LOG(SG_ATC, SG_DEBUG, "**** ATIS active on: " << prop <<
"transmission: " << transmission_readable);
}

View file

@ -60,6 +60,8 @@ class FGATIS : public FGATC {
bool _prev_display; // Previous value of _display flag
MSS _remap; // abbreviations to be expanded
std::string _commbase;
// Aircraft position
// ATIS is actually a special case in that unlike other ATC eg.tower it doesn't actually know about
// or the whereabouts of the aircraft it is transmitting to. However, to ensure consistancy of
@ -69,9 +71,9 @@ class FGATIS : public FGATC {
//SGPropertyNode_ptr airplane_lat_node;
//SGPropertyNode_ptr airplane_elev_node;
public:
public:
FGATIS(void);
FGATIS(const std::string& commbase);
~FGATIS(void);
virtual void Init();
void attend (int);
@ -81,12 +83,12 @@ class FGATIS : public FGATC {
//inline void set_type(const atc_type tp) {type = tp;}
inline const std::string& get_trans_ident() { return trans_ident; }
inline void set_refname(const std::string& r) { refname = r; }
private:
std::string refname; // Holds the refname of a transmission in progress
protected:
virtual FGATCVoice* GetVoicePointer();
private:
// Generate the ATIS transmission text:
int GenTransmission(const int regen, const int special);

View file

@ -77,7 +77,7 @@
#include <AIModel/AIManager.hxx>
#include <ATCDCL/ATCmgr.hxx>
#include <ATCDCL/ATISmgr.hxx>
#include <ATC/atc_mgr.hxx>
#include <Autopilot/route_mgr.hxx>
@ -1158,27 +1158,20 @@ bool fgInitSubsystems() {
////////////////////////////////////////////////////////////////////
fgGetBool("/sim/rendering/bump-mapping", false);
////////////////////////////////////////////////////////////////////
// Initialise the ATC Manager
// Note that this is old stuff, but might be necessesary for the
// Initialise the ATIS Manager
// Note that this is old stuff, but is necessary for the
// current ATIS implementation. Therefore, leave it in here
// until the ATIS system is ported over to make use of the ATIS
// sub system infrastructure.
////////////////////////////////////////////////////////////////////
globals->add_subsystem("ATC-old", new FGATCMgr, SGSubsystemMgr::INIT);
globals->add_subsystem("ATIS", new FGATISMgr, SGSubsystemMgr::INIT, 0.4);
////////////////////////////////////////////////////////////////////
// Initialize the ATC subsystem
////////////////////////////////////////////////////////////////////
globals->add_subsystem("ATC", new FGATCManager, SGSubsystemMgr::POST_FDM);
////////////////////////////////////////////////////////////////////
// Initialise the ATIS Subsystem
////////////////////////////////////////////////////////////////////
//globals->add_subsystem("atis", new FGAtisManager, SGSubsystemMgr::POST_FDM);
////////////////////////////////////////////////////////////////////
// Initialize multiplayer subsystem

View file

@ -44,7 +44,7 @@
#include <Aircraft/controls.hxx>
#include <Airports/runways.hxx>
#include <ATCDCL/ATCmgr.hxx>
#include <ATCDCL/ATISmgr.hxx>
#include <Autopilot/route_mgr.hxx>
#include <Cockpit/panel.hxx>
#include <GUI/FGFontCache.hxx>
@ -135,7 +135,7 @@ FGGlobals::FGGlobals() :
matlib( NULL ),
route_mgr( NULL ),
current_panel( NULL ),
ATC_mgr( NULL ),
ATIS_mgr( NULL ),
controls( NULL ),
viewmgr( NULL ),
commands( SGCommandMgr::instance() ),
@ -191,7 +191,7 @@ FGGlobals::~FGGlobals()
delete route_mgr;
current_panel = NULL;
delete ATC_mgr;
delete ATIS_mgr;
if (controls)
{

View file

@ -55,7 +55,7 @@ class SGSubsystemMgr;
class SGSubsystem;
class SGSoundMgr;
class FGATCMgr;
class FGATISMgr;
class FGAircraftModel;
class FGControls;
class FGFlightPlanDispatcher;
@ -123,7 +123,7 @@ private:
SGSharedPtr<FGPanel> current_panel;
// ATC manager
FGATCMgr *ATC_mgr;
FGATISMgr *ATIS_mgr;
// control input state
FGControls *controls;
@ -240,8 +240,8 @@ public:
inline SGMaterialLib *get_matlib() const { return matlib; }
inline void set_matlib( SGMaterialLib *m ) { matlib = m; }
inline FGATCMgr *get_ATC_mgr() const { return ATC_mgr; }
inline void set_ATC_mgr( FGATCMgr *a ) {ATC_mgr = a; }
inline FGATISMgr *get_ATIS_mgr() const { return ATIS_mgr; }
inline void set_ATIS_mgr( FGATISMgr *a ) {ATIS_mgr = a; }
inline FGPanel *get_current_panel() const { return current_panel; }
void set_current_panel( FGPanel *cp );

View file

@ -41,37 +41,24 @@
// Class references
#include <simgear/scene/model/modellib.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/model/animation.hxx>
#include <simgear/scene/sky/sky.hxx>
#include <simgear/structure/event_mgr.hxx>
#include <simgear/props/AtomicChangeListener.hxx>
#include <simgear/props/props.hxx>
#include <simgear/timing/sg_time.hxx>
#include <simgear/timing/timestamp.hxx>
#include <simgear/magvar/magvar.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/io/raw_socket.hxx>
#include <simgear/scene/tsync/terrasync.hxx>
#include <simgear/sound/soundmgr_openal.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/math/sg_random.h>
#include <Time/light.hxx>
#include <Aircraft/replay.hxx>
#include <Aircraft/controls.hxx>
#include <Model/panelnode.hxx>
#include <Model/acmodel.hxx>
#include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx>
#include <Sound/fg_fx.hxx>
#include <Sound/beacon.hxx>
#include <Sound/morse.hxx>
#include <Sound/fg_fx.hxx>
#include <ATCDCL/ATCmgr.hxx>
#include <Time/TimeManager.hxx>
#include <Environment/environment_mgr.hxx>
#include <GUI/gui.h>
#include <GUI/new_gui.hxx>
#include <MultiPlayer/multiplaymgr.hxx>
#include <Viewer/CameraGroup.hxx>
#include <Viewer/viewer.hxx>
#include <Viewer/WindowSystemAdapter.hxx>
#include <Viewer/splash.hxx>
#include <Viewer/renderer.hxx>
@ -87,6 +74,7 @@
using namespace flightgear;
using std::cerr;
using std::vector;
// Specify our current idle function state. This is used to run all
// our initializations out of the idle callback so that we can get a