Compare commits

..
Author SHA1 Message Date
James Turner 506b9130a8 Adjust where we set the deployment SDK on Mac.
Contrary to the CMake docs, settings this value before project()
seems not to work, whereas setting it after works exactly as
desired.
2015-02-18 10:06:03 +00:00
James Turner 5d1b70a7f2 Force SDK version / C++ library on Mac. 2015-02-13 14:47:45 +00:00
Peter Sadrozinski eff3df57d9 memory reduced tile loading.
- do not save the TileGeometryBin and matcach in the randomObjectCallback
- recreate matcache, and get TileGeometry from scenegraph
- split obj.cxx into three distinct files - loadBTG, load surface geometry, and load tile details
- includes fix for sceneries that have missing materials
2015-02-11 09:04:53 +01:00
Rebecca N. Palmer 2931f3380f Fix UpdateOnceCallback crash (bug 1554/1556/1568)
(cherry picked from commit dc1816bb08)
2015-01-19 15:51:36 +00:00
114 changed files with 1452 additions and 3552 deletions
+19 -79
View File
@@ -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")
+182
View File
@@ -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()
-16
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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]; }
+23 -12
View File
@@ -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;
} }
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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) ),
+1 -1
View File
@@ -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);
+66 -104
View File
@@ -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
{ {
+2 -10
View File
@@ -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;
}; };
+1 -1
View File
@@ -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) )
{ {
+1 -1
View File
@@ -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);
+3 -18
View File
@@ -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) )
{ {
+1 -1
View File
@@ -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);
+11 -28
View File
@@ -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;
}; };
-6
View File
@@ -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.
// //
+1 -2
View File
@@ -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;
-1
View File
@@ -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";
} }
} }
+1 -1
View File
@@ -22,7 +22,7 @@
* $Id$ * $Id$
**************************************************************************/ **************************************************************************/
#include <cmath> #include <math.h>
#include "jupiter.hxx" #include "jupiter.hxx"
+1 -1
View File
@@ -22,7 +22,7 @@
* $Id$ * $Id$
**************************************************************************/ **************************************************************************/
#include <cmath> #include <math.h>
#include "mars.hxx" #include "mars.hxx"
+1 -1
View File
@@ -22,7 +22,7 @@
* $Id$ * $Id$
**************************************************************************/ **************************************************************************/
#include <cmath> #include <math.h>
#include "mercury.hxx" #include "mercury.hxx"
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -22,7 +22,7 @@
* $Id$ * $Id$
**************************************************************************/ **************************************************************************/
#include <cmath> #include <math.h>
#include "saturn.hxx" #include "saturn.hxx"
+1 -1
View File
@@ -22,7 +22,7 @@
* $Id$ * $Id$
**************************************************************************/ **************************************************************************/
#include <cmath> #include <math.h>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
+1 -1
View File
@@ -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:
+1 -1
View File
@@ -22,7 +22,7 @@
* $Id$ * $Id$
**************************************************************************/ **************************************************************************/
#include <cmath> #include <math.h>
#include "uranus.hxx" #include "uranus.hxx"
+1 -1
View File
@@ -22,7 +22,7 @@
* $Id$ * $Id$
**************************************************************************/ **************************************************************************/
#include <cmath> #include <math.h>
#include "venus.hxx" #include "venus.hxx"
+4 -7
View File
@@ -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)
+4 -4
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+13 -20
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+8 -14
View File
@@ -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);
+5 -8
View File
@@ -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;
-12
View File
@@ -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) {
-1
View File
@@ -27,7 +27,6 @@
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <algorithm>
namespace simgear { namespace simgear {
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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];
} }
} }
+1 -1
View File
@@ -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>
+3 -3
View File
@@ -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>
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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; }
+1 -1
View File
@@ -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 -5
View File
@@ -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()
+1 -5
View File
@@ -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");
-1
View File
@@ -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
View File
@@ -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
} }
-122
View File
@@ -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_
-1
View File
@@ -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"
+2 -2
View File
@@ -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}")
+8
View File
@@ -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 )
-6
View File
@@ -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 -6
View File
@@ -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
View File
@@ -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 {
-12
View File
@@ -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
View File
@@ -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
View File
@@ -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
-107
View File
@@ -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;
}
+30 -38
View File
@@ -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
View File
@@ -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);
} }
+5 -34
View File
@@ -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,
+3 -65
View File
@@ -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
+1 -22
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}; };
-64
View File
@@ -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>
+2 -3
View File
@@ -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
View File
@@ -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();
} }
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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;
-10
View File
@@ -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
} }
}; };
-1
View File
@@ -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);
-11
View File
@@ -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
+2 -2
View File
@@ -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());
} }
+1 -7
View File
@@ -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 );
}
} }
} }
} }
-4
View File
@@ -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);
+1 -5
View File
@@ -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 };
+7 -57
View File
@@ -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 ){
-1
View File
@@ -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;
+37 -69
View File
@@ -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)
+5 -5
View File
@@ -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
+1 -4
View File
@@ -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));
} }
} }
} }
+5 -9
View File
@@ -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));
} }
} }
} }
+12 -13
View File
@@ -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;
}; };
-4
View File
@@ -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();
+9 -47
View File
@@ -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)
+5 -7
View File
@@ -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(); }
+91 -150
View File
@@ -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
} }
-22
View File
@@ -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
} }
-1
View File
@@ -18,4 +18,3 @@
#cmakedefine SYSTEM_EXPAT #cmakedefine SYSTEM_EXPAT
#cmakedefine ENABLE_SOUND #cmakedefine ENABLE_SOUND
#cmakedefine ENABLE_CURL
+4 -7
View File
@@ -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();
} }
+7 -31
View File
@@ -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