]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/marker_beacon.cxx
Fixed intermittant marker beacon audio.
[flightgear.git] / src / Cockpit / marker_beacon.cxx
1 // marker_beacon.cxx -- class to manage the marker beacons
2 //
3 // Written by Curtis Olson, started April 2000.
4 //
5 // Copyright (C) 2000  Curtis L. Olson - curt@flightgear.org
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #include <stdio.h>      // snprintf
29
30 #include <simgear/compiler.h>
31 #include <simgear/math/sg_random.h>
32
33 #include <Aircraft/aircraft.hxx>
34 #include <Navaids/mkrbeacons.hxx>
35 #include <Time/FGEventMgr.hxx>
36
37 #include "marker_beacon.hxx"
38
39 #include <string>
40 SG_USING_STD(string);
41
42
43 // Constructor
44 FGMarkerBeacon::FGMarkerBeacon() :
45     lon_node(fgGetNode("/position/longitude-deg", true)),
46     lat_node(fgGetNode("/position/latitude-deg", true)),
47     alt_node(fgGetNode("/position/altitude-ft", true)),
48     bus_power(fgGetNode("/systems/electrical/outputs/navcom[0]", true)),
49     power_btn(fgGetNode("/radios/marker-beacon/power-btn", true)),
50     audio_btn(fgGetNode("/radios/marker-beacon/audio-btn", true)),
51     servicable(fgGetNode("/instrumentation/marker-beacons/servicable", true)),
52                  
53     need_update(true),
54     outer_blink(false),
55     middle_blink(false),
56     inner_blink(false)
57 {
58     SGPath path( globals->get_fg_root() );
59     SGPath term = path;
60     term.append( "Navaids/range.term" );
61     SGPath low = path;
62     low.append( "Navaids/range.low" );
63     SGPath high = path;
64     high.append( "Navaids/range.high" );
65
66     term_tbl = new SGInterpTable( term.str() );
67     low_tbl = new SGInterpTable( low.str() );
68     high_tbl = new SGInterpTable( high.str() );
69
70     power_btn->setBoolValue( true );
71     audio_btn->setBoolValue( true );
72     servicable->setBoolValue( true );
73 }
74
75
76 // Destructor
77 FGMarkerBeacon::~FGMarkerBeacon() 
78 {
79     delete term_tbl;
80     delete low_tbl;
81     delete high_tbl;
82 }
83
84
85 void
86 FGMarkerBeacon::init ()
87 {
88     morse.init();
89     beacon.init();
90     blink.stamp();
91 }
92
93
94 void
95 FGMarkerBeacon::bind ()
96 {
97
98     fgTie("/radios/marker-beacon/inner", this,
99           &FGMarkerBeacon::get_inner_blink);
100
101     fgTie("/radios/marker-beacon/middle", this,
102           &FGMarkerBeacon::get_middle_blink);
103
104     fgTie("/radios/marker-beacon/outer", this,
105           &FGMarkerBeacon::get_outer_blink);
106 }
107
108
109 void
110 FGMarkerBeacon::unbind ()
111 {
112     fgUntie("/radios/marker-beacon/inner");
113     fgUntie("/radios/marker-beacon/middle");
114     fgUntie("/radios/marker-beacon/outer");
115 }
116
117
118 // Update the various nav values based on position and valid tuned in navs
119 void 
120 FGMarkerBeacon::update(double dt) 
121 {
122     need_update = false;
123
124     if ( has_power() && servicable->getBoolValue() ) {
125         // marker beacon blinking
126         bool light_on = ( outer_blink || middle_blink || inner_blink );
127         SGTimeStamp current;
128         current.stamp();
129
130         if ( light_on && (current - blink > 400000) ) {
131             light_on = false;
132             blink.stamp();
133         } else if ( !light_on && (current - blink > 100000) ) {
134             light_on = true;
135             blink.stamp();
136         }
137
138         if ( outer_marker ) {
139             outer_blink = light_on;
140         } else {
141             outer_blink = false;
142         }
143
144         if ( middle_marker ) {
145             middle_blink = light_on;
146         } else {
147             middle_blink = false;
148         }
149
150         if ( inner_marker ) {
151             inner_blink = light_on;
152         } else {
153             inner_blink = false;
154         }
155
156         // cout << outer_blink << " " << middle_blink << " "
157         //      << inner_blink << endl;
158     } else {
159         inner_blink = middle_blink = outer_blink = false;
160     }
161 }
162
163
164 // Update current nav/adf radio stations based on current postition
165 void FGMarkerBeacon::search() 
166 {
167     static FGMkrBeacon::fgMkrBeacType last_beacon = FGMkrBeacon::NOBEACON;
168
169     double lon = lon_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
170     double lat = lat_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
171     double elev = alt_node->getDoubleValue() * SG_FEET_TO_METER;
172
173     ////////////////////////////////////////////////////////////////////////
174     // Beacons.
175     ////////////////////////////////////////////////////////////////////////
176
177     FGMkrBeacon::fgMkrBeacType beacon_type
178         = current_beacons->query( lon * SGD_RADIANS_TO_DEGREES,
179                                   lat * SGD_RADIANS_TO_DEGREES, elev );
180
181     outer_marker = middle_marker = inner_marker = false;
182
183     if ( beacon_type == FGMkrBeacon::NOBEACON
184          || !has_power() || !servicable->getBoolValue() )
185     {
186         // cout << "no marker" << endl;
187         beacon_type = FGMkrBeacon::NOBEACON;
188         globals->get_soundmgr()->stop( "outer-marker" );
189         globals->get_soundmgr()->stop( "middle-marker" );
190         globals->get_soundmgr()->stop( "inner-marker" );
191     } else if ( beacon_type == FGMkrBeacon::OUTER ) {
192         outer_marker = true;
193         // cout << "OUTER MARKER" << endl;
194         if ( last_beacon != FGMkrBeacon::OUTER ) {
195             if ( ! globals->get_soundmgr()->exists( "outer-marker" ) ) {
196                 FGSimpleSound *sound = beacon.get_outer();
197                 sound->set_volume( 0.3 );
198                 globals->get_soundmgr()->add( sound, "outer-marker" );
199             }
200         }
201         if ( audio_btn->getBoolValue() ) {
202             if ( !globals->get_soundmgr()->is_playing("outer-marker") ) {
203                 globals->get_soundmgr()->play_looped( "outer-marker" );
204             }
205         } else {
206             globals->get_soundmgr()->stop( "outer-marker" );
207         }
208     } else if ( beacon_type == FGMkrBeacon::MIDDLE ) {
209         middle_marker = true;
210         // cout << "MIDDLE MARKER" << endl;
211         if ( last_beacon != FGMkrBeacon::MIDDLE ) {
212             if ( ! globals->get_soundmgr()->exists( "middle-marker" ) ) {
213                 FGSimpleSound *sound = beacon.get_middle();
214                 sound->set_volume( 0.3 );
215                 globals->get_soundmgr()->add( sound, "middle-marker" );
216             }
217         }
218         if ( audio_btn->getBoolValue() ) {
219             if ( !globals->get_soundmgr()->is_playing("middle-marker") ) {
220                 globals->get_soundmgr()->play_looped( "middle-marker" );
221             }
222         } else {
223             globals->get_soundmgr()->stop( "middle-marker" );
224         }
225     } else if ( beacon_type == FGMkrBeacon::INNER ) {
226         inner_marker = true;
227         // cout << "INNER MARKER" << endl;
228         if ( last_beacon != FGMkrBeacon::INNER ) {
229             if ( ! globals->get_soundmgr()->exists( "inner-marker" ) ) {
230                 FGSimpleSound *sound = beacon.get_inner();
231                 sound->set_volume( 0.3 );
232                 globals->get_soundmgr()->add( sound, "inner-marker" );
233             }
234         }
235         if ( audio_btn->getBoolValue() ) {
236             if ( !globals->get_soundmgr()->is_playing("inner-marker") ) {
237                 globals->get_soundmgr()->play_looped( "inner-marker" );
238             }
239         } else {
240             globals->get_soundmgr()->stop( "inner-marker" );
241         }
242     }
243     last_beacon = beacon_type;
244 }