Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
506b9130a8 | ||
|
|
5d1b70a7f2 | ||
|
|
eff3df57d9 | ||
|
|
2931f3380f |
+19
-79
@@ -1,29 +1,14 @@
|
|||||||
cmake_minimum_required (VERSION 2.8.11)
|
cmake_minimum_required (VERSION 2.6.4)
|
||||||
|
|
||||||
if(COMMAND cmake_policy)
|
|
||||||
if(POLICY CMP0054)
|
|
||||||
cmake_policy(SET CMP0054 NEW)
|
|
||||||
endif()
|
|
||||||
if(POLICY CMP0042)
|
|
||||||
cmake_policy(SET CMP0042 NEW)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include (CheckFunctionExists)
|
include (CheckFunctionExists)
|
||||||
include (CheckIncludeFile)
|
include (CheckIncludeFile)
|
||||||
include (CheckLibraryExists)
|
|
||||||
include (CheckCXXSourceCompiles)
|
include (CheckCXXSourceCompiles)
|
||||||
include (CheckCXXCompilerFlag)
|
include (CheckCXXCompilerFlag)
|
||||||
include (GenerateExportHeader)
|
|
||||||
|
project(SimGear)
|
||||||
|
|
||||||
# using 10.7 because boost requires libc++ and 10.6 doesn't include it
|
# using 10.7 because boost requires libc++ and 10.6 doesn't include it
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
|
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
|
||||||
|
|
||||||
# only relevant for building shared libs but let's set it regardless
|
|
||||||
set(CMAKE_OSX_RPATH 1)
|
|
||||||
|
|
||||||
project(SimGear)
|
|
||||||
|
|
||||||
# read 'version' file into a variable (stripping any newlines or spaces)
|
# read 'version' file into a variable (stripping any newlines or spaces)
|
||||||
file(READ version versionFile)
|
file(READ version versionFile)
|
||||||
string(STRIP ${versionFile} SIMGEAR_VERSION)
|
string(STRIP ${versionFile} SIMGEAR_VERSION)
|
||||||
@@ -80,7 +65,12 @@ endif(NOT CMAKE_BUILD_TYPE)
|
|||||||
# Determine name of library installation directory, i.e. "lib" vs "lib64", which
|
# Determine name of library installation directory, i.e. "lib" vs "lib64", which
|
||||||
# differs between all Debian-based vs all other Linux distros.
|
# differs between all Debian-based vs all other Linux distros.
|
||||||
# See cmake bug #11964, http://cmake.org/gitweb?p=cmake.git;a=commit;h=126c993d
|
# See cmake bug #11964, http://cmake.org/gitweb?p=cmake.git;a=commit;h=126c993d
|
||||||
include(GNUInstallDirs)
|
# GNUInstallDirs requires CMake >= 2.8.5, use own file for older cmake
|
||||||
|
if(${CMAKE_VERSION} VERSION_GREATER 2.8.4)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
else(${CMAKE_VERSION} VERSION_GREATER 2.8.4)
|
||||||
|
include(OldGNUInstallDirs)
|
||||||
|
endif(${CMAKE_VERSION} VERSION_GREATER 2.8.4)
|
||||||
message(STATUS "Library installation directory: ${CMAKE_INSTALL_LIBDIR}")
|
message(STATUS "Library installation directory: ${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
|
||||||
#####################################################################################
|
#####################################################################################
|
||||||
@@ -117,7 +107,6 @@ option(ENABLE_RTI "Set to ON to build SimGear with RTI support" OFF)
|
|||||||
option(ENABLE_TESTS "Set to OFF to disable building SimGear's test applications" ON)
|
option(ENABLE_TESTS "Set to OFF to disable building SimGear's test applications" ON)
|
||||||
option(ENABLE_SOUND "Set to OFF to disable building SimGear's sound support" ON)
|
option(ENABLE_SOUND "Set to OFF to disable building SimGear's sound support" ON)
|
||||||
option(ENABLE_PKGUTIL "Set to ON to build the sg_pkgutil application (default)" ON)
|
option(ENABLE_PKGUTIL "Set to ON to build the sg_pkgutil application (default)" ON)
|
||||||
option(ENABLE_CURL "Set to ON to use libCurl as the HTTP client backend" OFF)
|
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
GET_FILENAME_COMPONENT(PARENT_DIR ${PROJECT_BINARY_DIR} PATH)
|
GET_FILENAME_COMPONENT(PARENT_DIR ${PROJECT_BINARY_DIR} PATH)
|
||||||
@@ -175,23 +164,13 @@ endif (MSVC AND MSVC_3RDPARTY_ROOT)
|
|||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
find_library(COCOA_LIBRARY Cocoa)
|
find_library(COCOA_LIBRARY Cocoa)
|
||||||
|
|
||||||
# this should be handled by setting CMAKE_OSX_DEPLOYMENT_TARGET
|
|
||||||
# but it's not working reliably, so forcing it for now
|
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7")
|
|
||||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.7")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR
|
|
||||||
${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
|
||||||
find_package(Threads REQUIRED)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Somehow this only works if included before searching for Boost...
|
# Somehow this only works if included before searching for Boost...
|
||||||
include(BoostTestTargets)
|
include(BoostTestTargets)
|
||||||
|
|
||||||
find_package(Boost REQUIRED)
|
find_package(Boost REQUIRED)
|
||||||
set (BOOST_CXX_FLAGS "-DBOOST_BIMAP_DISABLE_SERIALIZATION")
|
set (BOOST_CXX_FLAGS "-DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION -DBOOST_BIMAP_DISABLE_SERIALIZATION")
|
||||||
|
|
||||||
if(SIMGEAR_HEADLESS)
|
if(SIMGEAR_HEADLESS)
|
||||||
message(STATUS "SimGear mode: HEADLESS")
|
message(STATUS "SimGear mode: HEADLESS")
|
||||||
@@ -209,11 +188,7 @@ else()
|
|||||||
endif(SIMGEAR_HEADLESS)
|
endif(SIMGEAR_HEADLESS)
|
||||||
|
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
if (ENABLE_CURL)
|
|
||||||
find_package(CURL REQUIRED)
|
|
||||||
message(STATUS "Curl HTTP client: ENABLED")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (SYSTEM_EXPAT)
|
if (SYSTEM_EXPAT)
|
||||||
message(STATUS "Requested to use system Expat library, forcing SIMGEAR_SHARED to true")
|
message(STATUS "Requested to use system Expat library, forcing SIMGEAR_SHARED to true")
|
||||||
@@ -325,12 +300,11 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
# Boost redeclares class members
|
set(WARNING_FLAGS_CXX "-Wall -Wno-overloaded-virtual")
|
||||||
set(WARNING_FLAGS_CXX "-Wall -Wno-overloaded-virtual -Wno-redeclared-class-member")
|
set(WARNING_FLAGS_C "-Wall")
|
||||||
set(WARNING_FLAGS_C "-Wall")
|
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
|
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
@@ -380,7 +354,6 @@ include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS}
|
|||||||
${Boost_INCLUDE_DIRS}
|
${Boost_INCLUDE_DIRS}
|
||||||
${ZLIB_INCLUDE_DIR}
|
${ZLIB_INCLUDE_DIR}
|
||||||
${OPENAL_INCLUDE_DIR}
|
${OPENAL_INCLUDE_DIR}
|
||||||
${CURL_INCLUDE_DIRS}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DHAVE_CONFIG_H)
|
add_definitions(-DHAVE_CONFIG_H)
|
||||||
@@ -409,8 +382,7 @@ set(TEST_LIBS_INTERNAL_CORE
|
|||||||
${WINSOCK_LIBRARY}
|
${WINSOCK_LIBRARY}
|
||||||
${RT_LIBRARY}
|
${RT_LIBRARY}
|
||||||
${DL_LIBRARY}
|
${DL_LIBRARY}
|
||||||
${COCOA_LIBRARY}
|
${COCOA_LIBRARY})
|
||||||
${CURL_LIBRARIES})
|
|
||||||
set(TEST_LIBS SimGearCore ${TEST_LIBS_INTERNAL_CORE})
|
set(TEST_LIBS SimGearCore ${TEST_LIBS_INTERNAL_CORE})
|
||||||
|
|
||||||
if(NOT SIMGEAR_HEADLESS)
|
if(NOT SIMGEAR_HEADLESS)
|
||||||
@@ -424,40 +396,6 @@ include_directories(3rdparty/utf8/source)
|
|||||||
add_subdirectory(3rdparty)
|
add_subdirectory(3rdparty)
|
||||||
add_subdirectory(simgear)
|
add_subdirectory(simgear)
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
|
||||||
### Export stuff, see https://cmake.org/cmake/help/v3.2/manual/cmake-packages.7.html#creating-packages
|
|
||||||
#-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
generate_export_header(SimGearCore)
|
|
||||||
if(NOT SIMGEAR_HEADLESS)
|
|
||||||
generate_export_header(SimGearScene)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
|
|
||||||
write_basic_package_version_file(
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SimGear/SimGearConfigVersion.cmake"
|
|
||||||
VERSION ${SIMGEAR_VERSION}
|
|
||||||
COMPATIBILITY AnyNewerVersion
|
|
||||||
)
|
|
||||||
|
|
||||||
configure_file(SimGearConfig.cmake.in
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SimGear/SimGearConfig.cmake"
|
|
||||||
@ONLY
|
|
||||||
)
|
|
||||||
|
|
||||||
set(ConfigPackageLocation lib/cmake/SimGear)
|
|
||||||
install(EXPORT SimGearTargets
|
|
||||||
DESTINATION ${ConfigPackageLocation}
|
|
||||||
)
|
|
||||||
install(
|
|
||||||
FILES
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SimGear/SimGearConfig.cmake"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SimGear/SimGearConfigVersion.cmake"
|
|
||||||
DESTINATION ${ConfigPackageLocation}
|
|
||||||
COMPONENT Devel
|
|
||||||
)
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
### uninstall target
|
### uninstall target
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
@@ -467,3 +405,5 @@ CONFIGURE_FILE(
|
|||||||
IMMEDIATE @ONLY)
|
IMMEDIATE @ONLY)
|
||||||
ADD_CUSTOM_TARGET(uninstall
|
ADD_CUSTOM_TARGET(uninstall
|
||||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,182 @@
|
|||||||
|
# - Define GNU standard installation directories
|
||||||
|
# Provides install directory variables as defined for GNU software:
|
||||||
|
# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
|
||||||
|
# Inclusion of this module defines the following variables:
|
||||||
|
# CMAKE_INSTALL_<dir> - destination for files of a given type
|
||||||
|
# CMAKE_INSTALL_FULL_<dir> - corresponding absolute path
|
||||||
|
# where <dir> is one of:
|
||||||
|
# BINDIR - user executables (bin)
|
||||||
|
# SBINDIR - system admin executables (sbin)
|
||||||
|
# LIBEXECDIR - program executables (libexec)
|
||||||
|
# SYSCONFDIR - read-only single-machine data (etc)
|
||||||
|
# SHAREDSTATEDIR - modifiable architecture-independent data (com)
|
||||||
|
# LOCALSTATEDIR - modifiable single-machine data (var)
|
||||||
|
# LIBDIR - object code libraries (lib or lib64)
|
||||||
|
# INCLUDEDIR - C header files (include)
|
||||||
|
# OLDINCLUDEDIR - C header files for non-gcc (/usr/include)
|
||||||
|
# DATAROOTDIR - read-only architecture-independent data root (share)
|
||||||
|
# DATADIR - read-only architecture-independent data (DATAROOTDIR)
|
||||||
|
# INFODIR - info documentation (DATAROOTDIR/info)
|
||||||
|
# LOCALEDIR - locale-dependent data (DATAROOTDIR/locale)
|
||||||
|
# MANDIR - man documentation (DATAROOTDIR/man)
|
||||||
|
# DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME)
|
||||||
|
# Each CMAKE_INSTALL_<dir> value may be passed to the DESTINATION options of
|
||||||
|
# install() commands for the corresponding file type. If the includer does
|
||||||
|
# not define a value the above-shown default will be used and the value will
|
||||||
|
# appear in the cache for editing by the user.
|
||||||
|
# Each CMAKE_INSTALL_FULL_<dir> value contains an absolute path constructed
|
||||||
|
# from the corresponding destination by prepending (if necessary) the value
|
||||||
|
# of CMAKE_INSTALL_PREFIX.
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2011 Nikita Krupen'ko <krnekit@gmail.com>
|
||||||
|
# Copyright 2011 Kitware, Inc.
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
|
# License text for the above reference.)
|
||||||
|
|
||||||
|
# Installation directories
|
||||||
|
#
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_BINDIR)
|
||||||
|
set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_SBINDIR)
|
||||||
|
set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR)
|
||||||
|
set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR)
|
||||||
|
set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR)
|
||||||
|
set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR)
|
||||||
|
set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
||||||
|
set(_LIBDIR_DEFAULT "lib")
|
||||||
|
# Override this default 'lib' with 'lib64' iff:
|
||||||
|
# - we are on Linux system but NOT cross-compiling
|
||||||
|
# - we are NOT on debian
|
||||||
|
# - we are on a 64 bits system
|
||||||
|
# reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
|
||||||
|
# Note that the future of multi-arch handling may be even
|
||||||
|
# more complicated than that: http://wiki.debian.org/Multiarch
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES "Linux"
|
||||||
|
AND NOT CMAKE_CROSSCOMPILING
|
||||||
|
AND NOT EXISTS "/etc/debian_version")
|
||||||
|
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
|
||||||
|
message(AUTHOR_WARNING
|
||||||
|
"Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
|
||||||
|
"Please enable at least one language before including GNUInstallDirs.")
|
||||||
|
else()
|
||||||
|
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||||
|
set(_LIBDIR_DEFAULT "lib64")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
|
||||||
|
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR)
|
||||||
|
set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR)
|
||||||
|
set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Values whose defaults are relative to DATAROOTDIR. Store empty values in
|
||||||
|
# the cache and store the defaults in local variables if the cache values are
|
||||||
|
# not set explicitly. This auto-updates the defaults as DATAROOTDIR changes.
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_DATADIR)
|
||||||
|
set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)")
|
||||||
|
set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_INFODIR)
|
||||||
|
set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)")
|
||||||
|
set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_LOCALEDIR)
|
||||||
|
set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)")
|
||||||
|
set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_MANDIR)
|
||||||
|
set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)")
|
||||||
|
set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_DOCDIR)
|
||||||
|
set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
|
||||||
|
set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
mark_as_advanced(
|
||||||
|
CMAKE_INSTALL_BINDIR
|
||||||
|
CMAKE_INSTALL_SBINDIR
|
||||||
|
CMAKE_INSTALL_LIBEXECDIR
|
||||||
|
CMAKE_INSTALL_SYSCONFDIR
|
||||||
|
CMAKE_INSTALL_SHAREDSTATEDIR
|
||||||
|
CMAKE_INSTALL_LOCALSTATEDIR
|
||||||
|
CMAKE_INSTALL_LIBDIR
|
||||||
|
CMAKE_INSTALL_INCLUDEDIR
|
||||||
|
CMAKE_INSTALL_OLDINCLUDEDIR
|
||||||
|
CMAKE_INSTALL_DATAROOTDIR
|
||||||
|
CMAKE_INSTALL_DATADIR
|
||||||
|
CMAKE_INSTALL_INFODIR
|
||||||
|
CMAKE_INSTALL_LOCALEDIR
|
||||||
|
CMAKE_INSTALL_MANDIR
|
||||||
|
CMAKE_INSTALL_DOCDIR
|
||||||
|
)
|
||||||
|
|
||||||
|
# Result directories
|
||||||
|
#
|
||||||
|
foreach(dir
|
||||||
|
BINDIR
|
||||||
|
SBINDIR
|
||||||
|
LIBEXECDIR
|
||||||
|
SYSCONFDIR
|
||||||
|
SHAREDSTATEDIR
|
||||||
|
LOCALSTATEDIR
|
||||||
|
LIBDIR
|
||||||
|
INCLUDEDIR
|
||||||
|
OLDINCLUDEDIR
|
||||||
|
DATAROOTDIR
|
||||||
|
DATADIR
|
||||||
|
INFODIR
|
||||||
|
LOCALEDIR
|
||||||
|
MANDIR
|
||||||
|
DOCDIR
|
||||||
|
)
|
||||||
|
if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
|
||||||
|
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
|
||||||
|
else()
|
||||||
|
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
include(CMakeFindDependencyMacro)
|
|
||||||
|
|
||||||
find_dependency(ZLIB)
|
|
||||||
find_dependency(Threads)
|
|
||||||
|
|
||||||
# OSG
|
|
||||||
|
|
||||||
set(SIMGEAR_HEADLESS @SIMGEAR_HEADLESS@)
|
|
||||||
set(SIMGEAR_SOUND @ENABLE_SOUND@)
|
|
||||||
|
|
||||||
# OpenAL isn't a public dependency, so maybe not needed
|
|
||||||
#if (SIMGEAR_SOUND)
|
|
||||||
# find_dependency(OpenAL)
|
|
||||||
#endif()
|
|
||||||
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/SimGearTargets.cmake")
|
|
||||||
+11
-20
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
file(WRITE ${PROJECT_BINARY_DIR}/simgear/version.h "#define SIMGEAR_VERSION ${SIMGEAR_VERSION}")
|
file(WRITE ${PROJECT_BINARY_DIR}/simgear/version.h "#define SIMGEAR_VERSION ${SIMGEAR_VERSION}")
|
||||||
|
|
||||||
foreach( mylibfolder
|
foreach( mylibfolder
|
||||||
bucket
|
bucket
|
||||||
bvh
|
bvh
|
||||||
debug
|
debug
|
||||||
@@ -54,11 +54,9 @@ if(SIMGEAR_SHARED)
|
|||||||
set_property(TARGET SimGearCore PROPERTY LINKER_LANGUAGE CXX)
|
set_property(TARGET SimGearCore PROPERTY LINKER_LANGUAGE CXX)
|
||||||
set_property(TARGET SimGearCore PROPERTY VERSION ${SIMGEAR_VERSION})
|
set_property(TARGET SimGearCore PROPERTY VERSION ${SIMGEAR_VERSION})
|
||||||
set_property(TARGET SimGearCore PROPERTY SOVERSION ${SIMGEAR_SOVERSION})
|
set_property(TARGET SimGearCore PROPERTY SOVERSION ${SIMGEAR_SOVERSION})
|
||||||
install(TARGETS SimGearCore
|
install(TARGETS SimGearCore EXPORT SimGearCoreConfig LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
EXPORT SimGearTargets
|
install(EXPORT SimGearCoreConfig DESTINATION share/SimGearCore)
|
||||||
LIBRARY DESTINATION
|
|
||||||
${CMAKE_INSTALL_LIBDIR})
|
|
||||||
|
|
||||||
if(NOT SIMGEAR_HEADLESS)
|
if(NOT SIMGEAR_HEADLESS)
|
||||||
add_library(SimGearScene SHARED ${sceneSources})
|
add_library(SimGearScene SHARED ${sceneSources})
|
||||||
set_property(TARGET SimGearScene PROPERTY LINKER_LANGUAGE CXX)
|
set_property(TARGET SimGearScene PROPERTY LINKER_LANGUAGE CXX)
|
||||||
@@ -66,12 +64,10 @@ if(SIMGEAR_SHARED)
|
|||||||
set_property(TARGET SimGearScene PROPERTY SOVERSION ${SIMGEAR_SOVERSION})
|
set_property(TARGET SimGearScene PROPERTY SOVERSION ${SIMGEAR_SOVERSION})
|
||||||
|
|
||||||
# EXPORT SimGearSceneConfig
|
# EXPORT SimGearSceneConfig
|
||||||
install(TARGETS SimGearScene
|
install(TARGETS SimGearScene LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
||||||
EXPORT SimGearTargets
|
# install(EXPORT SimGearSceneConfig DESTINATION share/SimGearScene)
|
||||||
LIBRARY
|
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
else()
|
else()
|
||||||
message(STATUS "Library building mode: STATIC LIBRARIES")
|
message(STATUS "Library building mode: STATIC LIBRARIES")
|
||||||
|
|
||||||
@@ -94,10 +90,8 @@ else()
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_library(SimGearCore STATIC ${coreSources} ${localExpatSources})
|
add_library(SimGearCore STATIC ${coreSources} ${localExpatSources})
|
||||||
install(TARGETS SimGearCore
|
install(TARGETS SimGearCore ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
EXPORT SimGearTargets
|
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
||||||
|
|
||||||
if(NOT SIMGEAR_HEADLESS)
|
if(NOT SIMGEAR_HEADLESS)
|
||||||
get_property(FG_GROUPS_SCENE_SOURCES_C GLOBAL PROPERTY FG_GROUPS_SCENE_SOURCES_C)
|
get_property(FG_GROUPS_SCENE_SOURCES_C GLOBAL PROPERTY FG_GROUPS_SCENE_SOURCES_C)
|
||||||
string(REPLACE "@" ";" groups ${FG_GROUPS_SCENE_SOURCES_C} )
|
string(REPLACE "@" ";" groups ${FG_GROUPS_SCENE_SOURCES_C} )
|
||||||
@@ -118,9 +112,7 @@ else()
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_library(SimGearScene STATIC ${sceneSources})
|
add_library(SimGearScene STATIC ${sceneSources})
|
||||||
install(TARGETS SimGearScene
|
install(TARGETS SimGearScene ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
EXPORT SimGearTargets
|
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
||||||
endif(NOT SIMGEAR_HEADLESS)
|
endif(NOT SIMGEAR_HEADLESS)
|
||||||
endif(SIMGEAR_SHARED)
|
endif(SIMGEAR_SHARED)
|
||||||
|
|
||||||
@@ -130,8 +122,7 @@ target_link_libraries(SimGearCore
|
|||||||
${DL_LIBRARY}
|
${DL_LIBRARY}
|
||||||
${EXPAT_LIBRARIES}
|
${EXPAT_LIBRARIES}
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
${COCOA_LIBRARY}
|
${COCOA_LIBRARY})
|
||||||
${CURL_LIBRARIES})
|
|
||||||
|
|
||||||
if(NOT SIMGEAR_HEADLESS)
|
if(NOT SIMGEAR_HEADLESS)
|
||||||
target_link_libraries(SimGearScene
|
target_link_libraries(SimGearScene
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
void removeChild(BVHNode* child);
|
void removeChild(BVHNode* child);
|
||||||
|
|
||||||
unsigned getNumChildren() const
|
unsigned getNumChildren() const
|
||||||
{ return static_cast<unsigned>(_children.size()); }
|
{ return _children.size(); }
|
||||||
const BVHNode* getChild(unsigned i) const
|
const BVHNode* getChild(unsigned i) const
|
||||||
{ if (_children.size() <= i) return 0; return _children[i]; }
|
{ if (_children.size() <= i) return 0; return _children[i]; }
|
||||||
BVHNode* getChild(unsigned i)
|
BVHNode* getChild(unsigned i)
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ public:
|
|||||||
virtual ~BVHStaticData() {}
|
virtual ~BVHStaticData() {}
|
||||||
|
|
||||||
unsigned addVertex(const SGVec3f& vertex)
|
unsigned addVertex(const SGVec3f& vertex)
|
||||||
{ _vertices.push_back(vertex); return static_cast<unsigned>(_vertices.size() - 1); }
|
{ _vertices.push_back(vertex); return _vertices.size() - 1; }
|
||||||
const SGVec3f& getVertex(unsigned i) const
|
const SGVec3f& getVertex(unsigned i) const
|
||||||
{ return _vertices[i]; }
|
{ return _vertices[i]; }
|
||||||
|
|
||||||
|
|
||||||
unsigned addMaterial(const BVHMaterial* material)
|
unsigned addMaterial(const BVHMaterial* material)
|
||||||
{ _materials.push_back(material); return static_cast<unsigned>(_materials.size() - 1); }
|
{ _materials.push_back(material); return _materials.size() - 1; }
|
||||||
const BVHMaterial* getMaterial(unsigned i) const
|
const BVHMaterial* getMaterial(unsigned i) const
|
||||||
{ if (_materials.size() <= i) return 0; return _materials[i]; }
|
{ if (_materials.size() <= i) return 0; return _materials[i]; }
|
||||||
|
|
||||||
|
|||||||
@@ -207,6 +207,19 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
Element::~Element()
|
Element::~Element()
|
||||||
{
|
{
|
||||||
|
if( !_transform.valid() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < _transform->getNumChildren(); ++i)
|
||||||
|
{
|
||||||
|
OSGUserData* ud =
|
||||||
|
static_cast<OSGUserData*>(_transform->getChild(i)->getUserData());
|
||||||
|
|
||||||
|
if( ud )
|
||||||
|
// Ensure parent is cleared to prevent accessing released memory if an
|
||||||
|
// element somehow survives longer than his parent.
|
||||||
|
ud->element->_parent = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -233,7 +246,7 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
ElementPtr Element::getParent() const
|
ElementPtr Element::getParent() const
|
||||||
{
|
{
|
||||||
return _parent.lock();
|
return _parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -311,9 +324,8 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool Element::ascend(EventVisitor& visitor)
|
bool Element::ascend(EventVisitor& visitor)
|
||||||
{
|
{
|
||||||
ElementPtr parent = getParent();
|
if( _parent )
|
||||||
if( parent )
|
return _parent->accept(visitor);
|
||||||
return parent->accept(visitor);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,9 +374,9 @@ namespace canvas
|
|||||||
EventPropagationPath path;
|
EventPropagationPath path;
|
||||||
path.push_back( EventTarget(this) );
|
path.push_back( EventTarget(this) );
|
||||||
|
|
||||||
for( ElementPtr parent = getParent();
|
for( Element* parent = _parent;
|
||||||
parent.valid();
|
parent != NULL;
|
||||||
parent = parent->getParent() )
|
parent = parent->_parent )
|
||||||
path.push_front( EventTarget(parent) );
|
path.push_front( EventTarget(parent) );
|
||||||
|
|
||||||
CanvasPtr canvas = _canvas.lock();
|
CanvasPtr canvas = _canvas.lock();
|
||||||
@@ -760,7 +772,7 @@ namespace canvas
|
|||||||
Element::Element( const CanvasWeakPtr& canvas,
|
Element::Element( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
PropertyBasedElement(node),
|
PropertyBasedElement(node),
|
||||||
_canvas( canvas ),
|
_canvas( canvas ),
|
||||||
_parent( parent ),
|
_parent( parent ),
|
||||||
@@ -859,12 +871,11 @@ namespace canvas
|
|||||||
Element::getParentStyle(const SGPropertyNode* child) const
|
Element::getParentStyle(const SGPropertyNode* child) const
|
||||||
{
|
{
|
||||||
// Try to get value from parent...
|
// Try to get value from parent...
|
||||||
ElementPtr parent = getParent();
|
if( _parent )
|
||||||
if( parent )
|
|
||||||
{
|
{
|
||||||
Style::const_iterator style =
|
Style::const_iterator style =
|
||||||
parent->_style.find(child->getNameString());
|
_parent->_style.find(child->getNameString());
|
||||||
if( style != parent->_style.end() )
|
if( style != _parent->_style.end() )
|
||||||
return style->second;
|
return style->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -232,8 +232,8 @@ namespace canvas
|
|||||||
|
|
||||||
class RelativeScissor;
|
class RelativeScissor;
|
||||||
|
|
||||||
CanvasWeakPtr _canvas;
|
CanvasWeakPtr _canvas;
|
||||||
ElementWeakPtr _parent;
|
Element *_parent;
|
||||||
|
|
||||||
mutable uint32_t _attributes_dirty;
|
mutable uint32_t _attributes_dirty;
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ namespace canvas
|
|||||||
Element( const CanvasWeakPtr& canvas,
|
Element( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent );
|
Element* parent );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns false on first call and true on any successive call. Use to
|
* Returns false on first call and true on any successive call. Use to
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace canvas
|
|||||||
Group::Group( const CanvasWeakPtr& canvas,
|
Group::Group( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
Element(canvas, node, parent_style, parent)
|
Element(canvas, node, parent_style, parent)
|
||||||
{
|
{
|
||||||
staticInit();
|
staticInit();
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace canvas
|
|||||||
Group( const CanvasWeakPtr& canvas,
|
Group( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style = Style(),
|
const Style& parent_style = Style(),
|
||||||
ElementWeakPtr parent = 0 );
|
Element* parent = 0 );
|
||||||
virtual ~Group();
|
virtual ~Group();
|
||||||
|
|
||||||
ElementPtr createChild( const std::string& type,
|
ElementPtr createChild( const std::string& type,
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ namespace canvas
|
|||||||
Image::Image( const CanvasWeakPtr& canvas,
|
Image::Image( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
Element(canvas, node, parent_style, parent),
|
Element(canvas, node, parent_style, parent),
|
||||||
_texture(new osg::Texture2D),
|
_texture(new osg::Texture2D),
|
||||||
_node_src_rect( node->getNode("source", 0, true) ),
|
_node_src_rect( node->getNode("source", 0, true) ),
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace canvas
|
|||||||
Image( const CanvasWeakPtr& canvas,
|
Image( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style = Style(),
|
const Style& parent_style = Style(),
|
||||||
ElementWeakPtr parent = 0 );
|
Element* parent = 0 );
|
||||||
virtual ~Image();
|
virtual ~Image();
|
||||||
|
|
||||||
virtual void update(double dt);
|
virtual void update(double dt);
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ namespace canvas
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
const std::string GEO = "-geo";
|
const std::string GEO = "-geo";
|
||||||
const std::string HDG = "hdg";
|
|
||||||
const std::string Map::TYPE_NAME = "map";
|
const std::string Map::TYPE_NAME = "map";
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -62,7 +61,7 @@ namespace canvas
|
|||||||
Map::Map( const CanvasWeakPtr& canvas,
|
Map::Map( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
Group(canvas, node, parent_style, parent),
|
Group(canvas, node, parent_style, parent),
|
||||||
// TODO make projection configurable
|
// TODO make projection configurable
|
||||||
_projection(new SansonFlamsteedProjection),
|
_projection(new SansonFlamsteedProjection),
|
||||||
@@ -113,50 +112,87 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Map::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
|
void Map::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
|
||||||
{
|
{
|
||||||
if( boost::ends_with(child->getNameString(), GEO) )
|
if( !boost::ends_with(child->getNameString(), GEO) )
|
||||||
_geo_nodes[child].reset(new GeoNodePair());
|
|
||||||
else if( parent != _node && child->getNameString() == HDG )
|
|
||||||
_hdg_nodes.insert(child);
|
|
||||||
else
|
|
||||||
return Element::childAdded(parent, child);
|
return Element::childAdded(parent, child);
|
||||||
|
|
||||||
|
_geo_nodes[child].reset(new GeoNodePair());
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Map::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
|
void Map::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
|
||||||
{
|
{
|
||||||
if( boost::ends_with(child->getNameString(), GEO) )
|
if( !boost::ends_with(child->getNameString(), GEO) )
|
||||||
// TODO remove from other node
|
|
||||||
_geo_nodes.erase(child);
|
|
||||||
else if( parent != _node && child->getName() == HDG )
|
|
||||||
{
|
|
||||||
_hdg_nodes.erase(child);
|
|
||||||
|
|
||||||
// Remove rotation matrix (tf[0]) and return to element always being
|
|
||||||
// oriented upwards (or any orientation inside other matrices).
|
|
||||||
child->getParent()->removeChild("tf", 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return Element::childRemoved(parent, child);
|
return Element::childRemoved(parent, child);
|
||||||
|
|
||||||
|
// TODO remove from other node
|
||||||
|
_geo_nodes.erase(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Map::valueChanged(SGPropertyNode* child)
|
void Map::valueChanged(SGPropertyNode * child)
|
||||||
{
|
{
|
||||||
if( child->getParent() != _node )
|
const std::string& name = child->getNameString();
|
||||||
|
|
||||||
|
if( !boost::ends_with(name, GEO) )
|
||||||
|
return Group::valueChanged(child);
|
||||||
|
|
||||||
|
GeoNodes::iterator it_geo_node = _geo_nodes.find(child);
|
||||||
|
if( it_geo_node == _geo_nodes.end() )
|
||||||
|
LOG_GEO_RET("geo node not found!")
|
||||||
|
GeoNodePair* geo_node = it_geo_node->second.get();
|
||||||
|
|
||||||
|
geo_node->setDirty();
|
||||||
|
|
||||||
|
if( geo_node->getStatus() & GeoNodePair::INCOMPLETE )
|
||||||
{
|
{
|
||||||
const std::string& name = child->getNameString();
|
// Detect lat, lon tuples...
|
||||||
|
GeoCoord coord = parseGeoCoord(child->getStringValue());
|
||||||
|
int index_other = -1;
|
||||||
|
|
||||||
if( boost::ends_with(name, GEO) )
|
switch( coord.type )
|
||||||
return geoNodeChanged(child);
|
{
|
||||||
else if( name == HDG )
|
case GeoCoord::LATITUDE:
|
||||||
return hdgNodeChanged(child);
|
index_other = child->getIndex() + 1;
|
||||||
|
geo_node->setNodeLat(child);
|
||||||
|
break;
|
||||||
|
case GeoCoord::LONGITUDE:
|
||||||
|
index_other = child->getIndex() - 1;
|
||||||
|
geo_node->setNodeLon(child);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_GEO_RET("Invalid geo coord")
|
||||||
|
}
|
||||||
|
|
||||||
|
SGPropertyNode *other = child->getParent()->getChild(name, index_other);
|
||||||
|
if( !other )
|
||||||
|
return;
|
||||||
|
|
||||||
|
GeoCoord coord_other = parseGeoCoord(other->getStringValue());
|
||||||
|
if( coord_other.type == GeoCoord::INVALID
|
||||||
|
|| coord_other.type == coord.type )
|
||||||
|
return;
|
||||||
|
|
||||||
|
GeoNodes::iterator it_geo_node_other = _geo_nodes.find(other);
|
||||||
|
if( it_geo_node_other == _geo_nodes.end() )
|
||||||
|
LOG_GEO_RET("other geo node not found!")
|
||||||
|
GeoNodePair* geo_node_other = it_geo_node_other->second.get();
|
||||||
|
|
||||||
|
// Let use both nodes use the same GeoNodePair instance
|
||||||
|
if( geo_node_other != geo_node )
|
||||||
|
it_geo_node_other->second = it_geo_node->second;
|
||||||
|
|
||||||
|
if( coord_other.type == GeoCoord::LATITUDE )
|
||||||
|
geo_node->setNodeLat(other);
|
||||||
|
else
|
||||||
|
geo_node->setNodeLon(other);
|
||||||
|
|
||||||
|
// Set name for resulting screen coordinate nodes
|
||||||
|
geo_node->setTargetName( name.substr(0, name.length() - GEO.length()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return Group::valueChanged(child);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Map::childChanged(SGPropertyNode* child)
|
void Map::childChanged(SGPropertyNode * child)
|
||||||
{
|
{
|
||||||
if( child->getParent() != _node )
|
if( child->getParent() != _node )
|
||||||
return Group::childChanged(child);
|
return Group::childChanged(child);
|
||||||
@@ -165,14 +201,8 @@ namespace canvas
|
|||||||
|| child->getNameString() == "ref-lon" )
|
|| child->getNameString() == "ref-lon" )
|
||||||
_projection->setWorldPosition( _node->getDoubleValue("ref-lat"),
|
_projection->setWorldPosition( _node->getDoubleValue("ref-lat"),
|
||||||
_node->getDoubleValue("ref-lon") );
|
_node->getDoubleValue("ref-lon") );
|
||||||
else if( child->getNameString() == HDG )
|
else if( child->getNameString() == "hdg" )
|
||||||
{
|
|
||||||
_projection->setOrientation(child->getFloatValue());
|
_projection->setOrientation(child->getFloatValue());
|
||||||
for( NodeSet::iterator it = _hdg_nodes.begin();
|
|
||||||
it != _hdg_nodes.end();
|
|
||||||
++it )
|
|
||||||
hdgNodeChanged(*it);
|
|
||||||
}
|
|
||||||
else if( child->getNameString() == "range" )
|
else if( child->getNameString() == "range" )
|
||||||
_projection->setRange(child->getDoubleValue());
|
_projection->setRange(child->getDoubleValue());
|
||||||
else if( child->getNameString() == "screen-range" )
|
else if( child->getNameString() == "screen-range" )
|
||||||
@@ -183,74 +213,6 @@ namespace canvas
|
|||||||
_projection_dirty = true;
|
_projection_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void Map::geoNodeChanged(SGPropertyNode* child)
|
|
||||||
{
|
|
||||||
GeoNodes::iterator it_geo_node = _geo_nodes.find(child);
|
|
||||||
if( it_geo_node == _geo_nodes.end() )
|
|
||||||
LOG_GEO_RET("GeoNode not found!")
|
|
||||||
GeoNodePair* geo_node = it_geo_node->second.get();
|
|
||||||
|
|
||||||
geo_node->setDirty();
|
|
||||||
|
|
||||||
if( !(geo_node->getStatus() & GeoNodePair::INCOMPLETE) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Detect lat, lon tuples...
|
|
||||||
GeoCoord coord = parseGeoCoord(child->getStringValue());
|
|
||||||
int index_other = -1;
|
|
||||||
|
|
||||||
switch( coord.type )
|
|
||||||
{
|
|
||||||
case GeoCoord::LATITUDE:
|
|
||||||
index_other = child->getIndex() + 1;
|
|
||||||
geo_node->setNodeLat(child);
|
|
||||||
break;
|
|
||||||
case GeoCoord::LONGITUDE:
|
|
||||||
index_other = child->getIndex() - 1;
|
|
||||||
geo_node->setNodeLon(child);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_GEO_RET("Invalid geo coord")
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& name = child->getNameString();
|
|
||||||
SGPropertyNode *other = child->getParent()->getChild(name, index_other);
|
|
||||||
if( !other )
|
|
||||||
return;
|
|
||||||
|
|
||||||
GeoCoord coord_other = parseGeoCoord(other->getStringValue());
|
|
||||||
if( coord_other.type == GeoCoord::INVALID
|
|
||||||
|| coord_other.type == coord.type )
|
|
||||||
return;
|
|
||||||
|
|
||||||
GeoNodes::iterator it_geo_node_other = _geo_nodes.find(other);
|
|
||||||
if( it_geo_node_other == _geo_nodes.end() )
|
|
||||||
LOG_GEO_RET("other geo node not found!")
|
|
||||||
GeoNodePair* geo_node_other = it_geo_node_other->second.get();
|
|
||||||
|
|
||||||
// Let use both nodes use the same GeoNodePair instance
|
|
||||||
if( geo_node_other != geo_node )
|
|
||||||
it_geo_node_other->second = it_geo_node->second;
|
|
||||||
|
|
||||||
if( coord_other.type == GeoCoord::LATITUDE )
|
|
||||||
geo_node->setNodeLat(other);
|
|
||||||
else
|
|
||||||
geo_node->setNodeLon(other);
|
|
||||||
|
|
||||||
// Set name for resulting screen coordinate nodes
|
|
||||||
geo_node->setTargetName( name.substr(0, name.length() - GEO.length()) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void Map::hdgNodeChanged(SGPropertyNode* child)
|
|
||||||
{
|
|
||||||
child->getParent()->setFloatValue(
|
|
||||||
"tf[0]/rot",
|
|
||||||
SGMiscf::deg2rad(child->getFloatValue() - _projection->orientation())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
Map::GeoCoord Map::parseGeoCoord(const std::string& val) const
|
Map::GeoCoord Map::parseGeoCoord(const std::string& val) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
#include <boost/unordered_set.hpp>
|
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
@@ -42,7 +41,7 @@ namespace canvas
|
|||||||
Map( const CanvasWeakPtr& canvas,
|
Map( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent = 0 );
|
Element* parent = 0 );
|
||||||
virtual ~Map();
|
virtual ~Map();
|
||||||
|
|
||||||
virtual void update(double dt);
|
virtual void update(double dt);
|
||||||
@@ -60,18 +59,14 @@ namespace canvas
|
|||||||
typedef boost::unordered_map< SGPropertyNode*,
|
typedef boost::unordered_map< SGPropertyNode*,
|
||||||
boost::shared_ptr<GeoNodePair>
|
boost::shared_ptr<GeoNodePair>
|
||||||
> GeoNodes;
|
> GeoNodes;
|
||||||
typedef boost::unordered_set<SGPropertyNode*> NodeSet;
|
|
||||||
|
|
||||||
GeoNodes _geo_nodes;
|
GeoNodes _geo_nodes;
|
||||||
NodeSet _hdg_nodes;
|
|
||||||
boost::shared_ptr<HorizontalProjection> _projection;
|
boost::shared_ptr<HorizontalProjection> _projection;
|
||||||
bool _projection_dirty;
|
bool _projection_dirty;
|
||||||
|
|
||||||
struct GeoCoord
|
struct GeoCoord
|
||||||
{
|
{
|
||||||
GeoCoord():
|
GeoCoord():
|
||||||
type(INVALID),
|
type(INVALID)
|
||||||
value(0)
|
|
||||||
{}
|
{}
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@@ -82,9 +77,6 @@ namespace canvas
|
|||||||
double value;
|
double value;
|
||||||
};
|
};
|
||||||
|
|
||||||
void geoNodeChanged(SGPropertyNode * child);
|
|
||||||
void hdgNodeChanged(SGPropertyNode * child);
|
|
||||||
|
|
||||||
GeoCoord parseGeoCoord(const std::string& val) const;
|
GeoCoord parseGeoCoord(const std::string& val) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -531,7 +531,7 @@ namespace canvas
|
|||||||
Path::Path( const CanvasWeakPtr& canvas,
|
Path::Path( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
Element(canvas, node, parent_style, parent),
|
Element(canvas, node, parent_style, parent),
|
||||||
_path( new PathDrawable(this) )
|
_path( new PathDrawable(this) )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace canvas
|
|||||||
Path( const CanvasWeakPtr& canvas,
|
Path( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent = 0 );
|
Element* parent = 0 );
|
||||||
virtual ~Path();
|
virtual ~Path();
|
||||||
|
|
||||||
virtual void update(double dt);
|
virtual void update(double dt);
|
||||||
|
|||||||
@@ -159,12 +159,8 @@ namespace canvas
|
|||||||
|
|
||||||
if( empty() )
|
if( empty() )
|
||||||
return pos;
|
return pos;
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,5)
|
|
||||||
GlyphQuads::Coords2 const& coords = _quads->_coords;
|
GlyphQuads::Coords2 const& coords = _quads->_coords;
|
||||||
#else
|
|
||||||
GlyphQuads::Coords2 refCoords = _quads->_coords;
|
|
||||||
GlyphQuads::Coords2::element_type &coords = *refCoords.get();
|
|
||||||
#endif
|
|
||||||
size_t global_i = _begin + i;
|
size_t global_i = _begin + i;
|
||||||
|
|
||||||
if( global_i == _begin )
|
if( global_i == _begin )
|
||||||
@@ -198,12 +194,7 @@ namespace canvas
|
|||||||
return cursorPos(0);
|
return cursorPos(0);
|
||||||
|
|
||||||
GlyphQuads::Glyphs const& glyphs = _quads->_glyphs;
|
GlyphQuads::Glyphs const& glyphs = _quads->_glyphs;
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,5)
|
|
||||||
GlyphQuads::Coords2 const& coords = _quads->_coords;
|
GlyphQuads::Coords2 const& coords = _quads->_coords;
|
||||||
#else
|
|
||||||
GlyphQuads::Coords2 refCoords = _quads->_coords;
|
|
||||||
GlyphQuads::Coords2::element_type &coords = *refCoords.get();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float const HIT_FRACTION = 0.6;
|
float const HIT_FRACTION = 0.6;
|
||||||
float const character_width = _text->getCharacterHeight()
|
float const character_width = _text->getCharacterHeight()
|
||||||
@@ -636,13 +627,7 @@ namespace canvas
|
|||||||
|
|
||||||
const GlyphQuads& quads = _textureGlyphQuadMap.begin()->second;
|
const GlyphQuads& quads = _textureGlyphQuadMap.begin()->second;
|
||||||
const GlyphQuads::Glyphs& glyphs = quads._glyphs;
|
const GlyphQuads::Glyphs& glyphs = quads._glyphs;
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,5)
|
const GlyphQuads::Coords2& coords = quads._coords;
|
||||||
GlyphQuads::Coords2 const& coords = quads._coords;
|
|
||||||
#else
|
|
||||||
GlyphQuads::Coords2 refCoords = quads._coords;
|
|
||||||
GlyphQuads::Coords2::element_type &coords = *refCoords.get();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const GlyphQuads::LineNumbers& line_numbers = quads._lineNumbers;
|
const GlyphQuads::LineNumbers& line_numbers = quads._lineNumbers;
|
||||||
|
|
||||||
float wr = _characterHeight / getCharacterAspectRatio();
|
float wr = _characterHeight / getCharacterAspectRatio();
|
||||||
@@ -740,7 +725,7 @@ namespace canvas
|
|||||||
Text::Text( const CanvasWeakPtr& canvas,
|
Text::Text( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent ):
|
Element* parent ):
|
||||||
Element(canvas, node, parent_style, parent),
|
Element(canvas, node, parent_style, parent),
|
||||||
_text( new Text::TextOSG(this) )
|
_text( new Text::TextOSG(this) )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace canvas
|
|||||||
Text( const CanvasWeakPtr& canvas,
|
Text( const CanvasWeakPtr& canvas,
|
||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
ElementWeakPtr parent = 0 );
|
Element* parent = 0 );
|
||||||
~Text();
|
~Text();
|
||||||
|
|
||||||
void setText(const char* text);
|
void setText(const char* text);
|
||||||
|
|||||||
@@ -34,10 +34,7 @@ namespace canvas
|
|||||||
public:
|
public:
|
||||||
struct ScreenPosition
|
struct ScreenPosition
|
||||||
{
|
{
|
||||||
ScreenPosition():
|
ScreenPosition() {}
|
||||||
x(0),
|
|
||||||
y(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
ScreenPosition(double x, double y):
|
ScreenPosition(double x, double y):
|
||||||
x(x),
|
x(x),
|
||||||
@@ -70,11 +67,8 @@ namespace canvas
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
HorizontalProjection():
|
HorizontalProjection():
|
||||||
_ref_lat(0),
|
_cos_rot(1),
|
||||||
_ref_lon(0),
|
_sin_rot(0),
|
||||||
_angle(0),
|
|
||||||
_cos_angle(1),
|
|
||||||
_sin_angle(0),
|
|
||||||
_range(5)
|
_range(5)
|
||||||
{
|
{
|
||||||
setScreenRange(200);
|
setScreenRange(200);
|
||||||
@@ -94,19 +88,9 @@ namespace canvas
|
|||||||
*/
|
*/
|
||||||
void setOrientation(float hdg)
|
void setOrientation(float hdg)
|
||||||
{
|
{
|
||||||
_angle = hdg;
|
|
||||||
|
|
||||||
hdg = SGMiscf::deg2rad(hdg);
|
hdg = SGMiscf::deg2rad(hdg);
|
||||||
_sin_angle = sin(hdg);
|
_sin_rot = sin(hdg);
|
||||||
_cos_angle = cos(hdg);
|
_cos_rot = cos(hdg);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get orientation/heading of the projection (in degree)
|
|
||||||
*/
|
|
||||||
float orientation() const
|
|
||||||
{
|
|
||||||
return _angle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRange(double range)
|
void setRange(double range)
|
||||||
@@ -130,8 +114,8 @@ namespace canvas
|
|||||||
pos.y *= scale;
|
pos.y *= scale;
|
||||||
return ScreenPosition
|
return ScreenPosition
|
||||||
(
|
(
|
||||||
_cos_angle * pos.x - _sin_angle * pos.y,
|
_cos_rot * pos.x - _sin_rot * pos.y,
|
||||||
-_sin_angle * pos.x - _cos_angle * pos.y
|
-_sin_rot * pos.x - _cos_rot * pos.y
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,11 +129,10 @@ namespace canvas
|
|||||||
*/
|
*/
|
||||||
virtual ScreenPosition project(double lat, double lon) const = 0;
|
virtual ScreenPosition project(double lat, double lon) const = 0;
|
||||||
|
|
||||||
double _ref_lat, ///<! Reference latitude (radian)
|
double _ref_lat,
|
||||||
_ref_lon, ///<! Reference latitude (radian)
|
_ref_lon,
|
||||||
_angle, ///<! Map rotation angle (degree)
|
_cos_rot,
|
||||||
_cos_angle,
|
_sin_rot,
|
||||||
_sin_angle,
|
|
||||||
_range;
|
_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -190,12 +190,6 @@ inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
|
|||||||
# define DEPRECATED
|
# define DEPRECATED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
# define SG_NO_RETURN [[noreturn]]
|
|
||||||
#else
|
|
||||||
# define SG_NO_RETURN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// No user modifiable definitions beyond here.
|
// No user modifiable definitions beyond here.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ typedef enum {
|
|||||||
SG_SOUND = 0x00200000,
|
SG_SOUND = 0x00200000,
|
||||||
SG_NAVAID = 0x00400000,
|
SG_NAVAID = 0x00400000,
|
||||||
SG_GUI = 0x00800000,
|
SG_GUI = 0x00800000,
|
||||||
SG_TERRASYNC = 0x01000000,
|
SG_UNDEFD = 0x01000000, // For range checking
|
||||||
SG_UNDEFD = 0x02000000, // For range checking
|
|
||||||
|
|
||||||
SG_ALL = 0xFFFFFFFF
|
SG_ALL = 0xFFFFFFFF
|
||||||
} sgDebugClass;
|
} sgDebugClass;
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ const char* debugClassToString(sgDebugClass c)
|
|||||||
case SG_SOUND: return "sound";
|
case SG_SOUND: return "sound";
|
||||||
case SG_NAVAID: return "navaid";
|
case SG_NAVAID: return "navaid";
|
||||||
case SG_GUI: return "gui";
|
case SG_GUI: return "gui";
|
||||||
case SG_TERRASYNC: return "terrasync";
|
|
||||||
default: return "unknown";
|
default: return "unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "jupiter.hxx"
|
#include "jupiter.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "mars.hxx"
|
#include "mars.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "mercury.hxx"
|
#include "mercury.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
# define exception c_exception
|
# define exception c_exception
|
||||||
#endif
|
#endif
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "neptune.hxx"
|
#include "neptune.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "saturn.hxx"
|
#include "saturn.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public:
|
|||||||
bool load( const SGPath& path );
|
bool load( const SGPath& path );
|
||||||
|
|
||||||
// stars
|
// stars
|
||||||
inline int getNumStars() const { return static_cast<int>(_stars.size()); }
|
inline int getNumStars() const { return _stars.size(); }
|
||||||
inline SGVec3d *getStars() { return &(_stars[0]); }
|
inline SGVec3d *getStars() { return &(_stars[0]); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "uranus.hxx"
|
#include "uranus.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include "venus.hxx"
|
#include "venus.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ set(HEADERS
|
|||||||
HTTPFileRequest.hxx
|
HTTPFileRequest.hxx
|
||||||
HTTPMemoryRequest.hxx
|
HTTPMemoryRequest.hxx
|
||||||
HTTPRequest.hxx
|
HTTPRequest.hxx
|
||||||
|
HTTPContentDecode.hxx
|
||||||
DAVMultiStatus.hxx
|
DAVMultiStatus.hxx
|
||||||
SVNRepository.hxx
|
SVNRepository.hxx
|
||||||
SVNDirectory.hxx
|
SVNDirectory.hxx
|
||||||
@@ -40,17 +41,13 @@ set(SOURCES
|
|||||||
HTTPFileRequest.cxx
|
HTTPFileRequest.cxx
|
||||||
HTTPMemoryRequest.cxx
|
HTTPMemoryRequest.cxx
|
||||||
HTTPRequest.cxx
|
HTTPRequest.cxx
|
||||||
|
HTTPContentDecode.cxx
|
||||||
DAVMultiStatus.cxx
|
DAVMultiStatus.cxx
|
||||||
SVNRepository.cxx
|
SVNRepository.cxx
|
||||||
SVNDirectory.cxx
|
SVNDirectory.cxx
|
||||||
SVNReportParser.cxx
|
SVNReportParser.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
if (NOT ENABLE_CURL)
|
|
||||||
list(APPEND SOURCES HTTPContentDecode.cxx)
|
|
||||||
list(APPEND HEADERS HTTPContentDecode.hxx)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
simgear_component(io io "${SOURCES}" "${HEADERS}")
|
simgear_component(io io "${SOURCES}" "${HEADERS}")
|
||||||
|
|
||||||
if(ENABLE_TESTS)
|
if(ENABLE_TESTS)
|
||||||
@@ -73,8 +70,8 @@ add_executable(decode_binobj decode_binobj.cxx)
|
|||||||
target_link_libraries(decode_binobj ${TEST_LIBS})
|
target_link_libraries(decode_binobj ${TEST_LIBS})
|
||||||
|
|
||||||
add_executable(test_binobj test_binobj.cxx)
|
add_executable(test_binobj test_binobj.cxx)
|
||||||
target_link_libraries(test_binobj ${TEST_LIBS})
|
target_link_libraries(test_binobj ${TEST_LIBS})
|
||||||
|
|
||||||
add_test(binobj ${EXECUTABLE_OUTPUT_PATH}/test_binobj)
|
add_test(binobj ${EXECUTABLE_OUTPUT_PATH}/test_binobj)
|
||||||
|
|
||||||
endif(ENABLE_TESTS)
|
endif(ENABLE_TESTS)
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (tagStack.empty()) {
|
if (tagStack.empty()) {
|
||||||
if (strcmp(name, DAV_MULTISTATUS_TAG)) {
|
if (strcmp(name, DAV_MULTISTATUS_TAG)) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "root element is not " <<
|
SG_LOG(SG_IO, SG_WARN, "root element is not " <<
|
||||||
DAV_MULTISTATUS_TAG << ", got:" << name);
|
DAV_MULTISTATUS_TAG << ", got:" << name);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ public:
|
|||||||
// not at the root element
|
// not at the root element
|
||||||
if (tagStack.back() == DAV_MULTISTATUS_TAG) {
|
if (tagStack.back() == DAV_MULTISTATUS_TAG) {
|
||||||
if (strcmp(name, DAV_RESPONSE_TAG)) {
|
if (strcmp(name, DAV_RESPONSE_TAG)) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "multistatus child is not response: saw:"
|
SG_LOG(SG_IO, SG_WARN, "multistatus child is not response: saw:"
|
||||||
<< name);
|
<< name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,7 +362,7 @@ void DAVMultiStatus::parseXML(const char* data, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!XML_Parse(_d->xmlParser, data, size, false)) {
|
if (!XML_Parse(_d->xmlParser, data, size, false)) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "DAV parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser))
|
SG_LOG(SG_IO, SG_WARN, "DAV parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser))
|
||||||
<< " at line:" << XML_GetCurrentLineNumber(_d->xmlParser)
|
<< " at line:" << XML_GetCurrentLineNumber(_d->xmlParser)
|
||||||
<< " column " << XML_GetCurrentColumnNumber(_d->xmlParser));
|
<< " column " << XML_GetCurrentColumnNumber(_d->xmlParser));
|
||||||
|
|
||||||
@@ -376,7 +376,7 @@ void DAVMultiStatus::finishParse()
|
|||||||
{
|
{
|
||||||
if (_d->parserInited) {
|
if (_d->parserInited) {
|
||||||
if (!XML_Parse(_d->xmlParser, NULL, 0, true)) {
|
if (!XML_Parse(_d->xmlParser, NULL, 0, true)) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "DAV parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser))
|
SG_LOG(SG_IO, SG_WARN, "DAV parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser))
|
||||||
<< " at line:" << XML_GetCurrentLineNumber(_d->xmlParser)
|
<< " at line:" << XML_GetCurrentLineNumber(_d->xmlParser)
|
||||||
<< " column " << XML_GetCurrentColumnNumber(_d->xmlParser));
|
<< " column " << XML_GetCurrentColumnNumber(_d->xmlParser));
|
||||||
_d->valid = false;
|
_d->valid = false;
|
||||||
|
|||||||
+134
-380
File diff suppressed because it is too large
Load Diff
+13
-20
@@ -38,15 +38,15 @@ namespace HTTP
|
|||||||
|
|
||||||
// forward decls
|
// forward decls
|
||||||
class Connection;
|
class Connection;
|
||||||
|
|
||||||
class Client
|
class Client
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Client();
|
Client();
|
||||||
~Client();
|
~Client();
|
||||||
|
|
||||||
void update(int waitTimeout = 0);
|
void update(int waitTimeout = 0);
|
||||||
|
|
||||||
void makeRequest(const Request_ptr& r);
|
void makeRequest(const Request_ptr& r);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,51 +68,44 @@ public:
|
|||||||
|
|
||||||
void setUserAgent(const std::string& ua);
|
void setUserAgent(const std::string& ua);
|
||||||
void setProxy(const std::string& proxy, int port, const std::string& auth = "");
|
void setProxy(const std::string& proxy, int port, const std::string& auth = "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the maximum permitted simultaneous connections
|
* Specify the maximum permitted simultaneous connections
|
||||||
* (default value is 1)
|
* (default value is 1)
|
||||||
*/
|
*/
|
||||||
void setMaxConnections(unsigned int maxCons);
|
void setMaxConnections(unsigned int maxCons);
|
||||||
|
|
||||||
const std::string& userAgent() const;
|
const std::string& userAgent() const;
|
||||||
|
|
||||||
const std::string& proxyHost() const;
|
const std::string& proxyHost() const;
|
||||||
|
|
||||||
const std::string& proxyAuth() const;
|
const std::string& proxyAuth() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* predicate, check if at least one connection is active, with at
|
* predicate, check if at least one connection is active, with at
|
||||||
* least one request active or queued.
|
* least one request active or queued.
|
||||||
*/
|
*/
|
||||||
bool hasActiveRequests() const;
|
bool hasActiveRequests() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* crude tracking of bytes-per-second transferred over the socket.
|
* crude tracking of bytes-per-second transferred over the socket.
|
||||||
* suitable for user feedback and rough profiling, nothing more.
|
* suitable for user feedback and rough profiling, nothing more.
|
||||||
*/
|
*/
|
||||||
unsigned int transferRateBytesPerSec() const;
|
unsigned int transferRateBytesPerSec() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* total bytes downloaded by this HTTP client, for bandwidth usage
|
* total bytes downloaded by this HTTP client, for bandwidth usage
|
||||||
* monitoring
|
* monitoring
|
||||||
*/
|
*/
|
||||||
uint64_t totalBytesDownloaded() const;
|
uint64_t totalBytesDownloaded() const;
|
||||||
|
|
||||||
void debugDumpRequests();
|
|
||||||
private:
|
private:
|
||||||
// libCurl callbacks
|
|
||||||
static size_t requestWriteCallback(char *ptr, size_t size, size_t nmemb, void *userdata);
|
|
||||||
static size_t requestReadCallback(char *ptr, size_t size, size_t nmemb, void *userdata);
|
|
||||||
static size_t requestHeaderCallback(char *buffer, size_t size, size_t nitems, void *userdata);
|
|
||||||
|
|
||||||
void requestFinished(Connection* con);
|
void requestFinished(Connection* con);
|
||||||
|
|
||||||
void receivedBytes(unsigned int count);
|
void receivedBytes(unsigned int count);
|
||||||
|
|
||||||
friend class Connection;
|
friend class Connection;
|
||||||
friend class Request;
|
friend class Request;
|
||||||
|
|
||||||
class ClientPrivate;
|
class ClientPrivate;
|
||||||
std::auto_ptr<ClientPrivate> d;
|
std::auto_ptr<ClientPrivate> d;
|
||||||
};
|
};
|
||||||
|
|||||||
+11
-18
@@ -133,25 +133,19 @@ void Request::responseStart(const std::string& r)
|
|||||||
const int maxSplit = 2; // HTTP/1.1 nnn reason-string
|
const int maxSplit = 2; // HTTP/1.1 nnn reason-string
|
||||||
string_list parts = strutils::split(r, NULL, maxSplit);
|
string_list parts = strutils::split(r, NULL, maxSplit);
|
||||||
if (parts.size() != 3) {
|
if (parts.size() != 3) {
|
||||||
throw sg_io_exception("bad HTTP response:" + r);
|
throw sg_io_exception("bad HTTP response");
|
||||||
}
|
}
|
||||||
|
|
||||||
_responseVersion = decodeHTTPVersion(parts[0]);
|
_responseVersion = decodeHTTPVersion(parts[0]);
|
||||||
_responseStatus = strutils::to_int(parts[1]);
|
_responseStatus = strutils::to_int(parts[1]);
|
||||||
_responseReason = parts[2];
|
_responseReason = parts[2];
|
||||||
|
|
||||||
setReadyState(STATUS_RECEIVED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void Request::responseHeader(const std::string& key, const std::string& value)
|
void Request::responseHeader(const std::string& key, const std::string& value)
|
||||||
{
|
{
|
||||||
if( key == "connection" ) {
|
if( key == "connection" )
|
||||||
_willClose = (value.find("close") != std::string::npos);
|
_willClose = (value.find("close") != std::string::npos);
|
||||||
} else if (key == "content-length") {
|
|
||||||
int sz = strutils::to_int(value);
|
|
||||||
setResponseLength(sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
_responseHeaders[key] = value;
|
_responseHeaders[key] = value;
|
||||||
}
|
}
|
||||||
@@ -213,7 +207,7 @@ std::string Request::scheme() const
|
|||||||
if (firstColon > 0) {
|
if (firstColon > 0) {
|
||||||
return url().substr(0, firstColon);
|
return url().substr(0, firstColon);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""; // couldn't parse scheme
|
return ""; // couldn't parse scheme
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,20 +219,20 @@ std::string Request::path() const
|
|||||||
if (schemeEnd < 0) {
|
if (schemeEnd < 0) {
|
||||||
return ""; // couldn't parse scheme
|
return ""; // couldn't parse scheme
|
||||||
}
|
}
|
||||||
|
|
||||||
int hostEnd = u.find('/', schemeEnd + 3);
|
int hostEnd = u.find('/', schemeEnd + 3);
|
||||||
if (hostEnd < 0) {
|
if (hostEnd < 0) {
|
||||||
// couldn't parse host, or URL looks like 'http://foo.com' (no trailing '/')
|
// couldn't parse host, or URL looks like 'http://foo.com' (no trailing '/')
|
||||||
// fixup to root resource path: '/'
|
// fixup to root resource path: '/'
|
||||||
return "/";
|
return "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
int query = u.find('?', hostEnd + 1);
|
int query = u.find('?', hostEnd + 1);
|
||||||
if (query < 0) {
|
if (query < 0) {
|
||||||
// all remainder of URL is path
|
// all remainder of URL is path
|
||||||
return u.substr(hostEnd);
|
return u.substr(hostEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return u.substr(hostEnd, query - hostEnd);
|
return u.substr(hostEnd, query - hostEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +244,7 @@ std::string Request::query() const
|
|||||||
if (query < 0) {
|
if (query < 0) {
|
||||||
return ""; //no query string found
|
return ""; //no query string found
|
||||||
}
|
}
|
||||||
|
|
||||||
return u.substr(query); //includes question mark
|
return u.substr(query); //includes question mark
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,7 +319,6 @@ unsigned int Request::responseLength() const
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void Request::setFailure(int code, const std::string& reason)
|
void Request::setFailure(int code, const std::string& reason)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_IO, SG_WARN, "HTTP request: set failure:" << code << " reason " << reason);
|
|
||||||
_responseStatus = code;
|
_responseStatus = code;
|
||||||
_responseReason = reason;
|
_responseReason = reason;
|
||||||
|
|
||||||
|
|||||||
+14
-15
@@ -50,7 +50,6 @@ public:
|
|||||||
{
|
{
|
||||||
UNSENT = 0,
|
UNSENT = 0,
|
||||||
OPENED,
|
OPENED,
|
||||||
STATUS_RECEIVED,
|
|
||||||
HEADERS_RECEIVED,
|
HEADERS_RECEIVED,
|
||||||
LOADING,
|
LOADING,
|
||||||
DONE,
|
DONE,
|
||||||
@@ -125,19 +124,19 @@ public:
|
|||||||
void setBodyData( const SGPropertyNode* data );
|
void setBodyData( const SGPropertyNode* data );
|
||||||
|
|
||||||
virtual void setUrl(const std::string& url);
|
virtual void setUrl(const std::string& url);
|
||||||
|
|
||||||
virtual std::string method() const
|
virtual std::string method() const
|
||||||
{ return _method; }
|
{ return _method; }
|
||||||
virtual std::string url() const
|
virtual std::string url() const
|
||||||
{ return _url; }
|
{ return _url; }
|
||||||
|
|
||||||
virtual std::string scheme() const;
|
virtual std::string scheme() const;
|
||||||
virtual std::string path() const;
|
virtual std::string path() const;
|
||||||
virtual std::string host() const;
|
virtual std::string host() const;
|
||||||
virtual std::string hostAndPort() const;
|
virtual std::string hostAndPort() const;
|
||||||
virtual unsigned short port() const;
|
virtual unsigned short port() const;
|
||||||
virtual std::string query() const;
|
virtual std::string query() const;
|
||||||
|
|
||||||
StringMap const& responseHeaders() const
|
StringMap const& responseHeaders() const
|
||||||
{ return _responseHeaders; }
|
{ return _responseHeaders; }
|
||||||
|
|
||||||
@@ -145,13 +144,13 @@ public:
|
|||||||
|
|
||||||
virtual int responseCode() const
|
virtual int responseCode() const
|
||||||
{ return _responseStatus; }
|
{ return _responseStatus; }
|
||||||
|
|
||||||
virtual std::string responseReason() const
|
virtual std::string responseReason() const
|
||||||
{ return _responseReason; }
|
{ return _responseReason; }
|
||||||
|
|
||||||
void setResponseLength(unsigned int l);
|
void setResponseLength(unsigned int l);
|
||||||
virtual unsigned int responseLength() const;
|
virtual unsigned int responseLength() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if request contains body data.
|
* Check if request contains body data.
|
||||||
*/
|
*/
|
||||||
@@ -166,32 +165,32 @@ public:
|
|||||||
* Retrieve the size of the request body.
|
* Retrieve the size of the request body.
|
||||||
*/
|
*/
|
||||||
virtual size_t bodyLength() const;
|
virtual size_t bodyLength() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the body data bytes. Will be passed the maximum body bytes
|
* Retrieve the body data bytes. Will be passed the maximum body bytes
|
||||||
* to return in the buffer, and must return the actual number
|
* to return in the buffer, and must return the actual number
|
||||||
* of bytes written.
|
* of bytes written.
|
||||||
*/
|
*/
|
||||||
virtual size_t getBodyData(char* s, size_t offset, size_t max_count) const;
|
virtual size_t getBodyData(char* s, size_t offset, size_t max_count) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* running total of body bytes received so far. Can be used
|
* running total of body bytes received so far. Can be used
|
||||||
* to generate a completion percentage, if the response length is
|
* to generate a completion percentage, if the response length is
|
||||||
* known.
|
* known.
|
||||||
*/
|
*/
|
||||||
unsigned int responseBytesReceived() const
|
unsigned int responseBytesReceived() const
|
||||||
{ return _receivedBodyBytes; }
|
{ return _receivedBodyBytes; }
|
||||||
|
|
||||||
enum HTTPVersion {
|
enum HTTPVersion {
|
||||||
HTTP_VERSION_UNKNOWN = 0,
|
HTTP_VERSION_UNKNOWN = 0,
|
||||||
HTTP_0_x, // 0.9 or similar
|
HTTP_0_x, // 0.9 or similar
|
||||||
HTTP_1_0,
|
HTTP_1_0,
|
||||||
HTTP_1_1
|
HTTP_1_1
|
||||||
};
|
};
|
||||||
|
|
||||||
HTTPVersion responseVersion() const
|
HTTPVersion responseVersion() const
|
||||||
{ return _responseVersion; }
|
{ return _responseVersion; }
|
||||||
|
|
||||||
ReadyState readyState() const { return _ready_state; }
|
ReadyState readyState() const { return _ready_state; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -227,7 +226,7 @@ private:
|
|||||||
friend class Client;
|
friend class Client;
|
||||||
friend class Connection;
|
friend class Connection;
|
||||||
friend class ContentDecoder;
|
friend class ContentDecoder;
|
||||||
|
|
||||||
Request(const Request&); // = delete;
|
Request(const Request&); // = delete;
|
||||||
Request& operator=(const Request&); // = delete;
|
Request& operator=(const Request&); // = delete;
|
||||||
|
|
||||||
|
|||||||
@@ -96,14 +96,14 @@ void SVNDirectory::parseCache()
|
|||||||
LineState lineState = LINESTATE_HREF;
|
LineState lineState = LINESTATE_HREF;
|
||||||
std::ifstream file(p.c_str());
|
std::ifstream file(p.c_str());
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "unable to open cache file for reading:" << p);
|
SG_LOG(SG_IO, SG_WARN, "unable to open cache file for reading:" << p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool doneSelf = false;
|
bool doneSelf = false;
|
||||||
|
|
||||||
file.getline(href, 1024);
|
file.getline(href, 1024);
|
||||||
if (strcmp(CACHE_VERSION_4_TOKEN, href)) {
|
if (strcmp(CACHE_VERSION_4_TOKEN, href)) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "invalid cache file [missing header token]:" << p << " '" << href << "'");
|
SG_LOG(SG_IO, SG_WARN, "invalid cache file [missing header token]:" << p << " '" << href << "'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ void SVNDirectory::writeCache()
|
|||||||
void SVNDirectory::setBaseUrl(const string& url)
|
void SVNDirectory::setBaseUrl(const string& url)
|
||||||
{
|
{
|
||||||
if (_parent) {
|
if (_parent) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "setting base URL on non-root directory " << url);
|
SG_LOG(SG_IO, SG_ALERT, "setting base URL on non-root directory " << url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,6 +239,7 @@ void SVNDirectory::deleteChildByName(const std::string& nm)
|
|||||||
{
|
{
|
||||||
DAVResource* child = dav->childWithName(nm);
|
DAVResource* child = dav->childWithName(nm);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
|
// std::cerr << "ZZZ: deleteChildByName: unknown:" << nm << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,24 +247,17 @@ void SVNDirectory::deleteChildByName(const std::string& nm)
|
|||||||
|
|
||||||
if (child->isCollection()) {
|
if (child->isCollection()) {
|
||||||
Dir d(path);
|
Dir d(path);
|
||||||
bool ok = d.remove(true);
|
d.remove(true);
|
||||||
if (!ok) {
|
|
||||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "SVNDirectory::deleteChildByName: failed to remove dir:"
|
|
||||||
<< nm << " at path:\n\t" << path);
|
|
||||||
}
|
|
||||||
|
|
||||||
DirectoryList::iterator it = findChildDir(nm);
|
DirectoryList::iterator it = findChildDir(nm);
|
||||||
if (it != _children.end()) {
|
if (it != _children.end()) {
|
||||||
SVNDirectory* c = *it;
|
SVNDirectory* c = *it;
|
||||||
|
// std::cout << "YYY: deleting SVNDirectory for:" << nm << std::endl;
|
||||||
delete c;
|
delete c;
|
||||||
_children.erase(it);
|
_children.erase(it);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool ok = path.remove();
|
path.remove();
|
||||||
if (!ok) {
|
|
||||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "SVNDirectory::deleteChildByName: failed to remove path:" << nm
|
|
||||||
<< " at path:\n\t" << path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dav->removeChild(child);
|
dav->removeChild(child);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public:
|
|||||||
|
|
||||||
void updateFailed(HTTP::Request* req, SVNRepository::ResultCode err)
|
void updateFailed(HTTP::Request* req, SVNRepository::ResultCode err)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "SVN: failed to update from:" << req->url()
|
SG_LOG(SG_IO, SG_WARN, "SVN: failed to update from:" << req->url()
|
||||||
<< "\n(repository:" << p->baseUrl() << ")");
|
<< "\n(repository:" << p->baseUrl() << ")");
|
||||||
isUpdating = false;
|
isUpdating = false;
|
||||||
status = err;
|
status = err;
|
||||||
@@ -120,7 +120,6 @@ namespace { // anonmouse
|
|||||||
Request(repo->baseUrl, "PROPFIND"),
|
Request(repo->baseUrl, "PROPFIND"),
|
||||||
_repo(repo)
|
_repo(repo)
|
||||||
{
|
{
|
||||||
assert(repo);
|
|
||||||
requestHeader("Depth") = "0";
|
requestHeader("Depth") = "0";
|
||||||
setBodyData( PROPFIND_REQUEST_BODY,
|
setBodyData( PROPFIND_REQUEST_BODY,
|
||||||
"application/xml; charset=\"utf-8\"" );
|
"application/xml; charset=\"utf-8\"" );
|
||||||
@@ -134,13 +133,11 @@ namespace { // anonmouse
|
|||||||
} else if (responseCode() == 404) {
|
} else if (responseCode() == 404) {
|
||||||
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_NOT_FOUND);
|
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_NOT_FOUND);
|
||||||
} else {
|
} else {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "request for:" << url() <<
|
SG_LOG(SG_IO, SG_WARN, "request for:" << url() <<
|
||||||
" return code " << responseCode());
|
" return code " << responseCode());
|
||||||
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_SOCKET);
|
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_SOCKET);
|
||||||
_repo = NULL;
|
_repo = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Request::responseHeadersComplete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDone()
|
virtual void onDone()
|
||||||
@@ -231,7 +228,7 @@ protected:
|
|||||||
_repo->updateFailed(this, SVNRepository::SVN_ERROR_NOT_FOUND);
|
_repo->updateFailed(this, SVNRepository::SVN_ERROR_NOT_FOUND);
|
||||||
_failed = true;
|
_failed = true;
|
||||||
} else {
|
} else {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "SVN: request for:" << url() <<
|
SG_LOG(SG_IO, SG_WARN, "SVN: request for:" << url() <<
|
||||||
" got HTTP status " << responseCode());
|
" got HTTP status " << responseCode());
|
||||||
_repo->updateFailed(this, SVNRepository::SVN_ERROR_HTTP);
|
_repo->updateFailed(this, SVNRepository::SVN_ERROR_HTTP);
|
||||||
_failed = true;
|
_failed = true;
|
||||||
@@ -331,7 +328,7 @@ void SVNRepository::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_d->targetRevision == rootDir()->cachedRevision()) {
|
if (_d->targetRevision == rootDir()->cachedRevision()) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_DEBUG, baseUrl() << " in sync at version " << _d->targetRevision);
|
SG_LOG(SG_IO, SG_DEBUG, baseUrl() << " in sync at version " << _d->targetRevision);
|
||||||
_d->isUpdating = false;
|
_d->isUpdating = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -375,7 +372,7 @@ void SVNRepoPrivate::propFindComplete(HTTP::Request* req, DAVCollection* c)
|
|||||||
void SVNRepoPrivate::propFindFailed(HTTP::Request *req, SVNRepository::ResultCode err)
|
void SVNRepoPrivate::propFindFailed(HTTP::Request *req, SVNRepository::ResultCode err)
|
||||||
{
|
{
|
||||||
if (err != SVNRepository::SVN_ERROR_NOT_FOUND) {
|
if (err != SVNRepository::SVN_ERROR_NOT_FOUND) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_WARN, "PropFind failed for:" << req->url());
|
SG_LOG(SG_IO, SG_WARN, "PropFind failed for:" << req->url());
|
||||||
}
|
}
|
||||||
|
|
||||||
isUpdating = false;
|
isUpdating = false;
|
||||||
|
|||||||
@@ -227,13 +227,6 @@ void NetChannel::handleAccept (void) {
|
|||||||
|
|
||||||
void NetChannel::handleError (int error)
|
void NetChannel::handleError (int error)
|
||||||
{
|
{
|
||||||
if (error == EINPROGRESS) {
|
|
||||||
// this shoudl never happen, because we should use isNonBlocking to check
|
|
||||||
// such error codes.
|
|
||||||
SG_LOG(SG_IO, SG_WARN, "Got EINPROGRESS at NetChannel::handleError: suggests broken logic somewhere else");
|
|
||||||
return; // not an actual error, don't warn
|
|
||||||
}
|
|
||||||
|
|
||||||
// warn about address lookup failures seperately, don't warn again.
|
// warn about address lookup failures seperately, don't warn again.
|
||||||
// (and we (ab-)use ENOENT to mean 'name not found'.
|
// (and we (ab-)use ENOENT to mean 'name not found'.
|
||||||
if (error != ENOENT) {
|
if (error != ENOENT) {
|
||||||
@@ -258,11 +251,6 @@ NetChannelPoller::removeChannel(NetChannel* channel)
|
|||||||
assert(channel->poller == this);
|
assert(channel->poller == this);
|
||||||
channel->poller = NULL;
|
channel->poller = NULL;
|
||||||
|
|
||||||
// portability: MSVC throws assertion failure when empty
|
|
||||||
if (channels.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelList::iterator it = channels.begin();
|
ChannelList::iterator it = channels.begin();
|
||||||
for (; it != channels.end(); ++it) {
|
for (; it != channels.end(); ++it) {
|
||||||
if (*it == channel) {
|
if (*it == channel) {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib> // for atoi
|
#include <cstdlib> // for atoi
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
|||||||
+102
-227
@@ -3,23 +3,15 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <boost/algorithm/string/case_conv.hpp>
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
|
|
||||||
#include <simgear/simgear_config.h>
|
|
||||||
|
|
||||||
#include "HTTPClient.hxx"
|
#include "HTTPClient.hxx"
|
||||||
#include "HTTPRequest.hxx"
|
#include "HTTPRequest.hxx"
|
||||||
|
|
||||||
#include <simgear/io/sg_netChat.hxx>
|
#include <simgear/io/sg_netChat.hxx>
|
||||||
#include <simgear/misc/strutils.hxx>
|
#include <simgear/misc/strutils.hxx>
|
||||||
#include <simgear/timing/timestamp.hxx>
|
#include <simgear/timing/timestamp.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
|
||||||
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
#include <curl/multi.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::cerr;
|
using std::cerr;
|
||||||
@@ -54,7 +46,7 @@ char body2[body2Size];
|
|||||||
cerr << "failed:" << #a << endl; \
|
cerr << "failed:" << #a << endl; \
|
||||||
exit(1); \
|
exit(1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestRequest : public HTTP::Request
|
class TestRequest : public HTTP::Request
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -62,43 +54,41 @@ public:
|
|||||||
bool failed;
|
bool failed;
|
||||||
string bodyData;
|
string bodyData;
|
||||||
|
|
||||||
TestRequest(const std::string& url, const std::string method = "GET") :
|
TestRequest(const std::string& url, const std::string method = "GET") :
|
||||||
HTTP::Request(url, method),
|
HTTP::Request(url, method),
|
||||||
complete(false),
|
complete(false)
|
||||||
failed(false)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<string, string> headers;
|
std::map<string, string> headers;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void onDone()
|
virtual void onDone()
|
||||||
{
|
{
|
||||||
complete = true;
|
complete = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onFail()
|
virtual void onFail()
|
||||||
{
|
{
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void gotBodyData(const char* s, int n)
|
virtual void gotBodyData(const char* s, int n)
|
||||||
{
|
{
|
||||||
//std::cout << "got body data:'" << string(s, n) << "'" <<std::endl;
|
//std::cout << "got body data:'" << string(s, n) << "'" <<std::endl;
|
||||||
bodyData += string(s, n);
|
bodyData += string(s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void responseHeader(const string& header, const string& value)
|
virtual void responseHeader(const string& header, const string& value)
|
||||||
{
|
{
|
||||||
Request::responseHeader(header, value);
|
|
||||||
headers[header] = value;
|
headers[header] = value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestServerChannel : public NetChat
|
class TestServerChannel : public NetChat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum State
|
enum State
|
||||||
{
|
{
|
||||||
STATE_IDLE = 0,
|
STATE_IDLE = 0,
|
||||||
@@ -106,19 +96,19 @@ public:
|
|||||||
STATE_CLOSING,
|
STATE_CLOSING,
|
||||||
STATE_REQUEST_BODY
|
STATE_REQUEST_BODY
|
||||||
};
|
};
|
||||||
|
|
||||||
TestServerChannel()
|
TestServerChannel()
|
||||||
{
|
{
|
||||||
state = STATE_IDLE;
|
state = STATE_IDLE;
|
||||||
setTerminator("\r\n");
|
setTerminator("\r\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void collectIncomingData(const char* s, int n)
|
virtual void collectIncomingData(const char* s, int n)
|
||||||
{
|
{
|
||||||
buffer += string(s, n);
|
buffer += string(s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void foundTerminator(void)
|
virtual void foundTerminator(void)
|
||||||
{
|
{
|
||||||
if (state == STATE_IDLE) {
|
if (state == STATE_IDLE) {
|
||||||
@@ -128,16 +118,16 @@ public:
|
|||||||
cerr << "malformed request:" << buffer << endl;
|
cerr << "malformed request:" << buffer << endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
method = line[0];
|
method = line[0];
|
||||||
path = line[1];
|
path = line[1];
|
||||||
|
|
||||||
string::size_type queryPos = path.find('?');
|
string::size_type queryPos = path.find('?');
|
||||||
if (queryPos != string::npos) {
|
if (queryPos != string::npos) {
|
||||||
parseArgs(path.substr(queryPos + 1));
|
parseArgs(path.substr(queryPos + 1));
|
||||||
path = path.substr(0, queryPos);
|
path = path.substr(0, queryPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
httpVersion = line[2];
|
httpVersion = line[2];
|
||||||
requestHeaders.clear();
|
requestHeaders.clear();
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
@@ -148,10 +138,10 @@ public:
|
|||||||
receivedRequestHeaders();
|
receivedRequestHeaders();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type colonPos = buffer.find(':');
|
string::size_type colonPos = buffer.find(':');
|
||||||
if (colonPos == string::npos) {
|
if (colonPos == string::npos) {
|
||||||
cerr << "test malformed HTTP response header:" << buffer << endl;
|
cerr << "malformed HTTP response header:" << buffer << endl;
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -166,8 +156,8 @@ public:
|
|||||||
} else if (state == STATE_CLOSING) {
|
} else if (state == STATE_CLOSING) {
|
||||||
// ignore!
|
// ignore!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parseArgs(const string& argData)
|
void parseArgs(const string& argData)
|
||||||
{
|
{
|
||||||
string_list argv = strutils::split(argData, "&");
|
string_list argv = strutils::split(argData, "&");
|
||||||
@@ -183,10 +173,11 @@ public:
|
|||||||
args[key] = value;
|
args[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void receivedRequestHeaders()
|
void receivedRequestHeaders()
|
||||||
{
|
{
|
||||||
state = STATE_IDLE;
|
state = STATE_IDLE;
|
||||||
|
|
||||||
if (path == "/test1") {
|
if (path == "/test1") {
|
||||||
string contentStr(BODY1);
|
string contentStr(BODY1);
|
||||||
stringstream d;
|
stringstream d;
|
||||||
@@ -214,7 +205,7 @@ public:
|
|||||||
} else if (path == "/test_headers") {
|
} else if (path == "/test_headers") {
|
||||||
COMPARE(requestHeaders["X-Foo"], string("Bar"));
|
COMPARE(requestHeaders["X-Foo"], string("Bar"));
|
||||||
COMPARE(requestHeaders["X-AnotherHeader"], string("A longer value"));
|
COMPARE(requestHeaders["X-AnotherHeader"], string("A longer value"));
|
||||||
|
|
||||||
string contentStr(BODY1);
|
string contentStr(BODY1);
|
||||||
stringstream d;
|
stringstream d;
|
||||||
d << "HTTP/1.1 " << 200 << " " << reasonForCode(200) << "\r\n";
|
d << "HTTP/1.1 " << 200 << " " << reasonForCode(200) << "\r\n";
|
||||||
@@ -244,11 +235,11 @@ public:
|
|||||||
if (requestHeaders["Host"] != "www.google.com") {
|
if (requestHeaders["Host"] != "www.google.com") {
|
||||||
sendErrorResponse(400, true, "bad destination");
|
sendErrorResponse(400, true, "bad destination");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestHeaders["Proxy-Authorization"] != string()) {
|
if (requestHeaders["Proxy-Authorization"] != string()) {
|
||||||
sendErrorResponse(401, false, "bad auth, not empty"); // shouldn't supply auth
|
sendErrorResponse(401, false, "bad auth"); // shouldn't supply auth
|
||||||
}
|
}
|
||||||
|
|
||||||
sendBody2();
|
sendBody2();
|
||||||
} else if (path == "http://www.google.com/test3") {
|
} else if (path == "http://www.google.com/test3") {
|
||||||
// proxy test
|
// proxy test
|
||||||
@@ -256,28 +247,8 @@ public:
|
|||||||
sendErrorResponse(400, true, "bad destination");
|
sendErrorResponse(400, true, "bad destination");
|
||||||
}
|
}
|
||||||
|
|
||||||
string credentials = requestHeaders["Proxy-Authorization"];
|
if (requestHeaders["Proxy-Authorization"] != "ABCDEF") {
|
||||||
if (credentials.substr(0, 5) != "Basic") {
|
sendErrorResponse(401, false, "bad auth"); // forbidden
|
||||||
// request basic auth
|
|
||||||
stringstream d;
|
|
||||||
d << "HTTP/1.1 " << 407 << " " << reasonForCode(407) << "\r\n";
|
|
||||||
d << "WWW-Authenticate: Basic real=\"simgear\"\r\n";
|
|
||||||
d << "\r\n"; // final CRLF to terminate the headers
|
|
||||||
push(d.str().c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<unsigned char> userAndPass;
|
|
||||||
strutils::decodeBase64(credentials.substr(6), userAndPass);
|
|
||||||
std::string decodedUserPass((char*) userAndPass.data(), userAndPass.size());
|
|
||||||
|
|
||||||
if (decodedUserPass != "johndoe:swordfish") {
|
|
||||||
std::map<string, string>::const_iterator it;
|
|
||||||
for (it = requestHeaders.begin(); it != requestHeaders.end(); ++it) {
|
|
||||||
cerr << "header:" << it->first << " = " << it->second << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendErrorResponse(401, false, "bad auth, not as set"); // forbidden
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendBody2();
|
sendBody2();
|
||||||
@@ -301,12 +272,6 @@ public:
|
|||||||
d << contentStr;
|
d << contentStr;
|
||||||
push(d.str().c_str());
|
push(d.str().c_str());
|
||||||
closeAfterSending();
|
closeAfterSending();
|
||||||
} else if (path == "/test_abrupt_close") {
|
|
||||||
// simulate server doing socket close before sending any
|
|
||||||
// response - this used to cause a TerraSync failure since we
|
|
||||||
// would get stuck restarting the request
|
|
||||||
closeAfterSending();
|
|
||||||
|
|
||||||
} else if (path == "/test_args") {
|
} else if (path == "/test_args") {
|
||||||
if ((args["foo"] != "abc") || (args["bar"] != "1234") || (args["username"] != "johndoe")) {
|
if ((args["foo"] != "abc") || (args["bar"] != "1234") || (args["username"] != "johndoe")) {
|
||||||
sendErrorResponse(400, true, "bad arguments");
|
sendErrorResponse(400, true, "bad arguments");
|
||||||
@@ -326,78 +291,43 @@ public:
|
|||||||
sendErrorResponse(400, true, "bad content type");
|
sendErrorResponse(400, true, "bad content type");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
requestContentLength = strutils::to_int(requestHeaders["Content-Length"]);
|
requestContentLength = strutils::to_int(requestHeaders["Content-Length"]);
|
||||||
setByteCount(requestContentLength);
|
setByteCount(requestContentLength);
|
||||||
state = STATE_REQUEST_BODY;
|
state = STATE_REQUEST_BODY;
|
||||||
} else if ((path == "/test_put") || (path == "/test_create")) {
|
|
||||||
if (requestHeaders["Content-Type"] != "x-application/foobar") {
|
|
||||||
cerr << "bad content type: '" << requestHeaders["Content-Type"] << "'" << endl;
|
|
||||||
sendErrorResponse(400, true, "bad content type");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
requestContentLength = strutils::to_int(requestHeaders["Content-Length"]);
|
|
||||||
setByteCount(requestContentLength);
|
|
||||||
state = STATE_REQUEST_BODY;
|
|
||||||
} else {
|
} else {
|
||||||
sendErrorResponse(404, false, "");
|
sendErrorResponse(404, false, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void closeAfterSending()
|
void closeAfterSending()
|
||||||
{
|
{
|
||||||
state = STATE_CLOSING;
|
state = STATE_CLOSING;
|
||||||
closeWhenDone();
|
closeWhenDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
void receivedBody()
|
void receivedBody()
|
||||||
{
|
{
|
||||||
state = STATE_IDLE;
|
state = STATE_IDLE;
|
||||||
if (method == "POST") {
|
if (method == "POST") {
|
||||||
parseArgs(buffer);
|
parseArgs(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path == "/test_post") {
|
if (path == "/test_post") {
|
||||||
if ((args["foo"] != "abc") || (args["bar"] != "1234") || (args["username"] != "johndoe")) {
|
if ((args["foo"] != "abc") || (args["bar"] != "1234") || (args["username"] != "johndoe")) {
|
||||||
sendErrorResponse(400, true, "bad arguments");
|
sendErrorResponse(400, true, "bad arguments");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stringstream d;
|
stringstream d;
|
||||||
d << "HTTP/1.1 " << 204 << " " << reasonForCode(204) << "\r\n";
|
d << "HTTP/1.1 " << 204 << " " << reasonForCode(204) << "\r\n";
|
||||||
d << "\r\n"; // final CRLF to terminate the headers
|
d << "\r\n"; // final CRLF to terminate the headers
|
||||||
push(d.str().c_str());
|
push(d.str().c_str());
|
||||||
} else if (path == "/test_put") {
|
|
||||||
std::cerr << "sending PUT response" << std::endl;
|
cerr << "sent 204 response ok" << endl;
|
||||||
|
|
||||||
COMPARE(buffer, BODY3);
|
|
||||||
stringstream d;
|
|
||||||
d << "HTTP/1.1 " << 204 << " " << reasonForCode(204) << "\r\n";
|
|
||||||
d << "\r\n"; // final CRLF to terminate the headers
|
|
||||||
push(d.str().c_str());
|
|
||||||
} else if (path == "/test_create") {
|
|
||||||
std::cerr << "sending create response" << std::endl;
|
|
||||||
|
|
||||||
std::string entityStr = "http://localhost:2000/something.txt";
|
|
||||||
|
|
||||||
COMPARE(buffer, BODY3);
|
|
||||||
stringstream d;
|
|
||||||
d << "HTTP/1.1 " << 201 << " " << reasonForCode(201) << "\r\n";
|
|
||||||
d << "Location:" << entityStr << "\r\n";
|
|
||||||
d << "Content-Length:" << entityStr.size() << "\r\n";
|
|
||||||
d << "\r\n"; // final CRLF to terminate the headers
|
|
||||||
d << entityStr;
|
|
||||||
|
|
||||||
push(d.str().c_str());
|
|
||||||
} else {
|
|
||||||
std::cerr << "weird URL " << path << std::endl;
|
|
||||||
sendErrorResponse(400, true, "bad URL:" + path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendBody2()
|
void sendBody2()
|
||||||
{
|
{
|
||||||
stringstream d;
|
stringstream d;
|
||||||
@@ -407,36 +337,32 @@ public:
|
|||||||
push(d.str().c_str());
|
push(d.str().c_str());
|
||||||
bufferSend(body2, body2Size);
|
bufferSend(body2, body2Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendErrorResponse(int code, bool close, string content)
|
void sendErrorResponse(int code, bool close, string content)
|
||||||
{
|
{
|
||||||
cerr << "sending error " << code << " for " << path << endl;
|
cerr << "sending error " << code << " for " << path << endl;
|
||||||
cerr << "\tcontent:" << content << endl;
|
|
||||||
|
|
||||||
stringstream headerData;
|
stringstream headerData;
|
||||||
headerData << "HTTP/1.1 " << code << " " << reasonForCode(code) << "\r\n";
|
headerData << "HTTP/1.1 " << code << " " << reasonForCode(code) << "\r\n";
|
||||||
headerData << "Content-Length:" << content.size() << "\r\n";
|
headerData << "Content-Length:" << content.size() << "\r\n";
|
||||||
headerData << "\r\n"; // final CRLF to terminate the headers
|
headerData << "\r\n"; // final CRLF to terminate the headers
|
||||||
push(headerData.str().c_str());
|
push(headerData.str().c_str());
|
||||||
push(content.c_str());
|
push(content.c_str());
|
||||||
|
|
||||||
if (close) {
|
if (close) {
|
||||||
closeWhenDone();
|
closeWhenDone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string reasonForCode(int code)
|
string reasonForCode(int code)
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 200: return "OK";
|
case 200: return "OK";
|
||||||
case 201: return "Created";
|
|
||||||
case 204: return "no content";
|
case 204: return "no content";
|
||||||
case 404: return "not found";
|
case 404: return "not found";
|
||||||
case 407: return "proxy authentication required";
|
|
||||||
default: return "unknown code";
|
default: return "unknown code";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
State state;
|
State state;
|
||||||
string buffer;
|
string buffer;
|
||||||
string method;
|
string method;
|
||||||
@@ -450,22 +376,20 @@ public:
|
|||||||
class TestServer : public NetChannel
|
class TestServer : public NetChannel
|
||||||
{
|
{
|
||||||
simgear::NetChannelPoller _poller;
|
simgear::NetChannelPoller _poller;
|
||||||
public:
|
public:
|
||||||
TestServer()
|
TestServer()
|
||||||
{
|
{
|
||||||
Socket::initSockets();
|
|
||||||
|
|
||||||
open();
|
open();
|
||||||
bind(NULL, 2000); // localhost, any port
|
bind(NULL, 2000); // localhost, any port
|
||||||
listen(5);
|
listen(5);
|
||||||
|
|
||||||
_poller.addChannel(this);
|
_poller.addChannel(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~TestServer()
|
virtual ~TestServer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool writable (void) { return false ; }
|
virtual bool writable (void) { return false ; }
|
||||||
|
|
||||||
virtual void handleAccept (void)
|
virtual void handleAccept (void)
|
||||||
@@ -475,10 +399,10 @@ public:
|
|||||||
//cout << "did accept from " << addr.getHost() << ":" << addr.getPort() << endl;
|
//cout << "did accept from " << addr.getHost() << ":" << addr.getPort() << endl;
|
||||||
TestServerChannel* chan = new TestServerChannel();
|
TestServerChannel* chan = new TestServerChannel();
|
||||||
chan->setHandle(handle);
|
chan->setHandle(handle);
|
||||||
|
|
||||||
_poller.addChannel(chan);
|
_poller.addChannel(chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void poll()
|
void poll()
|
||||||
{
|
{
|
||||||
_poller.poll();
|
_poller.poll();
|
||||||
@@ -490,43 +414,42 @@ TestServer testServer;
|
|||||||
void waitForComplete(HTTP::Client* cl, TestRequest* tr)
|
void waitForComplete(HTTP::Client* cl, TestRequest* tr)
|
||||||
{
|
{
|
||||||
SGTimeStamp start(SGTimeStamp::now());
|
SGTimeStamp start(SGTimeStamp::now());
|
||||||
while (start.elapsedMSec() < 10000) {
|
while (start.elapsedMSec() < 1000) {
|
||||||
cl->update();
|
cl->update();
|
||||||
testServer.poll();
|
testServer.poll();
|
||||||
|
|
||||||
if (tr->complete) {
|
if (tr->complete) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SGTimeStamp::sleepForMSec(15);
|
SGTimeStamp::sleepForMSec(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "timed out" << endl;
|
cerr << "timed out" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForFailed(HTTP::Client* cl, TestRequest* tr)
|
void waitForFailed(HTTP::Client* cl, TestRequest* tr)
|
||||||
{
|
{
|
||||||
SGTimeStamp start(SGTimeStamp::now());
|
SGTimeStamp start(SGTimeStamp::now());
|
||||||
while (start.elapsedMSec() < 10000) {
|
while (start.elapsedMSec() < 1000) {
|
||||||
cl->update();
|
cl->update();
|
||||||
testServer.poll();
|
testServer.poll();
|
||||||
|
|
||||||
if (tr->failed) {
|
if (tr->failed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SGTimeStamp::sleepForMSec(15);
|
SGTimeStamp::sleepForMSec(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "timed out waiting for failure" << endl;
|
cerr << "timed out waiting for failure" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
sglog().setLogLevels( SG_ALL, SG_INFO );
|
|
||||||
|
|
||||||
HTTP::Client cl;
|
HTTP::Client cl;
|
||||||
// force all requests to use the same connection for this test
|
// force all requests to use the same connection for this test
|
||||||
cl.setMaxConnections(1);
|
cl.setMaxConnections(1);
|
||||||
|
|
||||||
// test URL parsing
|
// test URL parsing
|
||||||
TestRequest* tr1 = new TestRequest("http://localhost.woo.zar:2000/test1?foo=bar");
|
TestRequest* tr1 = new TestRequest("http://localhost.woo.zar:2000/test1?foo=bar");
|
||||||
COMPARE(tr1->scheme(), "http");
|
COMPARE(tr1->scheme(), "http");
|
||||||
@@ -534,14 +457,14 @@ int main(int argc, char* argv[])
|
|||||||
COMPARE(tr1->host(), "localhost.woo.zar");
|
COMPARE(tr1->host(), "localhost.woo.zar");
|
||||||
COMPARE(tr1->port(), 2000);
|
COMPARE(tr1->port(), 2000);
|
||||||
COMPARE(tr1->path(), "/test1");
|
COMPARE(tr1->path(), "/test1");
|
||||||
|
|
||||||
TestRequest* tr2 = new TestRequest("http://192.168.1.1/test1/dir/thing/file.png");
|
TestRequest* tr2 = new TestRequest("http://192.168.1.1/test1/dir/thing/file.png");
|
||||||
COMPARE(tr2->scheme(), "http");
|
COMPARE(tr2->scheme(), "http");
|
||||||
COMPARE(tr2->hostAndPort(), "192.168.1.1");
|
COMPARE(tr2->hostAndPort(), "192.168.1.1");
|
||||||
COMPARE(tr2->host(), "192.168.1.1");
|
COMPARE(tr2->host(), "192.168.1.1");
|
||||||
COMPARE(tr2->port(), 80);
|
COMPARE(tr2->port(), 80);
|
||||||
COMPARE(tr2->path(), "/test1/dir/thing/file.png");
|
COMPARE(tr2->path(), "/test1/dir/thing/file.png");
|
||||||
|
|
||||||
// basic get request
|
// basic get request
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test1");
|
TestRequest* tr = new TestRequest("http://localhost:2000/test1");
|
||||||
@@ -555,12 +478,12 @@ int main(int argc, char* argv[])
|
|||||||
COMPARE(tr->responseBytesReceived(), strlen(BODY1));
|
COMPARE(tr->responseBytesReceived(), strlen(BODY1));
|
||||||
COMPARE(tr->bodyData, string(BODY1));
|
COMPARE(tr->bodyData, string(BODY1));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/testLorem");
|
TestRequest* tr = new TestRequest("http://localhost:2000/testLorem");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
cl.makeRequest(tr);
|
cl.makeRequest(tr);
|
||||||
|
|
||||||
waitForComplete(&cl, tr);
|
waitForComplete(&cl, tr);
|
||||||
COMPARE(tr->responseCode(), 200);
|
COMPARE(tr->responseCode(), 200);
|
||||||
COMPARE(tr->responseReason(), string("OK"));
|
COMPARE(tr->responseReason(), string("OK"));
|
||||||
@@ -568,7 +491,7 @@ int main(int argc, char* argv[])
|
|||||||
COMPARE(tr->responseBytesReceived(), strlen(BODY3));
|
COMPARE(tr->responseBytesReceived(), strlen(BODY3));
|
||||||
COMPARE(tr->bodyData, string(BODY3));
|
COMPARE(tr->bodyData, string(BODY3));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_args?foo=abc&bar=1234&username=johndoe");
|
TestRequest* tr = new TestRequest("http://localhost:2000/test_args?foo=abc&bar=1234&username=johndoe");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
@@ -576,7 +499,9 @@ int main(int argc, char* argv[])
|
|||||||
waitForComplete(&cl, tr);
|
waitForComplete(&cl, tr);
|
||||||
COMPARE(tr->responseCode(), 200);
|
COMPARE(tr->responseCode(), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "done args" << endl;
|
||||||
|
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_headers");
|
TestRequest* tr = new TestRequest("http://localhost:2000/test_headers");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
@@ -591,12 +516,12 @@ int main(int argc, char* argv[])
|
|||||||
COMPARE(tr->responseBytesReceived(), strlen(BODY1));
|
COMPARE(tr->responseBytesReceived(), strlen(BODY1));
|
||||||
COMPARE(tr->bodyData, string(BODY1));
|
COMPARE(tr->bodyData, string(BODY1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// larger get request
|
// larger get request
|
||||||
for (unsigned int i=0; i<body2Size; ++i) {
|
for (unsigned int i=0; i<body2Size; ++i) {
|
||||||
body2[i] = (i << 4) | (i >> 2);
|
body2[i] = (i << 4) | (i >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test2");
|
TestRequest* tr = new TestRequest("http://localhost:2000/test2");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
@@ -606,8 +531,8 @@ int main(int argc, char* argv[])
|
|||||||
COMPARE(tr->responseBytesReceived(), body2Size);
|
COMPARE(tr->responseBytesReceived(), body2Size);
|
||||||
COMPARE(tr->bodyData, string(body2, body2Size));
|
COMPARE(tr->bodyData, string(body2, body2Size));
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "testing chunked transfer encoding" << endl;
|
cerr << "testing chunked" << endl;
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/testchunked");
|
TestRequest* tr = new TestRequest("http://localhost:2000/testchunked");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
@@ -621,7 +546,7 @@ int main(int argc, char* argv[])
|
|||||||
// check trailers made it too
|
// check trailers made it too
|
||||||
COMPARE(tr->headers["x-foobar"], string("wibble"));
|
COMPARE(tr->headers["x-foobar"], string("wibble"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// test 404
|
// test 404
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/not-found");
|
TestRequest* tr = new TestRequest("http://localhost:2000/not-found");
|
||||||
@@ -668,40 +593,15 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
cout << "done3" << endl;
|
cout << "done3" << endl;
|
||||||
// test connectToHost failure
|
// test connectToHost failure
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
TestRequest* tr = new TestRequest("http://not.found/something");
|
TestRequest* tr = new TestRequest("http://not.found/something");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
cl.makeRequest(tr);
|
cl.makeRequest(tr);
|
||||||
waitForFailed(&cl, tr);
|
waitForFailed(tr);
|
||||||
|
COMPARE(tr->responseCode(), -1);
|
||||||
|
|
||||||
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
const int HOST_NOT_FOUND_CODE = CURLE_COULDNT_RESOLVE_HOST;
|
|
||||||
#else
|
|
||||||
const int HOST_NOT_FOUND_CODE = ENOENT;
|
|
||||||
#endif
|
|
||||||
COMPARE(tr->responseCode(), HOST_NOT_FOUND_CODE);
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
cout << "testing abrupt close" << endl;
|
|
||||||
// test server-side abrupt close
|
|
||||||
{
|
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_abrupt_close");
|
|
||||||
HTTP::Request_ptr own(tr);
|
|
||||||
cl.makeRequest(tr);
|
|
||||||
waitForFailed(&cl, tr);
|
|
||||||
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
const int SERVER_NO_DATA_CODE = CURLE_GOT_NOTHING;
|
|
||||||
#else
|
|
||||||
const int SERVER_NO_DATA_CODE = 500;
|
|
||||||
#endif
|
|
||||||
COMPARE(tr->responseCode(), SERVER_NO_DATA_CODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << "testing proxy close" << endl;
|
|
||||||
// test proxy
|
// test proxy
|
||||||
{
|
{
|
||||||
cl.setProxy("localhost", 2000);
|
cl.setProxy("localhost", 2000);
|
||||||
@@ -713,10 +613,9 @@ cout << "testing proxy close" << endl;
|
|||||||
COMPARE(tr->responseLength(), body2Size);
|
COMPARE(tr->responseLength(), body2Size);
|
||||||
COMPARE(tr->bodyData, string(body2, body2Size));
|
COMPARE(tr->bodyData, string(body2, body2Size));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
{
|
{
|
||||||
cl.setProxy("localhost", 2000, "johndoe:swordfish");
|
cl.setProxy("localhost", 2000, "ABCDEF");
|
||||||
TestRequest* tr = new TestRequest("http://www.google.com/test3");
|
TestRequest* tr = new TestRequest("http://www.google.com/test3");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
cl.makeRequest(tr);
|
cl.makeRequest(tr);
|
||||||
@@ -725,105 +624,81 @@ cout << "testing proxy close" << endl;
|
|||||||
COMPARE(tr->responseBytesReceived(), body2Size);
|
COMPARE(tr->responseBytesReceived(), body2Size);
|
||||||
COMPARE(tr->bodyData, string(body2, body2Size));
|
COMPARE(tr->bodyData, string(body2, body2Size));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// pipelining
|
// pipelining
|
||||||
cout << "testing HTTP 1.1 pipelining" << endl;
|
cout << "testing HTTP 1.1 pipelineing" << endl;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
cl.setProxy("", 80);
|
cl.setProxy("", 80);
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test1");
|
TestRequest* tr = new TestRequest("http://localhost:2000/test1");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
cl.makeRequest(tr);
|
cl.makeRequest(tr);
|
||||||
|
|
||||||
|
|
||||||
TestRequest* tr2 = new TestRequest("http://localhost:2000/testLorem");
|
TestRequest* tr2 = new TestRequest("http://localhost:2000/testLorem");
|
||||||
HTTP::Request_ptr own2(tr2);
|
HTTP::Request_ptr own2(tr2);
|
||||||
cl.makeRequest(tr2);
|
cl.makeRequest(tr2);
|
||||||
|
|
||||||
TestRequest* tr3 = new TestRequest("http://localhost:2000/test1");
|
TestRequest* tr3 = new TestRequest("http://localhost:2000/test1");
|
||||||
HTTP::Request_ptr own3(tr3);
|
HTTP::Request_ptr own3(tr3);
|
||||||
cl.makeRequest(tr3);
|
cl.makeRequest(tr3);
|
||||||
|
|
||||||
waitForComplete(&cl, tr3);
|
waitForComplete(&cl, tr3);
|
||||||
VERIFY(tr->complete);
|
VERIFY(tr->complete);
|
||||||
VERIFY(tr2->complete);
|
VERIFY(tr2->complete);
|
||||||
COMPARE(tr->bodyData, string(BODY1));
|
COMPARE(tr->bodyData, string(BODY1));
|
||||||
|
|
||||||
COMPARE(tr2->responseLength(), strlen(BODY3));
|
COMPARE(tr2->responseLength(), strlen(BODY3));
|
||||||
COMPARE(tr2->responseBytesReceived(), strlen(BODY3));
|
COMPARE(tr2->responseBytesReceived(), strlen(BODY3));
|
||||||
COMPARE(tr2->bodyData, string(BODY3));
|
COMPARE(tr2->bodyData, string(BODY3));
|
||||||
|
|
||||||
COMPARE(tr3->bodyData, string(BODY1));
|
COMPARE(tr3->bodyData, string(BODY1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiple requests with an HTTP 1.0 server
|
// multiple requests with an HTTP 1.0 server
|
||||||
{
|
{
|
||||||
cout << "http 1.0 multiple requests" << endl;
|
cout << "http 1.0 multiple requests" << endl;
|
||||||
|
|
||||||
cl.setProxy("", 80);
|
cl.setProxy("", 80);
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_1_0/A");
|
TestRequest* tr = new TestRequest("http://localhost:2000/test_1_0/A");
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
cl.makeRequest(tr);
|
cl.makeRequest(tr);
|
||||||
|
|
||||||
TestRequest* tr2 = new TestRequest("http://localhost:2000/test_1_0/B");
|
TestRequest* tr2 = new TestRequest("http://localhost:2000/test_1_0/B");
|
||||||
HTTP::Request_ptr own2(tr2);
|
HTTP::Request_ptr own2(tr2);
|
||||||
cl.makeRequest(tr2);
|
cl.makeRequest(tr2);
|
||||||
|
|
||||||
TestRequest* tr3 = new TestRequest("http://localhost:2000/test_1_0/C");
|
TestRequest* tr3 = new TestRequest("http://localhost:2000/test_1_0/C");
|
||||||
HTTP::Request_ptr own3(tr3);
|
HTTP::Request_ptr own3(tr3);
|
||||||
cl.makeRequest(tr3);
|
cl.makeRequest(tr3);
|
||||||
|
|
||||||
waitForComplete(&cl, tr3);
|
waitForComplete(&cl, tr3);
|
||||||
VERIFY(tr->complete);
|
VERIFY(tr->complete);
|
||||||
VERIFY(tr2->complete);
|
VERIFY(tr2->complete);
|
||||||
|
|
||||||
COMPARE(tr->responseLength(), strlen(BODY1));
|
COMPARE(tr->responseLength(), strlen(BODY1));
|
||||||
COMPARE(tr->responseBytesReceived(), strlen(BODY1));
|
COMPARE(tr->responseBytesReceived(), strlen(BODY1));
|
||||||
COMPARE(tr->bodyData, string(BODY1));
|
COMPARE(tr->bodyData, string(BODY1));
|
||||||
|
|
||||||
COMPARE(tr2->responseLength(), strlen(BODY3));
|
COMPARE(tr2->responseLength(), strlen(BODY3));
|
||||||
COMPARE(tr2->responseBytesReceived(), strlen(BODY3));
|
COMPARE(tr2->responseBytesReceived(), strlen(BODY3));
|
||||||
COMPARE(tr2->bodyData, string(BODY3));
|
COMPARE(tr2->bodyData, string(BODY3));
|
||||||
COMPARE(tr3->bodyData, string(BODY1));
|
COMPARE(tr3->bodyData, string(BODY1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST
|
// POST
|
||||||
{
|
{
|
||||||
cout << "testing POST" << endl;
|
cout << "POST" << endl;
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_post?foo=abc&bar=1234&username=johndoe", "POST");
|
TestRequest* tr = new TestRequest("http://localhost:2000/test_post?foo=abc&bar=1234&username=johndoe", "POST");
|
||||||
tr->setBodyData("", "application/x-www-form-urlencoded");
|
tr->setBodyData("", "application/x-www-form-urlencoded");
|
||||||
|
|
||||||
HTTP::Request_ptr own(tr);
|
HTTP::Request_ptr own(tr);
|
||||||
cl.makeRequest(tr);
|
cl.makeRequest(tr);
|
||||||
waitForComplete(&cl, tr);
|
waitForComplete(&cl, tr);
|
||||||
COMPARE(tr->responseCode(), 204);
|
COMPARE(tr->responseCode(), 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT
|
|
||||||
{
|
|
||||||
cout << "testing PUT" << endl;
|
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_put", "PUT");
|
|
||||||
tr->setBodyData(BODY3, "x-application/foobar");
|
|
||||||
|
|
||||||
HTTP::Request_ptr own(tr);
|
|
||||||
cl.makeRequest(tr);
|
|
||||||
waitForComplete(&cl, tr);
|
|
||||||
COMPARE(tr->responseCode(), 204);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
cout << "testing PUT create" << endl;
|
|
||||||
TestRequest* tr = new TestRequest("http://localhost:2000/test_create", "PUT");
|
|
||||||
tr->setBodyData(BODY3, "x-application/foobar");
|
|
||||||
|
|
||||||
HTTP::Request_ptr own(tr);
|
|
||||||
cl.makeRequest(tr);
|
|
||||||
waitForComplete(&cl, tr);
|
|
||||||
COMPARE(tr->responseCode(), 201);
|
|
||||||
}
|
|
||||||
|
|
||||||
// test_zero_length_content
|
// test_zero_length_content
|
||||||
{
|
{
|
||||||
cout << "zero-length-content-response" << endl;
|
cout << "zero-length-content-response" << endl;
|
||||||
@@ -835,8 +710,8 @@ cout << "testing proxy close" << endl;
|
|||||||
COMPARE(tr->bodyData, string());
|
COMPARE(tr->bodyData, string());
|
||||||
COMPARE(tr->responseBytesReceived(), 0);
|
COMPARE(tr->responseBytesReceived(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cout << "all tests passed ok" << endl;
|
cout << "all tests passed ok" << endl;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
+73
-87
@@ -24,7 +24,7 @@
|
|||||||
// Put in some bullet-proofing to handle magnetic and geographic poles.
|
// Put in some bullet-proofing to handle magnetic and geographic poles.
|
||||||
// 3/28/2000 EAW
|
// 3/28/2000 EAW
|
||||||
//
|
//
|
||||||
// Updated coefficient arrays to use the current wmm2005 model,
|
// Updated coefficient arrays to use the current WMM2005 model,
|
||||||
// (valid between 2005.0 and 2010.0)
|
// (valid between 2005.0 and 2010.0)
|
||||||
// Also removed unused variables and corrected earth radii constants
|
// Also removed unused variables and corrected earth radii constants
|
||||||
// to the values for WGS84 and WMM2005.
|
// to the values for WGS84 and WMM2005.
|
||||||
@@ -36,20 +36,6 @@
|
|||||||
//
|
//
|
||||||
// 25/10/2006 Wim Van Hoydonck -- wim.van.hoydonck@gmail.com
|
// 25/10/2006 Wim Van Hoydonck -- wim.van.hoydonck@gmail.com
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// Updated coefficient arrays to use the current WMM2015 model,
|
|
||||||
// (valid between 2015.0 and 2020.0)
|
|
||||||
// Also removed unused variables and corrected earth radii constants
|
|
||||||
// to the values for WGS84 and WMM2015.
|
|
||||||
// Reference:
|
|
||||||
// A. Chulliat , S. Macmillan, P. Alken, C. Beggan, M.
|
|
||||||
// Nair, B. Hamilton, A. Woods, V. Ridley,
|
|
||||||
// S Maus, and A Thomson, December 2014, The
|
|
||||||
// US/UK World Magnetic Model for 2015-2020,
|
|
||||||
// NOAA Technical Report WMM2015_Report.pdf
|
|
||||||
//
|
|
||||||
// 18/06/2015 Jean-Paul Anceaux -- j.p.r.anceaux@gmail.com
|
|
||||||
|
|
||||||
|
|
||||||
// The routine uses a spherical harmonic expansion of the magnetic
|
// The routine uses a spherical harmonic expansion of the magnetic
|
||||||
// potential up to twelfth order, together with its time variation, as
|
// potential up to twelfth order, together with its time variation, as
|
||||||
@@ -66,7 +52,7 @@
|
|||||||
// the magnetic poles (where it is ill-defined) where the error may reach
|
// the magnetic poles (where it is ill-defined) where the error may reach
|
||||||
// 4 degrees or more.
|
// 4 degrees or more.
|
||||||
//
|
//
|
||||||
// Variation is undefined at both the geographic and
|
// Variation is undefined at both the geographic and
|
||||||
// magnetic poles, even though the field itself is well-behaved. To
|
// magnetic poles, even though the field itself is well-behaved. To
|
||||||
// avoid the routine blowing up, latitude entries corresponding to
|
// avoid the routine blowing up, latitude entries corresponding to
|
||||||
// the geographic poles are slightly offset. At the magnetic poles,
|
// the geographic poles are slightly offset. At the magnetic poles,
|
||||||
@@ -93,7 +79,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
#include <simgear/sg_inlines.h>
|
#include <simgear/sg_inlines.h>
|
||||||
@@ -104,72 +90,72 @@ static const double a = 6378.137; /* semi-major axis (equatorial radius) o
|
|||||||
static const double b = 6356.7523142; /* semi-minor axis referenced to the WGS84 ellipsoid */
|
static const double b = 6356.7523142; /* semi-minor axis referenced to the WGS84 ellipsoid */
|
||||||
static const double r_0 = 6371.2; /* standard Earth magnetic reference radius */
|
static const double r_0 = 6371.2; /* standard Earth magnetic reference radius */
|
||||||
|
|
||||||
static double gnm_wmm2015[13][13] =
|
static double gnm_wmm2005[13][13] =
|
||||||
{
|
{
|
||||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-29438.5, -1501.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-29556.8, -1671.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-2445.3, 3012.5, 1676.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-2340.6, 3046.9, 1657.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{1351.1, -2352.3, 1225.6, 581.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{1335.4, -2305.1, 1246.7, 674.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{907.2, 813.7, 120.3, -335.0, 70.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{919.8, 798.1, 211.3, -379.4, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-232.6, 360.1, 192.4, -141.0, -157.4, 4.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-227.4, 354.6, 208.7, -136.5, -168.3, -14.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{69.5, 67.4, 72.8, -129.8, -29.0, 13.2, -70.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{73.2, 69.7, 76.7, -151.2, -14.9, 14.6, -86.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{81.6, -76.1, -6.8, 51.9, 15.0, 9.3, -2.8, 6.7, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{80.1, -74.5, -1.4, 38.5, 12.4, 9.5, 5.7, 1.8, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{24.0, 8.6, -16.9, -3.2, -20.6, 13.3, 11.7, -16.0, -2.0, 0.0, 0.0, 0.0, 0.0},
|
{24.9, 7.7, -11.6, -6.9, -18.2, 10.0, 9.2, -11.6, -5.2, 0.0, 0.0, 0.0, 0.0},
|
||||||
{5.4, 8.8, 3.1, -3.1, 0.6, -13.3, -0.1, 8.7, -9.1, -10.5, 0.0, 0.0, 0.0},
|
{5.6, 9.9, 3.5, -7.0, 5.1, -10.8, -1.3, 8.8, -6.7, -9.1, 0.0, 0.0, 0.0},
|
||||||
{-1.9, -6.5, 0.2, 0.6, -0.6, 1.7, -0.7, 2.1, 2.3, -1.8, -3.6, 0.0, 0.0},
|
{-2.3, -6.3, 1.6, -2.6, 0.0, 3.1, 0.4, 2.1, 3.9, -0.1, -2.3, 0.0, 0.0},
|
||||||
{3.1, -1.5, -2.3, 2.1, -0.9, 0.6, -0.7, 0.2, 1.7, -0.2, 0.4, 3.5, 0.0},
|
{2.8, -1.6, -1.7, 1.7, -0.1, 0.1, -0.7, 0.7, 1.8, 0.0, 1.1, 4.1, 0.0},
|
||||||
{-2.0, -0.3, 0.4, 1.3, -0.9, 0.9, 0.1, 0.5, -0.4, -0.4, 0.2, -0.9, 0.0},
|
{-2.4, -0.4, 0.2, 0.8, -0.3, 1.1, -0.5, 0.4, -0.3, -0.3, -0.1, -0.3, -0.1},
|
||||||
};
|
};
|
||||||
|
|
||||||
static double hnm_wmm2015[13][13]=
|
static double hnm_wmm2005[13][13]=
|
||||||
{
|
{
|
||||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 4796.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 5079.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -2845.6, -642.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -2594.7, -516.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -115.3, 245.0, -538.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -199.9, 269.3, -524.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 283.4, -188.6, 180.9, -329.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 281.5, -226.0, 145.8, -304.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 47.4, 196.9, -119.4, 16.1, 100.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 42.4, 179.8, -123.0, -19.5, 103.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -20.7, 33.2, 58.8, -66.5, 7.3, 62.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -20.3, 54.7, 63.6, -63.4, -0.1, 50.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -54.1, -19.4, 5.6, 24.4, 3.3, -27.5, -2.3, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -61.5, -22.4, 7.2, 25.4, 11.0, -26.4, -5.1, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 10.2, -18.1, 13.2, -14.6, 16.2, 5.7, -9.1, 2.2, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 11.2, -21.0, 9.6, -19.8, 16.1, 7.7, -12.9, -0.2, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -21.6, 10.8, 11.7, -6.8, -6.9, 7.8, 1.0, -3.9, 8.5, 0.0, 0.0, 0.0},
|
{0.0, -20.1, 12.9, 12.6, -6.7, -8.1, 8.0, 2.9, -7.9, 6.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 3.3, -0.3, 4.6, 4.4, -7.9, -0.6, -4.1, -2.8, -1.1, -8.7, 0.0, 0.0},
|
{0.0, 2.4, 0.2, 4.4, 4.8, -6.5, -1.1, -3.4, -0.8, -2.3, -7.9, 0.0, 0.0},
|
||||||
{0.0, -0.1, 2.1, -0.7, -1.1, 0.7, -0.2, -2.1, -1.5, -2.5, -2.0, -2.3, 0.0},
|
{0.0, 0.3, 1.2, -0.8, -2.5, 0.9, -0.6, -2.7, -0.9, -1.3, -2.0, -1.2, 0.0},
|
||||||
{0.0, -1.0, 0.5, 1.8, -2.2, 0.3, 0.7, -0.1, 0.3, 0.2, -0.9, -0.2, 0.7},
|
{0.0, -0.4, 0.3, 2.4, -2.6, 0.6, 0.3, 0.0, 0.0, 0.3, -0.9, -0.4, 0.8},
|
||||||
};
|
};
|
||||||
|
|
||||||
static double gtnm_wmm2015[13][13]=
|
static double gtnm_wmm2005[13][13]=
|
||||||
{
|
{
|
||||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{10.7, 17.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{8.0, 10.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-8.6, -3.3, 2.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-15.1, -7.8, -0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{3.1, -6.2, -0.4, -10.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.4, -2.6, -1.2, -6.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-0.4, 0.8, -9.2, 4.0, -4.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-2.5, 2.8, -7.0, 6.2, -3.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-0.2, 0.1, -1.4, 0.0, 1.3, 3.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-2.8, 0.7, -3.2, -1.1, 0.1, -0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{-0.5, -0.2, -0.6, 2.4, -1.1, 0.3, 1.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{-0.7, 0.4, -0.3, 2.3, -2.1, -0.6, 1.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.2, -0.2, -0.4, 1.3, 0.2, -0.4, -0.9, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.2, -0.1, -0.3, 1.1, 0.6, 0.5, -0.4, 0.6, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.1, -0.5, 0.5, -0.2, 0.4, 0.2, -0.4, 0.3, 0.0, 0.0, 0.0, 0.0},
|
{0.1, 0.3, -0.4, 0.3, -0.3, 0.2, 0.4, -0.7, 0.4, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -0.1, -0.1, 0.4, -0.5, -0.2, 0.1, 0.0, -0.2, -0.1, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.0, -0.1, 0.3, -0.1, -0.1, -0.1, 0.0, -0.2, -0.1, -0.2, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.0, -0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1, -0.1, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.1, 0.0, 0.0, 0.1, -0.1, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
};
|
};
|
||||||
|
|
||||||
static double htnm_wmm2015[13][13]=
|
static double htnm_wmm2005[13][13]=
|
||||||
{
|
{
|
||||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -26.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -20.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -27.1, -13.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -23.2, -14.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 8.4, -0.4, 2.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 5.0, -7.0, -0.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -0.6, 5.3, 3.0, -5.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 2.2, 1.6, 5.8, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.4, 1.6, -1.1, 3.3, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 1.7, 2.1, 4.8, -1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.0, -2.2, -0.7, 0.1, 1.0, 1.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -0.6, -1.9, -0.4, -0.5, -0.3, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.7, 0.5, -0.2, -0.1, -0.7, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.6, 0.4, 0.2, 0.3, -0.8, -0.2, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -0.3, 0.3, 0.3, 0.6, -0.1, -0.2, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, -0.2, 0.1, 0.3, 0.4, 0.1, -0.2, 0.4, 0.4, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, -0.2, -0.1, -0.2, 0.1, 0.1, 0.0, -0.2, 0.4, 0.3, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.1, -0.1, 0.0, 0.0, -0.2, 0.1, -0.1, -0.2, 0.1, -0.1, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.0, 0.1, 0.0, 0.1, 0.0, 0.0, 0.1, 0.0, -0.1, 0.0, -0.1, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
{0.0, 0.0, 0.0, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int nmax = 12;
|
static const int nmax = 12;
|
||||||
@@ -188,7 +174,7 @@ static double roots[13][13][2];
|
|||||||
unsigned long int yymmdd_to_julian_days( int yy, int mm, int dd )
|
unsigned long int yymmdd_to_julian_days( int yy, int mm, int dd )
|
||||||
{
|
{
|
||||||
unsigned long jd;
|
unsigned long jd;
|
||||||
|
|
||||||
yy = (yy < 50) ? (2000 + yy) : (1900 + yy);
|
yy = (yy < 50) ? (2000 + yy) : (1900 + yy);
|
||||||
jd = dd - 32075L + 1461L * (yy + 4800L + (mm - 14) / 12 ) / 4;
|
jd = dd - 32075L + 1461L * (yy + 4800L + (mm - 14) / 12 ) / 4;
|
||||||
jd = jd + 367L * (mm - 2 - (mm - 14) / 12*12) / 12;
|
jd = jd + 367L * (mm - 2 - (mm - 14) / 12*12) / 12;
|
||||||
@@ -196,7 +182,7 @@ unsigned long int yymmdd_to_julian_days( int yy, int mm, int dd )
|
|||||||
|
|
||||||
/* printf("julian date = %d\n", jd ); */
|
/* printf("julian date = %d\n", jd ); */
|
||||||
return jd;
|
return jd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -209,8 +195,8 @@ double calc_magvar( double lat, double lon, double h, long dat, double* field )
|
|||||||
{
|
{
|
||||||
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
||||||
int n,m;
|
int n,m;
|
||||||
/* reference date for current model is 1 januari 2015 */
|
/* reference date for current model is 1 januari 2005 */
|
||||||
long date0_wmm2015 = yymmdd_to_julian_days(15,1,1);
|
long date0_wmm2005 = yymmdd_to_julian_days(5,1,1);
|
||||||
|
|
||||||
double yearfrac,sr,r,theta,c,s,psi,fn,fn_0,B_r,B_theta,B_phi,X,Y,Z;
|
double yearfrac,sr,r,theta,c,s,psi,fn,fn_0,B_r,B_theta,B_phi,X,Y,Z;
|
||||||
double sinpsi, cospsi, inv_s;
|
double sinpsi, cospsi, inv_s;
|
||||||
@@ -229,7 +215,7 @@ double calc_magvar( double lat, double lon, double h, long dat, double* field )
|
|||||||
/* theta is geocentric co-latitude */
|
/* theta is geocentric co-latitude */
|
||||||
|
|
||||||
r = h*h + 2.0*h * sr +
|
r = h*h + 2.0*h * sr +
|
||||||
(a*a*a*a - ( a*a*a*a - b*b*b*b ) * sinlat*sinlat ) /
|
(a*a*a*a - ( a*a*a*a - b*b*b*b ) * sinlat*sinlat ) /
|
||||||
(a*a - (a*a - b*b) * sinlat*sinlat );
|
(a*a - (a*a - b*b) * sinlat*sinlat );
|
||||||
|
|
||||||
r = sqrt(r);
|
r = sqrt(r);
|
||||||
@@ -238,7 +224,7 @@ double calc_magvar( double lat, double lon, double h, long dat, double* field )
|
|||||||
c = cos(theta);
|
c = cos(theta);
|
||||||
s = sin(theta);
|
s = sin(theta);
|
||||||
/* protect against zero divide at geographic poles */
|
/* protect against zero divide at geographic poles */
|
||||||
inv_s = 1.0 / (s + (s == 0.)*1.0e-8);
|
inv_s = 1.0 / (s + (s == 0.)*1.0e-8);
|
||||||
|
|
||||||
/* zero out arrays */
|
/* zero out arrays */
|
||||||
for ( n = 0; n <= nmax; n++ ) {
|
for ( n = 0; n <= nmax; n++ ) {
|
||||||
@@ -297,12 +283,12 @@ double calc_magvar( double lat, double lon, double h, long dat, double* field )
|
|||||||
|
|
||||||
/* compute Gauss coefficients gnm and hnm of degree n and order m for the desired time
|
/* compute Gauss coefficients gnm and hnm of degree n and order m for the desired time
|
||||||
achieved by adjusting the coefficients at time t0 for linear secular variation */
|
achieved by adjusting the coefficients at time t0 for linear secular variation */
|
||||||
/* WMM2015 */
|
/* WMM2005 */
|
||||||
yearfrac = (dat - date0_wmm2015) / 365.25;
|
yearfrac = (dat - date0_wmm2005) / 365.25;
|
||||||
for ( n = 1; n <= nmax; n++ ) {
|
for ( n = 1; n <= nmax; n++ ) {
|
||||||
for ( m = 0; m <= nmax; m++ ) {
|
for ( m = 0; m <= nmax; m++ ) {
|
||||||
gnm[n][m] = gnm_wmm2015[n][m] + yearfrac * gtnm_wmm2015[n][m];
|
gnm[n][m] = gnm_wmm2005[n][m] + yearfrac * gtnm_wmm2005[n][m];
|
||||||
hnm[n][m] = hnm_wmm2015[n][m] + yearfrac * htnm_wmm2015[n][m];
|
hnm[n][m] = hnm_wmm2005[n][m] + yearfrac * htnm_wmm2005[n][m];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +310,7 @@ double calc_magvar( double lat, double lon, double h, long dat, double* field )
|
|||||||
double c2_n=0;
|
double c2_n=0;
|
||||||
double c3_n=0;
|
double c3_n=0;
|
||||||
for ( m = 0; m <= n; m++ ) {
|
for ( m = 0; m <= n; m++ ) {
|
||||||
double tmp = (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]);
|
double tmp = (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]);
|
||||||
c1_n=c1_n + tmp * P[n][m];
|
c1_n=c1_n + tmp * P[n][m];
|
||||||
c2_n=c2_n + tmp * DP[n][m];
|
c2_n=c2_n + tmp * DP[n][m];
|
||||||
c3_n=c3_n + m * (gnm[n][m] * sm[m] - hnm[n][m] * cm[m]) * P[n][m];
|
c3_n=c3_n + m * (gnm[n][m] * sm[m] - hnm[n][m] * cm[m]) * P[n][m];
|
||||||
@@ -354,7 +340,7 @@ double calc_magvar( double lat, double lon, double h, long dat, double* field )
|
|||||||
/* find variation in radians */
|
/* find variation in radians */
|
||||||
/* return zero variation at magnetic pole X=Y=0. */
|
/* return zero variation at magnetic pole X=Y=0. */
|
||||||
/* E is positive */
|
/* E is positive */
|
||||||
return (X != 0. || Y != 0.) ? atan2(Y, X) : (double) 0.;
|
return (X != 0. || Y != 0.) ? atan2(Y, X) : (double) 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -364,7 +350,7 @@ double SGMagVarOrig( double lat, double lon, double h, long dat, double* field )
|
|||||||
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
||||||
int n,m;
|
int n,m;
|
||||||
/* reference dates */
|
/* reference dates */
|
||||||
long date0_wmm2015 = yymmdd_to_julian_days(5,1,1);
|
long date0_wmm2005 = yymmdd_to_julian_days(5,1,1);
|
||||||
|
|
||||||
double yearfrac,sr,r,theta,c,s,psi,fn,B_r,B_theta,B_phi,X,Y,Z;
|
double yearfrac,sr,r,theta,c,s,psi,fn,B_r,B_theta,B_phi,X,Y,Z;
|
||||||
|
|
||||||
@@ -376,7 +362,7 @@ double SGMagVarOrig( double lat, double lon, double h, long dat, double* field )
|
|||||||
/* theta is geocentric co-latitude */
|
/* theta is geocentric co-latitude */
|
||||||
|
|
||||||
r = h * h + 2.0*h * sr +
|
r = h * h + 2.0*h * sr +
|
||||||
(pow(a,4.0) - (pow(a,4.0) - pow(b,4.0)) * pow(sin(lat),2.0)) /
|
(pow(a,4.0) - (pow(a,4.0) - pow(b,4.0)) * pow(sin(lat),2.0)) /
|
||||||
(a * a - (a * a - b * b) * pow(sin(lat),2.0));
|
(a * a - (a * a - b * b) * pow(sin(lat),2.0));
|
||||||
|
|
||||||
r = sqrt(r);
|
r = sqrt(r);
|
||||||
@@ -421,12 +407,12 @@ double SGMagVarOrig( double lat, double lon, double h, long dat, double* field )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* compute gnm, hnm at dat */
|
/* compute gnm, hnm at dat */
|
||||||
/* WMM2015 */
|
/* WMM2005 */
|
||||||
yearfrac = (dat - date0_wmm2015) / 365.25;
|
yearfrac = (dat - date0_wmm2005) / 365.25;
|
||||||
for ( n = 1; n <= nmax; n++ ) {
|
for ( n = 1; n <= nmax; n++ ) {
|
||||||
for ( m = 0; m <= nmax; m++ ) {
|
for ( m = 0; m <= nmax; m++ ) {
|
||||||
gnm[n][m] = gnm_wmm2015[n][m] + yearfrac * gtnm_wmm2015[n][m];
|
gnm[n][m] = gnm_wmm2005[n][m] + yearfrac * gtnm_wmm2005[n][m];
|
||||||
hnm[n][m] = hnm_wmm2015[n][m] + yearfrac * htnm_wmm2015[n][m];
|
hnm[n][m] = hnm_wmm2005[n][m] + yearfrac * htnm_wmm2005[n][m];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include <simgear/magvar/magvar.hxx>
|
#include <simgear/magvar/magvar.hxx>
|
||||||
#include <simgear/math/SGMath.hxx>
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* 2/14/00 fixed help message- dip angle (down positive), variation (E positive) */
|
/* 2/14/00 fixed help message- dip angle (down positive), variation (E positive) */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ public:
|
|||||||
static bool isNaN(const T& v)
|
static bool isNaN(const T& v)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_ISNAN
|
#ifdef HAVE_ISNAN
|
||||||
return (isnan(v) != 0);
|
return isnan(v);
|
||||||
#elif defined HAVE_STD_ISNAN
|
#elif defined HAVE_STD_ISNAN
|
||||||
return std::isnan(v);
|
return std::isnan(v);
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace simgear
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setMaxSubdiv( size_t aMaxSubdiv ) { mMaxSubdiv = aMaxSubdiv; }
|
void setMaxSubdiv( size_t aMaxSubdiv ) { mMaxSubdiv = aMaxSubdiv; }
|
||||||
size_t getMaxSubdiv() const { return mMaxSubdiv; }
|
void getMaxSubdiv() const { return mMaxSubdiv; }
|
||||||
PointList &pointList() { return mPointList; }
|
PointList &pointList() { return mPointList; }
|
||||||
const PointList &pointList() const { return mPointList; }
|
const PointList &pointList() const { return mPointList; }
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ SGInterpTable::SGInterpTable( const std::string& file )
|
|||||||
while ( in ) {
|
while ( in ) {
|
||||||
double ind, dep;
|
double ind, dep;
|
||||||
in >> ind >> dep;
|
in >> ind >> dep;
|
||||||
in >> std::skipws;
|
in >> skipws;
|
||||||
_table[ind] = dep;
|
_table[ind] = dep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
include (SimGearComponent)
|
include (SimGearComponent)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
CSSBorder.hxx
|
CSSBorder.hxx
|
||||||
ListDiff.hxx
|
ListDiff.hxx
|
||||||
ResourceManager.hxx
|
ResourceManager.hxx
|
||||||
@@ -37,10 +37,6 @@ set(SOURCES
|
|||||||
gzcontainerfile.cxx
|
gzcontainerfile.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WINDOWS)
|
|
||||||
list(APPEND HEADERS sgversionhelpers.hxx)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
list(APPEND SOURCES CocoaHelpers.mm)
|
list(APPEND SOURCES CocoaHelpers.mm)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -141,12 +141,8 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// add
|
// add
|
||||||
pc.add("/opt/local");
|
pc.add("/opt/local");
|
||||||
#ifdef _WIN32
|
|
||||||
COMPARE(pc.str(), std::string("/usr/local/include/;/opt/local"));
|
|
||||||
#else
|
|
||||||
COMPARE(pc.str(), std::string("/usr/local/include/:/opt/local"));
|
COMPARE(pc.str(), std::string("/usr/local/include/:/opt/local"));
|
||||||
#endif
|
|
||||||
|
|
||||||
// concat
|
// concat
|
||||||
SGPath pd = pb;
|
SGPath pd = pb;
|
||||||
pd.concat("-1");
|
pd.concat("-1");
|
||||||
|
|||||||
@@ -382,7 +382,6 @@ bool Dir::remove(bool recursive)
|
|||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
if (!removeChildren()) {
|
if (!removeChildren()) {
|
||||||
SG_LOG(SG_IO, SG_WARN, "Dir at:" << _path << " failed to remove children");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // of recursive deletion
|
} // of recursive deletion
|
||||||
|
|||||||
+31
-94
@@ -56,10 +56,7 @@ static const char sgSearchPathSep = ':';
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <ShlObj.h> // for CSIDL
|
#include <ShlObj.h> // for CSIDL
|
||||||
// TODO: replace this include file with the official <versionhelpers.h> header
|
|
||||||
// included in the Windows 8.1 SDK
|
|
||||||
#include "sgversionhelpers.hxx"
|
|
||||||
|
|
||||||
static SGPath pathForCSIDL(int csidl, const SGPath& def)
|
static SGPath pathForCSIDL(int csidl, const SGPath& def)
|
||||||
{
|
{
|
||||||
@@ -83,42 +80,6 @@ static SGPath pathForCSIDL(int csidl, const SGPath& def)
|
|||||||
|
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SGPath pathForKnownFolder(REFKNOWNFOLDERID folderId, const SGPath& def)
|
|
||||||
{
|
|
||||||
typedef HRESULT (WINAPI*PSHGKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR*);
|
|
||||||
|
|
||||||
HINSTANCE shellDll = LoadLibrary(TEXT("shell32"));
|
|
||||||
if (shellDll != NULL) {
|
|
||||||
PSHGKFP pSHGetKnownFolderPath = (PSHGKFP) GetProcAddress(shellDll, "SHGetKnownFolderPath");
|
|
||||||
if (pSHGetKnownFolderPath != NULL) {
|
|
||||||
// system call will allocate dynamic memory... which we must release when done
|
|
||||||
wchar_t* localFolder = 0;
|
|
||||||
|
|
||||||
if (pSHGetKnownFolderPath(folderId, KF_FLAG_DEFAULT_PATH, NULL, &localFolder) == S_OK) {
|
|
||||||
// copy into local memory
|
|
||||||
char path[MAX_PATH];
|
|
||||||
size_t len;
|
|
||||||
if (wcstombs_s(&len, path, localFolder, MAX_PATH) != S_OK) {
|
|
||||||
path[0] = '\0';
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "WCS to MBS failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPath folder_path = SGPath(path, def.getPermissionChecker());
|
|
||||||
|
|
||||||
// release dynamic memory
|
|
||||||
CoTaskMemFree(static_cast<void*>(localFolder));
|
|
||||||
|
|
||||||
return folder_path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeLibrary(shellDll);
|
|
||||||
}
|
|
||||||
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
|
|
||||||
// defined in CocoaHelpers.mm
|
// defined in CocoaHelpers.mm
|
||||||
@@ -743,35 +704,20 @@ SGPath SGPath::standardLocation(StandardLocation type, const SGPath& def)
|
|||||||
{
|
{
|
||||||
case HOME:
|
case HOME:
|
||||||
return home(def);
|
return home(def);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
case DESKTOP:
|
case DESKTOP:
|
||||||
if (IsWindowsVistaOrGreater())
|
return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def);
|
||||||
return pathForKnownFolder(FOLDERID_Desktop, def);
|
|
||||||
|
|
||||||
return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def);
|
|
||||||
|
|
||||||
case DOWNLOADS:
|
case DOWNLOADS:
|
||||||
if (IsWindowsVistaOrGreater())
|
// TODO use KnownFolders
|
||||||
return pathForKnownFolder(FOLDERID_Downloads, def);
|
// http://msdn.microsoft.com/en-us/library/bb776911%28v=vs.85%29.aspx
|
||||||
|
if( !def.isNull() )
|
||||||
if (!def.isNull())
|
return def;
|
||||||
return def;
|
|
||||||
|
|
||||||
return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def);
|
|
||||||
|
|
||||||
|
return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def);
|
||||||
case DOCUMENTS:
|
case DOCUMENTS:
|
||||||
if (IsWindowsVistaOrGreater())
|
return pathForCSIDL(CSIDL_MYDOCUMENTS, def);
|
||||||
return pathForKnownFolder(FOLDERID_Documents, def);
|
|
||||||
|
|
||||||
return pathForCSIDL(CSIDL_MYDOCUMENTS, def);
|
|
||||||
|
|
||||||
case PICTURES:
|
case PICTURES:
|
||||||
if (IsWindowsVistaOrGreater())
|
return pathForCSIDL(CSIDL_MYPICTURES, def);
|
||||||
return pathForKnownFolder(FOLDERID_Pictures, def);
|
|
||||||
|
|
||||||
return pathForCSIDL(CSIDL_MYPICTURES, def);
|
|
||||||
|
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
// since this is C++, we can't include NSPathUtilities.h to access the enum
|
// since this is C++, we can't include NSPathUtilities.h to access the enum
|
||||||
// values, so hard-coding them here (they are stable, don't worry)
|
// values, so hard-coding them here (they are stable, don't worry)
|
||||||
@@ -810,15 +756,20 @@ SGPath SGPath::fromEnv(const char* name, const SGPath& def)
|
|||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
SGPath SGPath::home(const SGPath& def)
|
SGPath SGPath::home(const SGPath& def)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
// TODO
|
||||||
return fromEnv("USERPROFILE", def);
|
return def;
|
||||||
#else
|
|
||||||
return fromEnv("HOME", def);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
SGPath SGPath::home(const SGPath& def)
|
||||||
|
{
|
||||||
|
return fromEnv("HOME", def);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
SGPath SGPath::desktop(const SGPath& def)
|
SGPath SGPath::desktop(const SGPath& def)
|
||||||
@@ -835,39 +786,25 @@ SGPath SGPath::documents(const SGPath& def)
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
std::string SGPath::realpath() const
|
std::string SGPath::realpath() const
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER) /*for MS compilers */ || defined(_WIN32) /*needed for non MS windows compilers like MingW*/
|
#if (defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1050)
|
||||||
|
// Workaround for Mac OS 10.5. Somehow fgfs crashes on Mac at ::realpath.
|
||||||
|
// This means relative paths cannot be used on Mac OS <= 10.5
|
||||||
|
return path;
|
||||||
|
#else
|
||||||
|
#if defined(_MSC_VER) /*for MS compilers */ || defined(_WIN32) /*needed for non MS windows compilers like MingW*/
|
||||||
// with absPath NULL, will allocate, and ignore length
|
// with absPath NULL, will allocate, and ignore length
|
||||||
char *buf = _fullpath( NULL, path.c_str(), _MAX_PATH );
|
char *buf = _fullpath( NULL, path.c_str(), _MAX_PATH );
|
||||||
#else
|
#else
|
||||||
// POSIX
|
// POSIX
|
||||||
char* buf = ::realpath(path.c_str(), NULL);
|
char* buf = ::realpath(path.c_str(), NULL);
|
||||||
#endif
|
#endif
|
||||||
if (!buf) // File does not exist: return the realpath it would have if created now
|
if (!buf)
|
||||||
// (needed for fgValidatePath security)
|
|
||||||
{
|
{
|
||||||
if (path.empty()) {
|
SG_LOG(SG_IO, SG_ALERT, "ERROR: The path '" << path << "' does not exist in the file system.");
|
||||||
return SGPath(".").realpath(); // current directory
|
return path;
|
||||||
}
|
|
||||||
std::string this_dir = dir();
|
|
||||||
if (isAbsolute() && this_dir.empty()) { // top level
|
|
||||||
this_dir = "/";
|
|
||||||
}
|
|
||||||
if (file() == "..") {
|
|
||||||
this_dir = SGPath(SGPath(this_dir).realpath()).dir();
|
|
||||||
if (this_dir.empty()) { // invalid path: .. above root
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return SGPath(this_dir).realpath(); // use native path separator,
|
|
||||||
// and handle 'existing/nonexisting/../symlink' paths
|
|
||||||
}
|
|
||||||
return SGPath(this_dir).realpath() +
|
|
||||||
#if defined(_MSC_VER) || defined(_WIN32)
|
|
||||||
"\\" + file();
|
|
||||||
#else
|
|
||||||
"/" + file();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
std::string p(buf);
|
std::string p(buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
return p;
|
return p;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
// Clean drop-in replacement for the versionhelpers.h header
|
|
||||||
//
|
|
||||||
// Copyright (C) 2015 Alessandro Menti <alessandro.menti@hotmail.it>
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Library General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
|
|
||||||
#ifndef SG_VERSIONHELPERS_HXX_
|
|
||||||
#define SG_VERSIONHELPERS_HXX_
|
|
||||||
|
|
||||||
#include <sdkddkver.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define VERSIONHELPERAPI inline bool
|
|
||||||
#else
|
|
||||||
#define VERSIONHELPERAPI FORCEINLINE BOOL
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
/* Windows 8/8.1 version numbers, not defined in the Windows 7 SDK. */
|
|
||||||
#ifndef _WIN32_WINNT_WIN8
|
|
||||||
#define _WIN32_WINNT_WIN8 0x0602
|
|
||||||
#endif
|
|
||||||
#ifndef _WIN32_WINNT_WINBLUE
|
|
||||||
#define _WIN32_WINNT_WINBLUE 0x0603
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsVersionOrGreater(WORD wMajorVersion,
|
|
||||||
WORD wMinorVersion, WORD wServicePackMajor) {
|
|
||||||
OSVERSIONINFOEXW osVersionInfo;
|
|
||||||
DWORDLONG dwlConditionMask = 0;
|
|
||||||
ZeroMemory(&osVersionInfo, sizeof(osVersionInfo));
|
|
||||||
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
|
|
||||||
osVersionInfo.dwMajorVersion = wMajorVersion;
|
|
||||||
osVersionInfo.dwMinorVersion = wMinorVersion;
|
|
||||||
osVersionInfo.wServicePackMajor = wServicePackMajor;
|
|
||||||
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION,
|
|
||||||
VER_GREATER_EQUAL);
|
|
||||||
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION,
|
|
||||||
VER_GREATER_EQUAL);
|
|
||||||
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR,
|
|
||||||
VER_GREATER_EQUAL);
|
|
||||||
return VerifyVersionInfoW(&osVersionInfo, VER_MAJORVERSION
|
|
||||||
| VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsXPOrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP),
|
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsXPSP1OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP),
|
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsXPSP2OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP),
|
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsXPSP3OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP),
|
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsVistaOrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA),
|
|
||||||
LOBYTE(_WIN32_WINNT_VISTA), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsVistaSP1OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA),
|
|
||||||
LOBYTE(_WIN32_WINNT_VISTA), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsVistaSP2OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA),
|
|
||||||
LOBYTE(_WIN32_WINNT_VISTA), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindows7OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7),
|
|
||||||
LOBYTE(_WIN32_WINNT_WIN7), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindows7SP1OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7),
|
|
||||||
LOBYTE(_WIN32_WINNT_WIN7), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindows8OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8),
|
|
||||||
LOBYTE(_WIN32_WINNT_WIN8), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindows8Point1OrGreater() {
|
|
||||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE),
|
|
||||||
LOBYTE(_WIN32_WINNT_WINBLUE), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSIONHELPERAPI IsWindowsServer() {
|
|
||||||
OSVERSIONINFOEXW osVersionInfo;
|
|
||||||
DWORDLONG dwlConditionMask = 0;
|
|
||||||
ZeroMemory(&osVersionInfo, sizeof(osVersionInfo));
|
|
||||||
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
|
|
||||||
osVersionInfo.wProductType = VER_NT_WORKSTATION;
|
|
||||||
VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
|
|
||||||
return !VerifyVersionInfoW(&osVersionInfo, VER_PRODUCT_TYPE,
|
|
||||||
dwlConditionMask);
|
|
||||||
}
|
|
||||||
#endif // SG_VERSIONHELPERS_HXX_
|
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "strutils.hxx"
|
#include "strutils.hxx"
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ include (SimGearComponent)
|
|||||||
set(HEADERS
|
set(HEADERS
|
||||||
naref.h
|
naref.h
|
||||||
nasal.h
|
nasal.h
|
||||||
iolib.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
@@ -27,7 +26,8 @@ set(SOURCES
|
|||||||
vector.c
|
vector.c
|
||||||
code.h
|
code.h
|
||||||
data.h
|
data.h
|
||||||
|
iolib.h
|
||||||
parse.h
|
parse.h
|
||||||
)
|
)
|
||||||
|
|
||||||
simgear_component(nasal nasal "${SOURCES}" "${HEADERS}")
|
simgear_component(nasal nasal "${SOURCES}" "${HEADERS}")
|
||||||
@@ -66,6 +66,14 @@ namespace nasal
|
|||||||
void GhostMetadata::addDerived(const GhostMetadata* derived)
|
void GhostMetadata::addDerived(const GhostMetadata* derived)
|
||||||
{
|
{
|
||||||
assert(derived);
|
assert(derived);
|
||||||
|
|
||||||
|
SG_LOG
|
||||||
|
(
|
||||||
|
SG_NASAL,
|
||||||
|
SG_INFO,
|
||||||
|
"Ghost::addDerived: " << _name_strong << " -> "
|
||||||
|
<< derived->_name_strong
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -39,12 +39,6 @@ static void runNumTests( double (TestContext::*test_double)(const std::string&),
|
|||||||
BOOST_CHECK_EQUAL((c.*test_int)("0x755"), 0x755);
|
BOOST_CHECK_EQUAL((c.*test_int)("0x755"), 0x755);
|
||||||
BOOST_CHECK_EQUAL((c.*test_int)("0x055"), 0x55);
|
BOOST_CHECK_EQUAL((c.*test_int)("0x055"), 0x55);
|
||||||
BOOST_CHECK_EQUAL((c.*test_int)("-0x155"), -0x155);
|
BOOST_CHECK_EQUAL((c.*test_int)("-0x155"), -0x155);
|
||||||
|
|
||||||
BOOST_CHECK_CLOSE((c.*test_double)("2.000000953656983160"),
|
|
||||||
2.000000953656983160, 1e-5);
|
|
||||||
/* this value has bit pattern 0x400000007fff6789L,
|
|
||||||
* so will look like a pointer if the endianness is set wrong
|
|
||||||
* (see naref.h, data.h)*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( parse_num )
|
BOOST_AUTO_TEST_CASE( parse_num )
|
||||||
|
|||||||
@@ -142,9 +142,6 @@ naRef naIOGhost(naContext c, FILE* f)
|
|||||||
return naNewGhost(c, &naIOGhostType, ghost);
|
return naNewGhost(c, &naIOGhostType, ghost);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SG_NASAL_UNRESTRICTED_OPEN
|
|
||||||
// Allows unrestricted file access, which would be a security hole
|
|
||||||
// Replaced by the one in flightgear src/Scripting/NasalSys.cxx
|
|
||||||
static naRef f_open(naContext c, naRef me, int argc, naRef* args)
|
static naRef f_open(naContext c, naRef me, int argc, naRef* args)
|
||||||
{
|
{
|
||||||
FILE* f;
|
FILE* f;
|
||||||
@@ -155,7 +152,6 @@ static naRef f_open(naContext c, naRef me, int argc, naRef* args)
|
|||||||
if(!f) naRuntimeError(c, strerror(errno));
|
if(!f) naRuntimeError(c, strerror(errno));
|
||||||
return naIOGhost(c, f);
|
return naIOGhost(c, f);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// frees buffer before tossing an error
|
// frees buffer before tossing an error
|
||||||
static int getcguard(naContext ctx, FILE* f, void* buf)
|
static int getcguard(naContext ctx, FILE* f, void* buf)
|
||||||
@@ -248,9 +244,7 @@ static naCFuncItem funcs[] = {
|
|||||||
{ "seek", f_seek },
|
{ "seek", f_seek },
|
||||||
{ "tell", f_tell },
|
{ "tell", f_tell },
|
||||||
{ "flush", f_flush },
|
{ "flush", f_flush },
|
||||||
#if SG_NASAL_UNRESTRICTED_OPEN
|
|
||||||
{ "open", f_open },
|
{ "open", f_open },
|
||||||
#endif
|
|
||||||
{ "readln", f_readln },
|
{ "readln", f_readln },
|
||||||
{ "stat", f_stat },
|
{ "stat", f_stat },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
#ifndef _IOLIB_H
|
#ifndef _IOLIB_H
|
||||||
#define _IOLIB_H
|
#define _IOLIB_H
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
|
|
||||||
@@ -36,7 +33,5 @@ extern struct naIOType naStdIOType;
|
|||||||
|
|
||||||
// Defined in iolib.c, there is no "library" header to put this in
|
// Defined in iolib.c, there is no "library" header to put this in
|
||||||
naRef naIOGhost(naContext c, FILE* f);
|
naRef naIOGhost(naContext c, FILE* f);
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
#endif // _IOLIB_H
|
#endif // _IOLIB_H
|
||||||
|
|||||||
+15
-18
@@ -1,31 +1,28 @@
|
|||||||
#ifndef _NAREF_H
|
#ifndef _NAREF_H
|
||||||
#define _NAREF_H
|
#define _NAREF_H
|
||||||
|
|
||||||
|
/* Rather than play elaborate and complicated games with
|
||||||
|
* platform-dependent endianness headers, just detect the platforms we
|
||||||
|
* support. This list is simpler and smaller, yet still quite
|
||||||
|
* complete. */
|
||||||
#if (defined(__x86_64) && defined(__linux__)) || defined(__sparcv9) || \
|
#if (defined(__x86_64) && defined(__linux__)) || defined(__sparcv9) || \
|
||||||
defined(__powerpc64__)
|
defined(__powerpc64__)
|
||||||
/* NASAL_NAN64 mode requires 64 bit pointers that only use the
|
/* Win64 and Irix should work with this too, but have not been
|
||||||
* lower 48 bits; Win64 and Irix should work with this too, but
|
* tested */
|
||||||
* have not been tested */
|
|
||||||
# define NASAL_NAN64
|
# define NASAL_NAN64
|
||||||
#elif defined(__BYTE_ORDER__)
|
#elif defined(_M_IX86) || defined(i386) || defined(__x86_64) || \
|
||||||
/* GCC and Clang define these (as a builtin, while
|
|
||||||
* __LITTLE_ENDIAN__ requires a header), MSVC doesn't */
|
|
||||||
# if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
|
|
||||||
# define NASAL_LE
|
|
||||||
# elif __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
|
|
||||||
# define NASAL_BE
|
|
||||||
# else
|
|
||||||
# error Unrecognized endianness
|
|
||||||
# endif
|
|
||||||
#elif defined(_M_IX86) || defined(__i386) || defined(__x86_64) || \
|
|
||||||
defined(__ia64__) || defined(_M_IA64) || defined(__ARMEL__) || \
|
defined(__ia64__) || defined(_M_IA64) || defined(__ARMEL__) || \
|
||||||
defined(_M_X64) || defined(_M_ARM)
|
defined(_M_X64) || defined(__alpha__) || \
|
||||||
|
(defined(__sh__) && defined(__LITTLE_ENDIAN__))
|
||||||
# define NASAL_LE
|
# define NASAL_LE
|
||||||
#elif defined(__sparc) || defined(__ARMEB__) || \
|
#elif defined(__sparc) || defined(__ppc__) || defined(__PPC) || \
|
||||||
defined(__hppa__) || defined(__s390__) || defined(__s390x__)
|
defined (__powerpc__) || defined (__powerpc64__) || defined (__alpha__) || \
|
||||||
|
defined(__mips) || defined(__ARMEB__) || \
|
||||||
|
defined(__hppa__) || defined(__s390__) || defined(__s390x__) || \
|
||||||
|
(defined(__sh__) && !defined(__LITTLE_ENDIAN__))
|
||||||
# define NASAL_BE
|
# define NASAL_BE
|
||||||
#else
|
#else
|
||||||
# error Unknown endianness
|
# error Unrecognized CPU architecture
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
|||||||
@@ -26,15 +26,3 @@ if(ENABLE_PKGUTIL)
|
|||||||
add_executable(sg_pkgutil pkgutil.cxx)
|
add_executable(sg_pkgutil pkgutil.cxx)
|
||||||
target_link_libraries(sg_pkgutil ${TEST_LIBS})
|
target_link_libraries(sg_pkgutil ${TEST_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_TESTS)
|
|
||||||
|
|
||||||
add_executable(catalog_test CatalogTest.cxx)
|
|
||||||
target_link_libraries(catalog_test ${TEST_LIBS})
|
|
||||||
|
|
||||||
set_target_properties(catalog_test PROPERTIES
|
|
||||||
COMPILE_DEFINITIONS "SRC_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}\"" )
|
|
||||||
|
|
||||||
add_test(catalog_test ${EXECUTABLE_OUTPUT_PATH}/catalog_test)
|
|
||||||
|
|
||||||
endif(ENABLE_TESTS)
|
|
||||||
+90
-219
@@ -31,56 +31,12 @@
|
|||||||
#include <simgear/package/Package.hxx>
|
#include <simgear/package/Package.hxx>
|
||||||
#include <simgear/package/Root.hxx>
|
#include <simgear/package/Root.hxx>
|
||||||
#include <simgear/package/Install.hxx>
|
#include <simgear/package/Install.hxx>
|
||||||
#include <simgear/misc/strutils.hxx>
|
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
|
|
||||||
namespace pkg {
|
namespace pkg {
|
||||||
|
|
||||||
bool checkVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
CatalogList static_catalogs;
|
||||||
{
|
|
||||||
BOOST_FOREACH(SGPropertyNode* v, props->getChildren("version")) {
|
|
||||||
std::string s(v->getStringValue());
|
|
||||||
if (s == aVersion) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// examine each dot-seperated component in turn, supporting a wildcard
|
|
||||||
// in the versions from the catalog.
|
|
||||||
string_list appVersionParts = simgear::strutils::split(aVersion, ".");
|
|
||||||
string_list catVersionParts = simgear::strutils::split(s, ".");
|
|
||||||
|
|
||||||
size_t partCount = appVersionParts.size();
|
|
||||||
if (partCount != catVersionParts.size()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ok = true;
|
|
||||||
for (unsigned int p=0; p < partCount; ++p) {
|
|
||||||
if (catVersionParts[p] == "*") {
|
|
||||||
// always passes
|
|
||||||
} else if (appVersionParts[p] != catVersionParts[p]) {
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string redirectUrlForVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
|
||||||
{
|
|
||||||
BOOST_FOREACH(SGPropertyNode* v, props->getChildren("alternate-version")) {
|
|
||||||
if (v->getStringValue("version") == aVersion) {
|
|
||||||
return v->getStringValue("url");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -90,32 +46,25 @@ public:
|
|||||||
Downloader(CatalogRef aOwner, const std::string& aUrl) :
|
Downloader(CatalogRef aOwner, const std::string& aUrl) :
|
||||||
HTTP::Request(aUrl),
|
HTTP::Request(aUrl),
|
||||||
m_owner(aOwner)
|
m_owner(aOwner)
|
||||||
{
|
{
|
||||||
// refreshing
|
|
||||||
m_owner->changeStatus(Delegate::STATUS_IN_PROGRESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void gotBodyData(const char* s, int n)
|
virtual void gotBodyData(const char* s, int n)
|
||||||
{
|
{
|
||||||
m_buffer += std::string(s, n);
|
m_buffer += std::string(s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDone()
|
virtual void onDone()
|
||||||
{
|
{
|
||||||
if (responseCode() != 200) {
|
if (responseCode() != 200) {
|
||||||
Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
|
SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url());
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url()
|
m_owner->refreshComplete(Delegate::FAIL_DOWNLOAD);
|
||||||
<< "\n\t" << responseCode());
|
|
||||||
if (responseCode() == 404) {
|
|
||||||
code = Delegate::FAIL_NOT_FOUND;
|
|
||||||
}
|
|
||||||
m_owner->refreshComplete(code);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode* props = new SGPropertyNode;
|
SGPropertyNode* props = new SGPropertyNode;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
readProperties(m_buffer.data(), m_buffer.size(), props);
|
readProperties(m_buffer.data(), m_buffer.size(), props);
|
||||||
m_owner->parseProps(props);
|
m_owner->parseProps(props);
|
||||||
@@ -124,37 +73,15 @@ protected:
|
|||||||
m_owner->refreshComplete(Delegate::FAIL_EXTRACT);
|
m_owner->refreshComplete(Delegate::FAIL_EXTRACT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_owner->root()->catalogVersion() != props->getIntValue("catalog-version")) {
|
std::string ver(m_owner->root()->catalogVersion());
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "catalog:" << m_owner->url() << " is not version "
|
|
||||||
<< m_owner->root()->catalogVersion());
|
|
||||||
m_owner->refreshComplete(Delegate::FAIL_VERSION);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string ver(m_owner->root()->applicationVersion());
|
|
||||||
if (!checkVersion(ver, props)) {
|
if (!checkVersion(ver, props)) {
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url() << ", version mismatch:\n\t"
|
SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url() << ", version mismatch:\n\t"
|
||||||
<< props->getStringValue("version") << " vs required " << ver);
|
<< props->getStringValue("version") << " vs required " << ver);
|
||||||
|
m_owner->refreshComplete(Delegate::FAIL_VERSION);
|
||||||
// check for a version redirect entry
|
|
||||||
std::string url = redirectUrlForVersion(ver, props);
|
|
||||||
if (!url.empty()) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "redirecting from " << m_owner->url() <<
|
|
||||||
" to \n\t" << url);
|
|
||||||
|
|
||||||
// update the URL and kick off a new request
|
|
||||||
m_owner->m_url = url;
|
|
||||||
Downloader* dl = new Downloader(m_owner, url);
|
|
||||||
m_owner->root()->makeHTTPRequest(dl);
|
|
||||||
} else {
|
|
||||||
m_owner->refreshComplete(Delegate::FAIL_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} // of version check failed
|
}
|
||||||
|
|
||||||
// cache the catalog data, now we have a valid install root
|
// cache the catalog data, now we have a valid install root
|
||||||
Dir d(m_owner->installRoot());
|
Dir d(m_owner->installRoot());
|
||||||
SGPath p = d.file("catalog.xml");
|
SGPath p = d.file("catalog.xml");
|
||||||
@@ -162,39 +89,57 @@ protected:
|
|||||||
std::ofstream f(p.c_str(), std::ios::out | std::ios::trunc);
|
std::ofstream f(p.c_str(), std::ios::out | std::ios::trunc);
|
||||||
f.write(m_buffer.data(), m_buffer.size());
|
f.write(m_buffer.data(), m_buffer.size());
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
time(&m_owner->m_retrievedTime);
|
time(&m_owner->m_retrievedTime);
|
||||||
m_owner->writeTimestamp();
|
m_owner->writeTimestamp();
|
||||||
m_owner->refreshComplete(Delegate::STATUS_REFRESHED);
|
m_owner->refreshComplete(Delegate::FAIL_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool checkVersion(const std::string& aVersion, SGPropertyNode* aProps)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(SGPropertyNode* v, aProps->getChildren("version")) {
|
||||||
|
if (v->getStringValue() == aVersion) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
CatalogRef m_owner;
|
CatalogRef m_owner;
|
||||||
std::string m_buffer;
|
std::string m_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
CatalogList Catalog::allCatalogs()
|
||||||
|
{
|
||||||
|
return static_catalogs;
|
||||||
|
}
|
||||||
|
|
||||||
Catalog::Catalog(Root *aRoot) :
|
Catalog::Catalog(Root *aRoot) :
|
||||||
m_root(aRoot),
|
m_root(aRoot),
|
||||||
m_status(Delegate::FAIL_UNKNOWN),
|
|
||||||
m_retrievedTime(0)
|
m_retrievedTime(0)
|
||||||
{
|
{
|
||||||
|
static_catalogs.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Catalog::~Catalog()
|
Catalog::~Catalog()
|
||||||
{
|
{
|
||||||
|
CatalogList::iterator it = std::find(static_catalogs.begin(), static_catalogs.end(), this);
|
||||||
|
static_catalogs.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
CatalogRef Catalog::createFromUrl(Root* aRoot, const std::string& aUrl)
|
CatalogRef Catalog::createFromUrl(Root* aRoot, const std::string& aUrl)
|
||||||
{
|
{
|
||||||
CatalogRef c = new Catalog(aRoot);
|
CatalogRef c = new Catalog(aRoot);
|
||||||
c->m_url = aUrl;
|
c->m_url = aUrl;
|
||||||
c->refresh();
|
Downloader* dl = new Downloader(c, aUrl);
|
||||||
|
aRoot->makeHTTPRequest(dl);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
|
CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
|
||||||
{
|
{
|
||||||
SGPath xml = aPath;
|
SGPath xml = aPath;
|
||||||
@@ -202,66 +147,29 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
|
|||||||
if (!xml.exists()) {
|
if (!xml.exists()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode_ptr props;
|
SGPropertyNode_ptr props;
|
||||||
try {
|
try {
|
||||||
props = new SGPropertyNode;
|
props = new SGPropertyNode;
|
||||||
readProperties(xml.str(), props);
|
readProperties(xml.str(), props);
|
||||||
} catch (sg_exception& e) {
|
} catch (sg_exception& e) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props->getStringValue("version") != aRoot->catalogVersion()) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_WARN, "skipping catalog at " << aPath << ", version mismatch:\n\t"
|
||||||
|
<< props->getStringValue("version") << " vs required " << aRoot->catalogVersion());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool versionCheckOk = checkVersion(aRoot->applicationVersion(), props);
|
|
||||||
|
|
||||||
if (!versionCheckOk) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "catalog at:" << aPath << " failed version check: need" << aRoot->applicationVersion());
|
|
||||||
// keep the catalog but mark it as needing an update
|
|
||||||
} else {
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "creating catalog from:" << aPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
CatalogRef c = new Catalog(aRoot);
|
CatalogRef c = new Catalog(aRoot);
|
||||||
c->m_installRoot = aPath;
|
c->m_installRoot = aPath;
|
||||||
c->parseProps(props);
|
c->parseProps(props);
|
||||||
c->parseTimestamp();
|
c->parseTimestamp();
|
||||||
|
|
||||||
if (versionCheckOk) {
|
|
||||||
// parsed XML ok, mark status as valid
|
|
||||||
c->changeStatus(Delegate::STATUS_SUCCESS);
|
|
||||||
} else {
|
|
||||||
c->changeStatus(Delegate::FAIL_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Catalog::uninstall()
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
bool atLeastOneFailure = false;
|
|
||||||
|
|
||||||
BOOST_FOREACH(PackageRef p, installedPackages()) {
|
|
||||||
ok = p->existingInstall()->uninstall();
|
|
||||||
if (!ok) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "uninstall of package " <<
|
|
||||||
p->id() << " failed");
|
|
||||||
// continue trying other packages, bailing out here
|
|
||||||
// gains us nothing
|
|
||||||
atLeastOneFailure = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Dir d(m_installRoot);
|
|
||||||
ok = d.remove(true /* recursive */);
|
|
||||||
if (!ok) {
|
|
||||||
atLeastOneFailure = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
changeStatus(atLeastOneFailure ? Delegate::FAIL_FILESYSTEM
|
|
||||||
: Delegate::STATUS_SUCCESS);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageList const&
|
PackageList const&
|
||||||
Catalog::packages() const
|
Catalog::packages() const
|
||||||
{
|
{
|
||||||
@@ -288,7 +196,7 @@ Catalog::packagesNeedingUpdate() const
|
|||||||
if (!p->isInstalled()) {
|
if (!p->isInstalled()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->install()->hasUpdate()) {
|
if (p->install()->hasUpdate()) {
|
||||||
r.push_back(p);
|
r.push_back(p);
|
||||||
}
|
}
|
||||||
@@ -307,32 +215,31 @@ Catalog::installedPackages() const
|
|||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InstallRef Catalog::installForPackage(PackageRef pkg) const
|
||||||
|
{
|
||||||
|
PackageInstallDict::const_iterator it = m_installed.find(pkg);
|
||||||
|
if (it == m_installed.end()) {
|
||||||
|
// check if it exists on disk, create
|
||||||
|
|
||||||
|
SGPath p(pkg->pathOnDisk());
|
||||||
|
if (p.exists()) {
|
||||||
|
return Install::createFromPath(p, CatalogRef(const_cast<Catalog*>(this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
void Catalog::refresh()
|
void Catalog::refresh()
|
||||||
{
|
{
|
||||||
if (m_refreshRequest.valid()) {
|
|
||||||
// refresh in progress
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Downloader* dl = new Downloader(this, url());
|
Downloader* dl = new Downloader(this, url());
|
||||||
m_refreshRequest = dl;
|
|
||||||
// will update status to IN_PROGRESS
|
|
||||||
m_root->makeHTTPRequest(dl);
|
m_root->makeHTTPRequest(dl);
|
||||||
|
m_root->catalogRefreshBegin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FindById
|
|
||||||
{
|
|
||||||
FindById(const std::string &id) : m_id(id) {}
|
|
||||||
|
|
||||||
bool operator()(const PackageRef& ref) const
|
|
||||||
{
|
|
||||||
return ref->id() == m_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string m_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
void Catalog::parseProps(const SGPropertyNode* aProps)
|
void Catalog::parseProps(const SGPropertyNode* aProps)
|
||||||
{
|
{
|
||||||
// copy everything except package children?
|
// copy everything except package children?
|
||||||
@@ -346,14 +253,8 @@ void Catalog::parseProps(const SGPropertyNode* aProps)
|
|||||||
for (int i = 0; i < nChildren; i++) {
|
for (int i = 0; i < nChildren; i++) {
|
||||||
const SGPropertyNode* pkgProps = aProps->getChild(i);
|
const SGPropertyNode* pkgProps = aProps->getChild(i);
|
||||||
if (strcmp(pkgProps->getName(), "package") == 0) {
|
if (strcmp(pkgProps->getName(), "package") == 0) {
|
||||||
// can't use getPackageById here becuase the variant dict isn't
|
PackageRef p = getPackageById(pkgProps->getStringValue("id"));
|
||||||
// built yet. Instead we need to look at m_packages directly.
|
if (p) {
|
||||||
|
|
||||||
PackageList::iterator pit = std::find_if(m_packages.begin(), m_packages.end(),
|
|
||||||
FindById(pkgProps->getStringValue("id")));
|
|
||||||
PackageRef p;
|
|
||||||
if (pit != m_packages.end()) {
|
|
||||||
p = *pit;
|
|
||||||
// existing package
|
// existing package
|
||||||
p->updateFromProps(pkgProps);
|
p->updateFromProps(pkgProps);
|
||||||
orphans.erase(p); // not an orphan
|
orphans.erase(p); // not an orphan
|
||||||
@@ -393,13 +294,13 @@ void Catalog::parseProps(const SGPropertyNode* aProps)
|
|||||||
<< " is now at: " << m_props->getStringValue("url"));
|
<< " is now at: " << m_props->getStringValue("url"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_url = m_props->getStringValue("url");
|
m_url = m_props->getStringValue("url");
|
||||||
|
|
||||||
if (m_installRoot.isNull()) {
|
if (m_installRoot.isNull()) {
|
||||||
m_installRoot = m_root->path();
|
m_installRoot = m_root->path();
|
||||||
m_installRoot.append(id());
|
m_installRoot.append(id());
|
||||||
|
|
||||||
Dir d(m_installRoot);
|
Dir d(m_installRoot);
|
||||||
d.create(0755);
|
d.create(0755);
|
||||||
}
|
}
|
||||||
@@ -411,23 +312,11 @@ PackageRef Catalog::getPackageById(const std::string& aId) const
|
|||||||
// works as expected.
|
// works as expected.
|
||||||
PackageWeakMap::const_iterator it = m_variantDict.find(aId);
|
PackageWeakMap::const_iterator it = m_variantDict.find(aId);
|
||||||
if (it == m_variantDict.end())
|
if (it == m_variantDict.end())
|
||||||
return PackageRef();
|
return NULL;
|
||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageRef Catalog::getPackageByPath(const std::string& aPath) const
|
|
||||||
{
|
|
||||||
PackageList::const_iterator it;
|
|
||||||
for (it = m_packages.begin(); it != m_packages.end(); ++it) {
|
|
||||||
if ((*it)->dirName() == aPath) {
|
|
||||||
return *it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PackageRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Catalog::id() const
|
std::string Catalog::id() const
|
||||||
{
|
{
|
||||||
return m_props->getStringValue("id");
|
return m_props->getStringValue("id");
|
||||||
@@ -438,16 +327,11 @@ std::string Catalog::url() const
|
|||||||
return m_url;
|
return m_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Catalog::name() const
|
|
||||||
{
|
|
||||||
return getLocalisedString(m_props, "name");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Catalog::description() const
|
std::string Catalog::description() const
|
||||||
{
|
{
|
||||||
return getLocalisedString(m_props, "description");
|
return getLocalisedString(m_props, "description");
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode* Catalog::properties() const
|
SGPropertyNode* Catalog::properties() const
|
||||||
{
|
{
|
||||||
return m_props.ptr();
|
return m_props.ptr();
|
||||||
@@ -479,56 +363,43 @@ unsigned int Catalog::ageInSeconds() const
|
|||||||
|
|
||||||
bool Catalog::needsRefresh() const
|
bool Catalog::needsRefresh() const
|
||||||
{
|
{
|
||||||
// always refresh in these cases
|
|
||||||
if ((m_status == Delegate::FAIL_VERSION) || (m_status == Delegate::FAIL_DOWNLOAD)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int maxAge = m_props->getIntValue("max-age-sec", m_root->maxAgeSeconds());
|
unsigned int maxAge = m_props->getIntValue("max-age-sec", m_root->maxAgeSeconds());
|
||||||
return (ageInSeconds() > maxAge);
|
return (ageInSeconds() > maxAge);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Catalog::getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const
|
std::string Catalog::getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const
|
||||||
{
|
{
|
||||||
if (!aRoot) {
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aRoot->hasChild(m_root->getLocale())) {
|
if (aRoot->hasChild(m_root->getLocale())) {
|
||||||
const SGPropertyNode* localeRoot = aRoot->getChild(m_root->getLocale().c_str());
|
const SGPropertyNode* localeRoot = aRoot->getChild(m_root->getLocale().c_str());
|
||||||
if (localeRoot->hasChild(aName)) {
|
if (localeRoot->hasChild(aName)) {
|
||||||
return localeRoot->getStringValue(aName);
|
return localeRoot->getStringValue(aName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return aRoot->getStringValue(aName);
|
return aRoot->getStringValue(aName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Catalog::refreshComplete(Delegate::StatusCode aReason)
|
void Catalog::refreshComplete(Delegate::FailureCode aReason)
|
||||||
{
|
{
|
||||||
changeStatus(aReason);
|
m_root->catalogRefreshComplete(this, aReason);
|
||||||
m_refreshRequest.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Catalog::changeStatus(Delegate::StatusCode newStatus)
|
void Catalog::registerInstall(Install* ins)
|
||||||
{
|
{
|
||||||
if (m_status == newStatus) {
|
if (!ins || ins->package()->catalog() != this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_status = newStatus;
|
m_installed[ins->package()] = ins;
|
||||||
m_root->catalogRefreshStatus(this, newStatus);
|
|
||||||
m_statusCallbacks(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Catalog::addStatusCallback(const Callback& cb)
|
void Catalog::unregisterInstall(Install* ins)
|
||||||
{
|
{
|
||||||
m_statusCallbacks.push_back(cb);
|
if (!ins || ins->package()->catalog() != this) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
Delegate::StatusCode Catalog::status() const
|
|
||||||
{
|
m_installed.erase(ins->package());
|
||||||
return m_status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|||||||
+38
-56
@@ -22,23 +22,19 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
|
|
||||||
#include <simgear/structure/SGReferenced.hxx>
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
#include <simgear/structure/function_list.hxx>
|
|
||||||
#include <simgear/io/HTTPRequest.hxx>
|
|
||||||
|
|
||||||
#include <simgear/package/Delegate.hxx>
|
#include <simgear/package/Delegate.hxx>
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace HTTP { class Client; }
|
namespace HTTP { class Client; }
|
||||||
|
|
||||||
namespace pkg
|
namespace pkg
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -47,11 +43,11 @@ class Package;
|
|||||||
class Catalog;
|
class Catalog;
|
||||||
class Root;
|
class Root;
|
||||||
class Install;
|
class Install;
|
||||||
|
|
||||||
typedef SGSharedPtr<Package> PackageRef;
|
typedef SGSharedPtr<Package> PackageRef;
|
||||||
typedef SGSharedPtr<Catalog> CatalogRef;
|
typedef SGSharedPtr<Catalog> CatalogRef;
|
||||||
typedef SGSharedPtr<Install> InstallRef;
|
typedef SGSharedPtr<Install> InstallRef;
|
||||||
|
|
||||||
typedef std::vector<PackageRef> PackageList;
|
typedef std::vector<PackageRef> PackageList;
|
||||||
typedef std::vector<CatalogRef> CatalogList;
|
typedef std::vector<CatalogRef> CatalogList;
|
||||||
|
|
||||||
@@ -59,19 +55,16 @@ class Catalog : public SGReferenced
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Catalog();
|
virtual ~Catalog();
|
||||||
|
|
||||||
static CatalogRef createFromUrl(Root* aRoot, const std::string& aUrl);
|
static CatalogRef createFromUrl(Root* aRoot, const std::string& aUrl);
|
||||||
|
|
||||||
static CatalogRef createFromPath(Root* aRoot, const SGPath& aPath);
|
static CatalogRef createFromPath(Root* aRoot, const SGPath& aPath);
|
||||||
|
|
||||||
|
static CatalogList allCatalogs();
|
||||||
|
|
||||||
Root* root() const
|
Root* root() const
|
||||||
{ return m_root;};
|
{ return m_root;};
|
||||||
|
|
||||||
/**
|
|
||||||
* uninstall this catalog entirely, including all installed packages
|
|
||||||
*/
|
|
||||||
bool uninstall();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* perform a refresh of the catalog contents
|
* perform a refresh of the catalog contents
|
||||||
*/
|
*/
|
||||||
@@ -96,81 +89,70 @@ public:
|
|||||||
/**
|
/**
|
||||||
* retrieve all the packages in the catalog which are installed
|
* retrieve all the packages in the catalog which are installed
|
||||||
* and have a pendig update
|
* and have a pendig update
|
||||||
*/
|
*/
|
||||||
PackageList packagesNeedingUpdate() const;
|
PackageList packagesNeedingUpdate() const;
|
||||||
|
|
||||||
SGPath installRoot() const
|
SGPath installRoot() const
|
||||||
{ return m_installRoot; }
|
{ return m_installRoot; }
|
||||||
|
|
||||||
std::string id() const;
|
std::string id() const;
|
||||||
|
|
||||||
std::string url() const;
|
std::string url() const;
|
||||||
|
|
||||||
std::string name() const;
|
|
||||||
|
|
||||||
std::string description() const;
|
std::string description() const;
|
||||||
|
|
||||||
PackageRef getPackageById(const std::string& aId) const;
|
PackageRef getPackageById(const std::string& aId) const;
|
||||||
|
|
||||||
PackageRef getPackageByPath(const std::string& aPath) const;
|
InstallRef installForPackage(PackageRef pkg) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test if the catalog data was retrieved longer ago than the
|
* test if the catalog data was retrieved longer ago than the
|
||||||
* maximum permitted age for this catalog.
|
* maximum permitted age for this catalog.
|
||||||
*/
|
*/
|
||||||
bool needsRefresh() const;
|
bool needsRefresh() const;
|
||||||
|
|
||||||
unsigned int ageInSeconds() const;
|
unsigned int ageInSeconds() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* access the raw property data in the catalog
|
* access the raw property data in the catalog
|
||||||
*/
|
*/
|
||||||
SGPropertyNode* properties() const;
|
SGPropertyNode* properties() const;
|
||||||
|
|
||||||
Delegate::StatusCode status() const;
|
|
||||||
|
|
||||||
typedef boost::function<void(Catalog*)> Callback;
|
|
||||||
|
|
||||||
void addStatusCallback(const Callback& cb);
|
|
||||||
|
|
||||||
template<class C>
|
|
||||||
void addStatusCallback(C* instance, void (C::*mem_func)(Catalog*))
|
|
||||||
{
|
|
||||||
return addStatusCallback(boost::bind(mem_func, instance, _1));
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
Catalog(Root* aRoot);
|
Catalog(Root* aRoot);
|
||||||
|
|
||||||
class Downloader;
|
class Downloader;
|
||||||
friend class Downloader;
|
friend class Downloader;
|
||||||
|
|
||||||
|
friend class Install;
|
||||||
|
void registerInstall(Install* ins);
|
||||||
|
void unregisterInstall(Install* ins);
|
||||||
|
|
||||||
void parseProps(const SGPropertyNode* aProps);
|
void parseProps(const SGPropertyNode* aProps);
|
||||||
|
|
||||||
void refreshComplete(Delegate::StatusCode aReason);
|
void refreshComplete(Delegate::FailureCode aReason);
|
||||||
|
|
||||||
void parseTimestamp();
|
void parseTimestamp();
|
||||||
void writeTimestamp();
|
void writeTimestamp();
|
||||||
|
|
||||||
std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const;
|
std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const;
|
||||||
|
|
||||||
void changeStatus(Delegate::StatusCode newStatus);
|
|
||||||
|
|
||||||
Root* m_root;
|
Root* m_root;
|
||||||
SGPropertyNode_ptr m_props;
|
SGPropertyNode_ptr m_props;
|
||||||
SGPath m_installRoot;
|
SGPath m_installRoot;
|
||||||
std::string m_url;
|
std::string m_url;
|
||||||
Delegate::StatusCode m_status;
|
|
||||||
HTTP::Request_ptr m_refreshRequest;
|
|
||||||
|
|
||||||
PackageList m_packages;
|
PackageList m_packages;
|
||||||
time_t m_retrievedTime;
|
time_t m_retrievedTime;
|
||||||
|
|
||||||
typedef std::map<std::string, Package*> PackageWeakMap;
|
typedef std::map<std::string, Package*> PackageWeakMap;
|
||||||
PackageWeakMap m_variantDict;
|
PackageWeakMap m_variantDict;
|
||||||
|
|
||||||
function_list<Callback> m_statusCallbacks;
|
// important that this is a weak-ref to Installs,
|
||||||
|
// since it is only cleaned up in the Install destructor
|
||||||
|
typedef std::map<PackageRef, Install*> PackageInstallDict;
|
||||||
|
PackageInstallDict m_installed;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|
||||||
} // of namespace simgear
|
} // of namespace simgear
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
// Copyright (C) 2015 James Turner - zakalawe@mac.com
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Library General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include <simgear_config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <simgear/misc/test_macros.hxx>
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <simgear/package/Catalog.hxx>
|
|
||||||
#include <simgear/package/Root.hxx>
|
|
||||||
#include <simgear/package/Package.hxx>
|
|
||||||
|
|
||||||
#include <simgear/misc/sg_dir.hxx>
|
|
||||||
|
|
||||||
using namespace simgear;
|
|
||||||
|
|
||||||
int parseTest()
|
|
||||||
{
|
|
||||||
SGPath rootPath = simgear::Dir::current().path();
|
|
||||||
rootPath.append("testRoot");
|
|
||||||
pkg::Root* root = new pkg::Root(rootPath, "8.1.12");
|
|
||||||
pkg::CatalogRef cat = pkg::Catalog::createFromPath(root, SGPath(SRC_DIR "/catalogTest1"));
|
|
||||||
|
|
||||||
VERIFY(cat.valid());
|
|
||||||
|
|
||||||
COMPARE(cat->id(), "org.flightgear.test.catalog1");
|
|
||||||
COMPARE(cat->url(), "http://download.flightgear.org/catalog1/catalog.xml");
|
|
||||||
COMPARE(cat->description(), "First test catalog");
|
|
||||||
|
|
||||||
// check the packages too
|
|
||||||
COMPARE(cat->packages().size(), 3);
|
|
||||||
|
|
||||||
pkg::PackageRef p1 = cat->packages().front();
|
|
||||||
COMPARE(p1->catalog(), cat.ptr());
|
|
||||||
|
|
||||||
COMPARE(p1->id(), "alpha");
|
|
||||||
COMPARE(p1->qualifiedId(), "org.flightgear.test.catalog1.alpha");
|
|
||||||
COMPARE(p1->name(), "Alpha package");
|
|
||||||
COMPARE(p1->revision(), 8);
|
|
||||||
COMPARE(p1->fileSizeBytes(), 1234567);
|
|
||||||
|
|
||||||
|
|
||||||
pkg::PackageRef p2 = cat->getPackageById("c172p");
|
|
||||||
VERIFY(p2.valid());
|
|
||||||
COMPARE(p2->qualifiedId(), "org.flightgear.test.catalog1.c172p");
|
|
||||||
COMPARE(p2->description(), "A plane made by Cessna");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// test filtering / searching too
|
|
||||||
string_set tags(p2->tags());
|
|
||||||
COMPARE(tags.size(), 4);
|
|
||||||
VERIFY(tags.find("ifr") != tags.end());
|
|
||||||
VERIFY(tags.find("cessna") != tags.end());
|
|
||||||
VERIFY(tags.find("jet") == tags.end());
|
|
||||||
|
|
||||||
|
|
||||||
SGPropertyNode_ptr queryA(new SGPropertyNode);
|
|
||||||
queryA->setStringValue("tag", "ifr");
|
|
||||||
VERIFY(p2->matches(queryA.ptr()));
|
|
||||||
|
|
||||||
SGPropertyNode_ptr queryB(new SGPropertyNode);
|
|
||||||
queryB->setStringValue("name", "ces");
|
|
||||||
VERIFY(p2->matches(queryB.ptr()));
|
|
||||||
|
|
||||||
SGPropertyNode_ptr queryC(new SGPropertyNode);
|
|
||||||
queryC->setStringValue("name", "foo");
|
|
||||||
VERIFY(!p2->matches(queryC.ptr()));
|
|
||||||
|
|
||||||
SGPropertyNode_ptr queryD(new SGPropertyNode);
|
|
||||||
queryD->setIntValue("rating-FDM", 3);
|
|
||||||
VERIFY(p2->matches(queryD.ptr()));
|
|
||||||
|
|
||||||
SGPropertyNode_ptr queryE(new SGPropertyNode);
|
|
||||||
queryE->setIntValue("rating-model", 5);
|
|
||||||
queryE->setStringValue("description", "cessna");
|
|
||||||
VERIFY(p2->matches(queryE.ptr()));
|
|
||||||
|
|
||||||
|
|
||||||
delete root;
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
parseTest();
|
|
||||||
std::cout << "Successfully passed all tests!" << std::endl;
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
@@ -18,21 +18,15 @@
|
|||||||
#ifndef SG_PACKAGE_DELEGATE_HXX
|
#ifndef SG_PACKAGE_DELEGATE_HXX
|
||||||
#define SG_PACKAGE_DELEGATE_HXX
|
#define SG_PACKAGE_DELEGATE_HXX
|
||||||
|
|
||||||
#include <simgear/misc/stdint.hxx>
|
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace pkg
|
namespace pkg
|
||||||
{
|
{
|
||||||
|
|
||||||
class Install;
|
class Install;
|
||||||
class Catalog;
|
class Catalog;
|
||||||
|
|
||||||
typedef SGSharedPtr<Catalog> CatalogRef;
|
|
||||||
typedef SGSharedPtr<Install> InstallRef;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* package delegate is the mechanism to discover progress / completion /
|
* package delegate is the mechanism to discover progress / completion /
|
||||||
* errors in packaging steps asynchronously.
|
* errors in packaging steps asynchronously.
|
||||||
@@ -41,42 +35,40 @@ class Delegate
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef enum {
|
typedef enum {
|
||||||
STATUS_SUCCESS = 0,
|
FAIL_SUCCESS = 0, ///< not a failure :)
|
||||||
FAIL_UNKNOWN = 1,
|
FAIL_UNKNOWN = 1,
|
||||||
STATUS_IN_PROGRESS, ///< downloading/installation in progress
|
FAIL_IN_PROGRESS, ///< downloading/installation in progress (not a failure :P)
|
||||||
FAIL_CHECKSUM, ///< package MD5 verificstion failed
|
FAIL_CHECKSUM, ///< package MD5 verificstion failed
|
||||||
FAIL_DOWNLOAD, ///< network issue
|
FAIL_DOWNLOAD, ///< network issue
|
||||||
FAIL_EXTRACT, ///< package archive failed to extract cleanly
|
FAIL_EXTRACT, ///< package archive failed to extract cleanly
|
||||||
FAIL_FILESYSTEM, ///< unknown filesystem error occurred
|
FAIL_FILESYSTEM, ///< unknown filesystem error occurred
|
||||||
FAIL_VERSION, ///< version check mismatch
|
FAIL_VERSION ///< version check mismatch
|
||||||
FAIL_NOT_FOUND, ///< package URL returned a 404
|
} FailureCode;
|
||||||
STATUS_REFRESHED,
|
|
||||||
USER_CANCELLED
|
|
||||||
} StatusCode;
|
|
||||||
|
|
||||||
|
|
||||||
virtual ~Delegate() { }
|
virtual ~Delegate() { }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* emitted when a catalog refesh completes, either success or failure
|
* invoked when all catalogs have finished refreshing - either successfully
|
||||||
* If catalog is null, this means /all/ catalogs have been refreshed
|
* or with a failure.
|
||||||
*/
|
*/
|
||||||
virtual void catalogRefreshed(CatalogRef, StatusCode aReason) = 0;
|
virtual void refreshComplete() = 0;
|
||||||
|
|
||||||
virtual void startInstall(InstallRef aInstall) = 0;
|
|
||||||
virtual void installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal) = 0;
|
|
||||||
virtual void finishInstall(InstallRef aInstall, StatusCode aReason) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification when catalogs/packages are added or removed
|
* emitted when a catalog fails to refresh, due to a network issue or
|
||||||
|
* some other failure.
|
||||||
*/
|
*/
|
||||||
virtual void availablePackagesChanged() {}
|
virtual void failedRefresh(Catalog*, FailureCode aReason) = 0;
|
||||||
|
|
||||||
virtual void dataForThumbnail(const std::string& aThumbnailUrl,
|
virtual void startInstall(Install* aInstall) = 0;
|
||||||
size_t lenth, const uint8_t* bytes) {}
|
virtual void installProgress(Install* aInstall, unsigned int aBytes, unsigned int aTotal) = 0;
|
||||||
};
|
virtual void finishInstall(Install* aInstall) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void failedInstall(Install* aInstall, FailureCode aReason) = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|
||||||
} // of namespace simgear
|
} // of namespace simgear
|
||||||
|
|||||||
+74
-208
@@ -24,7 +24,6 @@
|
|||||||
#include <simgear/package/md5.h>
|
#include <simgear/package/md5.h>
|
||||||
|
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <simgear/props/props_io.hxx>
|
|
||||||
#include <simgear/package/Catalog.hxx>
|
#include <simgear/package/Catalog.hxx>
|
||||||
#include <simgear/package/Package.hxx>
|
#include <simgear/package/Package.hxx>
|
||||||
#include <simgear/package/Root.hxx>
|
#include <simgear/package/Root.hxx>
|
||||||
@@ -38,7 +37,7 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
|
|
||||||
namespace pkg {
|
namespace pkg {
|
||||||
|
|
||||||
class Install::PackageArchiveDownloader : public HTTP::Request
|
class Install::PackageArchiveDownloader : public HTTP::Request
|
||||||
@@ -46,87 +45,48 @@ class Install::PackageArchiveDownloader : public HTTP::Request
|
|||||||
public:
|
public:
|
||||||
PackageArchiveDownloader(InstallRef aOwner) :
|
PackageArchiveDownloader(InstallRef aOwner) :
|
||||||
HTTP::Request("" /* dummy URL */),
|
HTTP::Request("" /* dummy URL */),
|
||||||
m_owner(aOwner),
|
m_owner(aOwner)
|
||||||
m_downloaded(0)
|
|
||||||
{
|
{
|
||||||
m_urls = m_owner->package()->downloadUrls();
|
m_urls = m_owner->package()->downloadUrls();
|
||||||
if (m_urls.empty()) {
|
if (m_urls.empty()) {
|
||||||
throw sg_exception("no package download URLs");
|
throw sg_exception("no package download URLs");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO randomise order of m_urls
|
// TODO randomise order of m_urls
|
||||||
|
|
||||||
m_extractPath = aOwner->path().dir();
|
m_extractPath = aOwner->path().dir();
|
||||||
m_extractPath.append("_extract_" + aOwner->package()->md5());
|
m_extractPath.append("_DOWNLOAD"); // add some temporary value
|
||||||
|
|
||||||
// clean up any existing files
|
|
||||||
Dir d(m_extractPath);
|
|
||||||
if (d.exists()) {
|
|
||||||
d.remove(true /* recursive */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~PackageArchiveDownloader()
|
|
||||||
{
|
|
||||||
// always clean up our extraction dir: if we successfully downloaded
|
|
||||||
// and installed it will be an empty dir, if we failed it might contain
|
|
||||||
// (some) of the package files.
|
|
||||||
Dir d(m_extractPath);
|
|
||||||
if (d.exists()) {
|
|
||||||
d.remove(true /* recursive */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t downloadedBytes() const
|
|
||||||
{
|
|
||||||
return m_downloaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
int percentDownloaded() const
|
|
||||||
{
|
|
||||||
if (responseLength() <= 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (m_downloaded * 100) / responseLength();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual std::string url() const
|
virtual std::string url() const
|
||||||
{
|
{
|
||||||
return m_urls.front();
|
return m_urls.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void responseHeadersComplete()
|
virtual void responseHeadersComplete()
|
||||||
{
|
{
|
||||||
Request::responseHeadersComplete();
|
|
||||||
|
|
||||||
Dir d(m_extractPath);
|
Dir d(m_extractPath);
|
||||||
d.create(0755);
|
d.create(0755);
|
||||||
|
|
||||||
memset(&m_md5, 0, sizeof(SG_MD5_CTX));
|
memset(&m_md5, 0, sizeof(SG_MD5_CTX));
|
||||||
SG_MD5Init(&m_md5);
|
SG_MD5Init(&m_md5);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void gotBodyData(const char* s, int n)
|
virtual void gotBodyData(const char* s, int n)
|
||||||
{
|
{
|
||||||
m_buffer += std::string(s, n);
|
m_buffer += std::string(s, n);
|
||||||
SG_MD5Update(&m_md5, (unsigned char*) s, n);
|
SG_MD5Update(&m_md5, (unsigned char*) s, n);
|
||||||
|
|
||||||
m_downloaded = m_buffer.size();
|
|
||||||
m_owner->installProgress(m_buffer.size(), responseLength());
|
m_owner->installProgress(m_buffer.size(), responseLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDone()
|
virtual void onDone()
|
||||||
{
|
{
|
||||||
if (responseCode() != 200) {
|
if (responseCode() != 200) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "download failure:" << responseCode() <<
|
SG_LOG(SG_GENERAL, SG_ALERT, "download failure");
|
||||||
"\n\t" << url());
|
doFailure(Delegate::FAIL_DOWNLOAD);
|
||||||
Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
|
|
||||||
if (responseCode() == 404) {
|
|
||||||
code = Delegate::FAIL_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
doFailure(code);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,79 +103,65 @@ protected:
|
|||||||
doFailure(Delegate::FAIL_CHECKSUM);
|
doFailure(Delegate::FAIL_CHECKSUM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!extractUnzip()) {
|
if (!extractUnzip()) {
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "zip extraction failed");
|
SG_LOG(SG_GENERAL, SG_WARN, "zip extraction failed");
|
||||||
doFailure(Delegate::FAIL_EXTRACT);
|
doFailure(Delegate::FAIL_EXTRACT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_owner->path().exists()) {
|
if (m_owner->path().exists()) {
|
||||||
|
//std::cout << "removing existing path" << std::endl;
|
||||||
Dir destDir(m_owner->path());
|
Dir destDir(m_owner->path());
|
||||||
destDir.remove(true /* recursive */);
|
destDir.remove(true /* recursive */);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a path like /path/to/packages/org.some.catalog/Aircraft/extract_xxxx/MyAircraftDir
|
m_extractPath.append(m_owner->package()->id());
|
||||||
SGPath extractedPath = m_extractPath;
|
bool ok = m_extractPath.rename(m_owner->path());
|
||||||
extractedPath.append(m_owner->package()->dirName());
|
|
||||||
|
|
||||||
// rename it to path/to/packages/org.some.catalog/Aircraft/MyAircraftDir
|
|
||||||
bool ok = extractedPath.rename(m_owner->path());
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
doFailure(Delegate::FAIL_FILESYSTEM);
|
doFailure(Delegate::FAIL_FILESYSTEM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_owner->m_revision = m_owner->package()->revision();
|
m_owner->m_revision = m_owner->package()->revision();
|
||||||
m_owner->writeRevisionFile();
|
m_owner->writeRevisionFile();
|
||||||
m_owner->m_download.reset(); // so isDownloading reports false
|
m_owner->installResult(Delegate::FAIL_SUCCESS);
|
||||||
|
|
||||||
m_owner->installResult(Delegate::STATUS_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onFail()
|
|
||||||
{
|
|
||||||
if (responseCode() == -1) {
|
|
||||||
doFailure(Delegate::USER_CANCELLED);
|
|
||||||
} else {
|
|
||||||
doFailure(Delegate::FAIL_DOWNLOAD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void extractCurrentFile(unzFile zip, char* buffer, size_t bufferSize)
|
void extractCurrentFile(unzFile zip, char* buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
unz_file_info fileInfo;
|
unz_file_info fileInfo;
|
||||||
unzGetCurrentFileInfo(zip, &fileInfo,
|
unzGetCurrentFileInfo(zip, &fileInfo,
|
||||||
buffer, bufferSize,
|
buffer, bufferSize,
|
||||||
NULL, 0, /* extra field */
|
NULL, 0, /* extra field */
|
||||||
NULL, 0 /* comment field */);
|
NULL, 0 /* comment field */);
|
||||||
|
|
||||||
std::string name(buffer);
|
std::string name(buffer);
|
||||||
// no absolute paths, no 'up' traversals
|
// no absolute paths, no 'up' traversals
|
||||||
// we could also look for suspicious file extensions here (forbid .dll, .exe, .so)
|
// we could also look for suspicious file extensions here (forbid .dll, .exe, .so)
|
||||||
if ((name[0] == '/') || (name.find("../") != std::string::npos) || (name.find("..\\") != std::string::npos)) {
|
if ((name[0] == '/') || (name.find("../") != std::string::npos) || (name.find("..\\") != std::string::npos)) {
|
||||||
throw sg_format_exception("Bad zip path", name);
|
throw sg_format_exception("Bad zip path", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileInfo.uncompressed_size == 0) {
|
if (fileInfo.uncompressed_size == 0) {
|
||||||
// assume it's a directory for now
|
// assume it's a directory for now
|
||||||
// since we create parent directories when extracting
|
// since we create parent directories when extracting
|
||||||
// a path, we're done here
|
// a path, we're done here
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = unzOpenCurrentFile(zip);
|
int result = unzOpenCurrentFile(zip);
|
||||||
if (result != UNZ_OK) {
|
if (result != UNZ_OK) {
|
||||||
throw sg_io_exception("opening current zip file failed", sg_location(name));
|
throw sg_io_exception("opening current zip file failed", sg_location(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream outFile;
|
std::ofstream outFile;
|
||||||
bool eof = false;
|
bool eof = false;
|
||||||
SGPath path(m_extractPath);
|
SGPath path(m_extractPath);
|
||||||
path.append(name);
|
path.append(name);
|
||||||
|
|
||||||
// create enclosing directory heirarchy as required
|
// create enclosing directory heirarchy as required
|
||||||
Dir parentDir(path.dir());
|
Dir parentDir(path.dir());
|
||||||
if (!parentDir.exists()) {
|
if (!parentDir.exists()) {
|
||||||
@@ -224,12 +170,12 @@ private:
|
|||||||
throw sg_io_exception("failed to create directory heirarchy for extraction", path.c_str());
|
throw sg_io_exception("failed to create directory heirarchy for extraction", path.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outFile.open(path.c_str(), std::ios::binary | std::ios::trunc | std::ios::out);
|
outFile.open(path.c_str(), std::ios::binary | std::ios::trunc | std::ios::out);
|
||||||
if (outFile.fail()) {
|
if (outFile.fail()) {
|
||||||
throw sg_io_exception("failed to open output file for writing", path.c_str());
|
throw sg_io_exception("failed to open output file for writing", path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!eof) {
|
while (!eof) {
|
||||||
int bytes = unzReadCurrentFile(zip, buffer, bufferSize);
|
int bytes = unzReadCurrentFile(zip, buffer, bufferSize);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
@@ -240,30 +186,30 @@ private:
|
|||||||
outFile.write(buffer, bytes);
|
outFile.write(buffer, bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outFile.close();
|
outFile.close();
|
||||||
unzCloseCurrentFile(zip);
|
unzCloseCurrentFile(zip);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool extractUnzip()
|
bool extractUnzip()
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
zlib_filefunc_def memoryAccessFuncs;
|
zlib_filefunc_def memoryAccessFuncs;
|
||||||
fill_memory_filefunc(&memoryAccessFuncs);
|
fill_memory_filefunc(&memoryAccessFuncs);
|
||||||
|
|
||||||
char bufferName[128];
|
char bufferName[128];
|
||||||
snprintf(bufferName, 128, "%p+%lx", m_buffer.data(), m_buffer.size());
|
snprintf(bufferName, 128, "%p+%lx", m_buffer.data(), m_buffer.size());
|
||||||
unzFile zip = unzOpen2(bufferName, &memoryAccessFuncs);
|
unzFile zip = unzOpen2(bufferName, &memoryAccessFuncs);
|
||||||
|
|
||||||
const size_t BUFFER_SIZE = 32 * 1024;
|
const size_t BUFFER_SIZE = 32 * 1024;
|
||||||
void* buf = malloc(BUFFER_SIZE);
|
void* buf = malloc(BUFFER_SIZE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int result = unzGoToFirstFile(zip);
|
int result = unzGoToFirstFile(zip);
|
||||||
if (result != UNZ_OK) {
|
if (result != UNZ_OK) {
|
||||||
throw sg_exception("failed to go to first file in archive");
|
throw sg_exception("failed to go to first file in archive");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
extractCurrentFile(zip, (char*) buf, BUFFER_SIZE);
|
extractCurrentFile(zip, (char*) buf, BUFFER_SIZE);
|
||||||
result = unzGoToNextFile(zip);
|
result = unzGoToNextFile(zip);
|
||||||
@@ -276,53 +222,57 @@ private:
|
|||||||
} catch (sg_exception& e) {
|
} catch (sg_exception& e) {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
unzClose(zip);
|
unzClose(zip);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void doFailure(Delegate::StatusCode aReason)
|
void doFailure(Delegate::FailureCode aReason)
|
||||||
{
|
{
|
||||||
Dir dir(m_extractPath);
|
Dir dir(m_extractPath);
|
||||||
if (dir.exists()) {
|
dir.remove(true /* recursive */);
|
||||||
dir.remove(true /* recursive */);
|
|
||||||
|
if (m_urls.size() == 1) {
|
||||||
|
std::cout << "failure:" << aReason << std::endl;
|
||||||
|
m_owner->installResult(aReason);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO - try other mirrors
|
std::cout << "retrying download" << std::endl;
|
||||||
m_owner->m_download.reset(); // ensure we get cleaned up
|
m_urls.erase(m_urls.begin()); // pop first URL
|
||||||
m_owner->installResult(aReason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallRef m_owner;
|
InstallRef m_owner;
|
||||||
string_list m_urls;
|
string_list m_urls;
|
||||||
SG_MD5_CTX m_md5;
|
SG_MD5_CTX m_md5;
|
||||||
std::string m_buffer;
|
std::string m_buffer;
|
||||||
SGPath m_extractPath;
|
SGPath m_extractPath;
|
||||||
size_t m_downloaded;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
Install::Install(PackageRef aPkg, const SGPath& aPath) :
|
Install::Install(PackageRef aPkg, const SGPath& aPath) :
|
||||||
m_package(aPkg),
|
m_package(aPkg),
|
||||||
m_path(aPath),
|
m_path(aPath),
|
||||||
m_status(Delegate::STATUS_IN_PROGRESS)
|
m_download(NULL),
|
||||||
|
_status(Delegate::FAIL_IN_PROGRESS)
|
||||||
{
|
{
|
||||||
parseRevision();
|
parseRevision();
|
||||||
m_package->catalog()->root()->registerInstall(this);
|
m_package->catalog()->registerInstall(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Install::~Install()
|
Install::~Install()
|
||||||
{
|
{
|
||||||
|
m_package->catalog()->unregisterInstall(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat)
|
InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat)
|
||||||
{
|
{
|
||||||
std::string path = aPath.file();
|
std::string id = aPath.file();
|
||||||
PackageRef pkg = aCat->getPackageByPath(path);
|
PackageRef pkg = aCat->getPackageById(id);
|
||||||
if (!pkg)
|
if (!pkg)
|
||||||
throw sg_exception("no package with path:" + path);
|
throw sg_exception("no package with id:" + id);
|
||||||
|
|
||||||
return new Install(pkg, aPath);
|
return new Install(pkg, aPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +284,7 @@ void Install::parseRevision()
|
|||||||
m_revision = 0;
|
m_revision = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream f(revisionFile.c_str(), std::ios::in);
|
std::ifstream f(revisionFile.c_str(), std::ios::in);
|
||||||
f >> m_revision;
|
f >> m_revision;
|
||||||
}
|
}
|
||||||
@@ -357,108 +307,23 @@ void Install::startUpdate()
|
|||||||
if (m_download) {
|
if (m_download) {
|
||||||
return; // already active
|
return; // already active
|
||||||
}
|
}
|
||||||
|
|
||||||
m_download = new PackageArchiveDownloader(this);
|
m_download = new PackageArchiveDownloader(this);
|
||||||
m_package->catalog()->root()->makeHTTPRequest(m_download);
|
m_package->catalog()->root()->makeHTTPRequest(m_download);
|
||||||
m_package->catalog()->root()->startInstall(this);
|
m_package->catalog()->root()->startInstall(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Install::uninstall()
|
void Install::uninstall()
|
||||||
{
|
{
|
||||||
Dir d(m_path);
|
Dir d(m_path);
|
||||||
if (!d.remove(true)) {
|
d.remove(true);
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "package uninstall failed: couldn't remove path " << m_path);
|
m_package->catalog()->unregisterInstall(this);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_package->catalog()->root()->unregisterInstall(this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Install::isDownloading() const
|
|
||||||
{
|
|
||||||
return (m_download.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Install::isQueued() const
|
|
||||||
{
|
|
||||||
return m_package->catalog()->root()->isInstallQueued(const_cast<Install*>(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
int Install::downloadedPercent() const
|
|
||||||
{
|
|
||||||
if (!m_download.valid()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageArchiveDownloader* dl = static_cast<PackageArchiveDownloader*>(m_download.get());
|
|
||||||
return dl->percentDownloaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Install::downloadedBytes() const
|
|
||||||
{
|
|
||||||
if (!m_download.valid()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageArchiveDownloader* dl = static_cast<PackageArchiveDownloader*>(m_download.get());
|
|
||||||
return dl->downloadedBytes();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Install::cancelDownload()
|
|
||||||
{
|
|
||||||
if (m_download.valid()) {
|
|
||||||
m_download->abort("User cancelled download");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_revision == 0) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "cancel install of package, will unregister");
|
|
||||||
m_package->catalog()->root()->unregisterInstall(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_package->catalog()->root()->cancelDownload(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PathAppender
|
|
||||||
{
|
|
||||||
PathAppender(const SGPath& p) : m_path(p) {}
|
|
||||||
|
|
||||||
SGPath operator()(const std::string& s) const
|
|
||||||
{
|
|
||||||
SGPath p(m_path);
|
|
||||||
p.append(s);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPath m_path;
|
|
||||||
};
|
|
||||||
|
|
||||||
PathList Install::thumbnailPaths() const
|
|
||||||
{
|
|
||||||
const string_list& thumbs(m_package->thumbnails());
|
|
||||||
PathList result;
|
|
||||||
if (thumbs.empty())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
std::transform(thumbs.begin(), thumbs.end(),
|
|
||||||
std::back_inserter(result),
|
|
||||||
PathAppender(m_path));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPath Install::primarySetPath() const
|
|
||||||
{
|
|
||||||
SGPath setPath(m_path);
|
|
||||||
std::string ps(m_package->id());
|
|
||||||
setPath.append(ps + "-set.xml");
|
|
||||||
return setPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Install* Install::done(const Callback& cb)
|
Install* Install::done(const Callback& cb)
|
||||||
{
|
{
|
||||||
if( m_status == Delegate::STATUS_SUCCESS )
|
if( _status == Delegate::FAIL_SUCCESS )
|
||||||
cb(this);
|
cb(this);
|
||||||
else
|
else
|
||||||
_cb_done.push_back(cb);
|
_cb_done.push_back(cb);
|
||||||
@@ -469,8 +334,8 @@ Install* Install::done(const Callback& cb)
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Install* Install::fail(const Callback& cb)
|
Install* Install::fail(const Callback& cb)
|
||||||
{
|
{
|
||||||
if( m_status != Delegate::STATUS_SUCCESS
|
if( _status != Delegate::FAIL_SUCCESS
|
||||||
&& m_status != Delegate::STATUS_IN_PROGRESS )
|
&& _status != Delegate::FAIL_IN_PROGRESS )
|
||||||
cb(this);
|
cb(this);
|
||||||
else
|
else
|
||||||
_cb_fail.push_back(cb);
|
_cb_fail.push_back(cb);
|
||||||
@@ -481,7 +346,7 @@ Install* Install::fail(const Callback& cb)
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Install* Install::always(const Callback& cb)
|
Install* Install::always(const Callback& cb)
|
||||||
{
|
{
|
||||||
if( m_status != Delegate::STATUS_IN_PROGRESS )
|
if( _status != Delegate::FAIL_IN_PROGRESS )
|
||||||
cb(this);
|
cb(this);
|
||||||
else
|
else
|
||||||
_cb_always.push_back(cb);
|
_cb_always.push_back(cb);
|
||||||
@@ -497,12 +362,13 @@ Install* Install::progress(const ProgressCallback& cb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void Install::installResult(Delegate::StatusCode aReason)
|
void Install::installResult(Delegate::FailureCode aReason)
|
||||||
{
|
{
|
||||||
m_package->catalog()->root()->finishInstall(this, aReason);
|
if (aReason == Delegate::FAIL_SUCCESS) {
|
||||||
if (aReason == Delegate::STATUS_SUCCESS) {
|
m_package->catalog()->root()->finishInstall(this);
|
||||||
_cb_done(this);
|
_cb_done(this);
|
||||||
} else {
|
} else {
|
||||||
|
m_package->catalog()->root()->failedInstall(this, aReason);
|
||||||
_cb_fail(this);
|
_cb_fail(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,11 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/misc/sg_dir.hxx>
|
|
||||||
#include <simgear/package/Delegate.hxx>
|
#include <simgear/package/Delegate.hxx>
|
||||||
|
|
||||||
#include <simgear/structure/function_list.hxx>
|
#include <simgear/structure/function_list.hxx>
|
||||||
#include <simgear/structure/SGReferenced.hxx>
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
#include <simgear/io/HTTPRequest.hxx>
|
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
@@ -75,36 +73,9 @@ public:
|
|||||||
bool hasUpdate() const;
|
bool hasUpdate() const;
|
||||||
|
|
||||||
void startUpdate();
|
void startUpdate();
|
||||||
|
|
||||||
|
void uninstall();
|
||||||
|
|
||||||
bool uninstall();
|
|
||||||
|
|
||||||
bool isDownloading() const;
|
|
||||||
|
|
||||||
bool isQueued() const;
|
|
||||||
|
|
||||||
int downloadedPercent() const;
|
|
||||||
|
|
||||||
size_t downloadedBytes() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* full path to the primary -set.xml file for this install
|
|
||||||
*/
|
|
||||||
SGPath primarySetPath() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* if a download is in progress, cancel it. If this is the first install
|
|
||||||
* of the package (as opposed to an update), the install will be cleaned
|
|
||||||
* up once the last reference is gone.
|
|
||||||
*/
|
|
||||||
void cancelDownload();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return the thumbnails associated with this install, but as locations
|
|
||||||
* on the file system, not URLs. It is assumed the order of thumbnails
|
|
||||||
* is consistent with the URLs returned from Package::thumbnailUrls()
|
|
||||||
*/
|
|
||||||
PathList thumbnailPaths() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the handler to be called when the installation successfully
|
* Set the handler to be called when the installation successfully
|
||||||
* completes.
|
* completes.
|
||||||
@@ -174,16 +145,16 @@ private:
|
|||||||
void parseRevision();
|
void parseRevision();
|
||||||
void writeRevisionFile();
|
void writeRevisionFile();
|
||||||
|
|
||||||
void installResult(Delegate::StatusCode aReason);
|
void installResult(Delegate::FailureCode aReason);
|
||||||
void installProgress(unsigned int aBytes, unsigned int aTotal);
|
void installProgress(unsigned int aBytes, unsigned int aTotal);
|
||||||
|
|
||||||
PackageRef m_package;
|
PackageRef m_package;
|
||||||
unsigned int m_revision; ///< revision on disk
|
unsigned int m_revision; ///< revision on disk
|
||||||
SGPath m_path; ///< installation point on disk
|
SGPath m_path; ///< installation point on disk
|
||||||
|
|
||||||
HTTP::Request_ptr m_download;
|
PackageArchiveDownloader* m_download;
|
||||||
|
|
||||||
Delegate::StatusCode m_status;
|
Delegate::FailureCode _status;
|
||||||
|
|
||||||
function_list<Callback> _cb_done,
|
function_list<Callback> _cb_done,
|
||||||
_cb_fail,
|
_cb_fail,
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ SGPath Package::pathOnDisk() const
|
|||||||
{
|
{
|
||||||
SGPath p(m_catalog->installRoot());
|
SGPath p(m_catalog->installRoot());
|
||||||
p.append("Aircraft");
|
p.append("Aircraft");
|
||||||
p.append(dirName());
|
p.append(id());
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,12 +139,7 @@ InstallRef Package::install()
|
|||||||
|
|
||||||
InstallRef Package::existingInstall(const InstallCallback& cb) const
|
InstallRef Package::existingInstall(const InstallCallback& cb) const
|
||||||
{
|
{
|
||||||
InstallRef install;
|
InstallRef install = m_catalog->installForPackage(const_cast<Package*>(this));
|
||||||
try {
|
|
||||||
install = m_catalog->root()->existingInstallForPackage(const_cast<Package*>(this));
|
|
||||||
} catch (std::exception& e) {
|
|
||||||
return InstallRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( cb )
|
if( cb )
|
||||||
{
|
{
|
||||||
@@ -167,30 +162,13 @@ std::string Package::qualifiedId() const
|
|||||||
return m_catalog->id() + "." + id();
|
return m_catalog->id() + "." + id();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Package::qualifiedVariantId(const unsigned int variantIndex) const
|
|
||||||
{
|
|
||||||
return m_catalog->id() + "." + variants()[variantIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Package::md5() const
|
std::string Package::md5() const
|
||||||
{
|
{
|
||||||
return m_props->getStringValue("md5");
|
return m_props->getStringValue("md5");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Package::dirName() const
|
|
||||||
{
|
|
||||||
std::string r(m_props->getStringValue("dir"));
|
|
||||||
if (r.empty())
|
|
||||||
throw sg_exception("missing dir property on catalog package entry for " + m_id);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Package::revision() const
|
unsigned int Package::revision() const
|
||||||
{
|
{
|
||||||
if (!m_props) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_props->getIntValue("revision");
|
return m_props->getIntValue("revision");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,11 +186,6 @@ std::string Package::description() const
|
|||||||
{
|
{
|
||||||
return getLocalisedProp("description");
|
return getLocalisedProp("description");
|
||||||
}
|
}
|
||||||
|
|
||||||
string_set Package::tags() const
|
|
||||||
{
|
|
||||||
return m_tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPropertyNode* Package::properties() const
|
SGPropertyNode* Package::properties() const
|
||||||
{
|
{
|
||||||
@@ -222,36 +195,15 @@ SGPropertyNode* Package::properties() const
|
|||||||
string_list Package::thumbnailUrls() const
|
string_list Package::thumbnailUrls() const
|
||||||
{
|
{
|
||||||
string_list r;
|
string_list r;
|
||||||
if (!m_props) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail")) {
|
BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail")) {
|
||||||
r.push_back(dl->getStringValue());
|
r.push_back(dl->getStringValue());
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
string_list Package::thumbnails() const
|
|
||||||
{
|
|
||||||
string_list r;
|
|
||||||
if (!m_props) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail-path")) {
|
|
||||||
r.push_back(dl->getStringValue());
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_list Package::downloadUrls() const
|
string_list Package::downloadUrls() const
|
||||||
{
|
{
|
||||||
string_list r;
|
string_list r;
|
||||||
if (!m_props) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("url")) {
|
BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("url")) {
|
||||||
r.push_back(dl->getStringValue());
|
r.push_back(dl->getStringValue());
|
||||||
}
|
}
|
||||||
@@ -286,7 +238,7 @@ PackageList Package::dependencies() const
|
|||||||
|
|
||||||
// prefer local hangar package if possible, in case someone does something
|
// prefer local hangar package if possible, in case someone does something
|
||||||
// silly with naming. Of course flightgear's aircraft search doesn't know
|
// silly with naming. Of course flightgear's aircraft search doesn't know
|
||||||
// about hangars, so names still need to be unique.
|
// about hanagrs, so names still need to be unique.
|
||||||
PackageRef depPkg = m_catalog->getPackageById(depName);
|
PackageRef depPkg = m_catalog->getPackageById(depName);
|
||||||
if (!depPkg) {
|
if (!depPkg) {
|
||||||
Root* rt = m_catalog->root();
|
Root* rt = m_catalog->root();
|
||||||
@@ -338,20 +290,6 @@ std::string Package::nameForVariant(const std::string& vid) const
|
|||||||
throw sg_exception("Unknow variant +" + vid + " in package " + id());
|
throw sg_exception("Unknow variant +" + vid + " in package " + id());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Package::nameForVariant(const unsigned int vIndex) const
|
|
||||||
{
|
|
||||||
if (vIndex == 0)
|
|
||||||
return name();
|
|
||||||
|
|
||||||
// offset by minus one to allow for index 0 being the primary
|
|
||||||
SGPropertyNode_ptr var = m_props->getChild("variant", vIndex - 1);
|
|
||||||
if (var)
|
|
||||||
return var->getStringValue("name");
|
|
||||||
|
|
||||||
throw sg_exception("Unknow variant in package " + id());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|
||||||
} // of namespace simgear
|
} // of namespace simgear
|
||||||
|
|||||||
@@ -75,11 +75,6 @@ public:
|
|||||||
* Fully-qualified ID, including our catalog'd ID
|
* Fully-qualified ID, including our catalog'd ID
|
||||||
*/
|
*/
|
||||||
std::string qualifiedId() const;
|
std::string qualifiedId() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Fully-qualified ID, including our catalog'd ID
|
|
||||||
*/
|
|
||||||
std::string qualifiedVariantId(const unsigned int variantIndex) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* human-readable name - note this is probably not localised,
|
* human-readable name - note this is probably not localised,
|
||||||
@@ -92,8 +87,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::string nameForVariant(const std::string& vid) const;
|
std::string nameForVariant(const std::string& vid) const;
|
||||||
|
|
||||||
std::string nameForVariant(const unsigned int vIndex) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* syntactic sugar to get the localised description
|
* syntactic sugar to get the localised description
|
||||||
*/
|
*/
|
||||||
@@ -119,9 +112,7 @@ public:
|
|||||||
{ return m_catalog; }
|
{ return m_catalog; }
|
||||||
|
|
||||||
bool matches(const SGPropertyNode* aFilter) const;
|
bool matches(const SGPropertyNode* aFilter) const;
|
||||||
|
|
||||||
string_set tags() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* download URLs for the package
|
* download URLs for the package
|
||||||
*/
|
*/
|
||||||
@@ -129,28 +120,16 @@ public:
|
|||||||
|
|
||||||
string_list thumbnailUrls() const;
|
string_list thumbnailUrls() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* thumbnail file paths within the package on disk
|
|
||||||
*/
|
|
||||||
string_list thumbnails() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Packages we depend upon.
|
* Packages we depend upon.
|
||||||
* If the dependency list cannot be satisifed for some reason,
|
* If the dependency list cannot be satisifed for some reason,
|
||||||
* this will raise an sg_exception.
|
* this will raise an sg_exception.
|
||||||
*/
|
*/
|
||||||
PackageList dependencies() const;
|
PackageList dependencies() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the package directory on disk. This may or may not be the
|
|
||||||
* same as the primary ID, depending on the aircraft author
|
|
||||||
*/
|
|
||||||
std::string dirName() const;
|
|
||||||
private:
|
private:
|
||||||
SGPath pathOnDisk() const;
|
SGPath pathOnDisk() const;
|
||||||
|
|
||||||
friend class Catalog;
|
friend class Catalog;
|
||||||
friend class Root;
|
|
||||||
|
|
||||||
Package(const SGPropertyNode* aProps, CatalogRef aCatalog);
|
Package(const SGPropertyNode* aProps, CatalogRef aCatalog);
|
||||||
|
|
||||||
|
|||||||
+86
-387
@@ -34,173 +34,45 @@
|
|||||||
#include <simgear/package/Catalog.hxx>
|
#include <simgear/package/Catalog.hxx>
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
|
|
||||||
namespace pkg {
|
namespace pkg {
|
||||||
|
|
||||||
typedef std::map<std::string, CatalogRef> CatalogDict;
|
typedef std::map<std::string, CatalogRef> CatalogDict;
|
||||||
typedef std::vector<Delegate*> DelegateVec;
|
|
||||||
typedef std::map<std::string, std::string> MemThumbnailCache;
|
|
||||||
typedef std::deque<std::string> StringDeque;
|
|
||||||
|
|
||||||
class Root::ThumbnailDownloader : public HTTP::Request
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ThumbnailDownloader(Root::RootPrivate* aOwner, const std::string& aUrl) :
|
|
||||||
HTTP::Request(aUrl),
|
|
||||||
m_owner(aOwner)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void gotBodyData(const char* s, int n)
|
|
||||||
{
|
|
||||||
m_buffer += std::string(s, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onDone();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Root::RootPrivate* m_owner;
|
|
||||||
std::string m_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Root::RootPrivate
|
class Root::RootPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RootPrivate() :
|
RootPrivate() :
|
||||||
http(NULL),
|
http(NULL),
|
||||||
maxAgeSeconds(60 * 60 * 24)
|
maxAgeSeconds(60 * 60 * 24),
|
||||||
|
delegate(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fireStartInstall(InstallRef install)
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->startInstall(install);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void fireInstallProgress(InstallRef install,
|
|
||||||
unsigned int aBytes, unsigned int aTotal)
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->installProgress(install, aBytes, aTotal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void fireFinishInstall(InstallRef install, Delegate::StatusCode status)
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->finishInstall(install, status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void fireRefreshStatus(CatalogRef catalog, Delegate::StatusCode status)
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->catalogRefreshed(catalog, status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void firePackagesChanged()
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->availablePackagesChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void thumbnailDownloadComplete(HTTP::Request_ptr request,
|
|
||||||
Delegate::StatusCode status, const std::string& bytes)
|
|
||||||
{
|
|
||||||
std::string u(request->url());
|
|
||||||
if (status == Delegate::STATUS_SUCCESS) {
|
|
||||||
thumbnailCache[u] = bytes;
|
|
||||||
fireDataForThumbnail(u, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadNextPendingThumbnail();
|
|
||||||
}
|
|
||||||
|
|
||||||
void fireDataForThumbnail(const std::string& aUrl, const std::string& bytes)
|
|
||||||
{
|
|
||||||
DelegateVec::const_iterator it;
|
|
||||||
const uint8_t* data = reinterpret_cast<const uint8_t*>(bytes.data());
|
|
||||||
for (it = delegates.begin(); it != delegates.end(); ++it) {
|
|
||||||
(*it)->dataForThumbnail(aUrl, bytes.size(), data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void downloadNextPendingThumbnail()
|
|
||||||
{
|
|
||||||
thumbnailDownloadRequest.clear();
|
|
||||||
if (pendingThumbnails.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string u = pendingThumbnails.front();
|
|
||||||
pendingThumbnails.pop_front();
|
|
||||||
thumbnailDownloadRequest = new Root::ThumbnailDownloader(this, u);
|
|
||||||
|
|
||||||
if (http) {
|
|
||||||
http->makeRequest(thumbnailDownloadRequest);
|
|
||||||
} else {
|
|
||||||
httpPendingRequests.push_back(thumbnailDownloadRequest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateVec delegates;
|
|
||||||
|
|
||||||
SGPath path;
|
SGPath path;
|
||||||
std::string locale;
|
std::string locale;
|
||||||
HTTP::Client* http;
|
HTTP::Client* http;
|
||||||
CatalogDict catalogs;
|
CatalogDict catalogs;
|
||||||
CatalogList disabledCatalogs;
|
|
||||||
unsigned int maxAgeSeconds;
|
unsigned int maxAgeSeconds;
|
||||||
|
Delegate* delegate;
|
||||||
std::string version;
|
std::string version;
|
||||||
|
|
||||||
std::set<CatalogRef> refreshing;
|
std::set<CatalogRef> refreshing;
|
||||||
typedef std::deque<InstallRef> UpdateDeque;
|
std::deque<InstallRef> updateDeque;
|
||||||
UpdateDeque updateDeque;
|
|
||||||
std::deque<HTTP::Request_ptr> httpPendingRequests;
|
std::deque<HTTP::Request_ptr> httpPendingRequests;
|
||||||
|
|
||||||
HTTP::Request_ptr thumbnailDownloadRequest;
|
|
||||||
StringDeque pendingThumbnails;
|
|
||||||
MemThumbnailCache thumbnailCache;
|
|
||||||
|
|
||||||
typedef std::map<PackageRef, InstallRef> InstallCache;
|
|
||||||
InstallCache m_installs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void Root::ThumbnailDownloader::onDone()
|
|
||||||
{
|
|
||||||
if (responseCode() != 200) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "thumbnail download failure:" << url());
|
|
||||||
m_owner->thumbnailDownloadComplete(this, Delegate::FAIL_DOWNLOAD, std::string());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_owner->thumbnailDownloadComplete(this, Delegate::STATUS_SUCCESS, m_buffer);
|
|
||||||
//time(&m_owner->m_retrievedTime);
|
|
||||||
//m_owner->writeTimestamp();
|
|
||||||
//m_owner->refreshComplete(Delegate::STATUS_REFRESHED);
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPath Root::path() const
|
SGPath Root::path() const
|
||||||
{
|
{
|
||||||
return d->path;
|
return d->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::setMaxAgeSeconds(unsigned int seconds)
|
void Root::setMaxAgeSeconds(unsigned int seconds)
|
||||||
{
|
{
|
||||||
d->maxAgeSeconds = seconds;
|
d->maxAgeSeconds = seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Root::maxAgeSeconds() const
|
unsigned int Root::maxAgeSeconds() const
|
||||||
{
|
{
|
||||||
return d->maxAgeSeconds;
|
return d->maxAgeSeconds;
|
||||||
@@ -222,10 +94,10 @@ void Root::makeHTTPRequest(HTTP::Request *req)
|
|||||||
d->http->makeRequest(req);
|
d->http->makeRequest(req);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->httpPendingRequests.push_back(req);
|
d->httpPendingRequests.push_back(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
Root::Root(const SGPath& aPath, const std::string& aVersion) :
|
Root::Root(const SGPath& aPath, const std::string& aVersion) :
|
||||||
d(new RootPrivate)
|
d(new RootPrivate)
|
||||||
{
|
{
|
||||||
@@ -234,56 +106,45 @@ Root::Root(const SGPath& aPath, const std::string& aVersion) :
|
|||||||
if (getenv("LOCALE")) {
|
if (getenv("LOCALE")) {
|
||||||
d->locale = getenv("LOCALE");
|
d->locale = getenv("LOCALE");
|
||||||
}
|
}
|
||||||
|
|
||||||
Dir dir(aPath);
|
Dir dir(aPath);
|
||||||
if (!dir.exists()) {
|
if (!dir.exists()) {
|
||||||
dir.create(0755);
|
dir.create(0755);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(SGPath c, dir.children(Dir::TYPE_DIR | Dir::NO_DOT_OR_DOTDOT)) {
|
BOOST_FOREACH(SGPath c, dir.children(Dir::TYPE_DIR)) {
|
||||||
CatalogRef cat = Catalog::createFromPath(this, c);
|
CatalogRef cat = Catalog::createFromPath(this, c);
|
||||||
if (cat) {
|
if (cat) {
|
||||||
if (cat->status() == Delegate::STATUS_SUCCESS) {
|
d->catalogs[cat->id()] = cat;
|
||||||
d->catalogs[cat->id()] = cat;
|
|
||||||
} else {
|
|
||||||
// catalog has problems, such as needing an update
|
|
||||||
// keep it out of the main collection for now
|
|
||||||
d->disabledCatalogs.push_back(cat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // of child directories iteration
|
} // of child directories iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
Root::~Root()
|
Root::~Root()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Root::catalogVersion() const
|
std::string Root::catalogVersion() const
|
||||||
{
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Root::applicationVersion() const
|
|
||||||
{
|
{
|
||||||
return d->version;
|
return d->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
CatalogRef Root::getCatalogById(const std::string& aId) const
|
CatalogRef Root::getCatalogById(const std::string& aId) const
|
||||||
{
|
{
|
||||||
CatalogDict::const_iterator it = d->catalogs.find(aId);
|
CatalogDict::const_iterator it = d->catalogs.find(aId);
|
||||||
if (it == d->catalogs.end()) {
|
if (it == d->catalogs.end()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageRef Root::getPackageById(const std::string& aName) const
|
PackageRef Root::getPackageById(const std::string& aName) const
|
||||||
{
|
{
|
||||||
size_t lastDot = aName.rfind('.');
|
size_t lastDot = aName.rfind('.');
|
||||||
|
|
||||||
PackageRef pkg = NULL;
|
PackageRef pkg = NULL;
|
||||||
if (lastDot == std::string::npos) {
|
if (lastDot == std::string::npos) {
|
||||||
// naked package ID
|
// naked package ID
|
||||||
@@ -294,17 +155,17 @@ PackageRef Root::getPackageById(const std::string& aName) const
|
|||||||
return pkg;
|
return pkg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string catalogId = aName.substr(0, lastDot);
|
std::string catalogId = aName.substr(0, lastDot);
|
||||||
std::string id = aName.substr(lastDot + 1);
|
std::string id = aName.substr(lastDot + 1);
|
||||||
CatalogRef catalog = getCatalogById(catalogId);
|
CatalogRef catalog = getCatalogById(catalogId);
|
||||||
if (!catalog) {
|
if (!catalog) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return catalog->getPackageById(id);
|
return catalog->getPackageById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,21 +176,7 @@ CatalogList Root::catalogs() const
|
|||||||
for (; it != d->catalogs.end(); ++it) {
|
for (; it != d->catalogs.end(); ++it) {
|
||||||
r.push_back(it->second);
|
r.push_back(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageList
|
|
||||||
Root::allPackages() const
|
|
||||||
{
|
|
||||||
PackageList r;
|
|
||||||
|
|
||||||
CatalogDict::const_iterator it = d->catalogs.begin();
|
|
||||||
for (; it != d->catalogs.end(); ++it) {
|
|
||||||
const PackageList& r2(it->second->packages());
|
|
||||||
r.insert(r.end(), r2.begin(), r2.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,13 +184,13 @@ PackageList
|
|||||||
Root::packagesMatching(const SGPropertyNode* aFilter) const
|
Root::packagesMatching(const SGPropertyNode* aFilter) const
|
||||||
{
|
{
|
||||||
PackageList r;
|
PackageList r;
|
||||||
|
|
||||||
CatalogDict::const_iterator it = d->catalogs.begin();
|
CatalogDict::const_iterator it = d->catalogs.begin();
|
||||||
for (; it != d->catalogs.end(); ++it) {
|
for (; it != d->catalogs.end(); ++it) {
|
||||||
PackageList r2(it->second->packagesMatching(aFilter));
|
PackageList r2(it->second->packagesMatching(aFilter));
|
||||||
r.insert(r.end(), r2.begin(), r2.end());
|
r.insert(r.end(), r2.begin(), r2.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,59 +198,31 @@ PackageList
|
|||||||
Root::packagesNeedingUpdate() const
|
Root::packagesNeedingUpdate() const
|
||||||
{
|
{
|
||||||
PackageList r;
|
PackageList r;
|
||||||
|
|
||||||
CatalogDict::const_iterator it = d->catalogs.begin();
|
CatalogDict::const_iterator it = d->catalogs.begin();
|
||||||
for (; it != d->catalogs.end(); ++it) {
|
for (; it != d->catalogs.end(); ++it) {
|
||||||
PackageList r2(it->second->packagesNeedingUpdate());
|
PackageList r2(it->second->packagesNeedingUpdate());
|
||||||
r.insert(r.end(), r2.begin(), r2.end());
|
r.insert(r.end(), r2.begin(), r2.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::refresh(bool aForce)
|
void Root::refresh(bool aForce)
|
||||||
{
|
{
|
||||||
bool didStartAny = false;
|
|
||||||
|
|
||||||
// copy all candidate ctalogs to a seperate list, since refreshing
|
|
||||||
// can modify both the main collection and/or the disabled list
|
|
||||||
CatalogList toRefresh;
|
|
||||||
CatalogDict::iterator it = d->catalogs.begin();
|
CatalogDict::iterator it = d->catalogs.begin();
|
||||||
for (; it != d->catalogs.end(); ++it) {
|
for (; it != d->catalogs.end(); ++it) {
|
||||||
toRefresh.push_back(it->second);
|
if (aForce || it->second->needsRefresh()) {
|
||||||
}
|
it->second->refresh();
|
||||||
|
}
|
||||||
toRefresh.insert(toRefresh.end(), d->disabledCatalogs.begin(),
|
|
||||||
d->disabledCatalogs.end());
|
|
||||||
|
|
||||||
|
|
||||||
CatalogList::iterator j = toRefresh.begin();
|
|
||||||
for (; j != toRefresh.end(); ++j) {
|
|
||||||
(*j)->refresh();
|
|
||||||
didStartAny = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!didStartAny) {
|
|
||||||
// signal refresh complete to the delegate already
|
|
||||||
d->fireRefreshStatus(CatalogRef(), Delegate::STATUS_REFRESHED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::addDelegate(simgear::pkg::Delegate *aDelegate)
|
void Root::setDelegate(simgear::pkg::Delegate *aDelegate)
|
||||||
{
|
{
|
||||||
d->delegates.push_back(aDelegate);
|
d->delegate = aDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::removeDelegate(simgear::pkg::Delegate *aDelegate)
|
|
||||||
{
|
|
||||||
DelegateVec::iterator it = std::find(d->delegates.begin(),
|
|
||||||
d->delegates.end(), aDelegate);
|
|
||||||
if (it == d->delegates.end()) {
|
|
||||||
throw sg_exception("unknown delegate in removeDelegate");
|
|
||||||
}
|
|
||||||
d->delegates.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Root::setLocale(const std::string& aLocale)
|
void Root::setLocale(const std::string& aLocale)
|
||||||
{
|
{
|
||||||
d->locale = aLocale;
|
d->locale = aLocale;
|
||||||
@@ -419,7 +238,7 @@ void Root::scheduleToUpdate(InstallRef aInstall)
|
|||||||
if (!aInstall) {
|
if (!aInstall) {
|
||||||
throw sg_exception("missing argument to scheduleToUpdate");
|
throw sg_exception("missing argument to scheduleToUpdate");
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageList deps = aInstall->package()->dependencies();
|
PackageList deps = aInstall->package()->dependencies();
|
||||||
BOOST_FOREACH(Package* dep, deps) {
|
BOOST_FOREACH(Package* dep, deps) {
|
||||||
// will internally schedule for update if required
|
// will internally schedule for update if required
|
||||||
@@ -429,27 +248,24 @@ void Root::scheduleToUpdate(InstallRef aInstall)
|
|||||||
|
|
||||||
bool wasEmpty = d->updateDeque.empty();
|
bool wasEmpty = d->updateDeque.empty();
|
||||||
d->updateDeque.push_back(aInstall);
|
d->updateDeque.push_back(aInstall);
|
||||||
|
|
||||||
if (wasEmpty) {
|
if (wasEmpty) {
|
||||||
aInstall->startUpdate();
|
aInstall->startUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Root::isInstallQueued(InstallRef aInstall) const
|
|
||||||
{
|
|
||||||
RootPrivate::UpdateDeque::const_iterator it =
|
|
||||||
std::find(d->updateDeque.begin(), d->updateDeque.end(), aInstall);
|
|
||||||
return (it != d->updateDeque.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Root::startInstall(InstallRef aInstall)
|
void Root::startInstall(InstallRef aInstall)
|
||||||
{
|
{
|
||||||
d->fireStartInstall(aInstall);
|
if (d->delegate) {
|
||||||
|
d->delegate->startInstall(aInstall.ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal)
|
void Root::installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal)
|
||||||
{
|
{
|
||||||
d->fireInstallProgress(aInstall, aBytes, aTotal);
|
if (d->delegate) {
|
||||||
|
d->delegate->installProgress(aInstall.ptr(), aBytes, aTotal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::startNext(InstallRef aCurrent)
|
void Root::startNext(InstallRef aCurrent)
|
||||||
@@ -459,182 +275,65 @@ void Root::startNext(InstallRef aCurrent)
|
|||||||
} else {
|
} else {
|
||||||
d->updateDeque.pop_front();
|
d->updateDeque.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d->updateDeque.empty()) {
|
if (!d->updateDeque.empty()) {
|
||||||
d->updateDeque.front()->startUpdate();
|
d->updateDeque.front()->startUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::finishInstall(InstallRef aInstall, Delegate::StatusCode aReason)
|
void Root::finishInstall(InstallRef aInstall)
|
||||||
{
|
{
|
||||||
if (aReason != Delegate::STATUS_SUCCESS) {
|
if (d->delegate) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:"
|
d->delegate->finishInstall(aInstall.ptr());
|
||||||
<< aInstall->package()->id() << ":" << aReason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// order matters here, so a call to 'isQueued' from a finish-install
|
|
||||||
// callback returns false, not true
|
|
||||||
startNext(aInstall);
|
startNext(aInstall);
|
||||||
d->fireFinishInstall(aInstall, aReason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::cancelDownload(InstallRef aInstall)
|
void Root::failedInstall(InstallRef aInstall, Delegate::FailureCode aReason)
|
||||||
{
|
{
|
||||||
RootPrivate::UpdateDeque::iterator it =
|
SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:"
|
||||||
std::find(d->updateDeque.begin(), d->updateDeque.end(), aInstall);
|
<< aInstall->package()->id() << ":" << aReason);
|
||||||
if (it != d->updateDeque.end()) {
|
if (d->delegate) {
|
||||||
bool startNext = (aInstall == d->updateDeque.front());
|
d->delegate->failedInstall(aInstall.ptr(), aReason);
|
||||||
d->updateDeque.erase(it);
|
}
|
||||||
if (startNext) {
|
|
||||||
if (!d->updateDeque.empty()) {
|
startNext(aInstall);
|
||||||
d->updateDeque.front()->startUpdate();
|
|
||||||
}
|
|
||||||
} // of install was front item
|
|
||||||
} // of found install in queue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::catalogRefreshStatus(CatalogRef aCat, Delegate::StatusCode aReason)
|
void Root::catalogRefreshBegin(CatalogRef aCat)
|
||||||
|
{
|
||||||
|
d->refreshing.insert(aCat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Root::catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason)
|
||||||
{
|
{
|
||||||
CatalogDict::iterator catIt = d->catalogs.find(aCat->id());
|
CatalogDict::iterator catIt = d->catalogs.find(aCat->id());
|
||||||
d->fireRefreshStatus(aCat, aReason);
|
if (aReason != Delegate::FAIL_SUCCESS) {
|
||||||
|
if (d->delegate) {
|
||||||
if (aReason == Delegate::STATUS_IN_PROGRESS) {
|
d->delegate->failedRefresh(aCat, aReason);
|
||||||
d->refreshing.insert(aCat);
|
|
||||||
} else {
|
|
||||||
d->refreshing.erase(aCat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((aReason == Delegate::STATUS_REFRESHED) && (catIt == d->catalogs.end())) {
|
|
||||||
assert(!aCat->id().empty());
|
|
||||||
d->catalogs.insert(catIt, CatalogDict::value_type(aCat->id(), aCat));
|
|
||||||
|
|
||||||
// catalog might have been previously disabled, let's remove in that case
|
|
||||||
CatalogList::iterator j = std::find(d->disabledCatalogs.begin(),
|
|
||||||
d->disabledCatalogs.end(),
|
|
||||||
aCat);
|
|
||||||
if (j != d->disabledCatalogs.end()) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "re-enabling disabled catalog:" << aCat->id());
|
|
||||||
d->disabledCatalogs.erase(j);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// if the failure is permanent, delete the catalog from our
|
||||||
if ((aReason != Delegate::STATUS_REFRESHED) &&
|
// list (don't touch it on disk)
|
||||||
(aReason != Delegate::STATUS_IN_PROGRESS) &&
|
bool isPermanentFailure = (aReason == Delegate::FAIL_VERSION);
|
||||||
(aReason != Delegate::STATUS_SUCCESS))
|
if (isPermanentFailure) {
|
||||||
{
|
SG_LOG(SG_GENERAL, SG_WARN, "permanent failure for catalog:" << aCat->id());
|
||||||
// catalog has errors, disable it
|
if (catIt != d->catalogs.end()) {
|
||||||
CatalogList::iterator j = std::find(d->disabledCatalogs.begin(),
|
d->catalogs.erase(catIt);
|
||||||
d->disabledCatalogs.end(),
|
|
||||||
aCat);
|
|
||||||
if (j == d->disabledCatalogs.end()) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "disabling catalog:" << aCat->id());
|
|
||||||
d->disabledCatalogs.push_back(aCat);
|
|
||||||
}
|
|
||||||
|
|
||||||
// and remove it from the active collection
|
|
||||||
if (catIt != d->catalogs.end()) {
|
|
||||||
d->catalogs.erase(catIt);
|
|
||||||
}
|
|
||||||
} // of catalog has errors case
|
|
||||||
|
|
||||||
if (d->refreshing.empty()) {
|
|
||||||
d->fireRefreshStatus(CatalogRef(), Delegate::STATUS_REFRESHED);
|
|
||||||
d->firePackagesChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Root::removeCatalogById(const std::string& aId)
|
|
||||||
{
|
|
||||||
CatalogRef cat;
|
|
||||||
|
|
||||||
CatalogDict::iterator catIt = d->catalogs.find(aId);
|
|
||||||
if (catIt == d->catalogs.end()) {
|
|
||||||
// check the disabled list
|
|
||||||
CatalogList::iterator j = d->disabledCatalogs.begin();
|
|
||||||
for (; j != d->disabledCatalogs.end(); ++j) {
|
|
||||||
if ((*j)->id() == aId) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (catIt == d->catalogs.end()) {
|
||||||
if (j == d->disabledCatalogs.end()) {
|
// first fresh, add to our storage now
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: no catalog with id:" << aId);
|
d->catalogs.insert(catIt, CatalogDict::value_type(aCat->id(), aCat));
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
d->refreshing.erase(aCat);
|
||||||
|
if (d->refreshing.empty()) {
|
||||||
|
if (d->delegate) {
|
||||||
|
d->delegate->refreshComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
cat = *j;
|
|
||||||
d->disabledCatalogs.erase(j);
|
|
||||||
} else {
|
|
||||||
cat = catIt->second;
|
|
||||||
// drop the reference
|
|
||||||
d->catalogs.erase(catIt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = cat->uninstall();
|
|
||||||
if (!ok) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: catalog :" << aId
|
|
||||||
<< "failed to uninstall");
|
|
||||||
}
|
|
||||||
|
|
||||||
// notify that a catalog is being removed
|
|
||||||
d->firePackagesChanged();
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Root::requestThumbnailData(const std::string& aUrl)
|
|
||||||
{
|
|
||||||
MemThumbnailCache::iterator it = d->thumbnailCache.find(aUrl);
|
|
||||||
if (it == d->thumbnailCache.end()) {
|
|
||||||
// insert into cache to mark as pending
|
|
||||||
d->pendingThumbnails.push_front(aUrl);
|
|
||||||
d->thumbnailCache[aUrl] = std::string();
|
|
||||||
d->downloadNextPendingThumbnail();
|
|
||||||
} else if (!it->second.empty()) {
|
|
||||||
// already loaded, fire data synchronously
|
|
||||||
d->fireDataForThumbnail(aUrl, it->second);
|
|
||||||
} else {
|
|
||||||
// in cache but empty data, still fetching
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InstallRef Root::existingInstallForPackage(PackageRef p) const
|
|
||||||
{
|
|
||||||
RootPrivate::InstallCache::const_iterator it =
|
|
||||||
d->m_installs.find(p);
|
|
||||||
if (it == d->m_installs.end()) {
|
|
||||||
// check if it exists on disk, create
|
|
||||||
SGPath path(p->pathOnDisk());
|
|
||||||
if (path.exists()) {
|
|
||||||
// this will add to our cache, and hence, modify m_installs
|
|
||||||
return Install::createFromPath(path, p->catalog());
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert a null reference into the dictionary, so we don't call
|
|
||||||
// the pathOnDisk -> exists codepath repeatedley
|
|
||||||
d->m_installs[p] = InstallRef();
|
|
||||||
return InstallRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Root::registerInstall(InstallRef ins)
|
|
||||||
{
|
|
||||||
if (!ins.valid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->m_installs[ins->package()] = ins;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Root::unregisterInstall(InstallRef ins)
|
|
||||||
{
|
|
||||||
if (!ins .valid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->m_installs.erase(ins->package());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|||||||
+11
-42
@@ -62,10 +62,8 @@ public:
|
|||||||
|
|
||||||
void setLocale(const std::string& aLocale);
|
void setLocale(const std::string& aLocale);
|
||||||
|
|
||||||
void addDelegate(Delegate* aDelegate);
|
void setDelegate(Delegate* aDelegate);
|
||||||
|
|
||||||
void removeDelegate(Delegate* aDelegate);
|
|
||||||
|
|
||||||
std::string getLocale() const;
|
std::string getLocale() const;
|
||||||
|
|
||||||
CatalogList catalogs() const;
|
CatalogList catalogs() const;
|
||||||
@@ -83,28 +81,17 @@ public:
|
|||||||
void makeHTTPRequest(HTTP::Request* req);
|
void makeHTTPRequest(HTTP::Request* req);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The catalog XML/property version in use. This is used to make incomaptible
|
* the version string of the root. Catalogs must match this version,
|
||||||
* changes to the package/catalog syntax
|
|
||||||
*/
|
|
||||||
int catalogVersion() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the version string of the application. Catalogs must match this version,
|
|
||||||
* or they will be ignored / rejected.
|
* or they will be ignored / rejected.
|
||||||
*/
|
*/
|
||||||
std::string applicationVersion() const;
|
std::string catalogVersion() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* refresh catalogs which are more than the maximum age (24 hours by default)
|
* refresh catalogs which are more than the maximum age (24 hours by default)
|
||||||
* set force to true, to download all catalogs regardless of age.
|
* set force to true, to download all catalogs regardless of age.
|
||||||
*/
|
*/
|
||||||
void refresh(bool aForce = false);
|
void refresh(bool aForce = false);
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
PackageList allPackages() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* retrieve packages matching a filter.
|
* retrieve packages matching a filter.
|
||||||
* filter consists of required / minimum values, AND-ed together.
|
* filter consists of required / minimum values, AND-ed together.
|
||||||
@@ -122,39 +109,21 @@ public:
|
|||||||
CatalogRef getCatalogById(const std::string& aId) const;
|
CatalogRef getCatalogById(const std::string& aId) const;
|
||||||
|
|
||||||
void scheduleToUpdate(InstallRef aInstall);
|
void scheduleToUpdate(InstallRef aInstall);
|
||||||
|
|
||||||
/**
|
|
||||||
* remove a catalog. Will uninstall all packages originating
|
|
||||||
* from the catalog too.
|
|
||||||
*/
|
|
||||||
bool removeCatalogById(const std::string& aId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* request thumbnail data from the cache / network
|
|
||||||
*/
|
|
||||||
void requestThumbnailData(const std::string& aUrl);
|
|
||||||
|
|
||||||
bool isInstallQueued(InstallRef aInstall) const;
|
|
||||||
private:
|
private:
|
||||||
friend class Install;
|
friend class Install;
|
||||||
friend class Catalog;
|
friend class Catalog;
|
||||||
friend class Package;
|
|
||||||
|
|
||||||
InstallRef existingInstallForPackage(PackageRef p) const;
|
|
||||||
|
void catalogRefreshBegin(CatalogRef aCat);
|
||||||
void catalogRefreshStatus(CatalogRef aCat, Delegate::StatusCode aReason);
|
void catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason);
|
||||||
|
|
||||||
void startNext(InstallRef aCurrent);
|
void startNext(InstallRef aCurrent);
|
||||||
|
|
||||||
void startInstall(InstallRef aInstall);
|
void startInstall(InstallRef aInstall);
|
||||||
void installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal);
|
void installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal);
|
||||||
void finishInstall(InstallRef aInstall, Delegate::StatusCode aReason);
|
void finishInstall(InstallRef aInstall);
|
||||||
void cancelDownload(InstallRef aInstall);
|
void failedInstall(InstallRef aInstall, Delegate::FailureCode aReason);
|
||||||
|
|
||||||
void registerInstall(InstallRef ins);
|
|
||||||
void unregisterInstall(InstallRef ins);
|
|
||||||
|
|
||||||
class ThumbnailDownloader;
|
|
||||||
class RootPrivate;
|
class RootPrivate;
|
||||||
std::auto_ptr<RootPrivate> d;
|
std::auto_ptr<RootPrivate> d;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<PropertyList>
|
|
||||||
<id>org.flightgear.test.catalog1</id>
|
|
||||||
<description>First test catalog</description>
|
|
||||||
<url>http://download.flightgear.org/catalog1/catalog.xml</url>
|
|
||||||
<version>8.1.*</version>
|
|
||||||
<version>8.0.0</version>
|
|
||||||
<version>8.2.0</version>
|
|
||||||
|
|
||||||
<package>
|
|
||||||
<id>alpha</id>
|
|
||||||
<name>Alpha package</name>
|
|
||||||
<revision type="int">8</revision>
|
|
||||||
<file-size-bytes type="int">1234567</file-size-bytes>
|
|
||||||
</package>
|
|
||||||
|
|
||||||
<package>
|
|
||||||
<id>c172p</id>
|
|
||||||
<name>Cessna 172-P</name>
|
|
||||||
<description>A plane made by Cessna</description>
|
|
||||||
<revision type="int">42</revision>
|
|
||||||
<file-size-bytes type="int">34567</file-size-bytes>
|
|
||||||
|
|
||||||
<tag>cessna</tag>
|
|
||||||
<tag>ga</tag>
|
|
||||||
<tag>piston</tag>
|
|
||||||
<tag>ifr</tag>
|
|
||||||
|
|
||||||
<rating>
|
|
||||||
<FDM type="int">3</FDM>
|
|
||||||
<systems type="int">4</systems>
|
|
||||||
<model type="int">5</model>
|
|
||||||
<cockpit type="int">4</cockpit>
|
|
||||||
</rating>
|
|
||||||
|
|
||||||
<!-- local dependency -->
|
|
||||||
<depends>
|
|
||||||
<id>org.flightgear.test.catalog1.common-sounds</id>
|
|
||||||
<revision>10</revision>
|
|
||||||
</depends>
|
|
||||||
|
|
||||||
<variant>
|
|
||||||
<id>c172p-2d-panel</id>
|
|
||||||
<name>C172 with 2d panel only</name>
|
|
||||||
</variant>
|
|
||||||
|
|
||||||
<variant>
|
|
||||||
<id>c172p-floats</id>
|
|
||||||
<name>C172 with floats</name>
|
|
||||||
</variant>
|
|
||||||
|
|
||||||
<variant>
|
|
||||||
<id>c172p-skis</id>
|
|
||||||
<name>C172 with skis</name>
|
|
||||||
</variant>
|
|
||||||
</package>
|
|
||||||
|
|
||||||
<package>
|
|
||||||
<id>common-sounds</id>
|
|
||||||
<name>Common sound files for test catalog aircraft</name>
|
|
||||||
<revision>10</revision>
|
|
||||||
</package>
|
|
||||||
</PropertyList>
|
|
||||||
@@ -158,8 +158,7 @@ SG_MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
|
|||||||
{
|
{
|
||||||
u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
|
u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
|
||||||
|
|
||||||
#if ((defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || \
|
#ifndef WORDS_BIGENDIAN
|
||||||
defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) )
|
|
||||||
memcpy(in, block, sizeof(in));
|
memcpy(in, block, sizeof(in));
|
||||||
#else
|
#else
|
||||||
for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
|
for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
|
||||||
@@ -248,4 +247,4 @@ defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) )
|
|||||||
state[1] += b;
|
state[1] += b;
|
||||||
state[2] += c;
|
state[2] += c;
|
||||||
state[3] += d;
|
state[3] += d;
|
||||||
}
|
}
|
||||||
+39
-45
@@ -26,7 +26,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace simgear;
|
using namespace simgear;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
bool keepRunning = true;
|
bool keepRunning = true;
|
||||||
@@ -34,50 +34,44 @@ bool keepRunning = true;
|
|||||||
class MyDelegate : public pkg::Delegate
|
class MyDelegate : public pkg::Delegate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void catalogRefreshed(pkg::CatalogRef aCatalog, StatusCode aReason)
|
virtual void refreshComplete()
|
||||||
{
|
{
|
||||||
if (aReason == STATUS_REFRESHED) {
|
|
||||||
if (aCatalog.ptr() == NULL) {
|
|
||||||
cout << "refreshed all catalogs" << endl;
|
|
||||||
} else {
|
|
||||||
cout << "refreshed catalog " << aCatalog->url() << endl;
|
|
||||||
}
|
|
||||||
} else if (aReason == STATUS_IN_PROGRESS) {
|
|
||||||
cout << "started refresh of " << aCatalog->url() << endl;
|
|
||||||
} else {
|
|
||||||
cerr << "failed refresh of " << aCatalog->url() << ":" << aReason << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void startInstall(pkg::InstallRef aInstall)
|
virtual void failedRefresh(pkg::Catalog* aCatalog, FailureCode aReason)
|
||||||
|
{
|
||||||
|
cerr << "failed refresh of " << aCatalog->description() << ":" << aReason << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void startInstall(pkg::Install* aInstall)
|
||||||
{
|
{
|
||||||
_lastPercent = 999;
|
_lastPercent = 999;
|
||||||
cout << "starting install of " << aInstall->package()->name() << endl;
|
cout << "starting install of " << aInstall->package()->name() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void installProgress(pkg::InstallRef aInstall, unsigned int bytes, unsigned int total)
|
virtual void installProgress(pkg::Install* aInstall, unsigned int bytes, unsigned int total)
|
||||||
{
|
{
|
||||||
unsigned int percent = (bytes * 100) / total;
|
unsigned int percent = (bytes * 100) / total;
|
||||||
if (percent == _lastPercent) {
|
if (percent == _lastPercent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastPercent = percent;
|
_lastPercent = percent;
|
||||||
cout << percent << "%" << endl;
|
cout << percent << "%" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void finishInstall(pkg::InstallRef aInstall, StatusCode aReason)
|
virtual void finishInstall(pkg::Install* aInstall)
|
||||||
{
|
{
|
||||||
if (aReason == STATUS_SUCCESS) {
|
cout << "done install of " << aInstall->package()->name() << endl;
|
||||||
cout << "done install of " << aInstall->package()->name() << endl;
|
|
||||||
} else {
|
|
||||||
cerr << "failed install of " << aInstall->package()->name() << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void failedInstall(pkg::Install* aInstall, FailureCode aReason)
|
||||||
|
{
|
||||||
|
cerr << "failed install of " << aInstall->package()->name() << endl;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
unsigned int _lastPercent;
|
unsigned int _lastPercent;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void printRating(pkg::Package* pkg, const std::string& aRating, const std::string& aLabel)
|
void printRating(pkg::Package* pkg, const std::string& aRating, const std::string& aLabel)
|
||||||
@@ -93,24 +87,24 @@ void printPackageInfo(pkg::Package* pkg)
|
|||||||
cout << "Name:" << pkg->name() << endl;
|
cout << "Name:" << pkg->name() << endl;
|
||||||
cout << "Description:" << pkg->description() << endl;
|
cout << "Description:" << pkg->description() << endl;
|
||||||
cout << "Long description:\n" << pkg->getLocalisedProp("long-description") << endl << endl;
|
cout << "Long description:\n" << pkg->getLocalisedProp("long-description") << endl << endl;
|
||||||
|
|
||||||
if (pkg->properties()->hasChild("author")) {
|
if (pkg->properties()->hasChild("author")) {
|
||||||
cout << "Authors:" << endl;
|
cout << "Authors:" << endl;
|
||||||
BOOST_FOREACH(SGPropertyNode* author, pkg->properties()->getChildren("author")) {
|
BOOST_FOREACH(SGPropertyNode* author, pkg->properties()->getChildren("author")) {
|
||||||
if (author->hasChild("name")) {
|
if (author->hasChild("name")) {
|
||||||
cout << "\t" << author->getStringValue("name") << endl;
|
cout << "\t" << author->getStringValue("name") << endl;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// simple author structure
|
// simple author structure
|
||||||
cout << "\t" << author->getStringValue() << endl;
|
cout << "\t" << author->getStringValue() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << endl;
|
cout << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "Ratings:" << endl;
|
cout << "Ratings:" << endl;
|
||||||
printRating(pkg, "fdm", "Flight-model ");
|
printRating(pkg, "fdm", "Flight-model ");
|
||||||
printRating(pkg, "cockpit", "Cockpit ");
|
printRating(pkg, "cockpit", "Cockpit ");
|
||||||
@@ -123,15 +117,15 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
HTTP::Client* http = new HTTP::Client();
|
HTTP::Client* http = new HTTP::Client();
|
||||||
pkg::Root* root = new pkg::Root(Dir::current().path(), "");
|
pkg::Root* root = new pkg::Root(Dir::current().path(), "");
|
||||||
|
|
||||||
MyDelegate dlg;
|
MyDelegate dlg;
|
||||||
root->addDelegate(&dlg);
|
root->setDelegate(&dlg);
|
||||||
|
|
||||||
cout << "Package root is:" << Dir::current().path() << endl;
|
cout << "Package root is:" << Dir::current().path() << endl;
|
||||||
cout << "have " << root->catalogs().size() << " catalog(s)" << endl;
|
cout << "have " << pkg::Catalog::allCatalogs().size() << " catalog(s)" << endl;
|
||||||
|
|
||||||
root->setHTTPClient(http);
|
root->setHTTPClient(http);
|
||||||
|
|
||||||
if (!strcmp(argv[1], "add")) {
|
if (!strcmp(argv[1], "add")) {
|
||||||
std::string url(argv[2]);
|
std::string url(argv[2]);
|
||||||
pkg::Catalog::createFromUrl(root, url);
|
pkg::Catalog::createFromUrl(root, url);
|
||||||
@@ -143,12 +137,12 @@ int main(int argc, char** argv)
|
|||||||
cerr << "unknown package:" << argv[2] << endl;
|
cerr << "unknown package:" << argv[2] << endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkg->isInstalled()) {
|
if (pkg->isInstalled()) {
|
||||||
cout << "package " << pkg->id() << " is already installed at " << pkg->install()->path() << endl;
|
cout << "package " << pkg->id() << " is already installed at " << pkg->install()->path() << endl;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkg::CatalogRef catalog = pkg->catalog();
|
pkg::CatalogRef catalog = pkg->catalog();
|
||||||
cout << "Will install:" << pkg->id() << " from " << catalog->id() <<
|
cout << "Will install:" << pkg->id() << " from " << catalog->id() <<
|
||||||
"(" << catalog->description() << ")" << endl;
|
"(" << catalog->description() << ")" << endl;
|
||||||
@@ -159,12 +153,12 @@ int main(int argc, char** argv)
|
|||||||
cerr << "unknown package:" << argv[2] << endl;
|
cerr << "unknown package:" << argv[2] << endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pkg->isInstalled()) {
|
if (!pkg->isInstalled()) {
|
||||||
cerr << "package " << argv[2] << " not installed" << endl;
|
cerr << "package " << argv[2] << " not installed" << endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "Will uninstall:" << pkg->id() << endl;
|
cout << "Will uninstall:" << pkg->id() << endl;
|
||||||
pkg->install()->uninstall();
|
pkg->install()->uninstall();
|
||||||
} else if (!strcmp(argv[1], "update-all")) {
|
} else if (!strcmp(argv[1], "update-all")) {
|
||||||
@@ -178,7 +172,7 @@ int main(int argc, char** argv)
|
|||||||
cout << "no packages with updates" << endl;
|
cout << "no packages with updates" << endl;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << updates.size() << " packages have updates" << endl;
|
cout << updates.size() << " packages have updates" << endl;
|
||||||
BOOST_FOREACH(pkg::Package* p, updates) {
|
BOOST_FOREACH(pkg::Package* p, updates) {
|
||||||
cout << "\t" << p->id() << " " << p->getLocalisedProp("name") << endl;
|
cout << "\t" << p->id() << " " << p->getLocalisedProp("name") << endl;
|
||||||
@@ -189,13 +183,13 @@ int main(int argc, char** argv)
|
|||||||
cerr << "unknown package:" << argv[2] << endl;
|
cerr << "unknown package:" << argv[2] << endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
printPackageInfo(pkg);
|
printPackageInfo(pkg);
|
||||||
} else {
|
} else {
|
||||||
cerr << "unknown command:" << argv[1] << endl;
|
cerr << "unknown command:" << argv[1] << endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (http->hasActiveRequests()) {
|
while (http->hasActiveRequests()) {
|
||||||
http->update();
|
http->update();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,9 +144,9 @@ public:
|
|||||||
|
|
||||||
#undef SG_DEF_ASSIGN_OP
|
#undef SG_DEF_ASSIGN_OP
|
||||||
|
|
||||||
SGPropertyNode* node(bool aCreate = false) const
|
SGPropertyNode* node() const
|
||||||
{
|
{
|
||||||
return PropertyObjectBase::node(aCreate);
|
return PropertyObjectBase::node(false);
|
||||||
}
|
}
|
||||||
}; // of template PropertyObject
|
}; // of template PropertyObject
|
||||||
|
|
||||||
@@ -237,9 +237,9 @@ public:
|
|||||||
return (s == value);
|
return (s == value);
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode* node(bool aCreate = false) const
|
SGPropertyNode* node() const
|
||||||
{
|
{
|
||||||
return PropertyObjectBase::node(aCreate);
|
return PropertyObjectBase::node(false);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|||||||
+33
-254
@@ -11,6 +11,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "props.hxx"
|
#include "props.hxx"
|
||||||
|
#include "PropertyInterpolationMgr.hxx"
|
||||||
|
#include "vectorPropTemplates.hxx"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -22,30 +24,31 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/find_iterator.hpp>
|
||||||
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
#include <boost/algorithm/string/classification.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/functional/hash.hpp>
|
||||||
|
#include <boost/range.hpp>
|
||||||
|
|
||||||
#if PROPS_STANDALONE
|
#if PROPS_STANDALONE
|
||||||
# include <iostream>
|
#include <iostream>
|
||||||
using std::cerr;
|
|
||||||
#else
|
#else
|
||||||
# include <boost/algorithm/string/find_iterator.hpp>
|
|
||||||
# include <boost/algorithm/string/predicate.hpp>
|
|
||||||
# include <boost/algorithm/string/classification.hpp>
|
|
||||||
# include <boost/bind.hpp>
|
|
||||||
# include <boost/functional/hash.hpp>
|
|
||||||
# include <boost/range.hpp>
|
|
||||||
# include <simgear/compiler.h>
|
|
||||||
# include <simgear/debug/logstream.hxx>
|
|
||||||
|
|
||||||
# include "PropertyInterpolationMgr.hxx"
|
#include <simgear/compiler.h>
|
||||||
# include "vectorPropTemplates.hxx"
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
# if ( _MSC_VER == 1200 )
|
#if ( _MSC_VER == 1200 )
|
||||||
// MSVC 6 is buggy, and needs something strange here
|
// MSVC 6 is buggy, and needs something strange here
|
||||||
using std::vector<SGPropertyNode_ptr>;
|
using std::vector<SGPropertyNode_ptr>;
|
||||||
using std::vector<SGPropertyChangeListener *>;
|
using std::vector<SGPropertyChangeListener *>;
|
||||||
using std::vector<SGPropertyNode *>;
|
using std::vector<SGPropertyNode *>;
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PROPS_STANDALONE
|
||||||
|
using std::cerr;
|
||||||
|
#endif
|
||||||
using std::endl;
|
using std::endl;
|
||||||
using std::find;
|
using std::find;
|
||||||
using std::sort;
|
using std::sort;
|
||||||
@@ -81,14 +84,6 @@ public:
|
|||||||
// Local path normalization code.
|
// Local path normalization code.
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if PROPS_STANDALONE
|
|
||||||
struct PathComponent
|
|
||||||
{
|
|
||||||
string name;
|
|
||||||
int index;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the name for a path component.
|
* Parse the name for a path component.
|
||||||
*
|
*
|
||||||
@@ -151,149 +146,10 @@ inline bool validateName(const std::string& name)
|
|||||||
return false;
|
return false;
|
||||||
if (!isalpha(name[0]) && name[0] != '_')
|
if (!isalpha(name[0]) && name[0] != '_')
|
||||||
return false;
|
return false;
|
||||||
#if PROPS_STANDALONE
|
|
||||||
std::string is_any_of("_-.");
|
|
||||||
bool rv = true;
|
|
||||||
for(unsigned i=1; i<name.length(); ++i) {
|
|
||||||
if (!isalnum(name[i]) && is_any_of.find(name[i]) == std::string::npos) {
|
|
||||||
rv = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
#else
|
|
||||||
return all(make_iterator_range(name.begin(), name.end()),
|
return all(make_iterator_range(name.begin(), name.end()),
|
||||||
is_alnum() || is_any_of("_-."));
|
is_alnum() || is_any_of("_-."));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PROPS_STANDALONE
|
|
||||||
/**
|
|
||||||
* Parse the name for a path component.
|
|
||||||
*
|
|
||||||
* Name: [_a-zA-Z][-._a-zA-Z0-9]*
|
|
||||||
*/
|
|
||||||
static inline const string
|
|
||||||
parse_name (const string &path, int &i)
|
|
||||||
{
|
|
||||||
string name = "";
|
|
||||||
int max = (int)path.size();
|
|
||||||
|
|
||||||
if (path[i] == '.') {
|
|
||||||
i++;
|
|
||||||
if (i < max && path[i] == '.') {
|
|
||||||
i++;
|
|
||||||
name = "..";
|
|
||||||
} else {
|
|
||||||
name = ".";
|
|
||||||
}
|
|
||||||
if (i < max && path[i] != '/')
|
|
||||||
throw string("Illegal character after " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (isalpha(path[i]) || path[i] == '_') {
|
|
||||||
name += path[i];
|
|
||||||
i++;
|
|
||||||
|
|
||||||
// The rules inside a name are a little
|
|
||||||
// less restrictive.
|
|
||||||
while (i < max) {
|
|
||||||
if (isalpha(path[i]) || isdigit(path[i]) || path[i] == '_' ||
|
|
||||||
path[i] == '-' || path[i] == '.') {
|
|
||||||
name += path[i];
|
|
||||||
} else if (path[i] == '[' || path[i] == '/') {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
throw string("name may contain only ._- and alphanumeric characters");
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
if (name.size() == 0)
|
|
||||||
throw string("name must begin with alpha or '_'");
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the optional integer index for a path component.
|
|
||||||
*
|
|
||||||
* Index: "[" [0-9]+ "]"
|
|
||||||
*/
|
|
||||||
static inline int
|
|
||||||
parse_index (const string &path, int &i)
|
|
||||||
{
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (path[i] != '[')
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
i++;
|
|
||||||
|
|
||||||
for (int max = (int)path.size(); i < max; i++) {
|
|
||||||
if (isdigit(path[i])) {
|
|
||||||
index = (index * 10) + (path[i] - '0');
|
|
||||||
} else if (path[i] == ']') {
|
|
||||||
i++;
|
|
||||||
return index;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw string("unterminated index (looking for ']')");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a single path component.
|
|
||||||
*
|
|
||||||
* Component: Name Index?
|
|
||||||
*/
|
|
||||||
static inline PathComponent
|
|
||||||
parse_component (const string &path, int &i)
|
|
||||||
{
|
|
||||||
PathComponent component;
|
|
||||||
component.name = parse_name(path, i);
|
|
||||||
if (component.name[0] != '.')
|
|
||||||
component.index = parse_index(path, i);
|
|
||||||
else
|
|
||||||
component.index = -1;
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a path into its components.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
parse_path (const string &path, vector<PathComponent> &components)
|
|
||||||
{
|
|
||||||
int pos = 0;
|
|
||||||
int max = (int)path.size();
|
|
||||||
|
|
||||||
// Check for initial '/'
|
|
||||||
if (path[pos] == '/') {
|
|
||||||
PathComponent root;
|
|
||||||
root.name = "";
|
|
||||||
root.index = -1;
|
|
||||||
components.push_back(root);
|
|
||||||
pos++;
|
|
||||||
while (pos < max && path[pos] == '/')
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (pos < max) {
|
|
||||||
components.push_back(parse_component(path, pos));
|
|
||||||
while (pos < max && path[pos] == '/')
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Other static utility functions.
|
// Other static utility functions.
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@@ -326,13 +182,6 @@ static int
|
|||||||
find_child (Itr begin, Itr end, int index, const PropertyList& nodes)
|
find_child (Itr begin, Itr end, int index, const PropertyList& nodes)
|
||||||
{
|
{
|
||||||
size_t nNodes = nodes.size();
|
size_t nNodes = nodes.size();
|
||||||
#if PROPS_STANDALONE
|
|
||||||
for (int i = 0; i < nNodes; i++) {
|
|
||||||
SGPropertyNode * node = nodes[i];
|
|
||||||
if (node->getIndex() == index && compare_strings(node->getName(), begin))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
boost::iterator_range<Itr> name(begin, end);
|
boost::iterator_range<Itr> name(begin, end);
|
||||||
for (size_t i = 0; i < nNodes; i++) {
|
for (size_t i = 0; i < nNodes; i++) {
|
||||||
SGPropertyNode * node = nodes[i];
|
SGPropertyNode * node = nodes[i];
|
||||||
@@ -342,7 +191,6 @@ find_child (Itr begin, Itr end, int index, const PropertyList& nodes)
|
|||||||
if (node->getIndex() == index && boost::equals(node->getName(), name))
|
if (node->getIndex() == index && boost::equals(node->getName(), name))
|
||||||
return static_cast<int>(i);
|
return static_cast<int>(i);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,57 +333,11 @@ find_node_aux(SGPropertyNode * current, SplitItr& itr, bool create,
|
|||||||
|
|
||||||
// Internal function for parsing property paths. last_index provides
|
// Internal function for parsing property paths. last_index provides
|
||||||
// and index value for the last node name token, if supplied.
|
// and index value for the last node name token, if supplied.
|
||||||
#if PROPS_STANDALONE
|
|
||||||
static SGPropertyNode *
|
|
||||||
find_node (SGPropertyNode * current,
|
|
||||||
const vector<PathComponent> &components,
|
|
||||||
int position,
|
|
||||||
bool create)
|
|
||||||
{
|
|
||||||
// Run off the end of the list
|
|
||||||
if (current == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Success! This is the one we want.
|
|
||||||
else if (position >= (int)components.size()) {
|
|
||||||
return (current->getAttribute(SGPropertyNode::REMOVED) ? 0 : current);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty component means root.
|
|
||||||
else if (components[position].name == "") {
|
|
||||||
return find_node(current->getRootNode(), components, position + 1, create);
|
|
||||||
}
|
|
||||||
|
|
||||||
// . means current directory
|
|
||||||
else if (components[position].name == ".") {
|
|
||||||
return find_node(current, components, position + 1, create);
|
|
||||||
}
|
|
||||||
|
|
||||||
// .. means parent directory
|
|
||||||
else if (components[position].name == "..") {
|
|
||||||
SGPropertyNode * parent = current->getParent();
|
|
||||||
if (parent == 0)
|
|
||||||
throw string("Attempt to move past root with '..'");
|
|
||||||
else
|
|
||||||
return find_node(parent, components, position + 1, create);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, a child name
|
|
||||||
else {
|
|
||||||
SGPropertyNode * child =
|
|
||||||
current->getChild(components[position].name.c_str(),
|
|
||||||
components[position].index,
|
|
||||||
create);
|
|
||||||
return find_node(child, components, position + 1, create);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
template<typename Range>
|
template<typename Range>
|
||||||
SGPropertyNode*
|
SGPropertyNode*
|
||||||
find_node (SGPropertyNode * current,
|
find_node (SGPropertyNode * current,
|
||||||
const Range& path,
|
const Range& path,
|
||||||
bool create,
|
bool create,
|
||||||
int last_index = -1)
|
int last_index = -1)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
@@ -549,7 +351,6 @@ find_node (SGPropertyNode * current,
|
|||||||
else
|
else
|
||||||
return find_node_aux(current, itr, create, last_index);
|
return find_node_aux(current, itr, create, last_index);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Private methods from SGPropertyNode (may be inlined for speed).
|
// Private methods from SGPropertyNode (may be inlined for speed).
|
||||||
@@ -810,8 +611,13 @@ SGPropertyNode::make_string () const
|
|||||||
void
|
void
|
||||||
SGPropertyNode::trace_write () const
|
SGPropertyNode::trace_write () const
|
||||||
{
|
{
|
||||||
|
#if PROPS_STANDALONE
|
||||||
|
cerr << "TRACE: Write node " << getPath () << ", value \""
|
||||||
|
<< make_string() << '"' << endl;
|
||||||
|
#else
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Write node " << getPath()
|
SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Write node " << getPath()
|
||||||
<< ", value \"" << make_string() << '"');
|
<< ", value \"" << make_string() << '"');
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -820,8 +626,13 @@ SGPropertyNode::trace_write () const
|
|||||||
void
|
void
|
||||||
SGPropertyNode::trace_read () const
|
SGPropertyNode::trace_read () const
|
||||||
{
|
{
|
||||||
|
#if PROPS_STANDALONE
|
||||||
|
cerr << "TRACE: Write node " << getPath () << ", value \""
|
||||||
|
<< make_string() << '"' << endl;
|
||||||
|
#else
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Read node " << getPath()
|
SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Read node " << getPath()
|
||||||
<< ", value \"" << make_string() << '"');
|
<< ", value \"" << make_string() << '"');
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@@ -975,6 +786,8 @@ SGPropertyNode::alias (SGPropertyNode * target)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PROPS_STANDALONE
|
||||||
|
#else
|
||||||
if (!target)
|
if (!target)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||||
@@ -996,6 +809,7 @@ SGPropertyNode::alias (SGPropertyNode * target)
|
|||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create alias at " << target->getPath() << ". "
|
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create alias at " << target->getPath() << ". "
|
||||||
"Source " << getPath() << " is a tied property.");
|
"Source " << getPath() << " is a tied property.");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1143,18 +957,11 @@ SGPropertyNode::getChild (const char * name, int index, bool create)
|
|||||||
SGPropertyNode *
|
SGPropertyNode *
|
||||||
SGPropertyNode::getChild (const std::string& name, int index, bool create)
|
SGPropertyNode::getChild (const std::string& name, int index, bool create)
|
||||||
{
|
{
|
||||||
#if PROPS_STANDALONE
|
|
||||||
const char *n = name.c_str();
|
|
||||||
int pos = find_child(n, n + strlen(n), index, _children);
|
|
||||||
if (pos >= 0) {
|
|
||||||
return _children[pos];
|
|
||||||
#else
|
|
||||||
SGPropertyNode* node = getExistingChild(name.begin(), name.end(), index);
|
SGPropertyNode* node = getExistingChild(name.begin(), name.end(), index);
|
||||||
if (node) {
|
if (node) {
|
||||||
return node;
|
return node;
|
||||||
#endif
|
|
||||||
} else if (create) {
|
} else if (create) {
|
||||||
SGPropertyNode* node = new SGPropertyNode(name, index, this);
|
node = new SGPropertyNode(name, index, this);
|
||||||
_children.push_back(node);
|
_children.push_back(node);
|
||||||
fireChildAdded(node);
|
fireChildAdded(node);
|
||||||
return node;
|
return node;
|
||||||
@@ -1828,14 +1635,12 @@ SGPropertyNode::setUnspecifiedValue (const char * value)
|
|||||||
case props::UNSPECIFIED:
|
case props::UNSPECIFIED:
|
||||||
result = set_string(value);
|
result = set_string(value);
|
||||||
break;
|
break;
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
case props::VEC3D:
|
case props::VEC3D:
|
||||||
result = static_cast<SGRawValue<SGVec3d>*>(_value.val)->setValue(parseString<SGVec3d>(value));
|
result = static_cast<SGRawValue<SGVec3d>*>(_value.val)->setValue(parseString<SGVec3d>(value));
|
||||||
break;
|
break;
|
||||||
case props::VEC4D:
|
case props::VEC4D:
|
||||||
result = static_cast<SGRawValue<SGVec4d>*>(_value.val)->setValue(parseString<SGVec4d>(value));
|
result = static_cast<SGRawValue<SGVec4d>*>(_value.val)->setValue(parseString<SGVec4d>(value));
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case props::NONE:
|
case props::NONE:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1847,7 +1652,6 @@ SGPropertyNode::setUnspecifiedValue (const char * value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
bool SGPropertyNode::interpolate( const std::string& type,
|
bool SGPropertyNode::interpolate( const std::string& type,
|
||||||
const SGPropertyNode& target,
|
const SGPropertyNode& target,
|
||||||
double duration,
|
double duration,
|
||||||
@@ -1897,7 +1701,6 @@ simgear::PropertyInterpolationMgr* SGPropertyNode::getInterpolationMgr()
|
|||||||
}
|
}
|
||||||
|
|
||||||
simgear::PropertyInterpolationMgr* SGPropertyNode::_interpolation_mgr = 0;
|
simgear::PropertyInterpolationMgr* SGPropertyNode::_interpolation_mgr = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
std::ostream& SGPropertyNode::printOn(std::ostream& stream) const
|
std::ostream& SGPropertyNode::printOn(std::ostream& stream) const
|
||||||
@@ -2051,37 +1854,20 @@ SGPropertyNode::getRootNode () const
|
|||||||
SGPropertyNode *
|
SGPropertyNode *
|
||||||
SGPropertyNode::getNode (const char * relative_path, bool create)
|
SGPropertyNode::getNode (const char * relative_path, bool create)
|
||||||
{
|
{
|
||||||
#if PROPS_STANDALONE
|
|
||||||
vector<PathComponent> components;
|
|
||||||
parse_path(relative_path, components);
|
|
||||||
return find_node(this, components, 0, create);
|
|
||||||
|
|
||||||
#else
|
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
return find_node(this, make_iterator_range(relative_path, relative_path
|
return find_node(this, make_iterator_range(relative_path, relative_path
|
||||||
+ strlen(relative_path)),
|
+ strlen(relative_path)),
|
||||||
create);
|
create);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode *
|
SGPropertyNode *
|
||||||
SGPropertyNode::getNode (const char * relative_path, int index, bool create)
|
SGPropertyNode::getNode (const char * relative_path, int index, bool create)
|
||||||
{
|
{
|
||||||
#if PROPS_STANDALONE
|
|
||||||
vector<PathComponent> components;
|
|
||||||
parse_path(relative_path, components);
|
|
||||||
if (components.size() > 0)
|
|
||||||
components.back().index = index;
|
|
||||||
return find_node(this, components, 0, create);
|
|
||||||
|
|
||||||
#else
|
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
return find_node(this, make_iterator_range(relative_path, relative_path
|
return find_node(this, make_iterator_range(relative_path, relative_path
|
||||||
+ strlen(relative_path)),
|
+ strlen(relative_path)),
|
||||||
create, index);
|
create, index);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SGPropertyNode *
|
const SGPropertyNode *
|
||||||
@@ -2529,7 +2315,6 @@ SGPropertyChangeListener::unregister_property (SGPropertyNode * node)
|
|||||||
_properties.erase(it);
|
_properties.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
template<>
|
template<>
|
||||||
std::ostream& SGRawBase<SGVec3d>::printOn(std::ostream& stream) const
|
std::ostream& SGRawBase<SGVec3d>::printOn(std::ostream& stream) const
|
||||||
{
|
{
|
||||||
@@ -2566,11 +2351,9 @@ std::ostream& SGRawBase<SGVec4d>::printOn(std::ostream& stream) const
|
|||||||
}
|
}
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
template<>
|
template<>
|
||||||
std::istream& readFrom<SGVec4d>(std::istream& stream, SGVec4d& result)
|
std::istream& readFrom<SGVec4d>(std::istream& stream, SGVec4d& result)
|
||||||
{
|
{
|
||||||
@@ -2579,7 +2362,6 @@ std::istream& readFrom<SGVec4d>(std::istream& stream, SGVec4d& result)
|
|||||||
}
|
}
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -2607,12 +2389,10 @@ bool compareNodeValue(const SGPropertyNode& lhs, const SGPropertyNode& rhs)
|
|||||||
case props::STRING:
|
case props::STRING:
|
||||||
case props::UNSPECIFIED:
|
case props::UNSPECIFIED:
|
||||||
return !strcmp(lhs.getStringValue(), rhs.getStringValue());
|
return !strcmp(lhs.getStringValue(), rhs.getStringValue());
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
case props::VEC3D:
|
case props::VEC3D:
|
||||||
return lhs.getValue<SGVec3d>() == rhs.getValue<SGVec3d>();
|
return lhs.getValue<SGVec3d>() == rhs.getValue<SGVec3d>();
|
||||||
case props::VEC4D:
|
case props::VEC4D:
|
||||||
return lhs.getValue<SGVec4d>() == rhs.getValue<SGVec4d>();
|
return lhs.getValue<SGVec4d>() == rhs.getValue<SGVec4d>();
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2669,10 +2449,10 @@ struct PropertyPlaceLess {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
size_t hash_value(const SGPropertyNode& node)
|
size_t hash_value(const SGPropertyNode& node)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
if (node.nChildren() == 0) {
|
if (node.nChildren() == 0) {
|
||||||
switch (node.getType()) {
|
switch (node.getType()) {
|
||||||
case props::NONE:
|
case props::NONE:
|
||||||
@@ -2723,6 +2503,5 @@ size_t hash_value(const SGPropertyNode& node)
|
|||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// end of props.cxx
|
// end of props.cxx
|
||||||
|
|||||||
+9
-49
@@ -22,54 +22,24 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <boost/utility.hpp>
|
||||||
|
#include <boost/type_traits/is_enum.hpp>
|
||||||
|
|
||||||
#if PROPS_STANDALONE
|
#if PROPS_STANDALONE
|
||||||
// taken from: boost/utility/enable_if.hpp
|
|
||||||
#ifndef SG_LOG
|
|
||||||
# define SG_GENERAL 0
|
|
||||||
# define SG_ALERT 0
|
|
||||||
# define SG_WARN 1
|
|
||||||
# define SG_LOG(type, level, message) (type) ? (std::cerr <<message << endl) : (std::cout <<message << endl)
|
|
||||||
#endif
|
|
||||||
namespace boost {
|
|
||||||
template <bool B, class T = void>
|
|
||||||
struct enable_if_c {
|
|
||||||
typedef T type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
struct enable_if_c<false, T> {};
|
|
||||||
|
|
||||||
template <class Cond, class T = void>
|
|
||||||
struct enable_if : public enable_if_c<Cond::value, T> {};
|
|
||||||
|
|
||||||
template <bool B, class T = void>
|
|
||||||
struct disable_if_c {
|
|
||||||
typedef T type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
struct disable_if_c<true, T> {};
|
|
||||||
|
|
||||||
template <class Cond, class T = void>
|
|
||||||
struct disable_if : public disable_if_c<Cond::value, T> {};
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
# include <boost/utility.hpp>
|
#include <simgear/compiler.h>
|
||||||
# include <boost/type_traits/is_enum.hpp>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
# include <simgear/debug/logstream.hxx>
|
|
||||||
# include <simgear/math/SGMathFwd.hxx>
|
|
||||||
# include <simgear/math/sg_types.hxx>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <simgear/math/SGMathFwd.hxx>
|
||||||
|
#include <simgear/math/sg_types.hxx>
|
||||||
#include <simgear/structure/SGReferenced.hxx>
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
|
||||||
// XXX This whole file should be in the simgear namespace, but I don't
|
// XXX This whole file should be in the simgear namespace, but I don't
|
||||||
// have the guts yet...
|
// have the guts yet...
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -1305,7 +1275,6 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !PROPS_STANDALONE
|
|
||||||
/**
|
/**
|
||||||
* Interpolate current value to target value within given time.
|
* Interpolate current value to target value within given time.
|
||||||
*
|
*
|
||||||
@@ -1341,7 +1310,6 @@ public:
|
|||||||
* Get the interpolation manager
|
* Get the interpolation manager
|
||||||
*/
|
*/
|
||||||
static simgear::PropertyInterpolationMgr* getInterpolationMgr();
|
static simgear::PropertyInterpolationMgr* getInterpolationMgr();
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print the value of the property to a stream.
|
* Print the value of the property to a stream.
|
||||||
@@ -1839,11 +1807,7 @@ private:
|
|||||||
|
|
||||||
// Convenience functions for use in templates
|
// Convenience functions for use in templates
|
||||||
template<typename T>
|
template<typename T>
|
||||||
#if PROPS_STANDALONE
|
|
||||||
T
|
|
||||||
#else
|
|
||||||
typename boost::disable_if<boost::is_enum<T>, T>::type
|
typename boost::disable_if<boost::is_enum<T>, T>::type
|
||||||
#endif
|
|
||||||
getValue(const SGPropertyNode*);
|
getValue(const SGPropertyNode*);
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@@ -1907,11 +1871,7 @@ namespace simgear
|
|||||||
|
|
||||||
/** Extract enum from SGPropertyNode */
|
/** Extract enum from SGPropertyNode */
|
||||||
template<typename T>
|
template<typename T>
|
||||||
#if PROPS_STANDALONE
|
|
||||||
inline T
|
|
||||||
#else
|
|
||||||
inline typename boost::enable_if<boost::is_enum<T>, T>::type
|
inline typename boost::enable_if<boost::is_enum<T>, T>::type
|
||||||
#endif
|
|
||||||
getValue(const SGPropertyNode* node)
|
getValue(const SGPropertyNode* node)
|
||||||
{
|
{
|
||||||
typedef simgear::enum_traits<T> Traits;
|
typedef simgear::enum_traits<T> Traits;
|
||||||
|
|||||||
@@ -326,15 +326,9 @@ public:
|
|||||||
= GL2Extensions::Get(static_cast<unsigned>(contextId), true);
|
= GL2Extensions::Get(static_cast<unsigned>(contextId), true);
|
||||||
if (!extensions)
|
if (!extensions)
|
||||||
return;
|
return;
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
if (!extensions->isGlslSupported())
|
if (!extensions->isGlslSupported())
|
||||||
return;
|
return;
|
||||||
value = extensions->getLanguageVersion();
|
value = extensions->getLanguageVersion();
|
||||||
#else
|
|
||||||
if (!extensions->isGlslSupported)
|
|
||||||
return;
|
|
||||||
value = extensions->glslLanguageVersion;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -363,11 +357,7 @@ public:
|
|||||||
= GL2Extensions::Get(static_cast<unsigned>(contextId), true);
|
= GL2Extensions::Get(static_cast<unsigned>(contextId), true);
|
||||||
if (!extensions)
|
if (!extensions)
|
||||||
return;
|
return;
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
value = extensions->isGlslSupported();
|
value = extensions->isGlslSupported();
|
||||||
#else
|
|
||||||
value = extensions->isGlslSupported;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -323,7 +323,6 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
|
|||||||
|
|
||||||
// Random vegetation properties
|
// Random vegetation properties
|
||||||
wood_coverage = props->getDoubleValue("wood-coverage", 0.0);
|
wood_coverage = props->getDoubleValue("wood-coverage", 0.0);
|
||||||
tree_effect = props->getStringValue("tree-effect", "Effects/tree");
|
|
||||||
tree_height = props->getDoubleValue("tree-height-m", 0.0);
|
tree_height = props->getDoubleValue("tree-height-m", 0.0);
|
||||||
tree_width = props->getDoubleValue("tree-width-m", 0.0);
|
tree_width = props->getDoubleValue("tree-width-m", 0.0);
|
||||||
tree_range = props->getDoubleValue("tree-range-m", 0.0);
|
tree_range = props->getDoubleValue("tree-range-m", 0.0);
|
||||||
|
|||||||
@@ -273,14 +273,6 @@ public:
|
|||||||
* @return the texture to use for trees.
|
* @return the texture to use for trees.
|
||||||
*/
|
*/
|
||||||
inline std::string get_tree_texture () const { return tree_texture; }
|
inline std::string get_tree_texture () const { return tree_texture; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the effect file name to use for trees
|
|
||||||
*
|
|
||||||
* @return the effect to use for this set of trees.
|
|
||||||
*/
|
|
||||||
inline std::string get_tree_effect () const { return tree_effect; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the cosine of the maximum tree density slope angle. We
|
* Get the cosine of the maximum tree density slope angle. We
|
||||||
@@ -484,9 +476,6 @@ private:
|
|||||||
|
|
||||||
// Tree texture, typically a strip of applicable tree textures
|
// Tree texture, typically a strip of applicable tree textures
|
||||||
std::string tree_texture;
|
std::string tree_texture;
|
||||||
|
|
||||||
// Tree effect to be used for a particular material
|
|
||||||
std::string tree_effect;
|
|
||||||
|
|
||||||
// Object mask, a simple RGB texture used as a mask when placing
|
// Object mask, a simple RGB texture used as a mask when placing
|
||||||
// random vegetation, objects and buildings
|
// random vegetation, objects and buildings
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ SGMaterialCache *SGMaterialLib::generateMatCache(SGGeod center)
|
|||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
SGMaterialLib::~SGMaterialLib ( void ) {
|
SGMaterialLib::~SGMaterialLib ( void ) {
|
||||||
SG_LOG( SG_TERRAIN, SG_DEBUG, "SGMaterialLib::~SGMaterialLib() size=" << matlib.size());
|
SG_LOG( SG_GENERAL, SG_INFO, "SGMaterialLib::~SGMaterialLib() size=" << matlib.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
const SGMaterial *SGMaterialLib::findMaterial(const osg::Geode* geode)
|
const SGMaterial *SGMaterialLib::findMaterial(const osg::Geode* geode)
|
||||||
@@ -244,5 +244,5 @@ SGMaterial *SGMaterialCache::find(const string& material) const
|
|||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
SGMaterialCache::~SGMaterialCache ( void ) {
|
SGMaterialCache::~SGMaterialCache ( void ) {
|
||||||
SG_LOG( SG_TERRAIN, SG_DEBUG, "SGMaterialCache::~SGMaterialCache() size=" << cache.size());
|
SG_LOG( SG_GENERAL, SG_INFO, "SGMaterialCache::~SGMaterialCache() size=" << cache.size());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -364,8 +364,6 @@ public:
|
|||||||
if (_textureProp) {
|
if (_textureProp) {
|
||||||
std::string textureName = _textureProp->getStringValue();
|
std::string textureName = _textureProp->getStringValue();
|
||||||
if (_textureName != textureName) {
|
if (_textureName != textureName) {
|
||||||
_textureName = textureName;
|
|
||||||
|
|
||||||
while (stateSet->getTextureAttribute(0,
|
while (stateSet->getTextureAttribute(0,
|
||||||
osg::StateAttribute::TEXTURE)) {
|
osg::StateAttribute::TEXTURE)) {
|
||||||
stateSet->removeTextureAttribute(0, osg::StateAttribute::TEXTURE);
|
stateSet->removeTextureAttribute(0, osg::StateAttribute::TEXTURE);
|
||||||
@@ -379,12 +377,8 @@ public:
|
|||||||
osg::StateAttribute::OVERRIDE);
|
osg::StateAttribute::OVERRIDE);
|
||||||
stateSet->setTextureMode(0, GL_TEXTURE_2D,
|
stateSet->setTextureMode(0, GL_TEXTURE_2D,
|
||||||
osg::StateAttribute::ON);
|
osg::StateAttribute::ON);
|
||||||
|
_textureName = textureName;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
SG_LOG(SG_IO, SG_WARN, "texture animation: requested texture : " << textureName << " not found. Searched paths:" );
|
|
||||||
for( osgDB::FilePathList::iterator it = _texturePathList.begin(); it != _texturePathList.end(); ++it ) {
|
|
||||||
SG_LOG(SG_IO, SG_WARN, " - " << *it );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ SGModelLib::panel_func SGModelLib::static_panelFunc = NULL;
|
|||||||
void SGModelLib::init(const string &root_dir, SGPropertyNode* root)
|
void SGModelLib::init(const string &root_dir, SGPropertyNode* root)
|
||||||
{
|
{
|
||||||
osgDB::Registry::instance()->getDataFilePathList().push_front(root_dir);
|
osgDB::Registry::instance()->getDataFilePathList().push_front(root_dir);
|
||||||
osgDB::Registry::instance()->getOptions()->getDatabasePathList().push_front(root_dir);
|
|
||||||
static_propRoot = root;
|
static_propRoot = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +114,6 @@ SGModelLib::loadModel(const string &path,
|
|||||||
{
|
{
|
||||||
osg::ref_ptr<SGReaderWriterOptions> opt;
|
osg::ref_ptr<SGReaderWriterOptions> opt;
|
||||||
opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
|
opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
|
||||||
opt->getDatabasePathList().push_front( osgDB::getFilePath(path) );
|
|
||||||
opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
|
opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
|
||||||
opt->setModelData(data);
|
opt->setModelData(data);
|
||||||
|
|
||||||
@@ -138,10 +136,8 @@ SGModelLib::loadDeferredModel(const string &path, SGPropertyNode *prop_root,
|
|||||||
proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
|
proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
|
||||||
proxyNode->setFileName(0, path);
|
proxyNode->setFileName(0, path);
|
||||||
|
|
||||||
|
|
||||||
osg::ref_ptr<SGReaderWriterOptions> opt;
|
osg::ref_ptr<SGReaderWriterOptions> opt;
|
||||||
opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
|
opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
|
||||||
opt->getDatabasePathList().push_front( osgDB::getFilePath(path) );
|
|
||||||
opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
|
opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
|
||||||
opt->setModelData(data);
|
opt->setModelData(data);
|
||||||
opt->setLoadPanel(static_panelFunc);
|
opt->setLoadPanel(static_panelFunc);
|
||||||
|
|||||||
@@ -127,12 +127,8 @@ void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
|
|||||||
|
|
||||||
sortData.frameSorted = frameNumber;
|
sortData.frameSorted = frameNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
const Extensions* extensions = getExtensions(state.getContextID(),true);
|
const Extensions* extensions = getExtensions(state.getContextID(),true);
|
||||||
#else
|
|
||||||
const GLExtensions* extensions = GLExtensions::Get(state.getContextID(), true);
|
|
||||||
#endif
|
|
||||||
GLfloat ua1[3] = { (GLfloat) alpha_factor,
|
GLfloat ua1[3] = { (GLfloat) alpha_factor,
|
||||||
(GLfloat) shade_factor,
|
(GLfloat) shade_factor,
|
||||||
(GLfloat) cloud_height };
|
(GLfloat) cloud_height };
|
||||||
|
|||||||
@@ -216,46 +216,6 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
|
|||||||
|
|
||||||
sun_transform->addChild( geode );
|
sun_transform->addChild( geode );
|
||||||
|
|
||||||
|
|
||||||
// set up the brilliance state
|
|
||||||
|
|
||||||
geode = new osg::Geode;
|
|
||||||
stateSet = geode->getOrCreateStateSet();
|
|
||||||
stateSet->setRenderBinDetails(-9, "RenderBin");
|
|
||||||
|
|
||||||
|
|
||||||
texture = SGLoadTexture2D("brilliance.png", options.get());
|
|
||||||
stateSet->setTextureAttributeAndModes(0, texture);
|
|
||||||
|
|
||||||
|
|
||||||
// Build ssg structure
|
|
||||||
brilliance_cl = new osg::Vec4Array;
|
|
||||||
brilliance_cl->push_back(osg::Vec4(1, 1, 1, 1));
|
|
||||||
|
|
||||||
double brilliance_size = sun_size * 12.0;
|
|
||||||
osg::Vec3Array* brilliance_vl = new osg::Vec3Array;
|
|
||||||
brilliance_vl->push_back(osg::Vec3(-brilliance_size, 0, -brilliance_size));
|
|
||||||
brilliance_vl->push_back(osg::Vec3(brilliance_size, 0, -brilliance_size));
|
|
||||||
brilliance_vl->push_back(osg::Vec3(-brilliance_size, 0, brilliance_size));
|
|
||||||
brilliance_vl->push_back(osg::Vec3(brilliance_size, 0, brilliance_size));
|
|
||||||
|
|
||||||
osg::Vec2Array* brilliance_tl = new osg::Vec2Array;
|
|
||||||
brilliance_tl->push_back(osg::Vec2(0, 0));
|
|
||||||
brilliance_tl->push_back(osg::Vec2(1, 0));
|
|
||||||
brilliance_tl->push_back(osg::Vec2(0, 1));
|
|
||||||
brilliance_tl->push_back(osg::Vec2(1, 1));
|
|
||||||
|
|
||||||
geometry = new osg::Geometry;
|
|
||||||
geometry->setUseDisplayList(false);
|
|
||||||
geometry->setVertexArray(brilliance_vl);
|
|
||||||
geometry->setColorArray(brilliance_cl.get(), osg::Array::BIND_OVERALL);
|
|
||||||
geometry->setNormalBinding(osg::Geometry::BIND_OFF);
|
|
||||||
geometry->setTexCoordArray(0, brilliance_tl, osg::Array::BIND_PER_VERTEX);
|
|
||||||
geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
|
||||||
geode->addDrawable(geometry);
|
|
||||||
|
|
||||||
sun_transform->addChild( geode );
|
|
||||||
|
|
||||||
// force a repaint of the sun colors with arbitrary defaults
|
// force a repaint of the sun colors with arbitrary defaults
|
||||||
repaint( 0.0, 1.0 );
|
repaint( 0.0, 1.0 );
|
||||||
|
|
||||||
@@ -302,7 +262,7 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ok, now let's go and generate the sun and scene color
|
// ok, now let's go and generate the sun and scene color
|
||||||
osg::Vec4 i_halo_color, o_halo_color, scene_color, sun_color, brilliance_color;
|
osg::Vec4 i_halo_color, o_halo_color, scene_color, sun_color;
|
||||||
|
|
||||||
// Some comments:
|
// Some comments:
|
||||||
// * When the sunangle changes, light has to travel a longer
|
// * When the sunangle changes, light has to travel a longer
|
||||||
@@ -376,29 +336,16 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
|
|||||||
if (o_halo_color[3] > 1) o_halo_color[3] = 1;
|
if (o_halo_color[3] > 1) o_halo_color[3] = 1;
|
||||||
if (o_halo_color[3] < 0) o_halo_color[3] = 0;
|
if (o_halo_color[3] < 0) o_halo_color[3] = 0;
|
||||||
|
|
||||||
brilliance_color[0] = i_halo_color[0];
|
|
||||||
brilliance_color[1] = i_halo_color[1];
|
|
||||||
brilliance_color[2] = i_halo_color[2];
|
|
||||||
|
|
||||||
double norm = (i_halo_color[0] * i_halo_color[0] + i_halo_color[1] * i_halo_color[1] + i_halo_color[2] * i_halo_color[2])/1.732;
|
|
||||||
|
|
||||||
brilliance_color[3] = pow(norm, 6.0);
|
|
||||||
if (brilliance_color[3] < 0.0) {brilliance_color[3] = 0.0;}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gamma_correct_rgb( i_halo_color._v );
|
gamma_correct_rgb( i_halo_color._v );
|
||||||
gamma_correct_rgb( o_halo_color._v );
|
gamma_correct_rgb( o_halo_color._v );
|
||||||
gamma_correct_rgb( scene_color._v );
|
gamma_correct_rgb( scene_color._v );
|
||||||
gamma_correct_rgb( sun_color._v );
|
gamma_correct_rgb( sun_color._v );
|
||||||
gamma_correct_rgb( brilliance_color._v );
|
|
||||||
|
|
||||||
if (sun_angle >91.0 * 3.1415/180.0 + horizon_angle)
|
if (sun_angle >91.0 * 3.1415/180.0 + horizon_angle)
|
||||||
{
|
{
|
||||||
sun_color[3] = 0;
|
sun_color[3] = 0;
|
||||||
o_halo_color[3]=0;
|
o_halo_color[3]=0;
|
||||||
i_halo_color[3]=0;
|
i_halo_color[3]=0;
|
||||||
brilliance_color[3]=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(*sun_cl)[0] = sun_color;
|
(*sun_cl)[0] = sun_color;
|
||||||
@@ -409,8 +356,6 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
|
|||||||
ihalo_cl->dirty();
|
ihalo_cl->dirty();
|
||||||
(*ohalo_cl)[0] = o_halo_color;
|
(*ohalo_cl)[0] = o_halo_color;
|
||||||
ohalo_cl->dirty();
|
ohalo_cl->dirty();
|
||||||
(*brilliance_cl)[0] = brilliance_color;
|
|
||||||
brilliance_cl->dirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -427,14 +372,19 @@ bool SGSun::reposition( double rightAscension, double declination,
|
|||||||
{
|
{
|
||||||
// GST - GMT sidereal time
|
// GST - GMT sidereal time
|
||||||
osg::Matrix T2, RA, DEC;
|
osg::Matrix T2, RA, DEC;
|
||||||
|
|
||||||
// xglRotatef( ((SGD_RADIANS_TO_DEGREES * rightAscension)- 90.0),
|
// xglRotatef( ((SGD_RADIANS_TO_DEGREES * rightAscension)- 90.0),
|
||||||
// 0.0, 0.0, 1.0);
|
// 0.0, 0.0, 1.0);
|
||||||
RA.makeRotate(rightAscension - 90*SGD_DEGREES_TO_RADIANS, osg::Vec3(0, 0, 1));
|
RA.makeRotate(rightAscension - 90*SGD_DEGREES_TO_RADIANS, osg::Vec3(0, 0, 1));
|
||||||
|
|
||||||
// xglRotatef((SGD_RADIANS_TO_DEGREES * declination), 1.0, 0.0, 0.0);
|
// xglRotatef((SGD_RADIANS_TO_DEGREES * declination), 1.0, 0.0, 0.0);
|
||||||
DEC.makeRotate(declination, osg::Vec3(1, 0, 0));
|
DEC.makeRotate(declination, osg::Vec3(1, 0, 0));
|
||||||
|
|
||||||
// xglTranslatef(0,sun_dist);
|
// xglTranslatef(0,sun_dist);
|
||||||
T2.makeTranslate(osg::Vec3(0, sun_dist, 0));
|
T2.makeTranslate(osg::Vec3(0, sun_dist, 0));
|
||||||
|
|
||||||
sun_transform->setMatrix(T2*DEC*RA);
|
sun_transform->setMatrix(T2*DEC*RA);
|
||||||
|
|
||||||
// Suncolor related things:
|
// Suncolor related things:
|
||||||
if ( prev_sun_angle != sun_angle ) {
|
if ( prev_sun_angle != sun_angle ) {
|
||||||
if ( sun_angle == 0 ) sun_angle = 0.1;
|
if ( sun_angle == 0 ) sun_angle = 0.1;
|
||||||
@@ -462,7 +412,7 @@ bool SGSun::reposition( double rightAscension, double declination,
|
|||||||
if ( alt_half < 0.0 ) alt_half = 0.0;
|
if ( alt_half < 0.0 ) alt_half = 0.0;
|
||||||
|
|
||||||
//angle at which the sun is visible below the horizon
|
//angle at which the sun is visible below the horizon
|
||||||
horizon_angle = acos(min(r_earth/position_radius, 1.0));
|
horizon_angle = acos(r_earth/position_radius);
|
||||||
|
|
||||||
// Push the data to the property tree, so it can be used in the enviromental code
|
// Push the data to the property tree, so it can be used in the enviromental code
|
||||||
if ( env_node ){
|
if ( env_node ){
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ class SGSun : public SGReferenced {
|
|||||||
osg::ref_ptr<osg::Vec4Array> scene_cl;
|
osg::ref_ptr<osg::Vec4Array> scene_cl;
|
||||||
osg::ref_ptr<osg::Vec4Array> ihalo_cl;
|
osg::ref_ptr<osg::Vec4Array> ihalo_cl;
|
||||||
osg::ref_ptr<osg::Vec4Array> ohalo_cl;
|
osg::ref_ptr<osg::Vec4Array> ohalo_cl;
|
||||||
osg::ref_ptr<osg::Vec4Array> brilliance_cl;
|
|
||||||
|
|
||||||
double visibility;
|
double visibility;
|
||||||
double prev_sun_angle;
|
double prev_sun_angle;
|
||||||
|
|||||||
@@ -44,7 +44,6 @@
|
|||||||
#include <simgear/misc/sgstream.hxx>
|
#include <simgear/misc/sgstream.hxx>
|
||||||
#include <simgear/scene/util/OptionsReadFileCallback.hxx>
|
#include <simgear/scene/util/OptionsReadFileCallback.hxx>
|
||||||
#include <simgear/scene/util/OsgMath.hxx>
|
#include <simgear/scene/util/OsgMath.hxx>
|
||||||
#include <simgear/scene/util/QuadTreeBuilder.hxx>
|
|
||||||
#include <simgear/scene/util/RenderConstants.hxx>
|
#include <simgear/scene/util/RenderConstants.hxx>
|
||||||
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
||||||
#include <simgear/scene/tgdb/apt_signs.hxx>
|
#include <simgear/scene/tgdb/apt_signs.hxx>
|
||||||
@@ -114,79 +113,48 @@ struct ReaderWriterSTG::_ModelBin {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class DelayLoadReadFileCallback : public OptionsReadFileCallback {
|
class DelayLoadReadFileCallback : public OptionsReadFileCallback {
|
||||||
|
|
||||||
private:
|
|
||||||
// QuadTreeBuilder for structuring static objects
|
|
||||||
struct MakeQuadLeaf {
|
|
||||||
osg::LOD* operator() () const { return new osg::LOD; }
|
|
||||||
};
|
|
||||||
struct AddModelLOD {
|
|
||||||
void operator() (osg::LOD* leaf, _ObjectStatic o) const
|
|
||||||
{
|
|
||||||
osg::ref_ptr<osg::Node> node;
|
|
||||||
if (o._proxy) {
|
|
||||||
osg::ref_ptr<osg::ProxyNode> proxy = new osg::ProxyNode;
|
|
||||||
proxy->setName("proxyNode");
|
|
||||||
proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
|
|
||||||
proxy->setFileName(0, o._name);
|
|
||||||
proxy->setDatabaseOptions(o._options.get());
|
|
||||||
|
|
||||||
// Give the node some values so the Quadtree builder has
|
|
||||||
// a BoundingBox to work with prior to the model being loaded.
|
|
||||||
proxy->setCenter(osg::Vec3f(0.0f,0.0f,0.0f));
|
|
||||||
proxy->setRadius(10);
|
|
||||||
proxy->setCenterMode(osg::ProxyNode::UNION_OF_BOUNDING_SPHERE_AND_USER_DEFINED);
|
|
||||||
node = proxy;
|
|
||||||
} else {
|
|
||||||
node = osgDB::readRefNodeFile(o._name, o._options.get());
|
|
||||||
if (!node.valid()) {
|
|
||||||
SG_LOG(SG_TERRAIN, SG_ALERT, o._errorLocation << ": Failed to load "
|
|
||||||
<< o._token << " '" << o._name << "'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (SGPath(o._name).lower_extension() == "ac")
|
|
||||||
node->setNodeMask(~simgear::MODELLIGHT_BIT);
|
|
||||||
|
|
||||||
osg::Matrix matrix;
|
|
||||||
matrix = makeZUpFrame(SGGeod::fromDegM(o._lon, o._lat, o._elev));
|
|
||||||
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(o._hdg), osg::Vec3(0, 0, 1)));
|
|
||||||
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(o._pitch), osg::Vec3(0, 1, 0)));
|
|
||||||
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(o._roll), osg::Vec3(1, 0, 0)));
|
|
||||||
|
|
||||||
osg::MatrixTransform* matrixTransform;
|
|
||||||
matrixTransform = new osg::MatrixTransform(matrix);
|
|
||||||
matrixTransform->setName("rotateStaticObject");
|
|
||||||
matrixTransform->setDataVariance(osg::Object::STATIC);
|
|
||||||
matrixTransform->addChild(node.get());
|
|
||||||
leaf->addChild(matrixTransform, 0, 20000); //TODO: Make configurable?
|
|
||||||
}
|
|
||||||
};
|
|
||||||
struct GetModelLODCoord {
|
|
||||||
GetModelLODCoord() {}
|
|
||||||
GetModelLODCoord(const GetModelLODCoord& rhs)
|
|
||||||
{}
|
|
||||||
osg::Vec3 operator() (const _ObjectStatic& o) const
|
|
||||||
{
|
|
||||||
SGVec3d coord;
|
|
||||||
SGGeodesy::SGGeodToCart(SGGeod::fromDegM(o._lon, o._lat, o._elev), coord);
|
|
||||||
return toOsg(coord);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
typedef QuadTreeBuilder<osg::LOD*, _ObjectStatic, MakeQuadLeaf, AddModelLOD,
|
|
||||||
GetModelLODCoord> STGObjectsQuadtree;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual osgDB::ReaderWriter::ReadResult
|
virtual osgDB::ReaderWriter::ReadResult
|
||||||
readNode(const std::string&, const osgDB::Options*)
|
readNode(const std::string&, const osgDB::Options*)
|
||||||
{
|
{
|
||||||
STGObjectsQuadtree quadtree((GetModelLODCoord()), (AddModelLOD()));
|
osg::ref_ptr<osg::Group> group = new osg::Group;
|
||||||
quadtree.buildQuadTree(_objectStaticList.begin(), _objectStaticList.end());
|
|
||||||
osg::ref_ptr<osg::Group> group = quadtree.getRoot();
|
|
||||||
group->setName("STG-group-A");
|
group->setName("STG-group-A");
|
||||||
group->setDataVariance(osg::Object::STATIC);
|
group->setDataVariance(osg::Object::STATIC);
|
||||||
|
|
||||||
|
for (std::list<_ObjectStatic>::iterator i = _objectStaticList.begin(); i != _objectStaticList.end(); ++i) {
|
||||||
|
osg::ref_ptr<osg::Node> node;
|
||||||
|
if (i->_proxy) {
|
||||||
|
osg::ref_ptr<osg::ProxyNode> proxy = new osg::ProxyNode;
|
||||||
|
proxy->setName("proxyNode");
|
||||||
|
proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
|
||||||
|
proxy->setFileName(0, i->_name);
|
||||||
|
proxy->setDatabaseOptions(i->_options.get());
|
||||||
|
node = proxy;
|
||||||
|
} else {
|
||||||
|
node = osgDB::readRefNodeFile(i->_name, i->_options.get());
|
||||||
|
if (!node.valid()) {
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, i->_errorLocation << ": Failed to load "
|
||||||
|
<< i->_token << " '" << i->_name << "'");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (SGPath(i->_name).lower_extension() == "ac")
|
||||||
|
node->setNodeMask(~simgear::MODELLIGHT_BIT);
|
||||||
|
|
||||||
|
osg::Matrix matrix;
|
||||||
|
matrix = makeZUpFrame(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev));
|
||||||
|
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_hdg), osg::Vec3(0, 0, 1)));
|
||||||
|
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_pitch), osg::Vec3(0, 1, 0)));
|
||||||
|
matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_roll), osg::Vec3(1, 0, 0)));
|
||||||
|
|
||||||
|
osg::MatrixTransform* matrixTransform;
|
||||||
|
matrixTransform = new osg::MatrixTransform(matrix);
|
||||||
|
matrixTransform->setName("positionStaticObject");
|
||||||
|
matrixTransform->setDataVariance(osg::Object::STATIC);
|
||||||
|
matrixTransform->addChild(node.get());
|
||||||
|
group->addChild(matrixTransform);
|
||||||
|
}
|
||||||
|
|
||||||
simgear::AirportSignBuilder signBuilder(_options->getMaterialLib(), _bucket.get_center());
|
simgear::AirportSignBuilder signBuilder(_options->getMaterialLib(), _bucket.get_center());
|
||||||
for (std::list<_Sign>::iterator i = _signList.begin(); i != _signList.end(); ++i)
|
for (std::list<_Sign>::iterator i = _signList.begin(); i != _signList.end(); ++i)
|
||||||
signBuilder.addSign(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev), i->_hdg, i->_name, i->_size);
|
signBuilder.addSign(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev), i->_hdg, i->_name, i->_size);
|
||||||
@@ -298,7 +266,7 @@ struct ReaderWriterSTG::_ModelBin {
|
|||||||
// read a line
|
// read a line
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline(stream, line);
|
std::getline(stream, line);
|
||||||
|
|
||||||
// strip comments
|
// strip comments
|
||||||
std::string::size_type hash_pos = line.find('#');
|
std::string::size_type hash_pos = line.find('#');
|
||||||
if (hash_pos != std::string::npos)
|
if (hash_pos != std::string::npos)
|
||||||
|
|||||||
@@ -386,10 +386,10 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
|||||||
int row = ((int) (mt_rand(&seed) * 1000)) % 5;
|
int row = ((int) (mt_rand(&seed) * 1000)) % 5;
|
||||||
float base_y = (float) row * 16.0 * 3.0 / 1024.0;
|
float base_y = (float) row * 16.0 * 3.0 / 1024.0;
|
||||||
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
||||||
float left_x = 32.0 / 1024.0 * SGMisc<double>::round((float)building.width / 6.0f);
|
float left_x = 32.0 / 1024.0 * round((float) building.width / 6.0f);
|
||||||
float right_x = 0.0f;
|
float right_x = 0.0f;
|
||||||
float front_x = 384.0/1024.0;
|
float front_x = 384.0/1024.0;
|
||||||
float back_x = 384.0 / 1024.0 + 32.0 / 1024.0 * SGMisc<double>::round((float)building.depth / 6.0f);
|
float back_x = 384.0/1024.0 + 32.0 / 1024.0 * round((float) building.depth/ 6.0f);
|
||||||
|
|
||||||
// BASEMENT - uses the baseline texture
|
// BASEMENT - uses the baseline texture
|
||||||
for (unsigned int i = 0; i < 16; i++) {
|
for (unsigned int i = 0; i < 16; i++) {
|
||||||
@@ -424,7 +424,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
|||||||
if (building.pitched) {
|
if (building.pitched) {
|
||||||
// Use the entire height of the roof texture
|
// Use the entire height of the roof texture
|
||||||
top_y = base_y + 16.0 * 3.0 / 1024.0;
|
top_y = base_y + 16.0 * 3.0 / 1024.0;
|
||||||
left_x = 512 / 1024.0 + 32.0 / 1024.0 * SGMisc<double>::round(building.width / 6.0f);
|
left_x = 512/1024.0 + 32.0 / 1024.0 * round(building.width / 6.0f);
|
||||||
right_x = 512/1024.0;
|
right_x = 512/1024.0;
|
||||||
front_x = 480.0/1024.0;
|
front_x = 480.0/1024.0;
|
||||||
back_x = 512.0/1024.0;
|
back_x = 512.0/1024.0;
|
||||||
@@ -475,7 +475,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
|||||||
int column = ((int) (mt_rand(&seed) * 1000)) % 5;
|
int column = ((int) (mt_rand(&seed) * 1000)) % 5;
|
||||||
float base_y = 288 / 1024.0;
|
float base_y = 288 / 1024.0;
|
||||||
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
||||||
float left_x = column * 192.0 / 1024.0 + 32.0 / 1024.0 * SGMisc<double>::round((float)building.width / 10.0f);
|
float left_x = column * 192.0 /1024.0 + 32.0 / 1024.0 * round((float) building.width / 10.0f);
|
||||||
float right_x = column * 192.0 /1024.0;
|
float right_x = column * 192.0 /1024.0;
|
||||||
|
|
||||||
// BASEMENT - uses the baseline texture
|
// BASEMENT - uses the baseline texture
|
||||||
@@ -560,7 +560,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
|||||||
int column = ((int) (mt_rand(&seed) * 1000)) % 8;
|
int column = ((int) (mt_rand(&seed) * 1000)) % 8;
|
||||||
float base_y = 576 / 1024.0;
|
float base_y = 576 / 1024.0;
|
||||||
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
||||||
float left_x = column * 128.0 / 1024.0 + 32.0 / 1024.0 * SGMisc<double>::round((float)building.width / 20.0f);
|
float left_x = column * 128.0 /1024.0 + 32.0 / 1024.0 * round((float) building.width / 20.0f);
|
||||||
float right_x = column * 128.0 /1024.0;
|
float right_x = column * 128.0 /1024.0;
|
||||||
|
|
||||||
// BASEMENT - uses the baseline texture
|
// BASEMENT - uses the baseline texture
|
||||||
|
|||||||
@@ -291,8 +291,7 @@ public:
|
|||||||
float vegetation_density,
|
float vegetation_density,
|
||||||
float cos_max_density_angle,
|
float cos_max_density_angle,
|
||||||
float cos_zero_density_angle,
|
float cos_zero_density_angle,
|
||||||
std::vector<SGVec3f>& points,
|
std::vector<SGVec3f>& points)
|
||||||
std::vector<SGVec3f>& normals)
|
|
||||||
{
|
{
|
||||||
if ( !geometries.empty() ) {
|
if ( !geometries.empty() ) {
|
||||||
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
||||||
@@ -367,11 +366,9 @@ public:
|
|||||||
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
||||||
// The red channel contains the rotation for this object
|
// The red channel contains the rotation for this object
|
||||||
points.push_back(randomPoint);
|
points.push_back(randomPoint);
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
points.push_back(randomPoint);
|
points.push_back(randomPoint);
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
#include <osg/Geometry>
|
#include <osg/Geometry>
|
||||||
#include <osg/PrimitiveSet>
|
#include <osg/PrimitiveSet>
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
#include <osg/ref_ptr>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <simgear/math/sg_random.h>
|
#include <simgear/math/sg_random.h>
|
||||||
@@ -123,16 +122,16 @@ public:
|
|||||||
osg::DrawElements* getDrawElements()
|
osg::DrawElements* getDrawElements()
|
||||||
{
|
{
|
||||||
if (count > 65535) {
|
if (count > 65535) {
|
||||||
_ushortElements = 0;
|
free (_ushortElements);
|
||||||
return _uintElements;
|
return _uintElements;
|
||||||
} else {
|
} else {
|
||||||
_uintElements = 0;
|
free (_uintElements);
|
||||||
return _ushortElements;
|
return _ushortElements;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
osg::ref_ptr<osg::DrawElementsUShort> _ushortElements;
|
osg::DrawElementsUShort* _ushortElements;
|
||||||
osg::ref_ptr<osg::DrawElementsUInt> _uintElements;
|
osg::DrawElementsUInt* _uintElements;
|
||||||
unsigned count;
|
unsigned count;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -216,8 +215,7 @@ public:
|
|||||||
float vegetation_density,
|
float vegetation_density,
|
||||||
float cos_max_density_angle,
|
float cos_max_density_angle,
|
||||||
float cos_zero_density_angle,
|
float cos_zero_density_angle,
|
||||||
std::vector<SGVec3f>& points,
|
std::vector<SGVec3f>& points)
|
||||||
std::vector<SGVec3f>& normals)
|
|
||||||
{
|
{
|
||||||
unsigned num = getNumTriangles();
|
unsigned num = getNumTriangles();
|
||||||
for (unsigned i = 0; i < num; ++i) {
|
for (unsigned i = 0; i < num; ++i) {
|
||||||
@@ -283,11 +281,9 @@ public:
|
|||||||
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
||||||
// The red channel contains the rotation for this object
|
// The red channel contains the rotation for this object
|
||||||
points.push_back(randomPoint);
|
points.push_back(randomPoint);
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
points.push_back(randomPoint);
|
points.push_back(randomPoint);
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ public:
|
|||||||
virtual ~SGTileDetailsCallback()
|
virtual ~SGTileDetailsCallback()
|
||||||
{
|
{
|
||||||
num_tdcb--;
|
num_tdcb--;
|
||||||
SG_LOG( SG_TERRAIN, SG_DEBUG, "SGTileDetailsCallback::~SGTileDetailsCallback() num cbs left " << num_tdcb );
|
SG_LOG( SG_GENERAL, SG_INFO, "SGTileDetailsCallback::~SGTileDetailsCallback() num cbs left " << num_tdcb );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual osgDB::ReaderWriter::ReadResult readNode(
|
virtual osgDB::ReaderWriter::ReadResult readNode(
|
||||||
@@ -723,7 +723,6 @@ public:
|
|||||||
BOOST_FOREACH(bin, randomForest)
|
BOOST_FOREACH(bin, randomForest)
|
||||||
{
|
{
|
||||||
if ((bin->texture == mat->get_tree_texture() ) &&
|
if ((bin->texture == mat->get_tree_texture() ) &&
|
||||||
(bin->teffect == mat->get_tree_effect() ) &&
|
|
||||||
(bin->texture_varieties == mat->get_tree_varieties()) &&
|
(bin->texture_varieties == mat->get_tree_varieties()) &&
|
||||||
(bin->range == mat->get_tree_range() ) &&
|
(bin->range == mat->get_tree_range() ) &&
|
||||||
(bin->width == mat->get_tree_width() ) &&
|
(bin->width == mat->get_tree_width() ) &&
|
||||||
@@ -736,9 +735,7 @@ public:
|
|||||||
if (!found) {
|
if (!found) {
|
||||||
bin = new TreeBin();
|
bin = new TreeBin();
|
||||||
bin->texture = mat->get_tree_texture();
|
bin->texture = mat->get_tree_texture();
|
||||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Tree texture " << bin->texture);
|
SG_LOG(SG_INPUT, SG_DEBUG, "Tree texture " << bin->texture);
|
||||||
bin->teffect = mat->get_tree_effect();
|
|
||||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Tree effect " << bin->teffect);
|
|
||||||
bin->range = mat->get_tree_range();
|
bin->range = mat->get_tree_range();
|
||||||
bin->width = mat->get_tree_width();
|
bin->width = mat->get_tree_width();
|
||||||
bin->height = mat->get_tree_height();
|
bin->height = mat->get_tree_height();
|
||||||
@@ -747,19 +744,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SGVec3f> randomPoints;
|
std::vector<SGVec3f> randomPoints;
|
||||||
std::vector<SGVec3f> randomPointNormals;
|
|
||||||
matTris[i].addRandomTreePoints(wood_coverage,
|
matTris[i].addRandomTreePoints(wood_coverage,
|
||||||
mat->get_one_object_mask(matTris[i].getTextureIndex()),
|
mat->get_one_object_mask(matTris[i].getTextureIndex()),
|
||||||
vegetation_density,
|
vegetation_density,
|
||||||
mat->get_cos_tree_max_density_slope_angle(),
|
mat->get_cos_tree_max_density_slope_angle(),
|
||||||
mat->get_cos_tree_zero_density_slope_angle(),
|
mat->get_cos_tree_zero_density_slope_angle(),
|
||||||
randomPoints,
|
randomPoints);
|
||||||
randomPointNormals);
|
|
||||||
|
|
||||||
std::vector<SGVec3f>::iterator k;
|
std::vector<SGVec3f>::iterator k;
|
||||||
std::vector<SGVec3f>::iterator j;
|
for (k = randomPoints.begin(); k != randomPoints.end(); ++k) {
|
||||||
for (k = randomPoints.begin(), j = randomPointNormals.begin(); k != randomPoints.end(); ++k, ++j) {
|
bin->insert(*k);
|
||||||
bin->insert(*k, *j);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -789,6 +783,11 @@ public:
|
|||||||
float coverage = mat->get_light_coverage();
|
float coverage = mat->get_light_coverage();
|
||||||
if (coverage <= 0)
|
if (coverage <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
if (coverage < 10000.0) {
|
||||||
|
SG_LOG(SG_INPUT, SG_ALERT, "Light coverage is "
|
||||||
|
<< coverage << ", pushing up to 10000");
|
||||||
|
coverage = 10000;
|
||||||
|
}
|
||||||
|
|
||||||
int texIndex = matTris[i].getTextureIndex();
|
int texIndex = matTris[i].getTextureIndex();
|
||||||
|
|
||||||
@@ -872,7 +871,7 @@ public:
|
|||||||
lightGroup->addChild(groundLights2);
|
lightGroup->addChild(groundLights2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! vasiLights.empty()) {
|
if (vasiLights.empty()) {
|
||||||
EffectGeode* vasiGeode = new EffectGeode;
|
EffectGeode* vasiGeode = new EffectGeode;
|
||||||
Effect* vasiEffect = getLightEffect(24, osg::Vec3(1, 0.0001, 0.000001), 1, 24, true, _options);
|
Effect* vasiEffect = getLightEffect(24, osg::Vec3(1, 0.0001, 0.000001), 1, 24, true, _options);
|
||||||
vasiGeode->setEffect(vasiEffect);
|
vasiGeode->setEffect(vasiEffect);
|
||||||
@@ -1138,4 +1137,4 @@ public:
|
|||||||
SGDirectionalLightListBin holdshortLights;
|
SGDirectionalLightListBin holdshortLights;
|
||||||
SGDirectionalLightListBin guardLights;
|
SGDirectionalLightListBin guardLights;
|
||||||
SGDirectionalLightListBin reilLights;
|
SGDirectionalLightListBin reilLights;
|
||||||
};
|
};
|
||||||
@@ -47,11 +47,7 @@ void ShaderGeometry::addObject(const Vec3& position, float scale,
|
|||||||
void ShaderGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
|
void ShaderGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
|
||||||
{
|
{
|
||||||
State& state = *renderInfo.getState();
|
State& state = *renderInfo.getState();
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
const Extensions* extensions = getExtensions(state.getContextID(), true);
|
const Extensions* extensions = getExtensions(state.getContextID(), true);
|
||||||
#else
|
|
||||||
const GLExtensions* extensions = GLExtensions::Get(state.getContextID(), true);
|
|
||||||
#endif
|
|
||||||
Vec4Array::const_iterator citer = _posScaleArray->begin();
|
Vec4Array::const_iterator citer = _posScaleArray->begin();
|
||||||
Vec4Array::const_iterator cend = _posScaleArray->end();
|
Vec4Array::const_iterator cend = _posScaleArray->end();
|
||||||
FloatArray::const_iterator viter = _vertexAttribArray->begin();
|
FloatArray::const_iterator viter = _vertexAttribArray->begin();
|
||||||
|
|||||||
@@ -49,7 +49,6 @@
|
|||||||
#include <simgear/scene/util/QuadTreeBuilder.hxx>
|
#include <simgear/scene/util/QuadTreeBuilder.hxx>
|
||||||
#include <simgear/scene/util/RenderConstants.hxx>
|
#include <simgear/scene/util/RenderConstants.hxx>
|
||||||
#include <simgear/scene/util/StateAttributeFactory.hxx>
|
#include <simgear/scene/util/StateAttributeFactory.hxx>
|
||||||
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
|
||||||
#include <simgear/structure/OSGUtils.hxx>
|
#include <simgear/structure/OSGUtils.hxx>
|
||||||
|
|
||||||
#include "ShaderGeometry.hxx"
|
#include "ShaderGeometry.hxx"
|
||||||
@@ -63,9 +62,6 @@ using namespace osg;
|
|||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
|
|
||||||
bool use_tree_shadows;
|
|
||||||
bool use_tree_normals;
|
|
||||||
|
|
||||||
// Tree instance scheme:
|
// Tree instance scheme:
|
||||||
// vertex - local position of quad vertex.
|
// vertex - local position of quad vertex.
|
||||||
// normal - x y scaling, z number of varieties
|
// normal - x y scaling, z number of varieties
|
||||||
@@ -168,24 +164,15 @@ Geometry* createTreeGeometry(float width, float height, int varieties)
|
|||||||
// Positions
|
// Positions
|
||||||
quadGeom->setColorArray(new Vec3Array);
|
quadGeom->setColorArray(new Vec3Array);
|
||||||
quadGeom->setColorBinding(Geometry::BIND_PER_VERTEX);
|
quadGeom->setColorBinding(Geometry::BIND_PER_VERTEX);
|
||||||
// Normals
|
FloatArray* rotation = new FloatArray(2);
|
||||||
if (use_tree_shadows || use_tree_normals)
|
|
||||||
{
|
|
||||||
quadGeom->setSecondaryColorArray(new Vec3Array);
|
|
||||||
quadGeom->setSecondaryColorBinding(Geometry::BIND_PER_VERTEX);
|
|
||||||
}
|
|
||||||
FloatArray* rotation = new FloatArray(3);
|
|
||||||
(*rotation)[0] = 0.0;
|
(*rotation)[0] = 0.0;
|
||||||
(*rotation)[1] = PI_2;
|
(*rotation)[1] = PI_2;
|
||||||
if (use_tree_shadows) {(*rotation)[2] = -1.0;}
|
|
||||||
quadGeom->setFogCoordArray(rotation);
|
quadGeom->setFogCoordArray(rotation);
|
||||||
quadGeom->setFogCoordBinding(Geometry::BIND_PER_PRIMITIVE_SET);
|
quadGeom->setFogCoordBinding(Geometry::BIND_PER_PRIMITIVE_SET);
|
||||||
// The primitive sets render the same geometry, but the second
|
// The primitive sets render the same geometry, but the second
|
||||||
// will rotated 90 degrees by the vertex shader, which uses the
|
// will rotated 90 degrees by the vertex shader, which uses the
|
||||||
// fog coordinate as a rotation.
|
// fog coordinate as a rotation.
|
||||||
int imax = 2;
|
for (int i = 0; i < 2; ++i)
|
||||||
if (use_tree_shadows) {imax = 3;}
|
|
||||||
for (int i = 0; i < imax; ++i)
|
|
||||||
quadGeom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS));
|
quadGeom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS));
|
||||||
return quadGeom;
|
return quadGeom;
|
||||||
}
|
}
|
||||||
@@ -197,17 +184,13 @@ EffectGeode* createTreeGeode(float width, float height, int varieties)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTreeToLeafGeode(Geode* geode, const SGVec3f& p, const SGVec3f& t)
|
void addTreeToLeafGeode(Geode* geode, const SGVec3f& p)
|
||||||
{
|
{
|
||||||
Vec3 pos = toOsg(p);
|
Vec3 pos = toOsg(p);
|
||||||
Vec3 ter = toOsg(t);
|
|
||||||
unsigned int numDrawables = geode->getNumDrawables();
|
unsigned int numDrawables = geode->getNumDrawables();
|
||||||
Geometry* geom
|
Geometry* geom
|
||||||
= static_cast<Geometry*>(geode->getDrawable(numDrawables - 1));
|
= static_cast<Geometry*>(geode->getDrawable(numDrawables - 1));
|
||||||
Vec3Array* posArray = static_cast<Vec3Array*>(geom->getColorArray());
|
Vec3Array* posArray = static_cast<Vec3Array*>(geom->getColorArray());
|
||||||
Vec3Array* tnormalArray;
|
|
||||||
if (use_tree_shadows || use_tree_normals)
|
|
||||||
{tnormalArray = static_cast<Vec3Array*>(geom->getSecondaryColorArray());}
|
|
||||||
if (posArray->size()
|
if (posArray->size()
|
||||||
>= static_cast<Vec3Array*>(geom->getVertexArray())->size()) {
|
>= static_cast<Vec3Array*>(geom->getVertexArray())->size()) {
|
||||||
Vec3Array* paramsArray
|
Vec3Array* paramsArray
|
||||||
@@ -215,17 +198,11 @@ void addTreeToLeafGeode(Geode* geode, const SGVec3f& p, const SGVec3f& t)
|
|||||||
Vec3 params = (*paramsArray)[0];
|
Vec3 params = (*paramsArray)[0];
|
||||||
geom = createTreeGeometry(params.x(), params.y(), params.z());
|
geom = createTreeGeometry(params.x(), params.y(), params.z());
|
||||||
posArray = static_cast<Vec3Array*>(geom->getColorArray());
|
posArray = static_cast<Vec3Array*>(geom->getColorArray());
|
||||||
if (use_tree_shadows || use_tree_normals)
|
|
||||||
{tnormalArray = static_cast<Vec3Array*>(geom->getSecondaryColorArray());}
|
|
||||||
geode->addDrawable(geom);
|
geode->addDrawable(geom);
|
||||||
}
|
}
|
||||||
posArray->insert(posArray->end(), 4, pos);
|
posArray->insert(posArray->end(), 4, pos);
|
||||||
if (use_tree_shadows || use_tree_normals)
|
|
||||||
{tnormalArray->insert(tnormalArray->end(),4,ter);}
|
|
||||||
size_t numVerts = posArray->size();
|
size_t numVerts = posArray->size();
|
||||||
int imax = 2;
|
for (int i = 0; i < 2; ++i) {
|
||||||
if (use_tree_shadows) {imax = 3;}
|
|
||||||
for (int i = 0; i < imax; ++i) {
|
|
||||||
DrawArrays* primSet
|
DrawArrays* primSet
|
||||||
= static_cast<DrawArrays*>(geom->getPrimitiveSet(i));
|
= static_cast<DrawArrays*>(geom->getPrimitiveSet(i));
|
||||||
primSet->setCount(numVerts);
|
primSet->setCount(numVerts);
|
||||||
@@ -241,14 +218,14 @@ namespace
|
|||||||
{
|
{
|
||||||
struct MakeTreesLeaf
|
struct MakeTreesLeaf
|
||||||
{
|
{
|
||||||
MakeTreesLeaf(float range, int varieties, float width, float height,
|
MakeTreesLeaf(float range, int varieties, float width, float height,
|
||||||
Effect* effect) :
|
Effect* effect) :
|
||||||
_range(range), _varieties(varieties),
|
_range(range), _varieties(varieties),
|
||||||
_width(width), _height(height), _effect(effect) {}
|
_width(width), _height(height), _effect(effect) {}
|
||||||
|
|
||||||
MakeTreesLeaf(const MakeTreesLeaf& rhs) :
|
MakeTreesLeaf(const MakeTreesLeaf& rhs) :
|
||||||
_range(rhs._range),
|
_range(rhs._range),
|
||||||
_varieties(rhs._varieties), _width(rhs._width), _height(rhs._height),
|
_varieties(rhs._varieties), _width(rhs._width), _height(rhs._height),
|
||||||
_effect(rhs._effect)
|
_effect(rhs._effect)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -278,7 +255,7 @@ struct AddTreesLeafObject
|
|||||||
void operator() (LOD* lod, const TreeBin::Tree& tree) const
|
void operator() (LOD* lod, const TreeBin::Tree& tree) const
|
||||||
{
|
{
|
||||||
Geode* geode = static_cast<Geode*>(lod->getChild(int(tree.position.x() * 10.0f) % lod->getNumChildren()));
|
Geode* geode = static_cast<Geode*>(lod->getChild(int(tree.position.x() * 10.0f) % lod->getNumChildren()));
|
||||||
addTreeToLeafGeode(geode, tree.position, tree.tnormal);
|
addTreeToLeafGeode(geode, tree.position);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -300,8 +277,7 @@ struct TreeTransformer
|
|||||||
TreeBin::Tree operator()(const TreeBin::Tree& tree) const
|
TreeBin::Tree operator()(const TreeBin::Tree& tree) const
|
||||||
{
|
{
|
||||||
Vec3 pos = toOsg(tree.position);
|
Vec3 pos = toOsg(tree.position);
|
||||||
Vec3 norm = toOsg(tree.tnormal);
|
return TreeBin::Tree(toSG(pos * mat));
|
||||||
return TreeBin::Tree(toSG(pos * mat),toSG(norm * mat));
|
|
||||||
}
|
}
|
||||||
Matrix mat;
|
Matrix mat;
|
||||||
};
|
};
|
||||||
@@ -356,20 +332,6 @@ osg::Group* createForest(SGTreeBinList& forestList, const osg::Matrix& transform
|
|||||||
MatrixTransform* mt = new MatrixTransform(transform);
|
MatrixTransform* mt = new MatrixTransform(transform);
|
||||||
|
|
||||||
SGTreeBinList::iterator i;
|
SGTreeBinList::iterator i;
|
||||||
|
|
||||||
use_tree_shadows = false;
|
|
||||||
use_tree_normals = false;
|
|
||||||
if (options) {
|
|
||||||
SGPropertyNode* propertyNode = options->getPropertyNode().get();
|
|
||||||
if (propertyNode) {
|
|
||||||
use_tree_shadows
|
|
||||||
= propertyNode->getBoolValue("/sim/rendering/random-vegetation-shadows",
|
|
||||||
use_tree_shadows);
|
|
||||||
use_tree_normals
|
|
||||||
= propertyNode->getBoolValue("/sim/rendering/random-vegetation-normals",
|
|
||||||
use_tree_normals);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = forestList.begin(); i != forestList.end(); ++i) {
|
for (i = forestList.begin(); i != forestList.end(); ++i) {
|
||||||
TreeBin* forest = *i;
|
TreeBin* forest = *i;
|
||||||
@@ -381,7 +343,7 @@ osg::Group* createForest(SGTreeBinList& forestList, const osg::Matrix& transform
|
|||||||
(!iter->second.lock(effect)))
|
(!iter->second.lock(effect)))
|
||||||
{
|
{
|
||||||
SGPropertyNode_ptr effectProp = new SGPropertyNode;
|
SGPropertyNode_ptr effectProp = new SGPropertyNode;
|
||||||
makeChild(effectProp, "inherits-from")->setStringValue(forest->teffect);
|
makeChild(effectProp, "inherits-from")->setStringValue("Effects/tree");
|
||||||
SGPropertyNode* params = makeChild(effectProp, "parameters");
|
SGPropertyNode* params = makeChild(effectProp, "parameters");
|
||||||
// emphasize n = 0
|
// emphasize n = 0
|
||||||
params->getChild("texture", 0, true)->getChild("image", 0, true)
|
params->getChild("texture", 0, true)->getChild("image", 0, true)
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ namespace simgear
|
|||||||
class TreeBin {
|
class TreeBin {
|
||||||
public:
|
public:
|
||||||
struct Tree {
|
struct Tree {
|
||||||
SGVec3f position;
|
Tree(const SGVec3f& p) :
|
||||||
SGVec3f tnormal;
|
position(p)
|
||||||
Tree(const SGVec3f& p, const SGVec3f& t) : position(p),tnormal(t)
|
|
||||||
{ }
|
{ }
|
||||||
|
SGVec3f position;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<Tree> TreeList;
|
typedef std::vector<Tree> TreeList;
|
||||||
@@ -49,13 +49,11 @@ public:
|
|||||||
float height;
|
float height;
|
||||||
float width;
|
float width;
|
||||||
std::string texture;
|
std::string texture;
|
||||||
std::string teffect;
|
|
||||||
|
|
||||||
void insert(const Tree& t)
|
void insert(const Tree& t)
|
||||||
{ _trees.push_back(t); }
|
{ _trees.push_back(t); }
|
||||||
|
void insert(const SGVec3f& p, int t, float s)
|
||||||
void insert(const SGVec3f& p, const SGVec3f& tnorm)
|
{ insert(Tree(p)); }
|
||||||
{insert(Tree(p,tnorm));}
|
|
||||||
|
|
||||||
unsigned getNumTrees() const
|
unsigned getNumTrees() const
|
||||||
{ return _trees.size(); }
|
{ return _trees.size(); }
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <simgear/version.h>
|
|
||||||
|
|
||||||
#include "terrasync.hxx"
|
#include "terrasync.hxx"
|
||||||
|
|
||||||
@@ -71,7 +70,7 @@ static const bool svn_built_in_available = true;
|
|||||||
using namespace simgear;
|
using namespace simgear;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const char* rsync_cmd =
|
const char* rsync_cmd =
|
||||||
"rsync --verbose --archive --delete --perms --owner --group";
|
"rsync --verbose --archive --delete --perms --owner --group";
|
||||||
|
|
||||||
const char* svn_options =
|
const char* svn_options =
|
||||||
@@ -122,30 +121,30 @@ public:
|
|||||||
SharedModels,
|
SharedModels,
|
||||||
AIData
|
AIData
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Status
|
enum Status
|
||||||
{
|
{
|
||||||
Invalid = 0,
|
Invalid = 0,
|
||||||
Waiting,
|
Waiting,
|
||||||
Cached, ///< using already cached result
|
Cached, ///< using already cached result
|
||||||
Updated,
|
Updated,
|
||||||
NotFound,
|
NotFound,
|
||||||
Failed
|
Failed
|
||||||
};
|
};
|
||||||
|
|
||||||
SyncItem() :
|
SyncItem() :
|
||||||
_dir(),
|
_dir(),
|
||||||
_type(Stop),
|
_type(Stop),
|
||||||
_status(Invalid)
|
_status(Invalid)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncItem(string dir, Type ty) :
|
SyncItem(string dir, Type ty) :
|
||||||
_dir(dir),
|
_dir(dir),
|
||||||
_type(ty),
|
_type(ty),
|
||||||
_status(Waiting)
|
_status(Waiting)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
string _dir;
|
string _dir;
|
||||||
Type _type;
|
Type _type;
|
||||||
Status _status;
|
Status _status;
|
||||||
@@ -165,14 +164,14 @@ public:
|
|||||||
isNewDirectory(false),
|
isNewDirectory(false),
|
||||||
busy(false)
|
busy(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SyncItem currentItem;
|
SyncItem currentItem;
|
||||||
bool isNewDirectory;
|
bool isNewDirectory;
|
||||||
std::queue<SyncItem> queue;
|
std::queue<SyncItem> queue;
|
||||||
std::auto_ptr<SVNRepository> repository;
|
std::auto_ptr<SVNRepository> repository;
|
||||||
SGTimeStamp stamp;
|
SGTimeStamp stamp;
|
||||||
bool busy; ///< is the slot working or idle
|
bool busy; ///< is the slot working or idle
|
||||||
|
|
||||||
unsigned int nextWarnTimeout;
|
unsigned int nextWarnTimeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -194,49 +193,12 @@ static unsigned int syncSlotForType(SyncItem::Type ty)
|
|||||||
return SYNC_SLOT_SHARED_DATA;
|
return SYNC_SLOT_SHARED_DATA;
|
||||||
case SyncItem::AIData:
|
case SyncItem::AIData:
|
||||||
return SYNC_SLOT_AI_DATA;
|
return SYNC_SLOT_AI_DATA;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return SYNC_SLOT_SHARED_DATA;
|
return SYNC_SLOT_SHARED_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Base server query
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class ServerSelectQuery : public HTTP::Request
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ServerSelectQuery() :
|
|
||||||
HTTP::Request("http://scenery.flightgear.org/svn-server", "GET")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string svnUrl() const
|
|
||||||
{
|
|
||||||
std::string s = simgear::strutils::strip(m_url);
|
|
||||||
if (s.at(s.length() - 1) == '/') {
|
|
||||||
s = s.substr(0, s.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
virtual void gotBodyData(const char* s, int n)
|
|
||||||
{
|
|
||||||
m_url.append(std::string(s, n));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onFail()
|
|
||||||
{
|
|
||||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "Failed to query TerraSync SVN server");
|
|
||||||
HTTP::Request::onFail();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_url;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// SGTerraSync::SvnThread /////////////////////////////////////////////////////
|
// SGTerraSync::SvnThread /////////////////////////////////////////////////////
|
||||||
@@ -258,7 +220,7 @@ public:
|
|||||||
|
|
||||||
void setSvnServer(string server) { _svn_server = stripPath(server);}
|
void setSvnServer(string server) { _svn_server = stripPath(server);}
|
||||||
void setSvnDataServer(string server) { _svn_data_server = stripPath(server);}
|
void setSvnDataServer(string server) { _svn_data_server = stripPath(server);}
|
||||||
|
|
||||||
void setExtSvnUtility(string svn_util) { _svn_command = simgear::strutils::strip(svn_util);}
|
void setExtSvnUtility(string svn_util) { _svn_command = simgear::strutils::strip(svn_util);}
|
||||||
void setRsyncServer(string server) { _rsync_server = simgear::strutils::strip(server);}
|
void setRsyncServer(string server) { _rsync_server = simgear::strutils::strip(server);}
|
||||||
void setLocalDir(string dir) { _local_dir = stripPath(dir);}
|
void setLocalDir(string dir) { _local_dir = stripPath(dir);}
|
||||||
@@ -283,10 +245,10 @@ public:
|
|||||||
volatile int _transfer_rate;
|
volatile int _transfer_rate;
|
||||||
// kbytes, not bytes, because bytes might overflow 2^31
|
// kbytes, not bytes, because bytes might overflow 2^31
|
||||||
volatile int _total_kb_downloaded;
|
volatile int _total_kb_downloaded;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void run();
|
virtual void run();
|
||||||
|
|
||||||
// external model run and helpers
|
// external model run and helpers
|
||||||
void runExternal();
|
void runExternal();
|
||||||
void syncPathExternal(const SyncItem& next);
|
void syncPathExternal(const SyncItem& next);
|
||||||
@@ -297,14 +259,14 @@ private:
|
|||||||
void updateSyncSlot(SyncSlot& slot);
|
void updateSyncSlot(SyncSlot& slot);
|
||||||
|
|
||||||
// commond helpers between both internal and external models
|
// commond helpers between both internal and external models
|
||||||
|
|
||||||
SyncItem::Status isPathCached(const SyncItem& next) const;
|
SyncItem::Status isPathCached(const SyncItem& next) const;
|
||||||
void initCompletedTilesPersistentCache();
|
void initCompletedTilesPersistentCache();
|
||||||
void writeCompletedTilesPersistentCache() const;
|
void writeCompletedTilesPersistentCache() const;
|
||||||
void updated(SyncItem item, bool isNewDirectory);
|
void updated(SyncItem item, bool isNewDirectory);
|
||||||
void fail(SyncItem failedItem);
|
void fail(SyncItem failedItem);
|
||||||
void notFound(SyncItem notFoundItem);
|
void notFound(SyncItem notFoundItem);
|
||||||
|
|
||||||
bool _use_built_in;
|
bool _use_built_in;
|
||||||
HTTP::Client _http;
|
HTTP::Client _http;
|
||||||
SyncSlot _syncSlots[NUM_SYNC_SLOTS];
|
SyncSlot _syncSlots[NUM_SYNC_SLOTS];
|
||||||
@@ -312,10 +274,10 @@ private:
|
|||||||
volatile bool _is_dirty;
|
volatile bool _is_dirty;
|
||||||
volatile bool _stop;
|
volatile bool _stop;
|
||||||
SGBlockingDeque <SyncItem> waitingTiles;
|
SGBlockingDeque <SyncItem> waitingTiles;
|
||||||
|
|
||||||
TileAgeCache _completedTiles;
|
TileAgeCache _completedTiles;
|
||||||
TileAgeCache _notFoundItems;
|
TileAgeCache _notFoundItems;
|
||||||
|
|
||||||
SGBlockingDeque <SyncItem> _freshTiles;
|
SGBlockingDeque <SyncItem> _freshTiles;
|
||||||
bool _use_svn;
|
bool _use_svn;
|
||||||
string _svn_server;
|
string _svn_server;
|
||||||
@@ -344,7 +306,7 @@ SGTerraSync::SvnThread::SvnThread() :
|
|||||||
_stop(false),
|
_stop(false),
|
||||||
_use_svn(true)
|
_use_svn(true)
|
||||||
{
|
{
|
||||||
_http.setUserAgent("terrascenery-" SG_STRINGIZE(SIMGEAR_VERSION));
|
_http.setUserAgent("terrascenery-" SG_STRINGIZE(SG_VERSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SGTerraSync::SvnThread::stop()
|
void SGTerraSync::SvnThread::stop()
|
||||||
@@ -370,7 +332,7 @@ bool SGTerraSync::SvnThread::start()
|
|||||||
|
|
||||||
if (_local_dir=="")
|
if (_local_dir=="")
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot start scenery download. Local cache directory is undefined.");
|
"Cannot start scenery download. Local cache directory is undefined.");
|
||||||
_fail_count++;
|
_fail_count++;
|
||||||
_stalled = true;
|
_stalled = true;
|
||||||
@@ -380,7 +342,7 @@ bool SGTerraSync::SvnThread::start()
|
|||||||
SGPath path(_local_dir);
|
SGPath path(_local_dir);
|
||||||
if (!path.exists())
|
if (!path.exists())
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot start scenery download. Directory '" << _local_dir <<
|
"Cannot start scenery download. Directory '" << _local_dir <<
|
||||||
"' does not exist. Set correct directory path or create directory folder.");
|
"' does not exist. Set correct directory path or create directory folder.");
|
||||||
_fail_count++;
|
_fail_count++;
|
||||||
@@ -391,7 +353,7 @@ bool SGTerraSync::SvnThread::start()
|
|||||||
path.append("version");
|
path.append("version");
|
||||||
if (path.exists())
|
if (path.exists())
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot start scenery download. Directory '" << _local_dir <<
|
"Cannot start scenery download. Directory '" << _local_dir <<
|
||||||
"' contains the base package. Use a separate directory.");
|
"' contains the base package. Use a separate directory.");
|
||||||
_fail_count++;
|
_fail_count++;
|
||||||
@@ -401,10 +363,17 @@ bool SGTerraSync::SvnThread::start()
|
|||||||
|
|
||||||
_use_svn |= _use_built_in;
|
_use_svn |= _use_built_in;
|
||||||
|
|
||||||
|
if ((_use_svn)&&(_svn_server==""))
|
||||||
|
{
|
||||||
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
|
"Cannot start scenery download. Subversion scenery server is undefined.");
|
||||||
|
_fail_count++;
|
||||||
|
_stalled = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ((!_use_svn)&&(_rsync_server==""))
|
if ((!_use_svn)&&(_rsync_server==""))
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot start scenery download. Rsync scenery server is undefined.");
|
"Cannot start scenery download. Rsync scenery server is undefined.");
|
||||||
_fail_count++;
|
_fail_count++;
|
||||||
_stalled = true;
|
_stalled = true;
|
||||||
@@ -436,7 +405,7 @@ bool SGTerraSync::SvnThread::start()
|
|||||||
|
|
||||||
// not really an alert - but we want to (always) see this message, so user is
|
// not really an alert - but we want to (always) see this message, so user is
|
||||||
// aware we're downloading scenery (and using bandwidth).
|
// aware we're downloading scenery (and using bandwidth).
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Starting automatic scenery download/synchronization. "
|
"Starting automatic scenery download/synchronization. "
|
||||||
<< status
|
<< status
|
||||||
<< "Directory: '" << _local_dir << "'.");
|
<< "Directory: '" << _local_dir << "'.");
|
||||||
@@ -468,7 +437,7 @@ bool SGTerraSync::SvnThread::runExternalSyncCommand(const char* dir)
|
|||||||
// windows command line parsing is just lovely...
|
// windows command line parsing is just lovely...
|
||||||
// to allow white spaces, the system call needs this:
|
// to allow white spaces, the system call needs this:
|
||||||
// ""C:\Program Files\something.exe" somearg "some other arg""
|
// ""C:\Program Files\something.exe" somearg "some other arg""
|
||||||
// Note: whitespace strings quoted by a pair of "" _and_ the
|
// Note: whitespace strings quoted by a pair of "" _and_ the
|
||||||
// entire string needs to be wrapped by "" too.
|
// entire string needs to be wrapped by "" too.
|
||||||
// The svn url needs forward slashes (/) as a path separator while
|
// The svn url needs forward slashes (/) as a path separator while
|
||||||
// the local path needs windows-native backslash as a path separator.
|
// the local path needs windows-native backslash as a path separator.
|
||||||
@@ -476,7 +445,7 @@ bool SGTerraSync::SvnThread::runExternalSyncCommand(const char* dir)
|
|||||||
#else
|
#else
|
||||||
command = buf.str();
|
command = buf.str();
|
||||||
#endif
|
#endif
|
||||||
SG_LOG(SG_TERRASYNC,SG_DEBUG, "sync command '" << command << "'");
|
SG_LOG(SG_TERRAIN,SG_DEBUG, "sync command '" << command << "'");
|
||||||
|
|
||||||
#ifdef SG_WINDOWS
|
#ifdef SG_WINDOWS
|
||||||
// tbd: does Windows support "popen"?
|
// tbd: does Windows support "popen"?
|
||||||
@@ -491,7 +460,7 @@ bool SGTerraSync::SvnThread::runExternalSyncCommand(const char* dir)
|
|||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Failed to synchronize directory '" << dir << "', " <<
|
"Failed to synchronize directory '" << dir << "', " <<
|
||||||
"error code= " << rc);
|
"error code= " << rc);
|
||||||
return false;
|
return false;
|
||||||
@@ -503,39 +472,13 @@ void SGTerraSync::SvnThread::run()
|
|||||||
{
|
{
|
||||||
_active = true;
|
_active = true;
|
||||||
initCompletedTilesPersistentCache();
|
initCompletedTilesPersistentCache();
|
||||||
|
|
||||||
{
|
|
||||||
if (_svn_server.empty()) {
|
|
||||||
SG_LOG(SG_TERRASYNC,SG_INFO, "Querying closest TerraSync server");
|
|
||||||
ServerSelectQuery* ssq = new ServerSelectQuery;
|
|
||||||
HTTP::Request_ptr req = ssq;
|
|
||||||
_http.makeRequest(req);
|
|
||||||
while (!req->isComplete()) {
|
|
||||||
_http.update(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req->readyState() == HTTP::Request::DONE) {
|
|
||||||
_svn_server = ssq->svnUrl();
|
|
||||||
SG_LOG(SG_TERRASYNC,SG_INFO, "Closest TerraSync server:" << _svn_server);
|
|
||||||
} else {
|
|
||||||
SG_LOG(SG_TERRASYNC,SG_WARN, "Failed to query closest TerraSync server");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SG_LOG(SG_TERRASYNC,SG_INFO, "Explicit: TerraSync server:" << _svn_server);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_svn_server.empty()) {
|
|
||||||
// default value
|
|
||||||
_svn_server = "http://foxtrot.mgras.net:8080/terrascenery/trunk/data/Scenery";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_use_built_in) {
|
if (_use_built_in) {
|
||||||
runInternal();
|
runInternal();
|
||||||
} else {
|
} else {
|
||||||
runExternal();
|
runExternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
_active = false;
|
_active = false;
|
||||||
_running = false;
|
_running = false;
|
||||||
_is_dirty = true;
|
_is_dirty = true;
|
||||||
@@ -552,14 +495,14 @@ void SGTerraSync::SvnThread::runExternal()
|
|||||||
SyncItem::Status cacheStatus = isPathCached(next);
|
SyncItem::Status cacheStatus = isPathCached(next);
|
||||||
if (cacheStatus != SyncItem::Invalid) {
|
if (cacheStatus != SyncItem::Invalid) {
|
||||||
_cache_hits++;
|
_cache_hits++;
|
||||||
SG_LOG(SG_TERRASYNC, SG_DEBUG,
|
SG_LOG(SG_TERRAIN, SG_DEBUG,
|
||||||
"Cache hit for: '" << next._dir << "'");
|
"Cache hit for: '" << next._dir << "'");
|
||||||
next._status = cacheStatus;
|
next._status = cacheStatus;
|
||||||
_freshTiles.push_back(next);
|
_freshTiles.push_back(next);
|
||||||
_is_dirty = true;
|
_is_dirty = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
syncPathExternal(next);
|
syncPathExternal(next);
|
||||||
|
|
||||||
if ((_allowed_errors >= 0)&&
|
if ((_allowed_errors >= 0)&&
|
||||||
@@ -577,17 +520,17 @@ void SGTerraSync::SvnThread::syncPathExternal(const SyncItem& next)
|
|||||||
SGPath path( _local_dir );
|
SGPath path( _local_dir );
|
||||||
path.append( next._dir );
|
path.append( next._dir );
|
||||||
bool isNewDirectory = !path.exists();
|
bool isNewDirectory = !path.exists();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isNewDirectory) {
|
if (isNewDirectory) {
|
||||||
int rc = path.create_dir( 0755 );
|
int rc = path.create_dir( 0755 );
|
||||||
if (rc) {
|
if (rc) {
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot create directory '" << path << "', return code = " << rc );
|
"Cannot create directory '" << path << "', return code = " << rc );
|
||||||
throw sg_exception("Cannot create directory for terrasync", path.str());
|
throw sg_exception("Cannot create directory for terrasync", path.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!runExternalSyncCommand(next._dir.c_str())) {
|
if (!runExternalSyncCommand(next._dir.c_str())) {
|
||||||
throw sg_exception("Running external sync command failed");
|
throw sg_exception("Running external sync command failed");
|
||||||
}
|
}
|
||||||
@@ -596,7 +539,7 @@ void SGTerraSync::SvnThread::syncPathExternal(const SyncItem& next)
|
|||||||
_busy = false;
|
_busy = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updated(next, isNewDirectory);
|
updated(next, isNewDirectory);
|
||||||
_busy = false;
|
_busy = false;
|
||||||
}
|
}
|
||||||
@@ -605,16 +548,16 @@ void SGTerraSync::SvnThread::updateSyncSlot(SyncSlot &slot)
|
|||||||
{
|
{
|
||||||
if (slot.repository.get()) {
|
if (slot.repository.get()) {
|
||||||
if (slot.repository->isDoingSync()) {
|
if (slot.repository->isDoingSync()) {
|
||||||
#if 1
|
#if 0
|
||||||
if (slot.stamp.elapsedMSec() > (int)slot.nextWarnTimeout) {
|
if (slot.stamp.elapsedMSec() > slot.nextWarnTimeout) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_INFO, "sync taking a long time:" << slot.currentItem._dir << " taken " << slot.stamp.elapsedMSec());
|
SG_LOG(SG_TERRAIN, SG_INFO, "sync taking a long time:" << slot.currentItem._dir << " taken " << slot.stamp.elapsedMSec());
|
||||||
SG_LOG(SG_TERRASYNC, SG_INFO, "HTTP request count:" << _http.hasActiveRequests());
|
SG_LOG(SG_TERRAIN, SG_INFO, "HTTP status:" << _http.hasActiveRequests());
|
||||||
slot.nextWarnTimeout += 10000;
|
slot.nextWarnTimeout += 10000;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return; // easy, still working
|
return; // easy, still working
|
||||||
}
|
}
|
||||||
|
|
||||||
// check result
|
// check result
|
||||||
SVNRepository::ResultCode res = slot.repository->failure();
|
SVNRepository::ResultCode res = slot.repository->failure();
|
||||||
if (res == SVNRepository::SVN_ERROR_NOT_FOUND) {
|
if (res == SVNRepository::SVN_ERROR_NOT_FOUND) {
|
||||||
@@ -623,7 +566,7 @@ void SGTerraSync::SvnThread::updateSyncSlot(SyncSlot &slot)
|
|||||||
fail(slot.currentItem);
|
fail(slot.currentItem);
|
||||||
} else {
|
} else {
|
||||||
updated(slot.currentItem, slot.isNewDirectory);
|
updated(slot.currentItem, slot.isNewDirectory);
|
||||||
SG_LOG(SG_TERRASYNC, SG_DEBUG, "sync of " << slot.repository->baseUrl() << " finished ("
|
SG_LOG(SG_TERRAIN, SG_DEBUG, "sync of " << slot.repository->baseUrl() << " finished ("
|
||||||
<< slot.stamp.elapsedMSec() << " msec");
|
<< slot.stamp.elapsedMSec() << " msec");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,38 +574,38 @@ void SGTerraSync::SvnThread::updateSyncSlot(SyncSlot &slot)
|
|||||||
slot.busy = false;
|
slot.busy = false;
|
||||||
slot.repository.reset();
|
slot.repository.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// init and start sync of the next repository
|
// init and start sync of the next repository
|
||||||
if (!slot.queue.empty()) {
|
if (!slot.queue.empty()) {
|
||||||
slot.currentItem = slot.queue.front();
|
slot.currentItem = slot.queue.front();
|
||||||
slot.queue.pop();
|
slot.queue.pop();
|
||||||
|
|
||||||
SGPath path(_local_dir);
|
SGPath path(_local_dir);
|
||||||
path.append(slot.currentItem._dir);
|
path.append(slot.currentItem._dir);
|
||||||
slot.isNewDirectory = !path.exists();
|
slot.isNewDirectory = !path.exists();
|
||||||
if (slot.isNewDirectory) {
|
if (slot.isNewDirectory) {
|
||||||
int rc = path.create_dir( 0755 );
|
int rc = path.create_dir( 0755 );
|
||||||
if (rc) {
|
if (rc) {
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Cannot create directory '" << path << "', return code = " << rc );
|
"Cannot create directory '" << path << "', return code = " << rc );
|
||||||
fail(slot.currentItem);
|
fail(slot.currentItem);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} // of creating directory step
|
} // of creating directory step
|
||||||
|
|
||||||
string serverUrl(_svn_server);
|
string serverUrl(_svn_server);
|
||||||
if (slot.currentItem._type == SyncItem::AIData) {
|
if (slot.currentItem._type == SyncItem::AIData) {
|
||||||
serverUrl = _svn_data_server;
|
serverUrl = _svn_data_server;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot.repository.reset(new SVNRepository(path, &_http));
|
slot.repository.reset(new SVNRepository(path, &_http));
|
||||||
slot.repository->setBaseUrl(serverUrl + "/" + slot.currentItem._dir);
|
slot.repository->setBaseUrl(serverUrl + "/" + slot.currentItem._dir);
|
||||||
slot.repository->update();
|
slot.repository->update();
|
||||||
|
|
||||||
slot.nextWarnTimeout = 20000;
|
slot.nextWarnTimeout = 20000;
|
||||||
slot.stamp.stamp();
|
slot.stamp.stamp();
|
||||||
slot.busy = true;
|
slot.busy = true;
|
||||||
SG_LOG(SG_TERRASYNC, SG_INFO, "sync of " << slot.repository->baseUrl() << " started, queue size is " << slot.queue.size());
|
SG_LOG(SG_TERRAIN, SG_DEBUG, "sync of " << slot.repository->baseUrl() << " started, queue size is " << slot.queue.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,17 +616,17 @@ void SGTerraSync::SvnThread::runInternal()
|
|||||||
_transfer_rate = _http.transferRateBytesPerSec();
|
_transfer_rate = _http.transferRateBytesPerSec();
|
||||||
// convert from bytes to kbytes
|
// convert from bytes to kbytes
|
||||||
_total_kb_downloaded = static_cast<int>(_http.totalBytesDownloaded() / 1024);
|
_total_kb_downloaded = static_cast<int>(_http.totalBytesDownloaded() / 1024);
|
||||||
|
|
||||||
if (_stop)
|
if (_stop)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// drain the waiting tiles queue into the sync slot queues.
|
// drain the waiting tiles queue into the sync slot queues.
|
||||||
while (!waitingTiles.empty()) {
|
while (!waitingTiles.empty()) {
|
||||||
SyncItem next = waitingTiles.pop_front();
|
SyncItem next = waitingTiles.pop_front();
|
||||||
SyncItem::Status cacheStatus = isPathCached(next);
|
SyncItem::Status cacheStatus = isPathCached(next);
|
||||||
if (cacheStatus != SyncItem::Invalid) {
|
if (cacheStatus != SyncItem::Invalid) {
|
||||||
_cache_hits++;
|
_cache_hits++;
|
||||||
SG_LOG(SG_TERRASYNC, SG_DEBUG, "\nTerraSync Cache hit for: '" << next._dir << "'");
|
SG_LOG(SG_TERRAIN, SG_DEBUG, "\nTerraSync Cache hit for: '" << next._dir << "'");
|
||||||
next._status = cacheStatus;
|
next._status = cacheStatus;
|
||||||
_freshTiles.push_back(next);
|
_freshTiles.push_back(next);
|
||||||
_is_dirty = true;
|
_is_dirty = true;
|
||||||
@@ -693,7 +636,7 @@ void SGTerraSync::SvnThread::runInternal()
|
|||||||
unsigned int slot = syncSlotForType(next._type);
|
unsigned int slot = syncSlotForType(next._type);
|
||||||
_syncSlots[slot].queue.push(next);
|
_syncSlots[slot].queue.push(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool anySlotBusy = false;
|
bool anySlotBusy = false;
|
||||||
// update each sync slot in turn
|
// update each sync slot in turn
|
||||||
for (unsigned int slot=0; slot < NUM_SYNC_SLOTS; ++slot) {
|
for (unsigned int slot=0; slot < NUM_SYNC_SLOTS; ++slot) {
|
||||||
@@ -720,7 +663,7 @@ SyncItem::Status SGTerraSync::SvnThread::isPathCached(const SyncItem& next) cons
|
|||||||
// higher levels the cache status
|
// higher levels the cache status
|
||||||
return (ii == _notFoundItems.end()) ? SyncItem::Invalid : SyncItem::NotFound;
|
return (ii == _notFoundItems.end()) ? SyncItem::Invalid : SyncItem::NotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the path still physically exists. This is needed to
|
// check if the path still physically exists. This is needed to
|
||||||
// cope with the user manipulating our cache dir
|
// cope with the user manipulating our cache dir
|
||||||
SGPath p(_local_dir);
|
SGPath p(_local_dir);
|
||||||
@@ -728,7 +671,7 @@ SyncItem::Status SGTerraSync::SvnThread::isPathCached(const SyncItem& next) cons
|
|||||||
if (!p.exists()) {
|
if (!p.exists()) {
|
||||||
return SyncItem::Invalid;
|
return SyncItem::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t now = time(0);
|
time_t now = time(0);
|
||||||
return (ii->second > now) ? SyncItem::Cached : SyncItem::Invalid;
|
return (ii->second > now) ? SyncItem::Cached : SyncItem::Invalid;
|
||||||
}
|
}
|
||||||
@@ -740,8 +683,6 @@ void SGTerraSync::SvnThread::fail(SyncItem failedItem)
|
|||||||
_fail_count++;
|
_fail_count++;
|
||||||
failedItem._status = SyncItem::Failed;
|
failedItem._status = SyncItem::Failed;
|
||||||
_freshTiles.push_back(failedItem);
|
_freshTiles.push_back(failedItem);
|
||||||
SG_LOG(SG_TERRASYNC,SG_INFO,
|
|
||||||
"Failed to sync'" << failedItem._dir << "'");
|
|
||||||
_completedTiles[ failedItem._dir ] = now + UpdateInterval::FailedAttempt;
|
_completedTiles[ failedItem._dir ] = now + UpdateInterval::FailedAttempt;
|
||||||
_is_dirty = true;
|
_is_dirty = true;
|
||||||
}
|
}
|
||||||
@@ -752,7 +693,7 @@ void SGTerraSync::SvnThread::notFound(SyncItem item)
|
|||||||
// as succesful download. Important for MP models and similar so
|
// as succesful download. Important for MP models and similar so
|
||||||
// we don't spam the server with lookups for models that don't
|
// we don't spam the server with lookups for models that don't
|
||||||
// exist
|
// exist
|
||||||
|
|
||||||
time_t now = time(0);
|
time_t now = time(0);
|
||||||
item._status = SyncItem::NotFound;
|
item._status = SyncItem::NotFound;
|
||||||
_freshTiles.push_back(item);
|
_freshTiles.push_back(item);
|
||||||
@@ -766,9 +707,9 @@ void SGTerraSync::SvnThread::updated(SyncItem item, bool isNewDirectory)
|
|||||||
time_t now = time(0);
|
time_t now = time(0);
|
||||||
_consecutive_errors = 0;
|
_consecutive_errors = 0;
|
||||||
_success_count++;
|
_success_count++;
|
||||||
SG_LOG(SG_TERRASYNC,SG_INFO,
|
SG_LOG(SG_TERRAIN,SG_INFO,
|
||||||
"Successfully synchronized directory '" << item._dir << "'");
|
"Successfully synchronized directory '" << item._dir << "'");
|
||||||
|
|
||||||
item._status = SyncItem::Updated;
|
item._status = SyncItem::Updated;
|
||||||
if (item._type == SyncItem::Tile) {
|
if (item._type == SyncItem::Tile) {
|
||||||
_updated_tile_count++;
|
_updated_tile_count++;
|
||||||
@@ -785,17 +726,17 @@ void SGTerraSync::SvnThread::initCompletedTilesPersistentCache()
|
|||||||
if (!_persistentCachePath.exists()) {
|
if (!_persistentCachePath.exists()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode_ptr cacheRoot(new SGPropertyNode);
|
SGPropertyNode_ptr cacheRoot(new SGPropertyNode);
|
||||||
time_t now = time(0);
|
time_t now = time(0);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
readProperties(_persistentCachePath.str(), cacheRoot);
|
readProperties(_persistentCachePath.str(), cacheRoot);
|
||||||
} catch (sg_exception& e) {
|
} catch (sg_exception& e) {
|
||||||
SG_LOG(SG_TERRASYNC, SG_INFO, "corrupted persistent cache, discarding");
|
SG_LOG(SG_TERRAIN, SG_INFO, "corrupted persistent cache, discarding");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<cacheRoot->nChildren(); ++i) {
|
for (int i=0; i<cacheRoot->nChildren(); ++i) {
|
||||||
SGPropertyNode* entry = cacheRoot->getChild(i);
|
SGPropertyNode* entry = cacheRoot->getChild(i);
|
||||||
bool isNotFound = (strcmp(entry->getName(), "not-found") == 0);
|
bool isNotFound = (strcmp(entry->getName(), "not-found") == 0);
|
||||||
@@ -804,7 +745,7 @@ void SGTerraSync::SvnThread::initCompletedTilesPersistentCache()
|
|||||||
if (stamp < now) {
|
if (stamp < now) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNotFound) {
|
if (isNotFound) {
|
||||||
_completedTiles[tileName] = stamp;
|
_completedTiles[tileName] = stamp;
|
||||||
} else {
|
} else {
|
||||||
@@ -819,12 +760,12 @@ void SGTerraSync::SvnThread::writeCompletedTilesPersistentCache() const
|
|||||||
if (_persistentCachePath.isNull()) {
|
if (_persistentCachePath.isNull()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream f(_persistentCachePath.c_str(), std::ios::trunc);
|
std::ofstream f(_persistentCachePath.c_str(), std::ios::trunc);
|
||||||
if (!f.is_open()) {
|
if (!f.is_open()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode_ptr cacheRoot(new SGPropertyNode);
|
SGPropertyNode_ptr cacheRoot(new SGPropertyNode);
|
||||||
TileAgeCache::const_iterator it = _completedTiles.begin();
|
TileAgeCache::const_iterator it = _completedTiles.begin();
|
||||||
for (; it != _completedTiles.end(); ++it) {
|
for (; it != _completedTiles.end(); ++it) {
|
||||||
@@ -832,14 +773,14 @@ void SGTerraSync::SvnThread::writeCompletedTilesPersistentCache() const
|
|||||||
entry->setStringValue("path", it->first);
|
entry->setStringValue("path", it->first);
|
||||||
entry->setIntValue("stamp", it->second);
|
entry->setIntValue("stamp", it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
it = _notFoundItems.begin();
|
it = _notFoundItems.begin();
|
||||||
for (; it != _notFoundItems.end(); ++it) {
|
for (; it != _notFoundItems.end(); ++it) {
|
||||||
SGPropertyNode* entry = cacheRoot->addChild("not-found");
|
SGPropertyNode* entry = cacheRoot->addChild("not-found");
|
||||||
entry->setStringValue("path", it->first);
|
entry->setStringValue("path", it->first);
|
||||||
entry->setIntValue("stamp", it->second);
|
entry->setIntValue("stamp", it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeProperties(f, cacheRoot, true /* write_all */);
|
writeProperties(f, cacheRoot, true /* write_all */);
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
@@ -853,9 +794,9 @@ SGTerraSync::SGTerraSync() :
|
|||||||
_inited(false)
|
_inited(false)
|
||||||
{
|
{
|
||||||
_svnThread = new SvnThread();
|
_svnThread = new SvnThread();
|
||||||
_log = new BufferedLogCallback(SG_TERRASYNC, SG_INFO);
|
_log = new BufferedLogCallback(SG_TERRAIN, SG_INFO);
|
||||||
_log->truncateAt(255);
|
_log->truncateAt(255);
|
||||||
|
|
||||||
sglog().addCallback(_log);
|
sglog().addCallback(_log);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,12 +819,12 @@ void SGTerraSync::init()
|
|||||||
if (_inited) {
|
if (_inited) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_inited = true;
|
_inited = true;
|
||||||
|
|
||||||
assert(_terraRoot);
|
assert(_terraRoot);
|
||||||
_terraRoot->setBoolValue("built-in-svn-available",svn_built_in_available);
|
_terraRoot->setBoolValue("built-in-svn-available",svn_built_in_available);
|
||||||
|
|
||||||
reinit();
|
reinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -900,7 +841,7 @@ void SGTerraSync::reinit()
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_svnThread->stop();
|
_svnThread->stop();
|
||||||
|
|
||||||
if (_terraRoot->getBoolValue("enabled",false))
|
if (_terraRoot->getBoolValue("enabled",false))
|
||||||
@@ -930,7 +871,7 @@ void SGTerraSync::bind()
|
|||||||
if (_bound) {
|
if (_bound) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_bound = true;
|
_bound = true;
|
||||||
_tiedProperties.Tie( _terraRoot->getNode("busy", true), (bool*) &_svnThread->_busy );
|
_tiedProperties.Tie( _terraRoot->getNode("busy", true), (bool*) &_svnThread->_busy );
|
||||||
_tiedProperties.Tie( _terraRoot->getNode("active", true), (bool*) &_svnThread->_active );
|
_tiedProperties.Tie( _terraRoot->getNode("active", true), (bool*) &_svnThread->_active );
|
||||||
@@ -939,11 +880,11 @@ void SGTerraSync::bind()
|
|||||||
_tiedProperties.Tie( _terraRoot->getNode("tile-count", true), (int*) &_svnThread->_updated_tile_count );
|
_tiedProperties.Tie( _terraRoot->getNode("tile-count", true), (int*) &_svnThread->_updated_tile_count );
|
||||||
_tiedProperties.Tie( _terraRoot->getNode("cache-hits", true), (int*) &_svnThread->_cache_hits );
|
_tiedProperties.Tie( _terraRoot->getNode("cache-hits", true), (int*) &_svnThread->_cache_hits );
|
||||||
_tiedProperties.Tie( _terraRoot->getNode("transfer-rate-bytes-sec", true), (int*) &_svnThread->_transfer_rate );
|
_tiedProperties.Tie( _terraRoot->getNode("transfer-rate-bytes-sec", true), (int*) &_svnThread->_transfer_rate );
|
||||||
|
|
||||||
// use kbytes here because propety doesn't support 64-bit and we might conceivably
|
// use kbytes here because propety doesn't support 64-bit and we might conceivably
|
||||||
// download more than 2G in a single session
|
// download more than 2G in a single session
|
||||||
_tiedProperties.Tie( _terraRoot->getNode("downloaded-kbytes", true), (int*) &_svnThread->_total_kb_downloaded );
|
_tiedProperties.Tie( _terraRoot->getNode("downloaded-kbytes", true), (int*) &_svnThread->_total_kb_downloaded );
|
||||||
|
|
||||||
_terraRoot->getNode("busy", true)->setAttribute(SGPropertyNode::WRITE,false);
|
_terraRoot->getNode("busy", true)->setAttribute(SGPropertyNode::WRITE,false);
|
||||||
_terraRoot->getNode("active", true)->setAttribute(SGPropertyNode::WRITE,false);
|
_terraRoot->getNode("active", true)->setAttribute(SGPropertyNode::WRITE,false);
|
||||||
_terraRoot->getNode("update-count", true)->setAttribute(SGPropertyNode::WRITE,false);
|
_terraRoot->getNode("update-count", true)->setAttribute(SGPropertyNode::WRITE,false);
|
||||||
@@ -963,7 +904,7 @@ void SGTerraSync::unbind()
|
|||||||
_tiedProperties.Untie();
|
_tiedProperties.Untie();
|
||||||
_bound = false;
|
_bound = false;
|
||||||
_inited = false;
|
_inited = false;
|
||||||
|
|
||||||
_terraRoot.clear();
|
_terraRoot.clear();
|
||||||
_stalledNode.clear();
|
_stalledNode.clear();
|
||||||
_cacheHits.clear();
|
_cacheHits.clear();
|
||||||
@@ -978,13 +919,13 @@ void SGTerraSync::update(double)
|
|||||||
{
|
{
|
||||||
if (_svnThread->_stalled)
|
if (_svnThread->_stalled)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Automatic scenery download/synchronization stalled. Too many errors.");
|
"Automatic scenery download/synchronization stalled. Too many errors.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// not really an alert - just always show this message
|
// not really an alert - just always show this message
|
||||||
SG_LOG(SG_TERRASYNC,SG_ALERT,
|
SG_LOG(SG_TERRAIN,SG_ALERT,
|
||||||
"Automatic scenery download/synchronization has stopped.");
|
"Automatic scenery download/synchronization has stopped.");
|
||||||
}
|
}
|
||||||
_stalledNode->setBoolValue(_svnThread->_stalled);
|
_stalledNode->setBoolValue(_svnThread->_stalled);
|
||||||
@@ -993,7 +934,7 @@ void SGTerraSync::update(double)
|
|||||||
while (_svnThread->hasNewTiles())
|
while (_svnThread->hasNewTiles())
|
||||||
{
|
{
|
||||||
SyncItem next = _svnThread->getNewTile();
|
SyncItem next = _svnThread->getNewTile();
|
||||||
|
|
||||||
if ((next._type == SyncItem::Tile) || (next._type == SyncItem::AIData)) {
|
if ((next._type == SyncItem::Tile) || (next._type == SyncItem::AIData)) {
|
||||||
_activeTileDirs.erase(next._dir);
|
_activeTileDirs.erase(next._dir);
|
||||||
}
|
}
|
||||||
@@ -1017,7 +958,7 @@ void SGTerraSync::syncAirportsModels()
|
|||||||
_svnThread->request( w );
|
_svnThread->request( w );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncItem w("Models", SyncItem::SharedModels);
|
SyncItem w("Models", SyncItem::SharedModels);
|
||||||
_svnThread->request( w );
|
_svnThread->request( w );
|
||||||
}
|
}
|
||||||
@@ -1031,7 +972,7 @@ void SGTerraSync::syncAreaByPath(const std::string& aPath)
|
|||||||
if (_activeTileDirs.find(dir) != _activeTileDirs.end()) {
|
if (_activeTileDirs.find(dir) != _activeTileDirs.end()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_activeTileDirs.insert(dir);
|
_activeTileDirs.insert(dir);
|
||||||
SyncItem w(dir, SyncItem::Tile);
|
SyncItem w(dir, SyncItem::Tile);
|
||||||
_svnThread->request( w );
|
_svnThread->request( w );
|
||||||
@@ -1050,7 +991,7 @@ bool SGTerraSync::isTileDirPending(const std::string& sceneryDir) const
|
|||||||
if (!_svnThread->_running) {
|
if (!_svnThread->_running) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* terrainobjects[3] = { "Terrain/", "Objects/", 0 };
|
const char* terrainobjects[3] = { "Terrain/", "Objects/", 0 };
|
||||||
for (const char** tree = &terrainobjects[0]; *tree; tree++) {
|
for (const char** tree = &terrainobjects[0]; *tree; tree++) {
|
||||||
string s = *tree + sceneryDir;
|
string s = *tree + sceneryDir;
|
||||||
@@ -1067,7 +1008,7 @@ void SGTerraSync::scheduleDataDir(const std::string& dataDir)
|
|||||||
if (_activeTileDirs.find(dataDir) != _activeTileDirs.end()) {
|
if (_activeTileDirs.find(dataDir) != _activeTileDirs.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_activeTileDirs.insert(dataDir);
|
_activeTileDirs.insert(dataDir);
|
||||||
SyncItem w(dataDir, SyncItem::AIData);
|
SyncItem w(dataDir, SyncItem::AIData);
|
||||||
_svnThread->request( w );
|
_svnThread->request( w );
|
||||||
@@ -1079,11 +1020,11 @@ bool SGTerraSync::isDataDirPending(const std::string& dataDir) const
|
|||||||
if (!_svnThread->_running) {
|
if (!_svnThread->_running) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (_activeTileDirs.find(dataDir) != _activeTileDirs.end());
|
return (_activeTileDirs.find(dataDir) != _activeTileDirs.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SGTerraSync::reposition()
|
void SGTerraSync::reposition()
|
||||||
{
|
{
|
||||||
// stub, remove
|
// stub, remove
|
||||||
}
|
}
|
||||||
@@ -25,13 +25,11 @@
|
|||||||
|
|
||||||
#include "SGSceneFeatures.hxx"
|
#include "SGSceneFeatures.hxx"
|
||||||
|
|
||||||
#include <osg/Version>
|
|
||||||
#include <osg/FragmentProgram>
|
#include <osg/FragmentProgram>
|
||||||
#include <osg/VertexProgram>
|
#include <osg/VertexProgram>
|
||||||
#include <osg/Point>
|
#include <osg/Point>
|
||||||
#include <osg/PointSprite>
|
#include <osg/PointSprite>
|
||||||
#include <osg/Texture>
|
#include <osg/Texture>
|
||||||
#include <osg/GLExtensions>
|
|
||||||
|
|
||||||
#include <OpenThreads/Mutex>
|
#include <OpenThreads/Mutex>
|
||||||
#include <OpenThreads/ScopedLock>
|
#include <OpenThreads/ScopedLock>
|
||||||
@@ -86,18 +84,12 @@ SGSceneFeatures::setTextureCompression(osg::Texture* texture) const
|
|||||||
bool
|
bool
|
||||||
SGSceneFeatures::getHavePointSprites(unsigned contextId) const
|
SGSceneFeatures::getHavePointSprites(unsigned contextId) const
|
||||||
{
|
{
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
return osg::PointSprite::isPointSpriteSupported(contextId);
|
return osg::PointSprite::isPointSpriteSupported(contextId);
|
||||||
#else
|
|
||||||
const osg::GLExtensions* ex = osg::GLExtensions::Get(contextId, true);
|
|
||||||
return ex && ex->isPointSpriteSupported;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SGSceneFeatures::getHaveFragmentPrograms(unsigned contextId) const
|
SGSceneFeatures::getHaveFragmentPrograms(unsigned contextId) const
|
||||||
{
|
{
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
const osg::FragmentProgram::Extensions* fpe;
|
const osg::FragmentProgram::Extensions* fpe;
|
||||||
fpe = osg::FragmentProgram::getExtensions(contextId, true);
|
fpe = osg::FragmentProgram::getExtensions(contextId, true);
|
||||||
if (!fpe)
|
if (!fpe)
|
||||||
@@ -106,16 +98,11 @@ SGSceneFeatures::getHaveFragmentPrograms(unsigned contextId) const
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
const osg::GLExtensions* ex = osg::GLExtensions::Get(contextId, true);
|
|
||||||
return ex && ex->isFragmentProgramSupported;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SGSceneFeatures::getHaveVertexPrograms(unsigned contextId) const
|
SGSceneFeatures::getHaveVertexPrograms(unsigned contextId) const
|
||||||
{
|
{
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
const osg::VertexProgram::Extensions* vpe;
|
const osg::VertexProgram::Extensions* vpe;
|
||||||
vpe = osg::VertexProgram::getExtensions(contextId, true);
|
vpe = osg::VertexProgram::getExtensions(contextId, true);
|
||||||
if (!vpe)
|
if (!vpe)
|
||||||
@@ -124,10 +111,6 @@ SGSceneFeatures::getHaveVertexPrograms(unsigned contextId) const
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
const osg::GLExtensions* ex = osg::GLExtensions::Get(contextId, true);
|
|
||||||
return ex && ex->isVertexProgramSupported;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -141,7 +124,6 @@ SGSceneFeatures::getHaveShaderPrograms(unsigned contextId) const
|
|||||||
bool
|
bool
|
||||||
SGSceneFeatures::getHavePointParameters(unsigned contextId) const
|
SGSceneFeatures::getHavePointParameters(unsigned contextId) const
|
||||||
{
|
{
|
||||||
#if OSG_VERSION_LESS_THAN(3,3,4)
|
|
||||||
const osg::Point::Extensions* pe;
|
const osg::Point::Extensions* pe;
|
||||||
pe = osg::Point::getExtensions(contextId, true);
|
pe = osg::Point::getExtensions(contextId, true);
|
||||||
if (!pe)
|
if (!pe)
|
||||||
@@ -149,9 +131,5 @@ SGSceneFeatures::getHavePointParameters(unsigned contextId) const
|
|||||||
if (!pe->isPointParametersSupported())
|
if (!pe->isPointParametersSupported())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
const osg::GLExtensions* ex = osg::GLExtensions::Get(contextId, true);
|
|
||||||
return ex && ex->isPointParametersSupported;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,4 +18,3 @@
|
|||||||
|
|
||||||
#cmakedefine SYSTEM_EXPAT
|
#cmakedefine SYSTEM_EXPAT
|
||||||
#cmakedefine ENABLE_SOUND
|
#cmakedefine ENABLE_SOUND
|
||||||
#cmakedefine ENABLE_CURL
|
|
||||||
|
|||||||
@@ -401,9 +401,8 @@ void SGSampleGroup::set_volume( float vol )
|
|||||||
|
|
||||||
// set the source position and orientation of all managed sounds
|
// set the source position and orientation of all managed sounds
|
||||||
void SGSampleGroup::update_pos_and_orientation() {
|
void SGSampleGroup::update_pos_and_orientation() {
|
||||||
|
|
||||||
SGVec3d base_position = SGVec3d::fromGeod(_base_pos);
|
SGVec3d position = SGVec3d::fromGeod(_base_pos) - _smgr->get_position();
|
||||||
SGVec3d smgr_position = _smgr->get_position();
|
|
||||||
SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos);
|
SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos);
|
||||||
SGQuatd ec2body = hlOr*_orientation;
|
SGQuatd ec2body = hlOr*_orientation;
|
||||||
|
|
||||||
@@ -419,14 +418,12 @@ void SGSampleGroup::update_pos_and_orientation() {
|
|||||||
sample->set_master_volume( _volume );
|
sample->set_master_volume( _volume );
|
||||||
sample->set_orientation( _orientation );
|
sample->set_orientation( _orientation );
|
||||||
sample->set_rotation( ec2body );
|
sample->set_rotation( ec2body );
|
||||||
sample->set_position(base_position);
|
sample->set_position( position );
|
||||||
sample->set_velocity( velocity );
|
sample->set_velocity( velocity );
|
||||||
|
|
||||||
// Test if a sample is farther away than max distance, if so
|
// Test if a sample is farther away than max distance, if so
|
||||||
// stop the sound playback and free it's source.
|
// stop the sound playback and free it's source.
|
||||||
if (!_tied_to_listener) {
|
if (!_tied_to_listener) {
|
||||||
sample->update_pos_and_orientation();
|
|
||||||
SGVec3d position = sample->get_position() - smgr_position;
|
|
||||||
float max2 = sample->get_max_dist() * sample->get_max_dist();
|
float max2 = sample->get_max_dist() * sample->get_max_dist();
|
||||||
float dist2 = position[0]*position[0]
|
float dist2 = position[0]*position[0]
|
||||||
+ position[1]*position[1] + position[2]*position[2];
|
+ position[1]*position[1] + position[2]*position[2];
|
||||||
@@ -452,7 +449,7 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample )
|
|||||||
} else {
|
} else {
|
||||||
sample->update_pos_and_orientation();
|
sample->update_pos_and_orientation();
|
||||||
orientation = sample->get_orientation();
|
orientation = sample->get_orientation();
|
||||||
position = sample->get_position() - _smgr->get_position();
|
position = sample->get_position();
|
||||||
velocity = sample->get_velocity();
|
velocity = sample->get_velocity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
#include <stdlib.h> // rand(), free()
|
#include <stdlib.h> // rand(), free()
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
@@ -79,12 +78,8 @@ SGSoundSample::SGSoundSample() :
|
|||||||
_playing(false),
|
_playing(false),
|
||||||
_static_changed(true),
|
_static_changed(true),
|
||||||
_out_of_range(false),
|
_out_of_range(false),
|
||||||
_is_file(false),
|
_is_file(false)
|
||||||
_use_pos_props(false)
|
|
||||||
{
|
{
|
||||||
_pos_prop[0] = 0;
|
|
||||||
_pos_prop[1] = 0;
|
|
||||||
_pos_prop[2] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -119,14 +114,10 @@ SGSoundSample::SGSoundSample(const char *file, const SGPath& currentDir) :
|
|||||||
_playing(false),
|
_playing(false),
|
||||||
_static_changed(true),
|
_static_changed(true),
|
||||||
_out_of_range(false),
|
_out_of_range(false),
|
||||||
_is_file(true),
|
_is_file(true)
|
||||||
_use_pos_props(false)
|
|
||||||
{
|
{
|
||||||
SGPath p = simgear::ResourceManager::instance()->findPath(file, currentDir);
|
SGPath p = simgear::ResourceManager::instance()->findPath(file, currentDir);
|
||||||
_refname = p.str();
|
_refname = p.str();
|
||||||
_pos_prop[0] = 0;
|
|
||||||
_pos_prop[1] = 0;
|
|
||||||
_pos_prop[2] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -161,14 +152,10 @@ SGSoundSample::SGSoundSample( const unsigned char** data,
|
|||||||
_playing(false),
|
_playing(false),
|
||||||
_static_changed(true),
|
_static_changed(true),
|
||||||
_out_of_range(false),
|
_out_of_range(false),
|
||||||
_is_file(false),
|
_is_file(false)
|
||||||
_use_pos_props(false)
|
|
||||||
{
|
{
|
||||||
SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
|
SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
|
||||||
_data = (unsigned char*)*data; *data = NULL;
|
_data = (unsigned char*)*data; *data = NULL;
|
||||||
_pos_prop[0] = 0;
|
|
||||||
_pos_prop[1] = 0;
|
|
||||||
_pos_prop[2] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -202,14 +189,10 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) :
|
|||||||
_playing(false),
|
_playing(false),
|
||||||
_static_changed(true),
|
_static_changed(true),
|
||||||
_out_of_range(false),
|
_out_of_range(false),
|
||||||
_is_file(false),
|
_is_file(false)
|
||||||
_use_pos_props(false)
|
|
||||||
{
|
{
|
||||||
SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
|
SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
|
||||||
_data = (unsigned char*)*data; *data = NULL;
|
_data = (unsigned char*)*data; *data = NULL;
|
||||||
_pos_prop[0] = 0;
|
|
||||||
_pos_prop[1] = 0;
|
|
||||||
_pos_prop[2] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -220,16 +203,9 @@ SGSoundSample::~SGSoundSample() {
|
|||||||
|
|
||||||
void SGSoundSample::update_pos_and_orientation() {
|
void SGSoundSample::update_pos_and_orientation() {
|
||||||
|
|
||||||
if (_use_pos_props) {
|
_absolute_pos = _base_pos;
|
||||||
if (_pos_prop[0]) _absolute_pos[0] = _pos_prop[0]->getDoubleValue();
|
if (_relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) {
|
||||||
if (_pos_prop[1]) _absolute_pos[1] = _pos_prop[1]->getDoubleValue();
|
_absolute_pos += _rotation.rotate( _relative_pos );
|
||||||
if (_pos_prop[2]) _absolute_pos[2] = _pos_prop[2]->getDoubleValue();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_absolute_pos = _base_pos;
|
|
||||||
if (_relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) {
|
|
||||||
_absolute_pos += _rotation.rotate( _relative_pos );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_orivec = SGVec3f::zeros();
|
_orivec = SGVec3f::zeros();
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user