]> git.mxchange.org Git - flightgear.git/blob - src/ATCDCL/ATISmgr.cxx
Restore ATIS reception with nav receivers.
[flightgear.git] / src / ATCDCL / ATISmgr.cxx
1 // ATISmgr.cxx - Implementation of FGATISMgr - a global Flightgear ATIS manager.
2 //
3 // Written by David Luff, started February 2002.
4 //
5 // Copyright (C) 2002  David C Luff - david.luff@nottingham.ac.uk
6 // Copyright (C) 2012  Thorsten Brehm
7 //
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.
12 //
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.
17 //
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.
21
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25
26 #include <simgear/misc/sg_path.hxx>
27 #include <simgear/debug/logstream.hxx>
28 #include <simgear/structure/exception.hxx>
29
30 #include <Airports/simple.hxx>
31 #include <ATC/CommStation.hxx>
32 #include <Main/fg_props.hxx>
33
34 #include "ATISmgr.hxx"
35 #include "ATCutils.hxx"
36 #include "atis.hxx"
37
38 using flightgear::CommStation;
39
40 FGATISMgr::FGATISMgr() :
41     _currentUnit(0),
42     _maxCommRadios(4),
43 #ifdef ENABLE_AUDIO_SUPPORT
44     voice(true),
45     voice1(0)
46 #else
47     voice(false)
48 #endif
49 {
50     globals->set_ATIS_mgr(this);
51 }
52
53 FGATISMgr::~FGATISMgr()
54 {
55     globals->set_ATIS_mgr(NULL);
56
57     for (unsigned int unit = 0;unit < _maxCommRadios; ++unit)
58     {
59         delete radios[unit].station;
60         radios[unit].station = NULL;
61     }
62
63 #ifdef ENABLE_AUDIO_SUPPORT
64     delete voice1;
65 #endif
66 }
67
68 void FGATISMgr::bind()
69 {
70 }
71
72 void FGATISMgr::unbind()
73 {
74 }
75
76 void FGATISMgr::init()
77 {
78     lon_node  = fgGetNode("/position/longitude-deg", true);
79     lat_node  = fgGetNode("/position/latitude-deg",  true);
80     elev_node = fgGetNode("/position/altitude-ft",   true);
81
82     for (unsigned int unit = 0;unit < _maxCommRadios; ++unit)
83     {
84         CommRadioData data;
85         string ncunit;
86         if (unit < _maxCommRadios/2)
87             ncunit = "comm[" + decimalNumeral(unit) + "]";
88         else
89             ncunit = "nav[" + decimalNumeral(unit - _maxCommRadios/2) + "]";
90         string commbase = "/instrumentation/" + ncunit;
91         string commfreq = commbase + "/frequencies/selected-mhz";
92
93         data.freq = fgGetNode(commfreq.c_str(), true);
94         data.station = new FGATIS(commbase);
95         radios.push_back(data);
96     }
97 }
98
99 void FGATISMgr::update(double dt)
100 {
101     // update only runs every now and then (1-2 per second)
102     if (++_currentUnit >= _maxCommRadios)
103         _currentUnit = 0;
104
105     FGATC* pStation = radios[_currentUnit].station;
106     if (pStation)
107         pStation->Update(dt * _maxCommRadios);
108
109     // Search the tuned frequencies
110     FreqSearch(_currentUnit);
111 }
112
113 // Return a pointer to an appropriate voice for a given type of ATC
114 // creating the voice if necessary - i.e. make sure exactly one copy
115 // of every voice in use exists in memory.
116 //
117 // TODO - in the future this will get more complex and dole out country/airport
118 // specific voices, and possible make sure that the same voice doesn't get used
119 // at different airports in quick succession if a large enough selection are available.
120 FGATCVoice* FGATISMgr::GetVoicePointer(const atc_type& type)
121 {
122     // TODO - implement me better - maintain a list of loaded voices and other voices!!
123     if(voice)
124     {
125         switch(type)
126         {
127         case ATIS: case AWOS:
128 #ifdef ENABLE_AUDIO_SUPPORT
129             // Delayed loading for all available voices, needed because the
130             // sound manager might not be initialized (at all) at this point.
131             // For now we'll do one hard-wired one
132
133             /* I've loaded the voice even if /sim/sound/pause is true
134              *  since I know no way of forcing load of the voice if the user
135              *  subsequently switches /sim/sound/audible to true.
136              *  (which is the right thing to do -- CLO) :-)
137              */
138             if (!voice1 && fgGetBool("/sim/sound/working")) {
139                 voice1 = new FGATCVoice;
140                 try {
141                     voice = voice1->LoadVoice("default");
142                 } catch ( sg_io_exception & e) {
143                     SG_LOG(SG_ATC, SG_ALERT, "Unable to load default voice : "
144                                             << e.getFormattedMessage().c_str());
145                     voice = false;
146                     delete voice1;
147                     voice1 = 0;
148                 }
149             }
150             if (voice)
151                 return voice1;
152 #endif
153             return NULL;
154         case TOWER:
155             return NULL;
156         case APPROACH:
157             return NULL;
158         case GROUND:
159             return NULL;
160         default:
161             return NULL;
162         }
163     }
164
165     return NULL;
166 }
167
168 class RangeFilter : public CommStation::Filter
169 {
170 public:
171     RangeFilter( const SGGeod & pos ) :
172       CommStation::Filter(),
173       _cart(SGVec3d::fromGeod(pos)),
174       _pos(pos)
175     {
176     }
177
178     virtual bool pass(FGPositioned* aPos) const
179     {
180         flightgear::CommStation * stn = dynamic_cast<flightgear::CommStation*>(aPos);
181         if( NULL == stn )
182             return false;
183
184         // do the range check in cartesian space, since the distances are potentially
185         // large enough that the geodetic functions become unstable
186         // (eg, station on opposite side of the planet)
187         double rangeM = SGMiscd::max( stn->rangeNm(), 10.0 ) * SG_NM_TO_METER;
188         double d2 = distSqr( aPos->cart(), _cart);
189
190         return d2 <= (rangeM * rangeM);
191     }
192 private:
193     SGVec3d _cart;
194     SGGeod _pos;
195 };
196
197 // Search for ATC stations by frequency
198 void FGATISMgr::FreqSearch(const unsigned int unit)
199 {
200     double frequency = radios[unit].freq->getDoubleValue();
201
202     // Note:  122.375 must be rounded DOWN to 12237 
203     // in order to be consistent with apt.dat et cetera.
204     int freqKhz = static_cast<int>(frequency * 100.0 + 0.25);
205
206     _aircraftPos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
207         lat_node->getDoubleValue(), elev_node->getDoubleValue());
208
209     RangeFilter rangeFilter(_aircraftPos );
210     CommStation* sta = CommStation::findByFreq(freqKhz, _aircraftPos, &rangeFilter );
211     radios[unit].station->SetStation(sta);
212 }