diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b88e91cb..ef8b6ade3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,9 @@ include (CPack) project(FlightGear) -file(READ version FLIGHTGEAR_VERSION) +# read 'version' file into a variable (stripping any newlines or spaces) +file(READ version versionFile) +string(STRIP ${versionFile} FLIGHTGEAR_VERSION) #packaging SET(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING") @@ -20,6 +22,25 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}") # autoconf compatibility set(PKGLIBDIR "foo") +if($ENV{BUILD_ID}) + set(HUDSON_BUILD_ID $ENV{BUILD_ID}) + set(HUDSON_BUILD_NUMBER $ENV{BUILD_NUMBER}) + message(STATUS "running under Hudson, build-number is ${HUDSON_BUILD_NUMBER}") +else() + set(HUDSON_BUILD_NUMBER 0) + set(HUDSON_BUILD_ID "none") +endif() + +find_package(Git) +if (GIT_FOUND) + execute_process(COMMAND git --git-dir ${PROJECT_SOURCE_DIR}/.git rev-parse HEAD + OUTPUT_VARIABLE REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE) + message(STATUS "Git revision is ${REVISION}") +else() + set(REVISION "none") +endif() + option(LOGGING "Set to OFF to build FlightGear without logging" ON) option(SP_FDMS "Set to ON to build FlightGear with special-purpose FDMs" OFF) @@ -28,6 +49,7 @@ option(ENABLE_LARCSIM "Set to ON to build FlightGear with LaRCsim FDM" ON) option(ENABLE_YASIM "Set to ON to build FlightGear with YASIM FDM" ON) option(ENABLE_JSBSIM "Set to ON to build FlightGear with JSBSim FDM" ON) option(EVENT_INPUT "Set to ON to build FlightGear with event-based Input support" OFF) +set(MSVC_3RDPARTY_DIR NOT_FOUND CACHE PATH "Location where the third-party dependencies are extracted") if(LOGGING) # nothing @@ -52,29 +74,32 @@ else(EVENT_INPUT) set(ENABLE_PLIB_JOYSTICK 1) endif(EVENT_INPUT) -# check required dependencies -if (MSVC) - # on MSVC, Olaf reports that the serialization library is required at - # link time. No one has you explained why, unfortunately. - set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_MULTITHREADED ON) - set(Boost_USE_STATIC_RUNTIME OFF) - find_package(Boost REQUIRED COMPONENTS serialization) -else (MSVC) - find_package(Boost REQUIRED) -endif (MSVC) +if (MSVC_3RDPARTY_DIR) + message(STATUS "3rdparty files located in ${MSVC_3RDPARTY_DIR}") + set (CMAKE_LIBRARY_PATH ${MSVC_3RDPARTY_DIR}/3rdParty/lib ${MSVC_3RDPARTY_DIR}/install/msvc90/OpenScenegraph/lib ${MSVC_3RDPARTY_DIR}/install/msvc90/SimGear/lib ) + set (CMAKE_INCLUDE_PATH ${MSVC_3RDPARTY_DIR}/3rdParty/include ${MSVC_3RDPARTY_DIR}/install/msvc90/OpenScenegraph/include ${MSVC_3RDPARTY_DIR}/install/msvc90/SimGear/include) + set (BOOST_ROOT ${MSVC_3RDPARTY_DIR}/boost_1_44_0) + set (OPENAL_INCLUDE_DIR ${MSVC_3RDPARTY_DIR}/3rdParty/include) + set (ALUT_INCLUDE_DIR ${MSVC_3RDPARTY_DIR}/3rdParty/include) + set (OPENAL_LIBRARY_DIR ${MSVC_3RDPARTY_DIR}/3rdParty/lib) +endif (MSVC_3RDPARTY_DIR) + +# check required dependencies +find_package(Boost REQUIRED) find_package(ZLIB REQUIRED) find_package(Threads REQUIRED) find_package(OpenGL REQUIRED) find_package(OpenAL REQUIRED) find_package(ALUT REQUIRED) find_package(OpenSceneGraph 2.8.2 REQUIRED osgText osgSim osgDB osgParticle osgFX osgUtil osgViewer osgGA) + find_package(PLIB REQUIRED puaux pu js fnt) find_package(SimGear 2.0.0 REQUIRED) check_include_file(unistd.h HAVE_UNISTD_H) check_include_file(sys/time.h HAVE_SYS_TIME_H) +check_include_file(windows.h HAVE_WINDOWS_H) # definition depends on OSG version set(CMAKE_REQUIRED_INCLUDES ${OPENSCENEGRAPH_INCLUDE_DIRS}) @@ -128,7 +153,7 @@ if(WIN32) # SET(WARNING_FLAGS "${WARNING_FLAGS} /wd${warning}") # endforeach(warning) - set(MSVC_FLAGS "-DNOMINMAX -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -D__CRT_NONSTDC_NO_WARNINGS") + set(MSVC_FLAGS "-DNOMINMAX -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS -D__CRT_NONSTDC_NO_WARNINGS") endif(MSVC) set(NOMINMAX 1) @@ -146,6 +171,10 @@ include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS} ${PLIB_INCLUDE_DIR} ) include_directories(${PROJECT_SOURCE_DIR}/src) + +# following is needed, because config.h is include 'bare', whereas +# version.h is included as - this should be cleaned up +include_directories(${PROJECT_BINARY_DIR}/src) include_directories(${PROJECT_BINARY_DIR}/src/Include) add_definitions(-DHAVE_CONFIG_H) @@ -156,7 +185,13 @@ configure_file ( "${PROJECT_SOURCE_DIR}/src/Include/config_cmake.h.in" "${PROJECT_BINARY_DIR}/src/Include/config.h" ) - + +#and the same for the version header +configure_file ( + "${PROJECT_SOURCE_DIR}/src/Include/version.h.cmake-in" + "${PROJECT_BINARY_DIR}/src/Include/version.h" + ) + add_subdirectory(src) add_subdirectory(utils) diff --git a/CMakeModules/FindPLIB.cmake b/CMakeModules/FindPLIB.cmake index 5fadcaf79..09188948f 100644 --- a/CMakeModules/FindPLIB.cmake +++ b/CMakeModules/FindPLIB.cmake @@ -67,76 +67,92 @@ FIND_LIBRARY(PLIB_LIBRARIES /Library/Frameworks ) +if (MSVC) + set (PUNAME "pui") +else (MSVC) + set (PUNAME "pu") +endif (MSVC) + + macro(find_static_component comp libs) - set(compLib "plib${comp}") - string(TOUPPER "PLIB_${comp}_LIBRARY" compLibName) - - FIND_LIBRARY(${compLibName} - NAMES ${compLib} - HINTS $ENV{PLIBDIR} - PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 - PATHS - /usr/local - /usr - /opt - ) - - set(componentLib ${${compLibName}}) - if (NOT ${componentLib} STREQUAL "componentLib-NOTFOUND") - #message(STATUS "found ${componentLib}") - list(APPEND ${libs} ${componentLib}) - #set(PLIB_LIBRARIES "${PLIB_LIBRARIES} ${componentLib}" PARENT_SCOPE) - endif() + # account for alternative Windows PLIB distribution naming + if(MSVC) + set(compLib "${comp}") + else(MSVC) + set(compLib "plib${comp}") + endif(MSVC) + + string(TOUPPER "PLIB_${comp}_LIBRARY" compLibName) + + FIND_LIBRARY(${compLibName} + NAMES ${compLib} + HINTS $ENV{PLIBDIR} + PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 + PATHS + /usr/local + /usr + /opt + ) + + set(componentLib ${${compLibName}}) + if (NOT ${componentLib} STREQUAL "componentLib-NOTFOUND") + list(APPEND ${libs} ${componentLib}) + endif() endmacro() -if(${PLIB_LIBRARIES} STREQUAL "PLIB_LIBRARIES-NOTFOUND") - set(PLIB_LIBRARIES "") # clear value - +if(${PLIB_LIBRARIES} STREQUAL "PLIB_LIBRARIES-NOTFOUND") + set(PLIB_LIBRARIES "") # clear value + # based on the contents of deps, add other required PLIB # static library dependencies. Eg PUI requires SSG and FNT - set(outDeps ${PLIB_FIND_COMPONENTS}) - - foreach(c ${PLIB_FIND_COMPONENTS}) - if (${c} STREQUAL "pu") - list(APPEND outDeps "fnt" "ssg" "sg") - elseif (${c} STREQUAL "puaux") - list(APPEND outDeps "pu" "fnt" "ssg" "sg") - elseif (${c} STREQUAL "ssg") - list(APPEND outDeps "sg") - endif() - endforeach() - - list(APPEND outDeps "ul") # everything needs ul - list(REMOVE_DUPLICATES outDeps) # clean up - - # look for traditional static libraries - foreach(component ${outDeps}) - find_static_component(${component} PLIB_LIBRARIES) - endforeach() + set(outDeps ${PLIB_FIND_COMPONENTS}) + + foreach(c ${PLIB_FIND_COMPONENTS}) + if (${c} STREQUAL "pu") + # handle MSVC confusion over pu/pui naming, by removing + # 'pu' and then adding it back + list(REMOVE_ITEM outDeps "pu") + list(APPEND outDeps ${PUNAME} "fnt" "ssg" "sg") + elseif (${c} STREQUAL "puaux") + list(APPEND outDeps ${PUNAME} "fnt" "ssg" "sg") + elseif (${c} STREQUAL "ssg") + list(APPEND outDeps "sg") + endif() + endforeach() + + list(APPEND outDeps "ul") # everything needs ul + list(REMOVE_DUPLICATES outDeps) # clean up + + + + # look for traditional static libraries + foreach(component ${outDeps}) + find_static_component(${component} PLIB_LIBRARIES) + endforeach() endif() list(FIND outDeps "js" haveJs) if(${haveJs} GREATER -1) - message(STATUS "adding runtime JS dependencies") - if(APPLE) - # resolve frameworks to full paths - find_library(IOKIT_LIBRARY IOKit) - find_library(CF_LIBRARY CoreFoundation) - set(JS_LIBS ${IOKIT_LIBRARY} ${CF_LIBRARY}) - elseif(WIN32) - find_library(WINMM_LIBRARY winmm) - set(JS_LIBS ${WINMM_LIBRARY}) - elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") - # anything needed here? - elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - find_library(USBHID_LIBRARY usbhid) - # check_function_exists(hidinit) - set(JS_LIBS ${USBHID_LIBRARY}) - else() - message(WARNING "Unsupported platform for PLIB JS libs") - endif() - - list(APPEND PLIB_LIBRARIES ${JS_LIBS}) + message(STATUS "adding runtime JS dependencies") + if(APPLE) + # resolve frameworks to full paths + find_library(IOKIT_LIBRARY IOKit) + find_library(CF_LIBRARY CoreFoundation) + set(JS_LIBS ${IOKIT_LIBRARY} ${CF_LIBRARY}) + elseif(WIN32) + find_library(WINMM_LIBRARY winmm) + set(JS_LIBS ${WINMM_LIBRARY}) + elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") + # anything needed here? + elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + find_library(USBHID_LIBRARY usbhid) + # check_function_exists(hidinit) + set(JS_LIBS ${USBHID_LIBRARY}) + else() + message(WARNING "Unsupported platform for PLIB JS libs") + endif() + + list(APPEND PLIB_LIBRARIES ${JS_LIBS}) endif() include(FindPackageHandleStandardArgs) diff --git a/CMakeModules/FindSimGear.cmake b/CMakeModules/FindSimGear.cmake index d6a4b7ba9..71ce82e09 100644 --- a/CMakeModules/FindSimGear.cmake +++ b/CMakeModules/FindSimGear.cmake @@ -134,7 +134,7 @@ SET(CMAKE_REQUIRED_INCLUDES ${SIMGEAR_INCLUDE_DIR}) check_cxx_source_runs( "#include - #include + #include \"simgear/version.h\" #define xstr(s) str(s) #define str(s) #s diff --git a/configure.ac b/configure.ac index 5f0dae1a8..c4ee12d68 100644 --- a/configure.ac +++ b/configure.ac @@ -530,7 +530,7 @@ if test "x$ac_cv_header_simgear_version_h" != "xyes"; then exit fi -AC_MSG_CHECKING([for SimGear 2.0.0 or newer]) +AC_MSG_CHECKING([for SimGear 2.2.0 or newer]) AC_TRY_RUN([ #include @@ -540,7 +540,7 @@ AC_TRY_RUN([ #define XSTRINGIFY(X) #X #define MIN_MAJOR 2 -#define MIN_MINOR 0 +#define MIN_MINOR 2 #define MIN_MICRO 0 int main() { @@ -837,6 +837,7 @@ AC_CONFIG_FILES([ \ scripts/debug/Makefile \ scripts/perl/Makefile \ scripts/perl/examples/Makefile \ + scripts/perl/traffic/Makefile \ scripts/python/Makefile \ src/Makefile \ src/Include/Makefile \ diff --git a/scripts/perl/Makefile.am b/scripts/perl/Makefile.am index aee2d7baa..9538e129c 100644 --- a/scripts/perl/Makefile.am +++ b/scripts/perl/Makefile.am @@ -1 +1,2 @@ -SUBDIRS = examples +SUBDIRS = examples \ + traffic diff --git a/scripts/perl/traffic/Makefile.am b/scripts/perl/traffic/Makefile.am new file mode 100644 index 000000000..b14050c96 --- /dev/null +++ b/scripts/perl/traffic/Makefile.am @@ -0,0 +1,3 @@ +EXTRA_DIST = \ + conf2xml.pl \ + xml2conf.pl diff --git a/scripts/perl/traffic/conf2xml.pl b/scripts/perl/traffic/conf2xml.pl new file mode 100755 index 000000000..0305ebd11 --- /dev/null +++ b/scripts/perl/traffic/conf2xml.pl @@ -0,0 +1,117 @@ +#!/usr/bin/perl -w + +sub parseTime { + # print "Parsing time @_\n"; + #die; + my $timeStr = $_[0]; + @timeArray = split(":", $timeStr); + # print STDERR "TimeArray: @timeArray\n"; + return ($timeArray[0] + $timeArray[1]/60.0); +} + + sub writeFlight { + print XMLFILE " \n"; + print XMLFILE " $_[0]\n"; + print XMLFILE " $_[1]\n"; + print XMLFILE " $_[2]\n"; + print XMLFILE " \n"; + print XMLFILE " $_[3]\n"; + if ($_[4] =~ /[0-6]/) { print XMLFILE " \n" } + else { print XMLFILE " \n" }; + print XMLFILE " \n"; + print XMLFILE " $_[6]\n"; + print XMLFILE " \n"; + print XMLFILE " $_[7]\n"; + if ($_[8] =~ /[0-6]/) { print XMLFILE " \n" } + else { print XMLFILE " \n" }; + print XMLFILE " \n"; + if (($_[4] =~ /[0-6]/) && ($_[8] =~ /[0-6]/)) { print XMLFILE " WEEK\n" } + else { print XMLFILE " 24Hr\n" }; + print XMLFILE " \n"; + return; +} + +@inputfiles = glob("???.conf"); +while ($infile = shift(@inputfiles)) { + open (CONF, $infile) or die "Unable to open input configuration file"; + ($outname = $infile) =~ s/conf/xml/; + print "Opening $outname\n"; + open XMLFILE, ">$outname"; + while ($buf = readline(CONF)) { + push @DataList, $buf; + } + close (CONF); + print XMLFILE "\n"; + print XMLFILE "\n"; + while ($dataline = shift(@DataList)) { + # print STDERR "Dataline: $dataline\n"; + @token = split(" ", $dataline); + if (scalar(@token) > 0) { + # print STDERR "Token: @token\n"; + if ($token[0] eq "AC") + { + print XMLFILE " \n"; + print XMLFILE " $token[12]\n"; + print XMLFILE " $token[6]\n"; + print XMLFILE " $token[5]\n"; + print XMLFILE " $token[1]\n"; + print XMLFILE " $token[3]$token[5]\n"; + print XMLFILE " $token[4]\n"; + print XMLFILE " $token[7]\n"; + print XMLFILE " $token[8]\n"; + print XMLFILE " $token[9]\n"; + print XMLFILE " $token[10]\n"; + print XMLFILE " $token[2]\n"; + print XMLFILE " $token[11]\n"; + print XMLFILE " \n"; + } + if ($token[0] eq "FLIGHT") { + $weekdays = $token[3]; + if (!(($weekdays =~ /^(0|\.)?(1|\.)?(2|\.)?(3|\.)?(4|\.)?(5|\.)?(6|\.)?$/) || ($weekdays eq "DAILY"))) { + die "Syntax Error! Check days $weekdays for flight no. $token[1]!\n"; + } + if ($token[4] !~ /^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])$/) { + die "Syntax Error! Check departure time $token[4] for flight no. $token[1]!\n" + } + if ($token[6] !~ /^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])$/) { + die "Syntax Error! Check arrival time $token[6] for flight no. $token[1]!\n" + } + # print STDERR "Weekdays: $weekdays\n"; + if ($weekdays =~ /^(0|\.)?(1|\.)?(2|\.)?(3|\.)?(4|\.)?(5|\.)?(6|\.)?$/) { + # print STDERR "Weekly for flight no. $token[1]\n"; + # print STDERR "Day: $_\n"; + @day = split(//, $weekdays); + foreach (@day) { + if ($_ eq "\.") { + next; + } else { + $depTime = parseTime($token[4]); + # print STDERR "depTime: $depTime\n"; + $arrTime = parseTime($token[6]); + # print STDERR "arrTime: $arrTime\n"; + $depDay = $_ + 1; + if ($depDay > 6) { $depDay = 0 }; + $arrDay = $depDay; + if ($depTime > $arrTime) { $arrDay++ }; + if ($arrDay > 6) { $arrDay = 0 }; + # print STDERR "depDay: $depDay, arrDay: $arrDay\n"; + writeFlight ($token[1], $token[9], $token[2], $token[5], $depDay, $token[4], $token[8], $token[7], $arrDay, $token[6]); + } + } + } + elsif ($weekdays eq "DAILY") { + # print STDERR "Daily flights for flight no. $token[1]\n"; + $depTime = parseTime($token[4]); + $arrTime = parseTime($token[6]); + writeFlight ($token[1], $token[9], $token[2], $token[5], 7, $token[4], $token[8], $token[7], 7, $token[6]); + } + else { + die "System Error! Can't find days to place a flight!\n"; + } + } + } + } + print XMLFILE "\n"; + close XMLFILE; +# print "Closing $outname\n"; +} diff --git a/scripts/perl/traffic/xml2conf.pl b/scripts/perl/traffic/xml2conf.pl new file mode 100755 index 000000000..f4f462070 --- /dev/null +++ b/scripts/perl/traffic/xml2conf.pl @@ -0,0 +1,99 @@ +#!/usr/bin/perl -w + +#use strict; +#use warnings; + +# DEBUG +# use Data::Dumper; +# print Dumper($data) . "\n"; +# END + +if (scalar (@ARGV) == 1) { + @files = glob("$ARGV[0]"); + print "Processing : ", @files, "\n"; +} else { + die "Usage : conf2xml.pl [ > outputfile ]\n"; +} +$file = shift(@files); + +use Switch; +use XML::LibXML; +my $parser = XML::LibXML->new(); +my $doc = $parser->load_xml(location => $file); +my $data; + +# reformatting days +# According to http://wiki.flightgear.org/index.php/Interactive_Traffic +# 0 = Sunday and 6 = saturday +# For convenience we switch here to "classical" numbering +# where 0 = Monday and 6 = sunday +sub parseDay { + my $day; + $day = substr($_[0],0,1); + switch ($day) { + case 0 {$day="......6"} # Sunday + case 1 {$day="0......"} # Monday + case 2 {$day=".1....."} # Tuesday + case 3 {$day="..2...."} # Wednesday + case 4 {$day="...3..."} # Thrusday + case 5 {$day="....4.."} # Friday + case 6 {$day=".....5."} # Saturday + else {$day="0123456"} # Daily + }; + return $day; +} + +# reformatting times +sub parseTime { + return substr($_[0],2,5); +} + +print "# AC Homeport Registration RequiredAC AcTyp Airline Livery Offset Radius Flighttype PerfClass Heavy Model\n"; +# get aircraft data +foreach $data ($doc->findnodes('/trafficlist/aircraft')) { + my $AcMdl = $data->findnodes('./model'); + my $AcLvy = $data->findnodes('./livery'); + my $AcAln = $data->findnodes('./airline'); + my $AcHp = $data->findnodes('./home-port'); + my $AcReq = $data->findnodes('./required-aircraft'); + my $AcTyp = $data->findnodes('./actype'); + my $AcO = $data->findnodes('./offset'); + my $AcRad = $data->findnodes('./radius'); + my $AcFt = $data->findnodes('./flighttype'); + my $AcPrf = $data->findnodes('./performance-class'); + my $AcReg = $data->findnodes('./registration'); + my $AcHvy = $data->findnodes('./heavy'); + print "AC $AcHp $AcReg $AcReq $AcTyp $AcAln $AcLvy $AcO $AcRad $AcFt $AcPrf $AcHvy $AcMdl\n"; +} +print "\n# FLIGHT Callsign Flightrule Days DeparTime DepartPort ArrivalTime ArrivalPort Altitude RequiredAc\n# 0 = Monday, 6 = Sunday\n"; +# get flight data +foreach $data ($doc->findnodes('/trafficlist/flight')) { + my $FlRep = $data->findnodes('repeat'); + my $FlDepPrt = $data->findnodes('departure/port'); + my $FlArrPrt = $data->findnodes('arrival/port'); + my $FlCs = $data->findnodes('callsign'); + my $FlFr = $data->findnodes('fltrules'); + my $FlCa = $data->findnodes('cruise-alt'); + my $FlReq = $data->findnodes('required-aircraft'); + my $FlDepDay = $data->findnodes('departure/time'); + my $FlDepTime = $data->findnodes('departure/time'); + my $FlArrDay = $data->findnodes('arrival/time'); + my $FlArrTime = $data->findnodes('arrival/time'); + my $FlDays = "......."; +# handle flights depending on weekly or daily schedule + if (lc($FlRep) eq "week") { + $FlDays = parseDay($FlDepTime); + $FlDepTime = parseTime($FlDepTime); + $FlArrTime = parseTime($FlArrTime); + } elsif (lc($FlRep) eq "24hr") { + $FlDepDay = $data->findnodes('departure/time'); + $FlDepTime = substr($data->findnodes('departure/time'),0,5); + $FlArrDay = $data->findnodes('arrival/time'); + $FlArrTime = substr($data->findnodes('arrival/time'),0,5); + $FlDays = "0123456"; + } else { + die "Error! No proper repetition found in XML!\n"; + } +# output data + print "FLIGHT $FlCs $FlFr $FlDays $FlDepTime $FlDepPrt $FlArrTime $FlArrPrt $FlCa $FlReq\n"; +} diff --git a/src/ATCDCL/atis.cxx b/src/ATCDCL/atis.cxx index 26e7674a8..16e94f67a 100644 --- a/src/ATCDCL/atis.cxx +++ b/src/ATCDCL/atis.cxx @@ -151,6 +151,7 @@ void FGATIS::Update(double dt) { // 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); + TreeOut(msg_OK); if (rslt || volume != old_volume) { //cout << "ATIS calling ATC::render volume: " << volume << endl; Render(transmission, volume, refname, true); @@ -207,6 +208,28 @@ const int minute(60); // measured in seconds const int ATIS_interval(60*minute); #endif +// FIXME: This is heuristic. It gets the right answer for +// more than 90% of the world's airports, which is a lot +// better than nothing ... but it's not 100%. +// We know "most" of the world uses millibars, +// but the US, Canada and *some* other places use inches of mercury, +// but (a) we have not implemented a reliable method of +// ascertaining which airports are in the US, let alone +// (b) ascertaining which other places use inches. +// +int Apt_US_CA(const string id) { +// Assume all IDs have length 3 or 4. +// No counterexamples have been seen. + if (id.length() == 4) { + if (id.substr(0,1) == "K") return 1; + if (id.substr(0,2) == "CY") return 1; + } + for (string::const_iterator ptr = id.begin(); ptr != id.end(); ptr++) { + if (isdigit(*ptr)) return 1; + } + return 0; +} + // Generate the actual broadcast ATIS transmission. // Regen means regenerate the /current/ transmission. // Special means generate a new transmission, with a new sequence. @@ -216,9 +239,12 @@ int FGATIS::GenTransmission(const int regen, const int special) { using namespace lex; string BRK = ".\n"; + string PAUSE = " / "; double tstamp = atof(fgGetString("sim/time/elapsed-sec")); - int interval = ATIS ? ATIS_interval : 2*minute; // AWOS updated frequently + int interval = _type == ATIS ? + ATIS_interval // ATIS updated hourly + : 2*minute; // AWOS updated more frequently int sequence = current_commlist->GetAtisSequence(ident, tstamp, interval, special); if (!regen && sequence > LTRS) { @@ -235,7 +261,9 @@ int FGATIS::GenTransmission(const int regen, const int special) { transmission = ""; - if (ident.substr(0,2) == "EG") { + int US_CA = Apt_US_CA(ident); + + if (!US_CA) { // UK CAA radiotelephony manual indicates ATIS transmissions start // with "This is ..." transmission += This_is + " "; @@ -320,6 +348,9 @@ int FGATIS::GenTransmission(const int regen, const int special) { transmission += " " + at + " " + ConvertNumToSpokenDigits(buf) + BRK; } +// Sounds better with a pause in there: + transmission += PAUSE; + int did_some(0); int did_ceiling(0); @@ -332,29 +363,39 @@ int FGATIS::GenTransmission(const int regen, const int special) { snprintf(buf, bs, "/environment/clouds/layer[%i]/elevation-ft", layer); double ceiling = int(fgGetDouble(buf) - _geod.getElevationFt()); if (ceiling > 12000) continue; - if (coverage == scattered) { - if (!did_some) transmission += " " + Sky_condition + ": "; - did_some++; + +// BEWARE: At the present time, the environment system has no +// way (so far as I know) to represent a "thin broken" or +// "thin overcast" layer. If/when such things are implemented +// in the environment system, code will have to be written here +// to handle them. + +// First, do the prefix if any: + if (coverage == scattered || coverage == few) { + if (!did_some) { + transmission += " " + Sky_condition + ": "; + did_some++; + } } else /* must be a ceiling */ if (!did_ceiling) { transmission += " " + Ceiling + ": "; did_ceiling++; did_some++; } else { - transmission += " "; + transmission += " "; // no prefix required } int cig00 = int(SGMiscd::round(ceiling/100)); // hundreds of feet if (cig00) { int cig000 = cig00/10; cig00 -= cig000*10; // just the hundreds digit if (cig000) { - snprintf(buf, bs, "%i", cig000); - transmission += ConvertNumToSpokenDigits(buf); - transmission += " " + thousand + " "; + snprintf(buf, bs, "%i", cig000); + transmission += ConvertNumToSpokenDigits(buf); + transmission += " " + thousand + " "; } if (cig00) { - snprintf(buf, bs, "%i", cig00); - transmission += ConvertNumToSpokenDigits(buf); - transmission += " " + hundred + " "; + snprintf(buf, bs, "%i", cig00); + transmission += ConvertNumToSpokenDigits(buf); + transmission += " " + hundred + " "; } } else { // Should this be "sky obscured?" @@ -362,6 +403,7 @@ int FGATIS::GenTransmission(const int regen, const int special) { } transmission += coverage + BRK; } + if (!did_some) transmission += " " + Sky + " " + clear + BRK; transmission += Temperature + ": "; double Tsl = fgGetDouble("/environment/temperature-sea-level-degc"); @@ -371,7 +413,7 @@ int FGATIS::GenTransmission(const int regen, const int special) { } snprintf(buf, bs, "%i", abs(temp)); transmission += ConvertNumToSpokenDigits(buf); - transmission += " " + Celsius; + if (US_CA) transmission += " " + Celsius; transmission += " " + dewpoint + " "; double dpsl = fgGetDouble("/environment/dewpoint-sea-level-degc"); temp = int(SGMiscd::round(FGAtmo().fake_dp_vs_a_us(dpsl, _geod.getElevationFt()))); @@ -380,7 +422,8 @@ int FGATIS::GenTransmission(const int regen, const int special) { } snprintf(buf, bs, "%i", abs(temp)); transmission += ConvertNumToSpokenDigits(buf); - transmission += " " + Celsius + BRK; + if (US_CA) transmission += " " + Celsius; + transmission += BRK; transmission += Visibility + ": "; double visibility = fgGetDouble("/environment/config/boundary/entry[0]/visibility-m"); @@ -403,7 +446,6 @@ int FGATIS::GenTransmission(const int regen, const int special) { } transmission += BRK; - transmission += Altimeter + ": "; double myQNH; double Psl = fgGetDouble("/environment/pressure-sea-level-inhg"); { @@ -418,63 +460,75 @@ int FGATIS::GenTransmission(const int regen, const int special) { #endif myQNH = FGAtmo().QNH(_geod.getElevationM(), press); } - if(ident.substr(0,2) == "EG" && fgGetBool("/sim/atc/use-millibars")) { - // Convert to millibars for the UK! + +// Convert to millibars for most of the world (not US, not CA) + if((!US_CA) || fgGetBool("/sim/atc/use-millibars")) { + transmission += QNH + ": "; myQNH /= mbar; if (myQNH > 1000) myQNH -= 1000; // drop high digit snprintf(buf, bs, "%03.0f", myQNH); + transmission += ConvertNumToSpokenDigits(buf) + " " + millibars + BRK; } else { - myQNH /= inHg; - myQNH *= 100.; // shift two decimal places - snprintf(buf, bs, "%04.0f", myQNH); + transmission += Altimeter + ": "; + double asetting = myQNH / inHg; // use inches of mercury + asetting *= 100.; // shift two decimal places + snprintf(buf, bs, "%04.0f", asetting); + transmission += ConvertNumToSpokenDigits(buf) + BRK; } - transmission += ConvertNumToSpokenDigits(buf) + BRK; if (_type == ATIS /* as opposed to AWOS */) { - const FGAirport* apt = fgFindAirportID(ident); - assert(apt); - string rwy_no = apt->getActiveRunwayForUsage()->ident(); + const FGAirport* apt = fgFindAirportID(ident); + if (apt) { + string rwy_no = apt->getActiveRunwayForUsage()->ident(); if(rwy_no != "NN") { transmission += Landing_and_departing_runway + " "; transmission += ConvertRwyNumToSpokenString(rwy_no) + BRK; +#ifdef ATIS_TEST if (msg_OK) { msg_time = cur_time; - //cout << "In atis.cxx, r.rwy_no: " << rwy_no - // << " wind_dir: " << wind_dir << endl; + cout << "In atis.cxx, r.rwy_no: " << rwy_no + << " wind_dir: " << wind_dir << endl; } +#endif + } } transmission += On_initial_contact_advise_you_have_information + " "; transmission += phonetic_seq_string; - transmission += "... " + BRK; + transmission += "... " + BRK + PAUSE + PAUSE; } -#ifdef ATIS_TEST - cout << "**** ATIS active on:"; -#endif - for (map::iterator act = active_on.begin(); act != active_on.end(); act++){ - string prop = "/instrumentation/" + act->first + "/atis"; - globals->get_props()->setStringValue(prop.c_str(), - ("
\n" + transmission + "
\n").c_str()); -#ifdef ATIS_TEST - cout << " " << prop; -#endif - } -#ifdef ATIS_TEST - cout << " ****" << endl; - cout << transmission << endl; -// Note that even if we aren't outputting the transmission -// on stdout, you can still see it by pointing a web browser -// at the property tree. The second comm radio is: -// http://localhost:5400/instrumentation/comm[1] -#endif - -// Take the previous English-looking string and munge it to + transmission_readable = transmission; +// Take the previous readable string and munge it to // be relatively-more acceptable to the primitive tts system. // Note that : ; and . are among the token-delimeters recognized // by the tts system. for (size_t where;;) { where = transmission.find_first_of(":."); if (where == string::npos) break; - transmission.replace(where, 1, " /_ "); + transmission.replace(where, 1, PAUSE); } return 1; } + +// Put the transmission into the property tree, +// possibly in multiple places if multiple radios +// are tuned to the same ATIS. +// 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::iterator act = active_on.begin(); + act != active_on.end(); + act++){ + string prop = "/instrumentation/" + act->first + "/atis"; + globals->get_props()->setStringValue(prop.c_str(), + ("
\n" + transmission_readable + "
\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 +} diff --git a/src/ATCDCL/atis.hxx b/src/ATCDCL/atis.hxx index cd35ea476..76809eb09 100644 --- a/src/ATCDCL/atis.hxx +++ b/src/ATCDCL/atis.hxx @@ -39,10 +39,15 @@ typedef std::map MSS; class FGATIS : public FGATC { //atc_type type; - std::string transmission; // The actual ATIS transmission - // This is not stored in default.atis but is generated - // from the prevailing conditions when required. + + // The actual ATIS transmission + // This is generated from the prevailing conditions when required. + // This is the version with markup, suitable for voice synthesis: + std::string transmission; + // Same as above, but in a form more readable as text. + std::string transmission_readable; + // for failure modeling std::string trans_ident; // transmitted ident double old_volume; @@ -82,9 +87,13 @@ class FGATIS : public FGATC { std::string refname; // Holds the refname of a transmission in progress - int GenTransmission(const int regen, - const int special); // Generate the transmission string + // Generate the ATIS transmission text: + int GenTransmission(const int regen, const int special); + // Put the text into the property tree + // (and in debug mode, print it on the console): + void TreeOut(int msgOK); + friend std::istream& operator>> ( std::istream&, FGATIS& ); }; diff --git a/src/ATCDCL/atis_lexicon.hxx b/src/ATCDCL/atis_lexicon.hxx index 2284f1f95..d201674ff 100644 --- a/src/ATCDCL/atis_lexicon.hxx +++ b/src/ATCDCL/atis_lexicon.hxx @@ -3,6 +3,9 @@ #include +// NOTE: This file serves as a database. +// It is read by some utility programs that synthesize +// the library of spoken words. #define Q(word) const std::string word(#word); @@ -34,10 +37,14 @@ Q(hundred) Q(zero) Q(Temperature) Q(clear) +Q(isolated) +Q(few) Q(scattered) Q(broken) Q(overcast) +Q(thin) Q(Sky_condition) +Q(Sky) Q(Ceiling) Q(minus) Q(dewpoint) @@ -48,6 +55,8 @@ Q(one_half) Q(three_quarters) Q(one_and_one_half) Q(Altimeter) +Q(QNH) +Q(millibars) Q(Landing_and_departing_runway) Q(On_initial_contact_advise_you_have_information) Q(This_is) diff --git a/src/ATCDCL/atis_remap.hxx b/src/ATCDCL/atis_remap.hxx index f679b70b9..2497197b3 100644 --- a/src/ATCDCL/atis_remap.hxx +++ b/src/ATCDCL/atis_remap.hxx @@ -1,8 +1,13 @@ +// NOTE: This file serves as a database. +// It is read by some utility programs that synthesize +// the library of spoken words. + REMAP(Intl, International) REMAP(Rgnl, Regional) REMAP(Co, County) REMAP(Muni, Municipal) REMAP(Mem, Memorial) +REMAP(Meml, Memorial) REMAP(Apt, Airport) REMAP(Arpt, Airport) REMAP(Fld, Field) diff --git a/src/Airports/simple.cxx b/src/Airports/simple.cxx index c5ac75baf..a085fab57 100644 --- a/src/Airports/simple.cxx +++ b/src/Airports/simple.cxx @@ -456,9 +456,13 @@ void FGAirport::readTowerData(SGPropertyNode* aRoot) SGPropertyNode* twrNode = aRoot->getChild("tower")->getChild("twr"); double lat = twrNode->getDoubleValue("lat"), lon = twrNode->getDoubleValue("lon"), - elevM = twrNode->getDoubleValue("elev-m"); - - _tower_location = SGGeod::fromDegM(lon, lat, elevM); + elevM = twrNode->getDoubleValue("elev-m"); +// tower elevation is AGL, not AMSL. Since we don't want to depend on the +// scenery for a precise terrain elevation, we use the field elevation +// (this is also what the apt.dat code does) + double fieldElevationM = geod().getElevationM(); + + _tower_location = SGGeod::fromDegM(lon, lat, fieldElevationM + elevM); } bool FGAirport::buildApproach(Waypt* aEnroute, STAR* aSTAR, FGRunway* aRwy, WayptVec& aRoute) diff --git a/src/GUI/MapWidget.cxx b/src/GUI/MapWidget.cxx index bdd73a11e..fd02ebe0b 100644 --- a/src/GUI/MapWidget.cxx +++ b/src/GUI/MapWidget.cxx @@ -1285,6 +1285,22 @@ void MapWidget::drawILS(bool tuned, FGRunway* rwy) glVertex2dv(endCentre.data()); glVertex2dv(endR.data()); glEnd(); + + if (validDataForKey(loc)) { + setAnchorForKey(loc, endR); + return; + } + + char buffer[1024]; + ::snprintf(buffer, 1024, "%s\n%s\n%3.2fMHz", + loc->name().c_str(), loc->ident().c_str(),loc->get_freq()/100.0); + + MapData* d = createDataForKey(loc); + d->setPriority(40); + d->setLabel(loc->ident()); + d->setText(buffer); + d->setOffset(MapData::HALIGN_CENTER | MapData::VALIGN_BOTTOM, 10); + d->setAnchor(endR); } void MapWidget::drawTraffic() diff --git a/src/Include/config_cmake.h.in b/src/Include/config_cmake.h.in index 237d26e52..4505aa2dc 100644 --- a/src/Include/config_cmake.h.in +++ b/src/Include/config_cmake.h.in @@ -17,9 +17,12 @@ #define ENABLE_AUDIO_SUPPORT 1 #cmakedefine HAVE_SYS_TIME_H +#cmakedefine HAVE_WINDOWS_H #cmakedefine HAVE_CULLSETTINGS_CLEAR_MASK -#define VERSION "@FLIGHTGEAR_VERSION" +#define VERSION "@FLIGHTGEAR_VERSION@" + +#define HAVE_VERSION_H 1 // version.h is assumed for CMake builds #cmakedefine ENABLE_UIUC_MODEL #cmakedefine ENABLE_LARCSIM diff --git a/src/Include/version.h.cmake-in b/src/Include/version.h.cmake-in new file mode 100644 index 000000000..140e14009 --- /dev/null +++ b/src/Include/version.h.cmake-in @@ -0,0 +1,10 @@ + +#define FLIGHTGEAR_VERSION "@FLIGHTGEAR_VERSION@" + +#define HUDSON_BUILD_NUMBER @HUDSON_BUILD_NUMBER@ +#define HUDSON_BUILD_ID "@HUDSON_BUILD_ID@" +#define REVISION "@REVISION@" + + + + diff --git a/src/Main/CMakeLists.txt b/src/Main/CMakeLists.txt index 6eb4513c0..ffc87c857 100644 --- a/src/Main/CMakeLists.txt +++ b/src/Main/CMakeLists.txt @@ -39,7 +39,6 @@ target_link_libraries(fgfs ${ALUT_LIBRARY} ${ZLIB_LIBRARIES} ${PLIB_LIBRARIES} - ${RT_LIBRARY} - ${Boost_SERIALIZATION_LIBRARY}) + ${RT_LIBRARY}) install(TARGETS fgfs RUNTIME DESTINATION bin) diff --git a/src/Navaids/navrecord.hxx b/src/Navaids/navrecord.hxx index 2773629f4..09abb6e97 100644 --- a/src/Navaids/navrecord.hxx +++ b/src/Navaids/navrecord.hxx @@ -33,14 +33,6 @@ #define FG_DME_DEFAULT_RANGE 50 // nm #define FG_NAV_MAX_RANGE 300 // nm -// FIXME - get rid of these, and use the real enum directly -#define FG_NAV_VOR FGPositioned::VOR -#define FG_NAV_NDB FGPositioned::NDB -#define FG_NAV_ILS FGPositioned::ILS -#define FG_NAV_ANY FGPositioned::INVALID - -typedef FGPositioned::Type fg_nav_types; - // forward decls class FGRunway; class SGPropertyNode;