Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a773f30e6 | ||
|
|
eb03782908 | ||
|
|
c79580d853 | ||
|
|
1b3c048363 | ||
|
|
01f689a0e4 | ||
|
|
b155f2e40f | ||
|
|
10ab8b830a | ||
|
|
8a4871db83 | ||
|
|
9a8c10cb0b | ||
|
|
fd32023437 | ||
|
|
c1ee4a9172 | ||
|
|
a5b32f8eb2 | ||
|
|
4a86368c8f | ||
|
|
3730cc48a5 | ||
|
|
8a55c2f44f | ||
|
|
ef1cbae22b | ||
|
|
61f322f201 | ||
|
|
becbef96f5 | ||
|
|
89b3fadf0f | ||
|
|
4a1a9ea9c1 | ||
|
|
efc609577f | ||
|
|
6ffc501566 | ||
|
|
9785cadbd0 |
+15
-11
@@ -10,6 +10,9 @@ if(COMMAND cmake_policy)
|
|||||||
if(POLICY CMP0067)
|
if(POLICY CMP0067)
|
||||||
cmake_policy(SET CMP0067 NEW)
|
cmake_policy(SET CMP0067 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
if(POLICY CMP0093)
|
||||||
|
cmake_policy(SET CMP0093 NEW)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
@@ -32,6 +35,7 @@ include (GenerateExportHeader)
|
|||||||
|
|
||||||
# only relevant for building shared libs but let's set it regardless
|
# only relevant for building shared libs but let's set it regardless
|
||||||
set(CMAKE_OSX_RPATH 1)
|
set(CMAKE_OSX_RPATH 1)
|
||||||
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
|
||||||
|
|
||||||
# let's use & require C++11 - note these are only functional with CMake 3.1
|
# let's use & require C++11 - note these are only functional with CMake 3.1
|
||||||
# we do manual fallbacks for CMake 3.0 in the compilers section
|
# we do manual fallbacks for CMake 3.0 in the compilers section
|
||||||
@@ -44,12 +48,7 @@ string(STRIP ${versionFile} SIMGEAR_VERSION)
|
|||||||
|
|
||||||
project(SimGear VERSION ${SIMGEAR_VERSION} LANGUAGES C CXX)
|
project(SimGear VERSION ${SIMGEAR_VERSION} LANGUAGES C CXX)
|
||||||
|
|
||||||
# using 10.7 because boost requires libc++ and 10.6 doesn't include it
|
# add a dependency on the version file
|
||||||
# Cmake documentation says we must set this before calling project(), but
|
|
||||||
# it only seems to be picked up setting it /after/ the call to project()
|
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.7")
|
|
||||||
|
|
||||||
# add a dependency on the versino file
|
|
||||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS version)
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS version)
|
||||||
|
|
||||||
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE)
|
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE)
|
||||||
@@ -129,9 +128,14 @@ option(ENABLE_SOUND "Set to OFF to disable building SimGear's sound support"
|
|||||||
option(USE_AEONWAVE "Set to ON to use AeonWave instead of OpenAL" ON)
|
option(USE_AEONWAVE "Set to ON to use AeonWave instead of OpenAL" 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_DNS "Set to ON to use udns library and DNS service resolver" ON)
|
option(ENABLE_DNS "Set to ON to use udns library and DNS service resolver" ON)
|
||||||
option(ENABLE_SIMD "Enable SSE/SSE2 support for x86 compilers" ON)
|
option(ENABLE_SIMD "Enable SSE/SSE2 support for compilers" ON)
|
||||||
|
option(ENABLE_SIMD_CODE "Enable SSE/SSE2 support code for compilers" OFF)
|
||||||
option(ENABLE_OPENMP "Enable OpenMP compiler support" OFF)
|
option(ENABLE_OPENMP "Enable OpenMP compiler support" OFF)
|
||||||
|
|
||||||
|
if (NOT ENABLE_SIMD AND ENABLE_SIMD_CODE)
|
||||||
|
set(ENABLE_SIMD_CODE OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
include (DetectArch)
|
include (DetectArch)
|
||||||
|
|
||||||
# until the fstream fix is applied and generally available in OSG,
|
# until the fstream fix is applied and generally available in OSG,
|
||||||
@@ -416,8 +420,8 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
"${CMAKE_CXX_FLAGS} -O0 -fno-omit-frame-pointer -fno-inline")
|
"${CMAKE_CXX_FLAGS} -O0 -fno-omit-frame-pointer -fno-inline")
|
||||||
elseif (ENABLE_SIMD)
|
elseif (ENABLE_SIMD)
|
||||||
if (X86 OR X86_64)
|
if (X86 OR X86_64)
|
||||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse")
|
set(CMAKE_C_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse -ftree-vectorize -ftree-slp-vectorize")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse")
|
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse -ftree-vectorize -ftree-slp-vectorize")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -444,8 +448,8 @@ if (CLANG)
|
|||||||
"${CMAKE_CXX_FLAGS} -O0 -fno-omit-frame-pointer -fno-inline-functions")
|
"${CMAKE_CXX_FLAGS} -O0 -fno-omit-frame-pointer -fno-inline-functions")
|
||||||
elseif (ENABLE_SIMD)
|
elseif (ENABLE_SIMD)
|
||||||
if (X86 OR X86_64)
|
if (X86 OR X86_64)
|
||||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse")
|
set(CMAKE_C_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse -ftree-vectorize -ftree-slp-vectorize")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse")
|
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse -ftree-vectorize -ftree-slp-vectorize")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -46,11 +46,17 @@ set(BOOST_TEST_TARGET_PREFIX "test")
|
|||||||
if(NOT Boost_FOUND)
|
if(NOT Boost_FOUND)
|
||||||
find_package(Boost 1.34.0 QUIET)
|
find_package(Boost 1.34.0 QUIET)
|
||||||
endif()
|
endif()
|
||||||
if("${Boost_VERSION}0" LESS "1034000")
|
|
||||||
|
if (NOT Boost_VERSION_MACRO)
|
||||||
|
# Compatibility with pre CMP0093 (CMake 3.15)
|
||||||
|
set(Boost_VERSION_MACRO ${Boost_VERSION})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${Boost_VERSION_MACRO}0" LESS "1034000")
|
||||||
set(_shared_msg
|
set(_shared_msg
|
||||||
"NOTE: boost::test-based targets and tests cannot "
|
"NOTE: boost::test-based targets and tests cannot "
|
||||||
"be added: boost >= 1.34.0 required but not found. "
|
"be added: boost >= 1.34.0 required but not found. "
|
||||||
"(found: '${Boost_VERSION}'; want >=103400) ")
|
"(found: '${Boost_VERSION_MACRO}'; want >=103400) ")
|
||||||
if(ENABLE_TESTS)
|
if(ENABLE_TESTS)
|
||||||
message(FATAL_ERROR
|
message(FATAL_ERROR
|
||||||
${_shared_msg}
|
${_shared_msg}
|
||||||
@@ -66,7 +72,7 @@ endif()
|
|||||||
include(GetForceIncludeDefinitions)
|
include(GetForceIncludeDefinitions)
|
||||||
include(CopyResourcesToBuildTree)
|
include(CopyResourcesToBuildTree)
|
||||||
|
|
||||||
if(Boost_FOUND AND NOT "${Boost_VERSION}0" LESS "1034000")
|
if(Boost_FOUND AND NOT "${Boost_VERSION_MACRO}0" LESS "1034000")
|
||||||
set(_boosttesttargets_libs)
|
set(_boosttesttargets_libs)
|
||||||
set(_boostConfig "BoostTestTargetsIncluded.h")
|
set(_boostConfig "BoostTestTargetsIncluded.h")
|
||||||
if(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY)
|
if(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY)
|
||||||
@@ -129,7 +135,7 @@ function(add_boost_test _name)
|
|||||||
"Syntax error in use of add_boost_test: at least one source file required!")
|
"Syntax error in use of add_boost_test: at least one source file required!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(Boost_FOUND AND NOT "${Boost_VERSION}0" LESS "1034000")
|
if(Boost_FOUND AND NOT "${Boost_VERSION_MACRO}0" LESS "1034000")
|
||||||
|
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
@@ -221,7 +227,7 @@ function(add_boost_test _name)
|
|||||||
set(_test_command ${_target_name})
|
set(_test_command ${_target_name})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(TESTS AND ( "${Boost_VERSION}" VERSION_GREATER "103799" ))
|
if(TESTS AND ( "${Boost_VERSION_MACRO}" VERSION_GREATER "103799" ))
|
||||||
foreach(_test ${TESTS})
|
foreach(_test ${TESTS})
|
||||||
add_test(
|
add_test(
|
||||||
${_name}-${_test}
|
${_name}-${_test}
|
||||||
|
|||||||
@@ -472,12 +472,26 @@ size_t Client::requestReadCallback(char *ptr, size_t size, size_t nmemb, void *u
|
|||||||
return actualBytes;
|
return actualBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isRedirectStatus(int code)
|
||||||
|
{
|
||||||
|
return ((code >= 300) && (code < 400));
|
||||||
|
}
|
||||||
|
|
||||||
size_t Client::requestHeaderCallback(char *rawBuffer, size_t size, size_t nitems, void *userdata)
|
size_t Client::requestHeaderCallback(char *rawBuffer, size_t size, size_t nitems, void *userdata)
|
||||||
{
|
{
|
||||||
size_t byteSize = size * nitems;
|
size_t byteSize = size * nitems;
|
||||||
Request* req = static_cast<Request*>(userdata);
|
Request* req = static_cast<Request*>(userdata);
|
||||||
std::string h = strutils::simplify(std::string(rawBuffer, byteSize));
|
std::string h = strutils::simplify(std::string(rawBuffer, byteSize));
|
||||||
|
|
||||||
|
if (req->readyState() >= HTTP::Request::HEADERS_RECEIVED) {
|
||||||
|
// this can happen with chunked transfers (secondary chunks)
|
||||||
|
// or redirects
|
||||||
|
if (isRedirectStatus(req->responseCode())) {
|
||||||
|
req->responseStart(h);
|
||||||
|
return byteSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (req->readyState() == HTTP::Request::OPENED) {
|
if (req->readyState() == HTTP::Request::OPENED) {
|
||||||
req->responseStart(h);
|
req->responseStart(h);
|
||||||
return byteSize;
|
return byteSize;
|
||||||
|
|||||||
@@ -1049,9 +1049,6 @@ HTTPRepository::failure() const
|
|||||||
entry.lengthBytes = strtol(sizeData.c_str(), NULL, 10);
|
entry.lengthBytes = strtol(sizeData.c_str(), NULL, 10);
|
||||||
hashes.push_back(entry);
|
hashes.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
SG_LOG(SG_TERRASYNC, SG_INFO, "restored hashes:" << hashes.size());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DirectoryWithPath
|
class DirectoryWithPath
|
||||||
|
|||||||
@@ -328,6 +328,16 @@ unsigned int Request::responseLength() const
|
|||||||
return _responseLength;
|
return _responseLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void Request::setSuccess(int code)
|
||||||
|
{
|
||||||
|
_responseStatus = code;
|
||||||
|
_responseReason.clear();
|
||||||
|
if( !isComplete() ) {
|
||||||
|
setReadyState(DONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void Request::setFailure(int code, const std::string& reason)
|
void Request::setFailure(int code, const std::string& reason)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ protected:
|
|||||||
virtual void onAlways();
|
virtual void onAlways();
|
||||||
|
|
||||||
void setFailure(int code, const std::string& reason);
|
void setFailure(int code, const std::string& reason);
|
||||||
|
void setSuccess(int code);
|
||||||
private:
|
private:
|
||||||
friend class Client;
|
friend class Client;
|
||||||
friend class Connection;
|
friend class Connection;
|
||||||
|
|||||||
@@ -273,7 +273,23 @@ public:
|
|||||||
d << "\r\n"; // final CRLF to terminate the headers
|
d << "\r\n"; // final CRLF to terminate the headers
|
||||||
d << contentStr;
|
d << contentStr;
|
||||||
push(d.str().c_str());
|
push(d.str().c_str());
|
||||||
|
} else if (path == "/test_redirect") {
|
||||||
|
string contentStr("<html>See <a href=\"wibble\">Here</a></html>");
|
||||||
|
stringstream d;
|
||||||
|
d << "HTTP/1.1 " << 302 << " " << "Found" << "\r\n";
|
||||||
|
d << "Location:" << " http://localhost:2000/was_redirected" << "\r\n";
|
||||||
|
d << "Content-Length:" << contentStr.size() << "\r\n";
|
||||||
|
d << "\r\n"; // final CRLF to terminate the headers
|
||||||
|
d << contentStr;
|
||||||
|
push(d.str().c_str());
|
||||||
|
} else if (path == "/was_redirected") {
|
||||||
|
string contentStr(BODY1);
|
||||||
|
stringstream d;
|
||||||
|
d << "HTTP/1.1 " << 200 << " " << reasonForCode(200) << "\r\n";
|
||||||
|
d << "Content-Length:" << contentStr.size() << "\r\n";
|
||||||
|
d << "\r\n"; // final CRLF to terminate the headers
|
||||||
|
d << contentStr;
|
||||||
|
push(d.str().c_str());
|
||||||
} else {
|
} else {
|
||||||
TestServerChannel::processRequestHeaders();
|
TestServerChannel::processRequestHeaders();
|
||||||
}
|
}
|
||||||
@@ -774,6 +790,24 @@ cout << "testing proxy close" << endl;
|
|||||||
SG_CHECK_EQUAL(tr2->responseBytesReceived(), strlen(BODY1));
|
SG_CHECK_EQUAL(tr2->responseBytesReceived(), strlen(BODY1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cout << "redirect test" << endl;
|
||||||
|
// redirect test
|
||||||
|
testServer.disconnectAll();
|
||||||
|
cl.clearAllConnections();
|
||||||
|
|
||||||
|
TestRequest* tr = new TestRequest("http://localhost:2000/test_redirect");
|
||||||
|
HTTP::Request_ptr own(tr);
|
||||||
|
cl.makeRequest(tr);
|
||||||
|
|
||||||
|
waitForComplete(&cl, tr);
|
||||||
|
SG_CHECK_EQUAL(tr->responseCode(), 200);
|
||||||
|
SG_CHECK_EQUAL(tr->responseReason(), string("OK"));
|
||||||
|
SG_CHECK_EQUAL(tr->responseLength(), strlen(BODY1));
|
||||||
|
SG_CHECK_EQUAL(tr->responseBytesReceived(), strlen(BODY1));
|
||||||
|
SG_CHECK_EQUAL(tr->bodyData, string(BODY1));
|
||||||
|
}
|
||||||
|
|
||||||
cout << "all tests passed ok" << endl;
|
cout << "all tests passed ok" << endl;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ public:
|
|||||||
|
|
||||||
virtual ~TestServerChannel()
|
virtual ~TestServerChannel()
|
||||||
{
|
{
|
||||||
std::cerr << "dtor test server channel" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void collectIncomingData(const char* s, int n)
|
virtual void collectIncomingData(const char* s, int n)
|
||||||
@@ -139,8 +138,8 @@ public:
|
|||||||
|
|
||||||
void sendErrorResponse(int code, bool close, std::string content)
|
void sendErrorResponse(int code, bool close, std::string content)
|
||||||
{
|
{
|
||||||
std::cerr << "sending error " << code << " for " << path << std::endl;
|
// std::cerr << "sending error " << code << " for " << path << std::endl;
|
||||||
std::cerr << "\tcontent:" << content << std::endl;
|
// std::cerr << "\tcontent:" << content << std::endl;
|
||||||
|
|
||||||
std::stringstream headerData;
|
std::stringstream headerData;
|
||||||
headerData << "HTTP/1.1 " << code << " " << reasonForCode(code) << "\r\n";
|
headerData << "HTTP/1.1 " << code << " " << reasonForCode(code) << "\r\n";
|
||||||
@@ -168,7 +167,6 @@ public:
|
|||||||
|
|
||||||
virtual void handleClose (void)
|
virtual void handleClose (void)
|
||||||
{
|
{
|
||||||
std::cerr << "channel close" << std::endl;
|
|
||||||
NetBufferChannel::handleClose();
|
NetBufferChannel::handleClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ inline simd4_t<T,N> operator*(simd4_t<T,N> v, T f) {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_SIMD
|
#ifdef ENABLE_SIMD_CODE
|
||||||
|
|
||||||
# ifdef __SSE__
|
# ifdef __SSE__
|
||||||
namespace simd4
|
namespace simd4
|
||||||
@@ -1305,7 +1305,7 @@ inline simd4_t<int,N> max(simd4_t<int,N> v1, const simd4_t<int,N>& v2) {
|
|||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif /* ENABLE_SIMD */
|
#endif /* ENABLE_SIMD_CODE */
|
||||||
|
|
||||||
#endif /* __SIMD_H__ */
|
#endif /* __SIMD_H__ */
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ inline simd4x4_t<T,N> operator*(const simd4x4_t<T,N>& m1, const simd4x4_t<T,N>&
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_SIMD
|
#ifdef ENABLE_SIMD_CODE
|
||||||
|
|
||||||
# ifdef __SSE__
|
# ifdef __SSE__
|
||||||
template<>
|
template<>
|
||||||
@@ -1191,7 +1191,7 @@ inline simd4_t<int,3> transform<int>(const simd4x4_t<int,4>& m, const simd4_t<in
|
|||||||
} /* namespace simd4x */
|
} /* namespace simd4x */
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif /* ENABLE_SIMD */
|
#endif /* ENABLE_SIMD_CODE */
|
||||||
|
|
||||||
#endif /* __SIMD4X4_H__ */
|
#endif /* __SIMD4X4_H__ */
|
||||||
|
|
||||||
|
|||||||
+6
-3
@@ -302,15 +302,18 @@ static char* dosprintf(char* f, ...)
|
|||||||
char* buf;
|
char* buf;
|
||||||
va_list va;
|
va_list va;
|
||||||
int olen, len = 16;
|
int olen, len = 16;
|
||||||
|
va_start(va, f);
|
||||||
while(1) {
|
while(1) {
|
||||||
buf = naAlloc(len);
|
buf = naAlloc(len);
|
||||||
va_start(va, f);
|
va_list vaCopy;
|
||||||
olen = vsnprintf(buf, len, f, va);
|
va_copy(vaCopy, va);
|
||||||
|
olen = vsnprintf(buf, len, f, vaCopy);
|
||||||
if(olen >= 0 && olen < len) {
|
if(olen >= 0 && olen < len) {
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
va_end(vaCopy);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
va_end(va);
|
va_end(vaCopy);
|
||||||
naFree(buf);
|
naFree(buf);
|
||||||
len *= 2;
|
len *= 2;
|
||||||
}
|
}
|
||||||
|
|||||||
+68
-18
@@ -82,16 +82,26 @@ bool checkVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string redirectUrlForVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
SGPropertyNode_ptr alternateForVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
||||||
{
|
{
|
||||||
for (SGPropertyNode* v : props->getChildren("alternate-version")) {
|
for (auto v : props->getChildren("alternate-version")) {
|
||||||
std::string s(v->getStringValue("version"));
|
for (auto versionSpec : v->getChildren("version")) {
|
||||||
if (checkVersionString(aVersion, s)) {
|
if (checkVersionString(aVersion, versionSpec->getStringValue())) {
|
||||||
return v->getStringValue("url");;
|
return v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::string();
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string redirectUrlForVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
||||||
|
{
|
||||||
|
auto node = alternateForVersion(aVersion, props);
|
||||||
|
if (node)
|
||||||
|
return node->getStringValue("url");;
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -139,19 +149,15 @@ protected:
|
|||||||
|
|
||||||
std::string ver(m_owner->root()->applicationVersion());
|
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() << ", but version required " << ver);
|
|
||||||
|
|
||||||
// check for a version redirect entry
|
// check for a version redirect entry
|
||||||
std::string url = redirectUrlForVersion(ver, props);
|
auto alt = alternateForVersion(ver, props);
|
||||||
if (!url.empty()) {
|
if (alt) {
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "redirecting from " << m_owner->url() <<
|
SG_LOG(SG_GENERAL, SG_WARN, "have alternate version of package at:"
|
||||||
" to \n\t" << url);
|
<< alt->getStringValue("url"));
|
||||||
|
m_owner->processAlternate(alt);
|
||||||
// update the URL and kick off a new request
|
|
||||||
m_owner->setUrl(url);
|
|
||||||
Downloader* dl = new Downloader(m_owner, url);
|
|
||||||
m_owner->root()->makeHTTPRequest(dl);
|
|
||||||
} else {
|
} else {
|
||||||
|
SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url()
|
||||||
|
<< ", but app version " << ver << " is not comaptible");
|
||||||
m_owner->refreshComplete(Delegate::FAIL_VERSION);
|
m_owner->refreshComplete(Delegate::FAIL_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +234,7 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
|
|||||||
|
|
||||||
bool versionCheckOk = checkVersion(aRoot->applicationVersion(), props);
|
bool versionCheckOk = checkVersion(aRoot->applicationVersion(), props);
|
||||||
if (!versionCheckOk) {
|
if (!versionCheckOk) {
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "catalog at:" << aPath << " failed version check: need version: "
|
SG_LOG(SG_GENERAL, SG_INFO, "catalog at:" << aPath << " failed version check: app version: "
|
||||||
<< aRoot->applicationVersion());
|
<< aRoot->applicationVersion());
|
||||||
// keep the catalog but mark it as needing an update
|
// keep the catalog but mark it as needing an update
|
||||||
} else {
|
} else {
|
||||||
@@ -598,6 +604,50 @@ bool Catalog::isEnabled() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Catalog::processAlternate(SGPropertyNode_ptr alt)
|
||||||
|
{
|
||||||
|
std::string altId;
|
||||||
|
const auto idPtr = alt->getStringValue("id");
|
||||||
|
if (idPtr) {
|
||||||
|
altId = std::string(idPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string altUrl;
|
||||||
|
if (alt->getStringValue("url")) {
|
||||||
|
altUrl = std::string(alt->getStringValue("url"));
|
||||||
|
}
|
||||||
|
|
||||||
|
CatalogRef existing;
|
||||||
|
if (!altId.empty()) {
|
||||||
|
existing = root()->getCatalogById(altId);
|
||||||
|
} else {
|
||||||
|
existing = root()->getCatalogByUrl(altUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existing && (existing != this)) {
|
||||||
|
// we already have the alternate, so just go quiet here
|
||||||
|
changeStatus(Delegate::FAIL_VERSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have an alternate ID, and it's differnt from our ID, so let's
|
||||||
|
// define a new catalog
|
||||||
|
if (!altId.empty()) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_INFO, "Adding new catalog:" << altId << " as version alternate for " << id());
|
||||||
|
// new catalog being added
|
||||||
|
createFromUrl(root(), altUrl);
|
||||||
|
|
||||||
|
// and we can go idle now
|
||||||
|
changeStatus(Delegate::FAIL_VERSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SG_LOG(SG_GENERAL, SG_INFO, "Migrating catalog " << id() << " to new URL:" << altUrl);
|
||||||
|
setUrl(altUrl);
|
||||||
|
Downloader* dl = new Downloader(this, altUrl);
|
||||||
|
root()->makeHTTPRequest(dl);
|
||||||
|
}
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|
||||||
} // of namespace simgear
|
} // of namespace simgear
|
||||||
|
|||||||
@@ -179,6 +179,8 @@ private:
|
|||||||
|
|
||||||
void changeStatus(Delegate::StatusCode newStatus);
|
void changeStatus(Delegate::StatusCode newStatus);
|
||||||
|
|
||||||
|
void processAlternate(SGPropertyNode_ptr alt);
|
||||||
|
|
||||||
Root* m_root;
|
Root* m_root;
|
||||||
SGPropertyNode_ptr m_props;
|
SGPropertyNode_ptr m_props;
|
||||||
SGPath m_installRoot;
|
SGPath m_installRoot;
|
||||||
|
|||||||
@@ -723,6 +723,130 @@ void testVersionMigrate(HTTP::Client* cl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testVersionMigrateToId(HTTP::Client* cl)
|
||||||
|
{
|
||||||
|
global_catalogVersion = 2; // version which has migration info
|
||||||
|
SGPath rootPath(simgear::Dir::current().path());
|
||||||
|
rootPath.append("cat_migrate_version_id");
|
||||||
|
simgear::Dir pd(rootPath);
|
||||||
|
pd.removeChildren();
|
||||||
|
|
||||||
|
{
|
||||||
|
pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
|
||||||
|
root->setHTTPClient(cl);
|
||||||
|
|
||||||
|
pkg::CatalogRef c = pkg::Catalog::createFromUrl(root.ptr(), "http://localhost:2000/catalogTest1/catalog.xml");
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_VERIFY(c->isEnabled());
|
||||||
|
|
||||||
|
// install a package
|
||||||
|
pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.b737-NG");
|
||||||
|
SG_CHECK_EQUAL(p1->id(), "b737-NG");
|
||||||
|
pkg::InstallRef ins = p1->install();
|
||||||
|
SG_VERIFY(ins->isQueued());
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_VERIFY(p1->isInstalled());
|
||||||
|
}
|
||||||
|
|
||||||
|
// change version to an alternate one
|
||||||
|
{
|
||||||
|
pkg::RootRef root(new pkg::Root(rootPath, "7.5"));
|
||||||
|
root->setHTTPClient(cl);
|
||||||
|
|
||||||
|
// this should cause the alternate package to be loaded
|
||||||
|
root->refresh(true);
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
|
||||||
|
pkg::CatalogRef cat = root->getCatalogById("org.flightgear.test.catalog1");
|
||||||
|
SG_VERIFY(!cat->isEnabled());
|
||||||
|
SG_CHECK_EQUAL(cat->status(), pkg::Delegate::FAIL_VERSION);
|
||||||
|
SG_CHECK_EQUAL(cat->id(), "org.flightgear.test.catalog1");
|
||||||
|
SG_CHECK_EQUAL(cat->url(), "http://localhost:2000/catalogTest1/catalog.xml");
|
||||||
|
|
||||||
|
auto enabledCats = root->catalogs();
|
||||||
|
auto it = std::find(enabledCats.begin(), enabledCats.end(), cat);
|
||||||
|
SG_VERIFY(it == enabledCats.end());
|
||||||
|
|
||||||
|
// ensure existing package is still installed
|
||||||
|
pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.b737-NG");
|
||||||
|
SG_VERIFY(p1 != pkg::PackageRef());
|
||||||
|
SG_CHECK_EQUAL(p1->id(), "b737-NG");
|
||||||
|
|
||||||
|
// but not listed
|
||||||
|
auto packs = root->allPackages();
|
||||||
|
auto k = std::find(packs.begin(), packs.end(), p1);
|
||||||
|
SG_VERIFY(k == packs.end());
|
||||||
|
|
||||||
|
// check the new catalog
|
||||||
|
auto altCat = root->getCatalogById("org.flightgear.test.catalog-alt");
|
||||||
|
SG_VERIFY(altCat->isEnabled());
|
||||||
|
SG_CHECK_EQUAL(altCat->status(), pkg::Delegate::STATUS_REFRESHED);
|
||||||
|
SG_CHECK_EQUAL(altCat->id(), "org.flightgear.test.catalog-alt");
|
||||||
|
SG_CHECK_EQUAL(altCat->url(), "http://localhost:2000/catalogTest1/catalog-alt.xml");
|
||||||
|
|
||||||
|
it = std::find(enabledCats.begin(), enabledCats.end(), altCat);
|
||||||
|
SG_VERIFY(it != enabledCats.end());
|
||||||
|
|
||||||
|
// install a parallel package from the new catalog
|
||||||
|
pkg::PackageRef p2 = root->getPackageById("org.flightgear.test.catalog-alt.b737-NG");
|
||||||
|
SG_CHECK_EQUAL(p2->id(), "b737-NG");
|
||||||
|
pkg::InstallRef ins = p2->install();
|
||||||
|
SG_VERIFY(ins->isQueued());
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_VERIFY(p2->isInstalled());
|
||||||
|
|
||||||
|
// do a non-scoped lookup, we should get the new one
|
||||||
|
pkg::PackageRef p3 = root->getPackageById("b737-NG");
|
||||||
|
SG_CHECK_EQUAL(p2, p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test that re-init-ing doesn't mirgate again
|
||||||
|
{
|
||||||
|
pkg::RootRef root(new pkg::Root(rootPath, "7.5"));
|
||||||
|
root->setHTTPClient(cl);
|
||||||
|
|
||||||
|
root->refresh(true);
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
|
||||||
|
pkg::CatalogRef cat = root->getCatalogById("org.flightgear.test.catalog1");
|
||||||
|
SG_VERIFY(!cat->isEnabled());
|
||||||
|
SG_CHECK_EQUAL(cat->status(), pkg::Delegate::FAIL_VERSION);
|
||||||
|
|
||||||
|
auto altCat = root->getCatalogById("org.flightgear.test.catalog-alt");
|
||||||
|
SG_VERIFY(altCat->isEnabled());
|
||||||
|
|
||||||
|
auto packs = root->allPackages();
|
||||||
|
SG_CHECK_EQUAL(packs.size(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// and now switch back to the older version
|
||||||
|
{
|
||||||
|
pkg::RootRef root(new pkg::Root(rootPath, "8.1.0"));
|
||||||
|
root->setHTTPClient(cl);
|
||||||
|
root->refresh(true);
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
|
||||||
|
pkg::CatalogRef cat = root->getCatalogById("org.flightgear.test.catalog1");
|
||||||
|
SG_VERIFY(cat->isEnabled());
|
||||||
|
SG_CHECK_EQUAL(cat->status(), pkg::Delegate::STATUS_REFRESHED);
|
||||||
|
|
||||||
|
auto altCat = root->getCatalogById("org.flightgear.test.catalog-alt");
|
||||||
|
SG_VERIFY(!altCat->isEnabled());
|
||||||
|
|
||||||
|
// verify the original aircraft is still installed and available
|
||||||
|
pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.b737-NG");
|
||||||
|
SG_VERIFY(p1 != pkg::PackageRef());
|
||||||
|
SG_CHECK_EQUAL(p1->id(), "b737-NG");
|
||||||
|
SG_VERIFY(p1->isInstalled());
|
||||||
|
|
||||||
|
// verify the alt package is still installed,
|
||||||
|
pkg::PackageRef p2 = root->getPackageById("org.flightgear.test.catalog-alt.b737-NG");
|
||||||
|
SG_VERIFY(p2 != pkg::PackageRef());
|
||||||
|
SG_CHECK_EQUAL(p2->id(), "b737-NG");
|
||||||
|
SG_VERIFY(p2->isInstalled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void testOfflineMode(HTTP::Client* cl)
|
void testOfflineMode(HTTP::Client* cl)
|
||||||
{
|
{
|
||||||
global_catalogVersion = 0;
|
global_catalogVersion = 0;
|
||||||
@@ -972,6 +1096,8 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
removeInvalidCatalog(&cl);
|
removeInvalidCatalog(&cl);
|
||||||
|
|
||||||
|
testVersionMigrateToId(&cl);
|
||||||
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "Successfully passed all tests!");
|
SG_LOG(SG_GENERAL, SG_INFO, "Successfully passed all tests!");
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-19
@@ -18,8 +18,8 @@
|
|||||||
#include <simgear_config.h>
|
#include <simgear_config.h>
|
||||||
#include <simgear/package/Install.hxx>
|
#include <simgear/package/Install.hxx>
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <simgear/package/unzip.h>
|
#include <simgear/package/unzip.h>
|
||||||
#include <simgear/package/md5.h>
|
#include <simgear/package/md5.h>
|
||||||
@@ -43,20 +43,16 @@ namespace pkg {
|
|||||||
class Install::PackageArchiveDownloader : public HTTP::Request
|
class Install::PackageArchiveDownloader : public HTTP::Request
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PackageArchiveDownloader(InstallRef aOwner) :
|
PackageArchiveDownloader(InstallRef aOwner, const string_list& urls) :
|
||||||
HTTP::Request("" /* dummy URL */),
|
HTTP::Request("" /* dummy URL */),
|
||||||
m_owner(aOwner)
|
m_owner(aOwner)
|
||||||
{
|
{
|
||||||
m_urls = m_owner->package()->downloadUrls();
|
m_urls = urls;
|
||||||
if (m_urls.empty()) {
|
if (urls.empty()) {
|
||||||
throw sg_exception("no package download URLs");
|
m_urls = m_owner->package()->downloadUrls();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (m_owner->package()->properties()->hasChild("archive-type")) {
|
selectMirrorUrl();
|
||||||
// setArchiveTypeFromExtension(m_owner->package()->properties()->getStringValue("archive-type"));
|
|
||||||
//}
|
|
||||||
|
|
||||||
// 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("_extract_" + aOwner->package()->md5());
|
||||||
@@ -93,12 +89,19 @@ public:
|
|||||||
return (m_downloaded * 100) / responseLength();
|
return (m_downloaded * 100) / responseLength();
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
virtual std::string url() const
|
void selectMirrorUrl()
|
||||||
{
|
{
|
||||||
return m_urls.front();
|
const int randomizedIndex = rand() % m_urls.size();
|
||||||
|
m_activeURL = m_urls.at(randomizedIndex);
|
||||||
|
m_urls.erase(m_urls.begin() + randomizedIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void responseHeadersComplete()
|
virtual std::string url() const override
|
||||||
|
{
|
||||||
|
return m_activeURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void responseHeadersComplete() override
|
||||||
{
|
{
|
||||||
Request::responseHeadersComplete();
|
Request::responseHeadersComplete();
|
||||||
|
|
||||||
@@ -110,7 +113,7 @@ protected:
|
|||||||
SG_MD5Init(&m_md5);
|
SG_MD5Init(&m_md5);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void gotBodyData(const char* s, int n)
|
void gotBodyData(const char* s, int n) override
|
||||||
{
|
{
|
||||||
const uint8_t* ubytes = (uint8_t*) s;
|
const uint8_t* ubytes = (uint8_t*) s;
|
||||||
SG_MD5Update(&m_md5, ubytes, n);
|
SG_MD5Update(&m_md5, ubytes, n);
|
||||||
@@ -119,10 +122,10 @@ protected:
|
|||||||
m_extractor->extractBytes(ubytes, n);
|
m_extractor->extractBytes(ubytes, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDone()
|
void onDone() override
|
||||||
{
|
{
|
||||||
if (responseCode() != 200) {
|
if (responseCode() != 200) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "download failure:" << responseCode() <<
|
SG_LOG(SG_GENERAL, SG_WARN, "download failure:" << responseCode() <<
|
||||||
"\n\t" << url());
|
"\n\t" << url());
|
||||||
Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
|
Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
|
||||||
if (responseCode() == 404) {
|
if (responseCode() == 404) {
|
||||||
@@ -139,7 +142,7 @@ protected:
|
|||||||
strutils::encodeHex(digest, MD5_DIGEST_LENGTH);
|
strutils::encodeHex(digest, MD5_DIGEST_LENGTH);
|
||||||
|
|
||||||
if (hex_md5 != m_owner->package()->md5()) {
|
if (hex_md5 != m_owner->package()->md5()) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "md5 verification failed:\n"
|
SG_LOG(SG_GENERAL, SG_WARN, "md5 verification failed:\n"
|
||||||
<< "\t" << hex_md5 << "\n\t"
|
<< "\t" << hex_md5 << "\n\t"
|
||||||
<< m_owner->package()->md5() << "\n\t"
|
<< m_owner->package()->md5() << "\n\t"
|
||||||
<< "downloading from:" << url());
|
<< "downloading from:" << url());
|
||||||
@@ -194,7 +197,7 @@ protected:
|
|||||||
m_owner->installResult(Delegate::STATUS_SUCCESS);
|
m_owner->installResult(Delegate::STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onFail()
|
void onFail() override
|
||||||
{
|
{
|
||||||
if (responseCode() == -1) {
|
if (responseCode() == -1) {
|
||||||
doFailure(Delegate::USER_CANCELLED);
|
doFailure(Delegate::USER_CANCELLED);
|
||||||
@@ -211,6 +214,18 @@ private:
|
|||||||
dir.remove(true /* recursive */);
|
dir.remove(true /* recursive */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto canRetry = (aReason == Delegate::FAIL_NOT_FOUND) || (aReason == Delegate::FAIL_DOWNLOAD);
|
||||||
|
if (canRetry && !m_urls.empty()) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_WARN, "archive download failed from:" << m_activeURL
|
||||||
|
<< "\n\twill retry with next mirror");
|
||||||
|
// becuase selectMirrorUrl erased the active URL from m_urls,
|
||||||
|
// this new request will select one of the other mirrors
|
||||||
|
auto retryDownload = new PackageArchiveDownloader(m_owner, m_urls);
|
||||||
|
m_owner->m_download.reset(retryDownload);
|
||||||
|
m_owner->package()->catalog()->root()->makeHTTPRequest(retryDownload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO - try other mirrors
|
// TODO - try other mirrors
|
||||||
m_owner->m_download.reset(); // ensure we get cleaned up
|
m_owner->m_download.reset(); // ensure we get cleaned up
|
||||||
m_owner->installResult(aReason);
|
m_owner->installResult(aReason);
|
||||||
@@ -218,6 +233,7 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
InstallRef m_owner;
|
InstallRef m_owner;
|
||||||
|
string m_activeURL;
|
||||||
string_list m_urls;
|
string_list m_urls;
|
||||||
SG_MD5_CTX m_md5;
|
SG_MD5_CTX m_md5;
|
||||||
SGPath m_extractPath;
|
SGPath m_extractPath;
|
||||||
@@ -281,7 +297,7 @@ void Install::startUpdate()
|
|||||||
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);
|
||||||
}
|
}
|
||||||
@@ -341,6 +357,7 @@ void Install::cancelDownload()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_package->catalog()->root()->cancelDownload(this);
|
m_package->catalog()->root()->cancelDownload(this);
|
||||||
|
m_download.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPath Install::primarySetPath() const
|
SGPath Install::primarySetPath() const
|
||||||
|
|||||||
@@ -414,7 +414,7 @@ Root::Root(const SGPath& aPath, const std::string& aVersion) :
|
|||||||
if (cat && cat->isEnabled()) {
|
if (cat && cat->isEnabled()) {
|
||||||
d->catalogs.insert({cat->id(), cat});
|
d->catalogs.insert({cat->id(), cat});
|
||||||
} else if (cat) {
|
} else if (cat) {
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "Package-Root init: catalog is disabled: " << cat->id());
|
SG_LOG(SG_GENERAL, SG_DEBUG, "Package-Root init: catalog is disabled: " << cat->id());
|
||||||
}
|
}
|
||||||
} // of child directories iteration
|
} // of child directories iteration
|
||||||
}
|
}
|
||||||
@@ -450,6 +450,17 @@ CatalogRef Root::getCatalogById(const std::string& aId) const
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CatalogRef Root::getCatalogByUrl(const std::string& aUrl) const
|
||||||
|
{
|
||||||
|
auto it = std::find_if(d->catalogs.begin(), d->catalogs.end(),
|
||||||
|
[aUrl](const CatalogDict::value_type& v)
|
||||||
|
{ return (v.second->url() == aUrl); });
|
||||||
|
if (it == d->catalogs.end())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
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('.');
|
||||||
@@ -595,6 +606,12 @@ void Root::scheduleToUpdate(InstallRef aInstall)
|
|||||||
throw sg_exception("missing argument to scheduleToUpdate");
|
throw sg_exception("missing argument to scheduleToUpdate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto it = std::find(d->updateDeque.begin(), d->updateDeque.end(), aInstall);
|
||||||
|
if (it != d->updateDeque.end()) {
|
||||||
|
// already scheduled to update
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PackageList deps = aInstall->package()->dependencies();
|
PackageList deps = aInstall->package()->dependencies();
|
||||||
for (Package* dep : deps) {
|
for (Package* dep : deps) {
|
||||||
// will internally schedule for update if required
|
// will internally schedule for update if required
|
||||||
|
|||||||
@@ -132,6 +132,8 @@ public:
|
|||||||
|
|
||||||
CatalogRef getCatalogById(const std::string& aId) const;
|
CatalogRef getCatalogById(const std::string& aId) const;
|
||||||
|
|
||||||
|
CatalogRef getCatalogByUrl(const std::string& aUrl) const;
|
||||||
|
|
||||||
void scheduleToUpdate(InstallRef aInstall);
|
void scheduleToUpdate(InstallRef aInstall);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<PropertyList>
|
||||||
|
<id>org.flightgear.test.catalog-alt</id>
|
||||||
|
<description>Alternate test catalog</description>
|
||||||
|
<url>http://localhost:2000/catalogTest1/catalog-alt.xml</url>
|
||||||
|
<catalog-version>4</catalog-version>
|
||||||
|
|
||||||
|
<version>7.*</version>
|
||||||
|
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>alpha</id>
|
||||||
|
<name>Alpha package</name>
|
||||||
|
<revision type="int">9</revision>
|
||||||
|
<file-size-bytes type="int">593</file-size-bytes>
|
||||||
|
|
||||||
|
<md5>a469c4b837f0521db48616cfe65ac1ea</md5>
|
||||||
|
<url>http://localhost:2000/catalogTest1/alpha.zip</url>
|
||||||
|
|
||||||
|
<dir>alpha</dir>
|
||||||
|
</package>
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>c172p</id>
|
||||||
|
<name>Cessna 172-P</name>
|
||||||
|
<dir>c172p</dir>
|
||||||
|
<description>A plane made by Cessna</description>
|
||||||
|
<revision type="int">42</revision>
|
||||||
|
<file-size-bytes type="int">860</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>
|
||||||
|
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>exterior</type>
|
||||||
|
<path>thumb-exterior.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-exterior.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<path>thumb-something.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-something.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172p-2d-panel</id>
|
||||||
|
<name>C172 with 2d panel only</name>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172p-floats</id>
|
||||||
|
<name>C172 with floats</name>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>exterior</type>
|
||||||
|
<path>thumb-exterior-floats.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-exterior-floats.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172p-skis</id>
|
||||||
|
<name>C172 with skis</name>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>exterior</type>
|
||||||
|
<path>thumb-exterior-skis.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-exterior-skis.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<md5>ec0e2ffdf98d6a5c05c77445e5447ff5</md5>
|
||||||
|
<url>http://localhost:2000/catalogTest1/c172p.zip</url>
|
||||||
|
|
||||||
|
</package>
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>b737-NG</id>
|
||||||
|
<name>Boeing 737 NG</name>
|
||||||
|
<dir>b737NG</dir>
|
||||||
|
<description>A popular twin-engined narrow body jet</description>
|
||||||
|
<revision type="int">112</revision>
|
||||||
|
<file-size-bytes type="int">860</file-size-bytes>
|
||||||
|
|
||||||
|
<tag>boeing</tag>
|
||||||
|
<tag>jet</tag>
|
||||||
|
<tag>ifr</tag>
|
||||||
|
|
||||||
|
<rating>
|
||||||
|
<FDM type="int">5</FDM>
|
||||||
|
<systems type="int">5</systems>
|
||||||
|
<model type="int">4</model>
|
||||||
|
<cockpit type="int">4</cockpit>
|
||||||
|
</rating>
|
||||||
|
|
||||||
|
<md5>a94ca5704f305b90767f40617d194ed6</md5>
|
||||||
|
<url>http://localhost:2000/catalogTest1/b737.tar.gz</url>
|
||||||
|
|
||||||
|
</package>
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>dc3</id>
|
||||||
|
<name>DC-3</name>
|
||||||
|
<revision type="int">9</revision>
|
||||||
|
<file-size-bytes type="int">593</file-size-bytes>
|
||||||
|
|
||||||
|
<md5>a469c4b837f0521db48616cfe65ac1ea</md5>
|
||||||
|
<url>http://localhost:2000/catalogTest1/alpha.zip</url>
|
||||||
|
|
||||||
|
<dir>dc3</dir>
|
||||||
|
</package>
|
||||||
|
</PropertyList>
|
||||||
@@ -15,6 +15,12 @@
|
|||||||
<url>http://localhost:2000/catalogTest1/catalog-v10.xml</url>
|
<url>http://localhost:2000/catalogTest1/catalog-v10.xml</url>
|
||||||
</alternate-version>
|
</alternate-version>
|
||||||
|
|
||||||
|
<alternate-version>
|
||||||
|
<version>7.*</version>
|
||||||
|
<id>org.flightgear.test.catalog-alt</id>
|
||||||
|
<url>http://localhost:2000/catalogTest1/catalog-alt.xml</url>
|
||||||
|
</alternate-version>
|
||||||
|
|
||||||
<package>
|
<package>
|
||||||
<id>alpha</id>
|
<id>alpha</id>
|
||||||
<name>Alpha package</name>
|
<name>Alpha package</name>
|
||||||
|
|||||||
@@ -257,7 +257,8 @@ bool setAttrs(const TexTuple& attrs, Texture* tex,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
osgDB::ReaderWriter::ReadResult result;
|
osgDB::ReaderWriter::ReadResult result;
|
||||||
result = osgDB::readImageFile(imageName, options);
|
|
||||||
|
result = osgDB::readRefImageFile(imageName, options);
|
||||||
osg::ref_ptr<osg::Image> image;
|
osg::ref_ptr<osg::Image> image;
|
||||||
if (result.success())
|
if (result.success())
|
||||||
image = result.getImage();
|
image = result.getImage();
|
||||||
@@ -590,27 +591,27 @@ Texture* CubeMapBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*
|
|||||||
osg::Image* image = result.getImage();
|
osg::Image* image = result.getImage();
|
||||||
cubeTexture->setImage(TextureCubeMap::POSITIVE_X, image);
|
cubeTexture->setImage(TextureCubeMap::POSITIVE_X, image);
|
||||||
}
|
}
|
||||||
result = osgDB::readImageFile(_tuple.get<1>(), options);
|
result = osgDB::readRefImageFile(_tuple.get<1>(), options);
|
||||||
if(result.success()) {
|
if(result.success()) {
|
||||||
osg::Image* image = result.getImage();
|
osg::Image* image = result.getImage();
|
||||||
cubeTexture->setImage(TextureCubeMap::NEGATIVE_X, image);
|
cubeTexture->setImage(TextureCubeMap::NEGATIVE_X, image);
|
||||||
}
|
}
|
||||||
result = osgDB::readImageFile(_tuple.get<2>(), options);
|
result = osgDB::readRefImageFile(_tuple.get<2>(), options);
|
||||||
if(result.success()) {
|
if(result.success()) {
|
||||||
osg::Image* image = result.getImage();
|
osg::Image* image = result.getImage();
|
||||||
cubeTexture->setImage(TextureCubeMap::POSITIVE_Y, image);
|
cubeTexture->setImage(TextureCubeMap::POSITIVE_Y, image);
|
||||||
}
|
}
|
||||||
result = osgDB::readImageFile(_tuple.get<3>(), options);
|
result = osgDB::readRefImageFile(_tuple.get<3>(), options);
|
||||||
if(result.success()) {
|
if(result.success()) {
|
||||||
osg::Image* image = result.getImage();
|
osg::Image* image = result.getImage();
|
||||||
cubeTexture->setImage(TextureCubeMap::NEGATIVE_Y, image);
|
cubeTexture->setImage(TextureCubeMap::NEGATIVE_Y, image);
|
||||||
}
|
}
|
||||||
result = osgDB::readImageFile(_tuple.get<4>(), options);
|
result = osgDB::readRefImageFile(_tuple.get<4>(), options);
|
||||||
if(result.success()) {
|
if(result.success()) {
|
||||||
osg::Image* image = result.getImage();
|
osg::Image* image = result.getImage();
|
||||||
cubeTexture->setImage(TextureCubeMap::POSITIVE_Z, image);
|
cubeTexture->setImage(TextureCubeMap::POSITIVE_Z, image);
|
||||||
}
|
}
|
||||||
result = osgDB::readImageFile(_tuple.get<5>(), options);
|
result = osgDB::readRefImageFile(_tuple.get<5>(), options);
|
||||||
if(result.success()) {
|
if(result.success()) {
|
||||||
osg::Image* image = result.getImage();
|
osg::Image* image = result.getImage();
|
||||||
cubeTexture->setImage(TextureCubeMap::NEGATIVE_Z, image);
|
cubeTexture->setImage(TextureCubeMap::NEGATIVE_Z, image);
|
||||||
@@ -634,7 +635,7 @@ Texture* CubeMapBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*
|
|||||||
return cubeTexture.release();
|
return cubeTexture.release();
|
||||||
|
|
||||||
osgDB::ReaderWriter::ReadResult result;
|
osgDB::ReaderWriter::ReadResult result;
|
||||||
result = osgDB::readImageFile(texname, options);
|
result = osgDB::readRefImageFile(texname, options);
|
||||||
if(result.success()) {
|
if(result.success()) {
|
||||||
osg::Image* image = result.getImage();
|
osg::Image* image = result.getImage();
|
||||||
image->flipVertical(); // Seems like the image coordinates are somewhat funny, flip to get better ones
|
image->flipVertical(); // Seems like the image coordinates are somewhat funny, flip to get better ones
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osg::Image* image = osgDB::readImageFile(fullMaskPath, options);
|
osg::Image* image = osgDB::readRefImageFile(fullMaskPath, options);
|
||||||
if (image && image->valid())
|
if (image && image->valid())
|
||||||
{
|
{
|
||||||
Texture2DRef object_mask = new osg::Texture2D;
|
Texture2DRef object_mask = new osg::Texture2D;
|
||||||
|
|||||||
@@ -280,19 +280,21 @@ ModelRegistry::readImage(const string& fileName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
osg::Node* DefaultCachePolicy::find(const string& fileName,
|
osg::ref_ptr<osg::Node> DefaultCachePolicy::find(const string& fileName, const Options* opt)
|
||||||
const Options* opt)
|
|
||||||
{
|
{
|
||||||
Registry* registry = Registry::instance();
|
Registry* registry = Registry::instance();
|
||||||
osg::Node* cached
|
#if OSG_VERSION_LESS_THAN(3,4,0)
|
||||||
= dynamic_cast<Node*>(registry->getFromObjectCache(fileName));
|
osg::ref_ptr<osg::Object> cachedObject = registry->getFromObjectCache(fileName);
|
||||||
if (cached)
|
#else
|
||||||
SG_LOG(SG_IO, SG_BULK, "Got cached model \""
|
osg::ref_ptr<osg::Object> cachedObject = registry->getRefFromObjectCache(fileName);
|
||||||
<< fileName << "\"");
|
#endif
|
||||||
|
|
||||||
|
ref_ptr<osg::Node> cachedNode = dynamic_cast<osg::Node*>(cachedObject.get());
|
||||||
|
if (cachedNode.valid())
|
||||||
|
SG_LOG(SG_IO, SG_BULK, "Got cached model \"" << fileName << "\"");
|
||||||
else
|
else
|
||||||
SG_LOG(SG_IO, SG_BULK, "Reading model \""
|
SG_LOG(SG_IO, SG_BULK, "Reading model \"" << fileName << "\"");
|
||||||
<< fileName << "\"");
|
return cachedNode;
|
||||||
return cached;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultCachePolicy::addToCache(const string& fileName,
|
void DefaultCachePolicy::addToCache(const string& fileName,
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ struct DefaultProcessPolicy {
|
|||||||
|
|
||||||
struct DefaultCachePolicy {
|
struct DefaultCachePolicy {
|
||||||
DefaultCachePolicy(const std::string& extension) {}
|
DefaultCachePolicy(const std::string& extension) {}
|
||||||
osg::Node* find(const std::string& fileName,
|
osg::ref_ptr<osg::Node> find(const std::string& fileName,
|
||||||
const osgDB::Options* opt);
|
const osgDB::Options* opt);
|
||||||
void addToCache(const std::string& filename, osg::Node* node);
|
void addToCache(const std::string& filename, osg::Node* node);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ sgLoad3DModel_internal(const SGPath& path,
|
|||||||
|
|
||||||
options->setDatabasePath(texturepath.local8BitStr());
|
options->setDatabasePath(texturepath.local8BitStr());
|
||||||
osgDB::ReaderWriter::ReadResult modelResult;
|
osgDB::ReaderWriter::ReadResult modelResult;
|
||||||
modelResult = osgDB::readNodeFile(modelpath.local8BitStr(), options.get());
|
modelResult = osgDB::readRefNodeFile(modelpath.local8BitStr(), options.get());
|
||||||
if (!modelResult.validNode())
|
if (!modelResult.validNode())
|
||||||
throw sg_io_exception("Failed to load 3D model:" + modelResult.message(),
|
throw sg_io_exception("Failed to load 3D model:" + modelResult.message(),
|
||||||
modelpath);
|
modelpath);
|
||||||
@@ -481,7 +481,7 @@ sgLoad3DModel_internal(const SGPath& path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbOptions->getPluginStringData("SimGear::PARTICLESYSTEM") != "OFF") {
|
if (GlobalParticleCallback::getEnabled()){//dbOptions->getPluginStringData("SimGear::PARTICLESYSTEM") != "OFF") {
|
||||||
std::vector<SGPropertyNode_ptr> particle_nodes;
|
std::vector<SGPropertyNode_ptr> particle_nodes;
|
||||||
particle_nodes = props->getChildren("particlesystem");
|
particle_nodes = props->getChildren("particlesystem");
|
||||||
for (unsigned i = 0; i < particle_nodes.size(); ++i) {
|
for (unsigned i = 0; i < particle_nodes.size(); ++i) {
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ SGLoadTexture2D(bool staticTexture, const std::string& path,
|
|||||||
{
|
{
|
||||||
osg::Image* image;
|
osg::Image* image;
|
||||||
if (options)
|
if (options)
|
||||||
image = osgDB::readImageFile(path, options);
|
image = osgDB::readRefImageFile(path, options);
|
||||||
else
|
else
|
||||||
image = osgDB::readImageFile(path);
|
image = osgDB::readRefImageFile(path);
|
||||||
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
|
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
|
||||||
texture->setImage(image);
|
texture->setImage(image);
|
||||||
if (staticTexture)
|
if (staticTexture)
|
||||||
@@ -141,7 +141,7 @@ Texture2D* TextureUpdateVisitor::textureReplace(int unit, const StateAttribute*
|
|||||||
// If it is empty or they are identical then there is nothing to do
|
// If it is empty or they are identical then there is nothing to do
|
||||||
if (fullLiveryFile.empty() || fullLiveryFile == *fullFilePath)
|
if (fullLiveryFile.empty() || fullLiveryFile == *fullFilePath)
|
||||||
return 0;
|
return 0;
|
||||||
Image* newImage = readImageFile(fullLiveryFile);
|
Image* newImage = readRefImageFile(fullLiveryFile);
|
||||||
if (!newImage)
|
if (!newImage)
|
||||||
return 0;
|
return 0;
|
||||||
CopyOp copyOp(CopyOp::DEEP_COPY_ALL & ~CopyOp::DEEP_COPY_IMAGES);
|
CopyOp copyOp(CopyOp::DEEP_COPY_ALL & ~CopyOp::DEEP_COPY_IMAGES);
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ SGModelLib::loadDeferredModel(const string &path, SGPropertyNode *prop_root,
|
|||||||
osg::PagedLOD*
|
osg::PagedLOD*
|
||||||
SGModelLib::loadPagedModel(SGPropertyNode *prop_root, SGModelData *data, SGModelLOD model_lods)
|
SGModelLib::loadPagedModel(SGPropertyNode *prop_root, SGModelData *data, SGModelLOD model_lods)
|
||||||
{
|
{
|
||||||
|
unsigned int simple_models = 0;
|
||||||
osg::PagedLOD *plod = new osg::PagedLOD;
|
osg::PagedLOD *plod = new osg::PagedLOD;
|
||||||
|
|
||||||
osg::ref_ptr<SGReaderWriterOptions> opt;
|
osg::ref_ptr<SGReaderWriterOptions> opt;
|
||||||
@@ -189,15 +190,15 @@ SGModelLib::loadPagedModel(SGPropertyNode *prop_root, SGModelData *data, SGModel
|
|||||||
plod->setMinimumExpiryTime(i, prop_root->getDoubleValue("/sim/rendering/plod-minimum-expiry-time-secs", 180.0 ) );
|
plod->setMinimumExpiryTime(i, prop_root->getDoubleValue("/sim/rendering/plod-minimum-expiry-time-secs", 180.0 ) );
|
||||||
|
|
||||||
std::string lext = SGPath(lod.path).lower_extension();
|
std::string lext = SGPath(lod.path).lower_extension();
|
||||||
|
|
||||||
// We can only have one set of ReaderWriterOptions for the PagedLOD, so
|
|
||||||
// we will just have to assume that if one of the defined models can
|
|
||||||
// handle instantiated effects, then the other can as well.
|
|
||||||
if ((lext == "ac") || (lext == "obj")) {
|
if ((lext == "ac") || (lext == "obj")) {
|
||||||
opt->setInstantiateEffects(true);
|
simple_models++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If all we have are simple models, then we can instantiate effects in
|
||||||
|
// the loader.
|
||||||
|
if (simple_models == model_lods.getNumLODs()) opt->setInstantiateEffects(true);
|
||||||
|
|
||||||
plod->setDatabaseOptions(opt.get());
|
plod->setDatabaseOptions(opt.get());
|
||||||
|
|
||||||
return plod;
|
return plod;
|
||||||
|
|||||||
@@ -485,9 +485,11 @@ SGCloudLayer::rebuild()
|
|||||||
// repaint the cloud layer colors
|
// repaint the cloud layer colors
|
||||||
bool SGCloudLayer::repaint( const SGVec3f& fog_color ) {
|
bool SGCloudLayer::repaint( const SGVec3f& fog_color ) {
|
||||||
osg::Vec4f combineColor(toOsg(fog_color), cloud_alpha);
|
osg::Vec4f combineColor(toOsg(fog_color), cloud_alpha);
|
||||||
osg::TexEnvCombine* combiner
|
osg::StateAttribute* textureAtt = layer_root->getStateSet()->getTextureAttribute(1, osg::StateAttribute::TEXENV);
|
||||||
= dynamic_cast<osg::TexEnvCombine*>(layer_root->getStateSet()
|
osg::TexEnvCombine* combiner = dynamic_cast<osg::TexEnvCombine*>(textureAtt);
|
||||||
->getTextureAttribute(1, osg::StateAttribute::TEXENV));
|
|
||||||
|
if (combiner == nullptr)
|
||||||
|
return false;
|
||||||
combiner->setConstantColor(combineColor);
|
combiner->setConstantColor(combineColor);
|
||||||
|
|
||||||
// Set the fog color for the 3D clouds too.
|
// Set the fog color for the 3D clouds too.
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ ReaderWriterSPT::readObject(const std::string& fileName, const osgDB::Options* o
|
|||||||
imageFileName = osgDB::concatPaths(imageFileName, "Globe");
|
imageFileName = osgDB::concatPaths(imageFileName, "Globe");
|
||||||
imageFileName = osgDB::concatPaths(imageFileName, "world.topo.bathy.200407.3x4096x2048.png");
|
imageFileName = osgDB::concatPaths(imageFileName, "world.topo.bathy.200407.3x4096x2048.png");
|
||||||
}
|
}
|
||||||
if (osg::Image* image = osgDB::readImageFile(imageFileName, options)) {
|
if (osg::Image* image = osgDB::readRefImageFile(imageFileName, options)) {
|
||||||
osg::Texture2D* texture = new osg::Texture2D;
|
osg::Texture2D* texture = new osg::Texture2D;
|
||||||
texture->setImage(image);
|
texture->setImage(image);
|
||||||
texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
|
texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
|
||||||
|
|||||||
@@ -27,4 +27,5 @@
|
|||||||
#cmakedefine ENABLE_SOUND
|
#cmakedefine ENABLE_SOUND
|
||||||
#cmakedefine USE_AEONWAVE
|
#cmakedefine USE_AEONWAVE
|
||||||
#cmakedefine ENABLE_SIMD
|
#cmakedefine ENABLE_SIMD
|
||||||
|
#cmakedefine ENABLE_SIMD_CODE
|
||||||
#cmakedefine ENABLE_GDAL
|
#cmakedefine ENABLE_GDAL
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
// Modified for the new SoundSystem by Erik Hofman, October 2009
|
// Modified for the new SoundSystem by Erik Hofman, October 2009
|
||||||
//
|
//
|
||||||
// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
|
// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||||
// Copyright (C) 2009 Erik Hofman <erik@ehofman.com>
|
// Copyright (C) 2009-2019 Erik Hofman <erik@ehofman.com>
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU General Public License as
|
// modify it under the terms of the GNU General Public License as
|
||||||
@@ -418,8 +418,8 @@ void SGSoundMgr::release_source( unsigned int source )
|
|||||||
{
|
{
|
||||||
aax::Emitter& emitter = source_it->second;
|
aax::Emitter& emitter = source_it->second;
|
||||||
enum aaxState state = emitter.state();
|
enum aaxState state = emitter.state();
|
||||||
if (state == AAX_PLAYING || state == AAX_SUSPENDED) {
|
if (state != AAX_PROCESSED) {
|
||||||
TRY( emitter.set(AAX_STOPPED) );
|
TRY( emitter.set(AAX_PROCESSED) );
|
||||||
TRY( d->_aax.remove(emitter) );
|
TRY( d->_aax.remove(emitter) );
|
||||||
}
|
}
|
||||||
TRY( emitter.remove_buffer() );
|
TRY( emitter.remove_buffer() );
|
||||||
@@ -555,7 +555,6 @@ void SGSoundMgr::sample_play( SGSoundSample *sample )
|
|||||||
if (bufid == SGSoundMgr::FAILED_BUFFER ||
|
if (bufid == SGSoundMgr::FAILED_BUFFER ||
|
||||||
bufid == SGSoundMgr::NO_BUFFER)
|
bufid == SGSoundMgr::NO_BUFFER)
|
||||||
{
|
{
|
||||||
printf("A: release: %i, bufid: %i (%i, %i)\n", sample->get_source(), bufid, SGSoundMgr::FAILED_BUFFER, SGSoundMgr::NO_BUFFER);
|
|
||||||
release_source(sample->get_source());
|
release_source(sample->get_source());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -590,8 +589,7 @@ void SGSoundMgr::sample_stop( SGSoundSample *sample )
|
|||||||
if ( sample->is_looping() && !stopped) {
|
if ( sample->is_looping() && !stopped) {
|
||||||
#ifdef ENABLE_SOUND
|
#ifdef ENABLE_SOUND
|
||||||
aax::Emitter& emitter = d->get_emitter(source);
|
aax::Emitter& emitter = d->get_emitter(source);
|
||||||
TRY( emitter.set(AAX_STOPPED) );
|
TRY( emitter.set(AAX_PROCESSED) );
|
||||||
TRY( d->_aax.remove(emitter) );
|
|
||||||
#endif
|
#endif
|
||||||
stopped = is_sample_stopped(sample);
|
stopped = is_sample_stopped(sample);
|
||||||
}
|
}
|
||||||
@@ -610,8 +608,7 @@ void SGSoundMgr::sample_destroy( SGSoundSample *sample )
|
|||||||
unsigned int source = sample->get_source();
|
unsigned int source = sample->get_source();
|
||||||
if ( sample->is_playing() ) {
|
if ( sample->is_playing() ) {
|
||||||
aax::Emitter& emitter = d->get_emitter(source);
|
aax::Emitter& emitter = d->get_emitter(source);
|
||||||
TRY( emitter.set(AAX_STOPPED) );
|
TRY( emitter.set(AAX_PROCESSED) );
|
||||||
TRY( d->_aax.remove(emitter) );
|
|
||||||
}
|
}
|
||||||
release_source( source );
|
release_source( source );
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ void SGSoundMgr::suspend()
|
|||||||
for ( auto current = d->_sample_groups.begin();
|
for ( auto current = d->_sample_groups.begin();
|
||||||
current != d->_sample_groups.end(); ++current ) {
|
current != d->_sample_groups.end(); ++current ) {
|
||||||
SGSampleGroup *sgrp = current->second;
|
SGSampleGroup *sgrp = current->second;
|
||||||
sgrp->stop();
|
sgrp->suspend();
|
||||||
}
|
}
|
||||||
_active = false;
|
_active = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ SGXmlSound::~SGXmlSound()
|
|||||||
if (_sample)
|
if (_sample)
|
||||||
_sample->stop();
|
_sample->stop();
|
||||||
|
|
||||||
|
if (_sgrp && (_name != ""))
|
||||||
|
_sgrp->remove(_name);
|
||||||
|
|
||||||
_volume.clear();
|
_volume.clear();
|
||||||
_pitch.clear();
|
_pitch.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,6 +253,7 @@ SGSubsystemGroup::incrementalInit()
|
|||||||
{
|
{
|
||||||
// special case this, simplifies the logic below
|
// special case this, simplifies the logic below
|
||||||
if (_members.empty()) {
|
if (_members.empty()) {
|
||||||
|
_state = State::INIT;
|
||||||
return INIT_DONE;
|
return INIT_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -314,6 +314,7 @@ void testIncrementalInit()
|
|||||||
instruments->set_subsystem(radio1);
|
instruments->set_subsystem(radio1);
|
||||||
instruments->set_subsystem(radio2);
|
instruments->set_subsystem(radio2);
|
||||||
|
|
||||||
|
|
||||||
manager->bind();
|
manager->bind();
|
||||||
for ( ; ; ) {
|
for ( ; ; ) {
|
||||||
auto status = manager->incrementalInit();
|
auto status = manager->incrementalInit();
|
||||||
@@ -338,9 +339,34 @@ void testIncrementalInit()
|
|||||||
|
|
||||||
SG_VERIFY(d->hasEvent("fake-radio.nav2-will-init"));
|
SG_VERIFY(d->hasEvent("fake-radio.nav2-will-init"));
|
||||||
SG_VERIFY(d->hasEvent("fake-radio.nav2-did-init"));
|
SG_VERIFY(d->hasEvent("fake-radio.nav2-did-init"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void testEmptyGroup()
|
||||||
|
{
|
||||||
|
// testing the assert described here:
|
||||||
|
// https://sourceforge.net/p/flightgear/codetickets/2043/
|
||||||
|
// when an empty group is inited, we skipped setting the state
|
||||||
|
|
||||||
|
SGSharedPtr<SGSubsystemMgr> manager = new SGSubsystemMgr;
|
||||||
|
auto d = new RecorderDelegate;
|
||||||
|
manager->addDelegate(d);
|
||||||
|
|
||||||
|
auto mySub = manager->add<MySub1>(SGSubsystemMgr::POST_FDM);
|
||||||
|
auto anotherSub = manager->add<AnotherSub>(SGSubsystemMgr::POST_FDM);
|
||||||
|
auto instruments = manager->add<InstrumentGroup>(SGSubsystemMgr::POST_FDM);
|
||||||
|
|
||||||
|
manager->bind();
|
||||||
|
for ( ; ; ) {
|
||||||
|
auto status = manager->incrementalInit();
|
||||||
|
if (status == SGSubsystemMgr::INIT_DONE)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
manager->postinit();
|
||||||
|
|
||||||
|
SG_VERIFY(mySub->wasInited);
|
||||||
|
|
||||||
|
SG_VERIFY(d->hasEvent("instruments-will-init"));
|
||||||
|
SG_VERIFY(d->hasEvent("instruments-did-init"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSuspendResume()
|
void testSuspendResume()
|
||||||
@@ -520,6 +546,7 @@ int main(int argc, char* argv[])
|
|||||||
testSuspendResume();
|
testSuspendResume();
|
||||||
testPropertyRoot();
|
testPropertyRoot();
|
||||||
testAddRemoveAfterInit();
|
testAddRemoveAfterInit();
|
||||||
|
testEmptyGroup();
|
||||||
|
|
||||||
cout << __FILE__ << ": All tests passed" << endl;
|
cout << __FILE__ << ": All tests passed" << endl;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|||||||
Reference in New Issue
Block a user