diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ec1f627e..06f3517b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,6 +224,8 @@ include_directories(${PROJECT_BINARY_DIR}/src/Include) add_definitions(-DHAVE_CONFIG_H) +check_function_exists(mkfifo HAVE_MKFIFO) + # configure a header file to pass some of the CMake settings # to the source code configure_file ( diff --git a/src/ATC/trafficcontrol.cxx b/src/ATC/trafficcontrol.cxx index e15f9d3c9..9a957bd53 100644 --- a/src/ATC/trafficcontrol.cxx +++ b/src/ATC/trafficcontrol.cxx @@ -528,7 +528,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId, getName() + "-Ground"; atisInformation = rec->getAircraft()->getTrafficRef()->getDepartureAirport()-> - getDynamics()->getAtisInformation(); + getDynamics()->getAtisSequence(); break; case 4: receiver = diff --git a/src/ATCDCL/atis.cxx b/src/ATCDCL/atis.cxx index b2f358620..460cc31a8 100644 --- a/src/ATCDCL/atis.cxx +++ b/src/ATCDCL/atis.cxx @@ -53,6 +53,7 @@ #include
#include
#include +#include #include "ATCutils.hxx" @@ -228,47 +229,6 @@ int Apt_US_CA(const string id) { return 0; } -// Add structure and map for storing a log of atis transmissions -// made in this session of FlightGear. This allows the callsign -// to be allocated correctly wrt time. -typedef struct { - double tstamp; - int sequence; -} atis_transmission_type; - -typedef std::map < std::string, atis_transmission_type > atis_log_type; -typedef atis_log_type::iterator atis_log_iterator; -typedef atis_log_type::const_iterator atis_log_const_iterator; - -static atis_log_type atislog; - -int FGATIS::GetAtisSequence( const string& apt_id, - const double tstamp, const int interval, const int special) -{ - atis_transmission_type tran; - - if(atislog.find(apt_id) == atislog.end()) { // New station - tran.tstamp = tstamp - interval; -// Random number between 0 and 25 inclusive, i.e. 26 equiprobable outcomes: - tran.sequence = int(sg_random() * LTRS); - atislog[apt_id] = tran; - //cout << "New ATIS station: " << apt_id << " seq-1: " - // << tran.sequence << endl; - } - -// calculate the appropriate identifier and update the log - tran = atislog[apt_id]; - - int delta = int((tstamp - tran.tstamp) / interval); - tran.tstamp += delta * interval; - if (special && !delta) delta++; // a "special" ATIS update is required - tran.sequence = (tran.sequence + delta) % LTRS; - atislog[apt_id] = tran; - //if (delta) cout << "New ATIS sequence: " << tran.sequence - // << " Delta: " << delta << endl; - return(tran.sequence + (delta ? 0 : LTRS*1000)); -} - // Generate the actual broadcast ATIS transmission. // Regen means regenerate the /current/ transmission. // Special means generate a new transmission, with a new sequence. @@ -280,12 +240,12 @@ int FGATIS::GenTransmission(const int regen, const int special) { string BRK = ".\n"; string PAUSE = " / "; - double tstamp = atof(fgGetString("sim/time/elapsed-sec")); int interval = _type == ATIS ? ATIS_interval // ATIS updated hourly : 2*minute; // AWOS updated more frequently - - int sequence = GetAtisSequence(ident, tstamp, interval, special); + + FGAirport* apt = FGAirport::findByIdent(ident); + int sequence = apt->getDynamics()->updateAtisSequence(interval, special); if (!regen && sequence > LTRS) { //xx if (msg_OK) cout << "ATIS: no change: " << sequence << endl; //xx msg_time = cur_time; diff --git a/src/ATCDCL/atis.hxx b/src/ATCDCL/atis.hxx index 189b11106..0c6124b8d 100644 --- a/src/ATCDCL/atis.hxx +++ b/src/ATCDCL/atis.hxx @@ -95,9 +95,7 @@ class FGATIS : public FGATC { void TreeOut(int msgOK); friend std::istream& operator>> ( std::istream&, FGATIS& ); - - int GetAtisSequence( const std::string& apt_id, - const double tstamp, const int interval, const int special); + }; typedef int (FGATIS::*int_getter)() const; diff --git a/src/Airports/dynamics.cxx b/src/Airports/dynamics.cxx index 398920f32..9cbf9f6fa 100644 --- a/src/Airports/dynamics.cxx +++ b/src/Airports/dynamics.cxx @@ -36,6 +36,7 @@ #include
#include
#include +#include #include #include @@ -49,33 +50,12 @@ using std::random_shuffle; #include "dynamics.hxx" FGAirportDynamics::FGAirportDynamics(FGAirport * ap): -_ap(ap), rwyPrefs(ap), SIDs(ap),startupController(this) + _ap(ap), rwyPrefs(ap), SIDs(ap), + atisSequenceIndex(-1), + atisSequenceTimeStamp(0.0) + startupController(this); { lastUpdate = 0; - - // For testing only. This needs to be refined when we move ATIS functionality over. - atisInformation = "Sierra"; -} - -// Note that the ground network should also be copied -FGAirportDynamics:: -FGAirportDynamics(const FGAirportDynamics & other):rwyPrefs(other. - rwyPrefs), -SIDs(other.SIDs), startupController(other.startupController) -{ - for (FGParkingVecConstIterator ip = other.parkings.begin(); - ip != other.parkings.end(); ip++) - parkings.push_back(*(ip)); - // rwyPrefs = other.rwyPrefs; - lastUpdate = other.lastUpdate; - - stringVecConstIterator il; - for (il = other.landing.begin(); il != other.landing.end(); il++) - landing.push_back(*il); - for (il = other.takeoff.begin(); il != other.takeoff.end(); il++) - takeoff.push_back(*il); - lastUpdate = other.lastUpdate; - atisInformation = other.atisInformation; } // Destructor @@ -567,3 +547,33 @@ FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway, { return SIDs.getBest(activeRunway, heading); } + +const std::string FGAirportDynamics::getAtisSequence() +{ + if (atisSequenceIndex == -1) { + updateAtisSequence(1, false); + } + + return GetPhoneticLetter(atisSequenceIndex); +} + +int FGAirportDynamics::updateAtisSequence(int interval, bool forceUpdate) +{ + double now = globals->get_sim_time_sec(); + if (atisSequenceIndex == -1) { + // first computation + atisSequenceTimeStamp = now; + atisSequenceIndex = rand() % LTRS; // random initial sequence letters + return atisSequenceIndex; + } + + int steps = static_cast((now - atisSequenceTimeStamp) / interval); + atisSequenceTimeStamp += (interval * steps); + if (forceUpdate && (steps == 0)) { + ++steps; // a "special" ATIS update is required + } + + atisSequenceIndex = (atisSequenceIndex + steps) % LTRS; + // return a huge value if no update occurred + return (atisSequenceIndex + (steps ? 0 : LTRS*1000)); +} diff --git a/src/Airports/dynamics.hxx b/src/Airports/dynamics.hxx index 1aa61fe6f..3240f0938 100644 --- a/src/Airports/dynamics.hxx +++ b/src/Airports/dynamics.hxx @@ -22,24 +22,15 @@ #ifndef _AIRPORT_DYNAMICS_HXX_ #define _AIRPORT_DYNAMICS_HXX_ - -#ifndef __cplusplus -# error This library requires C++ -#endif - -#include - #include #include "parking.hxx" #include "groundnetwork.hxx" #include "runwayprefs.hxx" #include "sidstar.hxx" -//typedef vector DoubleVec; -//typedef vector::iterator DoubleVecIterator; - +// forward decls class FGAirport; - +class FGEnvironment; class FGAirportDynamics { @@ -55,7 +46,7 @@ private: FGApproachController approachController; time_t lastUpdate; - string prevTrafficType; + std::string prevTrafficType; stringVec landing; stringVec takeoff; stringVec milActive, comActive, genActive, ulActive; @@ -67,6 +58,7 @@ private: intVec freqTower; // intVec freqApproach; // +<<<<<<< HEAD:src/Airports/dynamics.hxx string atisInformation; string chooseRunwayFallback(); @@ -75,9 +67,16 @@ private: double elevation; +======= + int atisSequenceIndex; + double atisSequenceTimeStamp; + + std::string chooseRunwayFallback(); + bool innerGetActiveRunway(const std::string &trafficType, int action, std::string &runway, double heading); + std::string chooseRwyByHeading(stringVec rwys, double heading); +>>>>>>> next:src/Airports/dynamics.hxx public: FGAirportDynamics(FGAirport* ap); - FGAirportDynamics(const FGAirportDynamics &other); ~FGAirportDynamics(); void addAwosFreq (int val) { freqAwos.push_back(val); }; @@ -121,9 +120,15 @@ public: FGTowerController *getTowerController() { return &towerController; }; FGApproachController *getApproachController() { return &approachController; }; - const string& getAtisInformation() { return atisInformation; }; - int getGroundFrequency (unsigned leg); //{ return freqGround.size() ? freqGround[0] : 0; }; + int getGroundFrequency(unsigned leg); int getTowerFrequency (unsigned nr); + + /// get current ATIS sequence letter + const std::string getAtisSequence(); + + /// get the current ATIS sequence number, updating it if necessary + int updateAtisSequence(int interval, bool forceUpdate); + void setRwyUse(const FGRunwayPreference& ref); }; diff --git a/src/Airports/simple.cxx b/src/Airports/simple.cxx index f4f3d1adb..9df1cb254 100644 --- a/src/Airports/simple.cxx +++ b/src/Airports/simple.cxx @@ -96,20 +96,18 @@ bool FGAirport::isHeliport() const FGAirportDynamics * FGAirport::getDynamics() { - if (_dynamics != 0) { + if (_dynamics) { return _dynamics; - } else { - //cerr << "Trying to load dynamics for " << _id << endl; - _dynamics = new FGAirportDynamics(this); - XMLLoader::load(_dynamics); + } + + _dynamics = new FGAirportDynamics(this); + XMLLoader::load(_dynamics); - FGRunwayPreference rwyPrefs(this); - XMLLoader::load(&rwyPrefs); - _dynamics->setRwyUse(rwyPrefs); - - //FGSidStar SIDs(this); - XMLLoader::load(_dynamics->getSIDs()); - } + FGRunwayPreference rwyPrefs(this); + XMLLoader::load(&rwyPrefs); + _dynamics->setRwyUse(rwyPrefs); + XMLLoader::load(_dynamics->getSIDs()); + return _dynamics; } diff --git a/src/Include/config_cmake.h.in b/src/Include/config_cmake.h.in index 047717038..721253db8 100644 --- a/src/Include/config_cmake.h.in +++ b/src/Include/config_cmake.h.in @@ -19,6 +19,7 @@ #cmakedefine HAVE_SYS_TIME_H #cmakedefine HAVE_WINDOWS_H #cmakedefine HAVE_CULLSETTINGS_CLEAR_MASK +#cmakedefine HAVE_MKFIFO #define VERSION "@FLIGHTGEAR_VERSION@" diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index c2058ba19..f9933243d 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -34,6 +34,9 @@ #include #include #include +#include +#include +#include #include "fg_init.hxx" #include "fg_io.hxx" @@ -1349,7 +1352,63 @@ do_release_cockpit_button (const SGPropertyNode *arg) return true; } +static SGGeod commandSearchPos(const SGPropertyNode* arg) +{ + if (arg->hasChild("longitude-deg") && arg->hasChild("latitude-deg")) { + return SGGeod::fromDeg(arg->getDoubleValue("longitude-deg"), + arg->getDoubleValue("latitude-deg")); + } + + // use current viewer/aircraft position + return SGGeod::fromDeg(fgGetDouble("/position/longitude-deg"), + fgGetDouble("/position/latitude-deg")); +} + +static bool +do_comm_search(const SGPropertyNode* arg) +{ + SGGeod pos = commandSearchPos(arg); + int khz = static_cast(arg->getDoubleValue("frequency-mhz") * 100.0 + 0.25); + + flightgear::CommStation* sta = flightgear::CommStation::findByFreq(khz, pos, NULL); + if (!sta) { + return true; + } + + SGPropertyNode* result = fgGetNode(arg->getStringValue("result")); + sta->createBinding(result); + return true; +} +static bool +do_nav_search(const SGPropertyNode* arg) +{ + SGGeod pos = commandSearchPos(arg); + double mhz = arg->getDoubleValue("frequency-mhz"); + + FGNavList* navList = globals->get_navlist(); + string type(arg->getStringValue("type", "vor")); + if (type == "dme") { + navList = globals->get_dmelist(); + } else if (type == "tacan") { + navList = globals->get_tacanlist(); + } + + FGNavRecord* nav = navList->findByFreq(mhz, pos); + if (!nav && (type == "vor")) { + // if we're searching VORs, look for localizers too + nav = globals->get_loclist()->findByFreq(mhz, pos); + } + + if (!nav) { + return true; + } + + SGPropertyNode* result = fgGetNode(arg->getStringValue("result")); + nav->createBinding(result); + return true; +} + //////////////////////////////////////////////////////////////////////// // Command setup. //////////////////////////////////////////////////////////////////////// @@ -1421,6 +1480,10 @@ static struct { { "dump-terrainbranch", do_dump_terrain_branch }, { "print-visible-scene", do_print_visible_scene_info }, { "reload-shaders", do_reload_shaders }, + + { "find-navaid", do_nav_search }, + { "find-comm", do_comm_search }, + { 0, 0 } // zero-terminated }; diff --git a/src/Navaids/PositionedBinding.cxx b/src/Navaids/PositionedBinding.cxx index c1ecdf0aa..8a2f23f6f 100644 --- a/src/Navaids/PositionedBinding.cxx +++ b/src/Navaids/PositionedBinding.cxx @@ -148,12 +148,27 @@ AirportBinding::AirportBinding(const FGAirport* apt, SGPropertyNode* nd) : for (unsigned int c=0; ccommStations().size(); ++c) { flightgear::CommStation* comm = apt->commStations()[c]; std::string tynm = FGPositioned::nameForType(comm->type()); - int count = nd->getChildren(tynm).size(); - SGPropertyNode* commNode = nd->getChild(tynm, count, true); - commNode->setStringValue("ident", comm->ident()); - commNode->setDoubleValue("frequency-mhz", comm->freqMHz()); - } + // for some standard frequence types, we don't care about the ident, + // so just list the frequencies under one group. + if ((comm->type() == FGPositioned::FREQ_ATIS) || + (comm->type() == FGPositioned::FREQ_AWOS) || + (comm->type() == FGPositioned::FREQ_TOWER) || + (comm->type() == FGPositioned::FREQ_GROUND)) + { + SGPropertyNode* commNode = nd->getChild(tynm, 0, true); + int count = nd->getChildren("frequency-mhz").size(); + SGPropertyNode* freqNode = commNode->getChild("frequency-mhz", count, true); + freqNode->setDoubleValue(comm->freqMHz()); + } else { + // for other kinds of frequency, there's more variation, so list the ID too + int count = nd->getChildren(tynm).size(); + SGPropertyNode* commNode = nd->getChild(tynm, count, true); + commNode->setStringValue("ident", comm->ident()); + commNode->setDoubleValue("frequency-mhz", comm->freqMHz()); + + } + } // of airprot comm stations iteration } CommStationBinding::CommStationBinding(const CommStation* sta, SGPropertyNode* node) : diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx index b67e9c75d..7aa183eba 100644 --- a/src/Navaids/positioned.cxx +++ b/src/Navaids/positioned.cxx @@ -841,7 +841,7 @@ FGPositioned::sortByRange(List& aResult, const SGGeod& aPos) FGPositioned::Filter* createSearchFilter(const SGPropertyNode* arg) { - string sty(arg->getStringValue("type", 0)); + string sty(arg->getStringValue("type", "any")); FGPositioned::Type ty = FGPositioned::typeFromName(sty); double minRunwayLenFt = arg->getDoubleValue("min-runway-length-ft", -1.0); @@ -861,7 +861,7 @@ FGPositioned::Filter* createSearchFilter(const SGPropertyNode* arg) return NULL; } -SGGeod commandSearchPos(const SGPropertyNode* arg) +static SGGeod commandSearchPos(const SGPropertyNode* arg) { if (arg->hasChild("longitude-deg") && arg->hasChild("latitude-deg")) { return SGGeod::fromDeg(arg->getDoubleValue("longitude-deg"), @@ -932,7 +932,7 @@ bool commandFindByIdent(const SGPropertyNode* arg) if (arg->hasChild("name")) { results = FGPositioned::findAllWithName(arg->getStringValue("name"), filt.get(), exact); } else if (arg->hasChild("ident")) { - results = FGPositioned::findAllWithName(arg->getStringValue("ident"), filt.get(), exact); + results = FGPositioned::findAllWithIdent(arg->getStringValue("ident"), filt.get(), exact); } else { SG_LOG(SG_GENERAL, SG_WARN, "commandFindByIdent: no search term defined"); return false; diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index 2690bda6d..af67ae368 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -476,10 +476,9 @@ static naRef f_systime(naContext c, naRef me, int argc, naRef* args) // Converts from 100ns units in 1601 epoch to unix epoch in sec return naNum((t * 1e-7) - 11644473600.0); #else - time_t t; struct timeval td; - do { t = time(0); gettimeofday(&td, 0); } while(t != time(0)); - return naNum(t + 1e-6 * td.tv_usec); + gettimeofday(&td, 0); + return naNum(td.tv_sec + 1e-6 * td.tv_usec); #endif }