1 // ATISmgr.cxx - Implementation of FGATISMgr - a global Flightgear ATIS manager.
3 // Written by David Luff, started February 2002.
5 // Copyright (C) 2002 David C Luff - david.luff@nottingham.ac.uk
6 // Copyright (C) 2012 Thorsten Brehm
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 #include <simgear/misc/sg_path.hxx>
27 #include <simgear/debug/logstream.hxx>
28 #include <simgear/structure/exception.hxx>
30 #include <Airports/simple.hxx>
31 #include <ATC/CommStation.hxx>
32 #include <Main/fg_props.hxx>
34 #include "ATISmgr.hxx"
35 #include "ATCutils.hxx"
38 using flightgear::CommStation;
40 FGATISMgr::FGATISMgr() :
43 #ifdef ENABLE_AUDIO_SUPPORT
50 globals->set_ATIS_mgr(this);
53 FGATISMgr::~FGATISMgr()
55 globals->set_ATIS_mgr(NULL);
57 for (unsigned int unit = 0;unit < _maxCommRadios; ++unit)
59 delete radios[unit].station;
60 radios[unit].station = NULL;
63 #ifdef ENABLE_AUDIO_SUPPORT
68 void FGATISMgr::bind()
72 void FGATISMgr::unbind()
76 void FGATISMgr::init()
78 lon_node = fgGetNode("/position/longitude-deg", true);
79 lat_node = fgGetNode("/position/latitude-deg", true);
80 elev_node = fgGetNode("/position/altitude-ft", true);
82 for (unsigned int unit = 0;unit < _maxCommRadios; ++unit)
85 string ncunit = "comm[" + decimalNumeral(unit) + "]";
86 string commbase = "/instrumentation/" + ncunit;
87 string commfreq = commbase + "/frequencies/selected-mhz";
89 data.freq = fgGetNode(commfreq.c_str(), true);
90 data.station = new FGATIS(commbase);
91 radios.push_back(data);
95 void FGATISMgr::update(double dt)
97 // update only runs every now and then (1-2 per second)
98 if (++_currentUnit >= _maxCommRadios)
101 FGATC* pStation = radios[_currentUnit].station;
103 pStation->Update(dt * _maxCommRadios);
105 // Search the tuned frequencies
106 FreqSearch(_currentUnit);
109 // Return a pointer to an appropriate voice for a given type of ATC
110 // creating the voice if necessary - i.e. make sure exactly one copy
111 // of every voice in use exists in memory.
113 // TODO - in the future this will get more complex and dole out country/airport
114 // specific voices, and possible make sure that the same voice doesn't get used
115 // at different airports in quick succession if a large enough selection are available.
116 FGATCVoice* FGATISMgr::GetVoicePointer(const atc_type& type)
118 // TODO - implement me better - maintain a list of loaded voices and other voices!!
123 case ATIS: case AWOS:
124 #ifdef ENABLE_AUDIO_SUPPORT
125 // Delayed loading for all available voices, needed because the
126 // sound manager might not be initialized (at all) at this point.
127 // For now we'll do one hard-wired one
129 /* I've loaded the voice even if /sim/sound/pause is true
130 * since I know no way of forcing load of the voice if the user
131 * subsequently switches /sim/sound/audible to true.
132 * (which is the right thing to do -- CLO) :-)
134 if (!voice1 && fgGetBool("/sim/sound/working")) {
135 voice1 = new FGATCVoice;
137 voice = voice1->LoadVoice("default");
138 } catch ( sg_io_exception & e) {
139 SG_LOG(SG_ATC, SG_ALERT, "Unable to load default voice : "
140 << e.getFormattedMessage().c_str());
164 class RangeFilter : public CommStation::Filter
167 RangeFilter( const SGGeod & pos ) :
168 CommStation::Filter(),
169 _cart(SGVec3d::fromGeod(pos)),
174 virtual bool pass(FGPositioned* aPos) const
176 flightgear::CommStation * stn = dynamic_cast<flightgear::CommStation*>(aPos);
180 // do the range check in cartesian space, since the distances are potentially
181 // large enough that the geodetic functions become unstable
182 // (eg, station on opposite side of the planet)
183 double rangeM = SGMiscd::max( stn->rangeNm(), 10.0 ) * SG_NM_TO_METER;
184 double d2 = distSqr( aPos->cart(), _cart);
186 return d2 <= (rangeM * rangeM);
193 // Search for ATC stations by frequency
194 void FGATISMgr::FreqSearch(const unsigned int unit)
196 double frequency = radios[unit].freq->getDoubleValue();
198 // Note: 122.375 must be rounded DOWN to 12237
199 // in order to be consistent with apt.dat et cetera.
200 int freqKhz = static_cast<int>(frequency * 100.0 + 0.25);
202 _aircraftPos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
203 lat_node->getDoubleValue(), elev_node->getDoubleValue());
205 RangeFilter rangeFilter(_aircraftPos );
206 CommStation* sta = CommStation::findByFreq(freqKhz, _aircraftPos, &rangeFilter );
207 radios[unit].station->SetStation(sta);