Compare commits
288 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8d38cbdd0 | ||
|
|
21c24431db | ||
|
|
f2a059e985 | ||
|
|
1c4b1149e2 | ||
|
|
454be02eab | ||
|
|
072742cba5 | ||
|
|
9812bfc25f | ||
|
|
cbc7782b3a | ||
|
|
40afac6ae0 | ||
|
|
891457c11a | ||
|
|
e9a517985b | ||
|
|
a2058bc1e8 | ||
|
|
de96b8e43e | ||
|
|
d1e5d67336 | ||
|
|
5279697890 | ||
|
|
fd9166e32a | ||
|
|
6b9c53c3c0 | ||
|
|
3620e537ab | ||
|
|
e625fa3b33 | ||
|
|
f0b18e52a3 | ||
|
|
adecaca730 | ||
|
|
10ef3ff683 | ||
|
|
ef5b95d5b9 | ||
|
|
c3e9150125 | ||
|
|
ac0afbcc4a | ||
|
|
a9593e62b7 | ||
|
|
4b7bc99291 | ||
|
|
43e1aa9c01 | ||
|
|
d44d6515d8 | ||
|
|
7c636c6c17 | ||
|
|
c094314a2d | ||
|
|
9da87128f1 | ||
|
|
1036e1f3fb | ||
|
|
6b5fd054f6 | ||
|
|
91b6d68eae | ||
|
|
a0487b12be | ||
|
|
1e07b626c4 | ||
|
|
b247ca3f76 | ||
|
|
5f3cac46eb | ||
|
|
a7c424fc68 | ||
|
|
a35f159117 | ||
|
|
b865b92a6a | ||
|
|
2132978c41 | ||
|
|
97f6b9d845 | ||
|
|
6e4ef6f8a1 | ||
|
|
56bd48bd2a | ||
|
|
ca98523c41 | ||
|
|
290f143b5c | ||
|
|
123ded50ef | ||
|
|
18b7f6925a | ||
|
|
51aaa9f26b | ||
|
|
a75964c993 | ||
|
|
9bd9cb697e | ||
|
|
4d29117148 | ||
|
|
dd4f2e857b | ||
|
|
0b998da183 | ||
|
|
eef7596aeb | ||
|
|
4abf23f9a9 | ||
|
|
56d2754606 | ||
|
|
88ca93d24f | ||
|
|
72c85ef104 | ||
|
|
c6b1763d96 | ||
|
|
844444c33b | ||
|
|
c708408f64 | ||
|
|
03e9db98e6 | ||
|
|
bf3947dcc5 | ||
|
|
5140affe07 | ||
|
|
b808caaa0e | ||
|
|
658c617c75 | ||
|
|
05fcfc32bc | ||
|
|
05a4409b3d | ||
|
|
cadc08af87 | ||
|
|
2678d0f99e | ||
|
|
b1954e411b | ||
|
|
5d47c7ecfa | ||
|
|
f09d399e88 | ||
|
|
c592184aa6 | ||
|
|
bb297ac354 | ||
|
|
7871be05af | ||
|
|
1a9cd725b2 | ||
|
|
1e0395c26d | ||
|
|
7943adedaa | ||
|
|
2285830c8f | ||
|
|
eff4bc7ad6 | ||
|
|
794027d91e | ||
|
|
312625036b | ||
|
|
e7c1dc3b8e | ||
|
|
a29b50b4cd | ||
|
|
d03b03ac93 | ||
|
|
a891d2fdea | ||
|
|
de28034c20 | ||
|
|
01c639c261 | ||
|
|
fe21270bbc | ||
|
|
b9acd64221 | ||
|
|
9bf2092c7e | ||
|
|
0eba34d5a8 | ||
|
|
5257eec81e | ||
|
|
2d2513369a | ||
|
|
6e8cd5a4cc | ||
|
|
7749f8a99d | ||
|
|
ef32d0d321 | ||
|
|
f26d7c7bf2 | ||
|
|
86240966b6 | ||
|
|
f5d3bc2b7b | ||
|
|
b3bd91877c | ||
|
|
00123d2dde | ||
|
|
ecd58e3924 | ||
|
|
0ac3fd0563 | ||
|
|
a805d15797 | ||
|
|
28024d7a01 | ||
|
|
e0fb73414b | ||
|
|
94d6969fed | ||
|
|
8e5fad2209 | ||
|
|
ca49db02df | ||
|
|
08db85fa99 | ||
|
|
e57bcea3b6 | ||
|
|
5c5fae78c6 | ||
|
|
44f8f17763 | ||
|
|
78e7b288b8 | ||
|
|
78131d2d53 | ||
|
|
ca8aa4dc0a | ||
|
|
81ef1292ed | ||
|
|
b67f55cff7 | ||
|
|
9880134b4d | ||
|
|
cc32df6fd8 | ||
|
|
0e48a2196f | ||
|
|
39d27e3a4e | ||
|
|
48e6a4f535 | ||
|
|
7db5126182 | ||
|
|
0d4ac69465 | ||
|
|
32706065ac | ||
|
|
d571b8be81 | ||
|
|
f014c8207c | ||
|
|
b680b53128 | ||
|
|
e2cd11ccd7 | ||
|
|
ab4561aacc | ||
|
|
a7733a6c55 | ||
|
|
688aa50064 | ||
|
|
232bf22e51 | ||
|
|
171c1a5c44 | ||
|
|
80b4fe6613 | ||
|
|
18f640d73d | ||
|
|
9e2667261f | ||
|
|
18e33d2268 | ||
|
|
fd13ccf802 | ||
|
|
fbf947fcd7 | ||
|
|
958031dbaf | ||
|
|
7ddef751ef | ||
|
|
a81ecc2006 | ||
|
|
fedd094987 | ||
|
|
36a8a20434 | ||
|
|
f5204cc8f5 | ||
|
|
808e262a4d | ||
|
|
152cf42029 | ||
|
|
e69385861a | ||
|
|
87f87bf2ff | ||
|
|
b3d86e626b | ||
|
|
d80ebdc77d | ||
|
|
80ac46c9a5 | ||
|
|
4387118d55 | ||
|
|
c2abbaedc8 | ||
|
|
f8927a8a11 | ||
|
|
7054a2a6d2 | ||
|
|
f2f8ecab98 | ||
|
|
be9d417778 | ||
|
|
6e537cd322 | ||
|
|
19cae9b59b | ||
|
|
89e65ed89e | ||
|
|
9892d23735 | ||
|
|
10a3339019 | ||
|
|
8b658bd628 | ||
|
|
5a045db751 | ||
|
|
80e7854300 | ||
|
|
c83c1ed291 | ||
|
|
37412c8dd2 | ||
|
|
aaa1a5451e | ||
|
|
e3d45d99da | ||
|
|
60d9301646 | ||
|
|
23f070128a | ||
|
|
39e0e4ad9e | ||
|
|
bde1853862 | ||
|
|
637b70a723 | ||
|
|
d34c5034c3 | ||
|
|
8dc3dcd2ac | ||
|
|
b25643f0bf | ||
|
|
3231a7d25f | ||
|
|
855769c53e | ||
|
|
7cf069bf4c | ||
|
|
bd94e2ae73 | ||
|
|
6c2871402d | ||
|
|
341ca20529 | ||
|
|
0d300776ca | ||
|
|
fad498cfb8 | ||
|
|
39d3a58b49 | ||
|
|
e98792209e | ||
|
|
2d53641cd0 | ||
|
|
529c61fabe | ||
|
|
614a1c3bb6 | ||
|
|
663d9ce3d1 | ||
|
|
67b8c8d360 | ||
|
|
4c5379fe30 | ||
|
|
65c613fb3e | ||
|
|
d0f265f6d9 | ||
|
|
ec4d13741f | ||
|
|
d6b87f141f | ||
|
|
cd61a2ae20 | ||
|
|
d99528f4b4 | ||
|
|
775a7be958 | ||
|
|
77f5851b3c | ||
|
|
e4ac5c8f6c | ||
|
|
4f6ec26dc9 | ||
|
|
55fda48a3b | ||
|
|
5dc2bc06cf | ||
|
|
f2367575a2 | ||
|
|
345d5d99b3 | ||
|
|
5c86dfeb6e | ||
|
|
b119aa49ef | ||
|
|
8b84d5597f | ||
|
|
b060ba3c38 | ||
|
|
17c2e93c78 | ||
|
|
6a2353f08b | ||
|
|
da2d80d23a | ||
|
|
01f2e70f1d | ||
|
|
b77268b0e3 | ||
|
|
6a4c1f6ac6 | ||
|
|
1d6e21247e | ||
|
|
4a699d6160 | ||
|
|
06584a38ab | ||
|
|
d2dd03dcba | ||
|
|
3b631a4f90 | ||
|
|
3555967812 | ||
|
|
358135a890 | ||
|
|
73ac76a0eb | ||
|
|
972c92a3fe | ||
|
|
f6209dec34 | ||
|
|
738ce6422a | ||
|
|
dd3cb2b43c | ||
|
|
8fd1788ece | ||
|
|
d34bd5338d | ||
|
|
8dca737dc8 | ||
|
|
86ff77665c | ||
|
|
e5e665b9ee | ||
|
|
6863eb6651 | ||
|
|
0493a91a42 | ||
|
|
1ee939c7f7 | ||
|
|
ff8b4fd95a | ||
|
|
a68983b37f | ||
|
|
2d0905a4a6 | ||
|
|
eb96dee176 | ||
|
|
df2ca052ea | ||
|
|
e95c0a4631 | ||
|
|
fbbd45c674 | ||
|
|
69064e96f0 | ||
|
|
1e0b95ca68 | ||
|
|
a5ac768540 | ||
|
|
1c7772e731 | ||
|
|
2db2c96329 | ||
|
|
76616ee6f6 | ||
|
|
37c7a72505 | ||
|
|
b198e296cb | ||
|
|
f38754d0d6 | ||
|
|
e5a0393480 | ||
|
|
e62ef91404 | ||
|
|
71d78425be | ||
|
|
c7db5122c8 | ||
|
|
89fcf69948 | ||
|
|
724ea77bef | ||
|
|
b127dd514d | ||
|
|
a732635e75 | ||
|
|
5072f983ed | ||
|
|
6c9fca3f61 | ||
|
|
91b98bed05 | ||
|
|
195f7502b7 | ||
|
|
1b8779f93e | ||
|
|
f0f124a23a | ||
|
|
2772daa964 | ||
|
|
2338e8a186 | ||
|
|
ab7acd7149 | ||
|
|
43a9aedf7d | ||
|
|
5059d5e2da | ||
|
|
29195e8460 | ||
|
|
e49156a074 | ||
|
|
948ebe5213 | ||
|
|
2a64c07215 | ||
|
|
578a5719dd | ||
|
|
6804253bfc | ||
|
|
90d2dce07a | ||
|
|
d0c66e5efb |
@@ -4,7 +4,7 @@
|
||||
# other commands to guarantee full compatibility
|
||||
# with the version specified
|
||||
|
||||
cmake_minimum_required(VERSION 2.6.2 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR)
|
||||
|
||||
# Eventually the third-party support modules (cmake/*.cmake) should
|
||||
# know the full path to all libraries. Until that happens we need
|
||||
@@ -15,7 +15,7 @@ cmake_minimum_required(VERSION 2.6.2 FATAL_ERROR)
|
||||
# CMP0003 to OLD and link to one library (apr) on a per-configuration
|
||||
# basis to convince CMake to add the proper link directory. This line
|
||||
# can be removed when we use full paths for all libraries.
|
||||
cmake_policy(SET CMP0003 OLD)
|
||||
#cmake_policy(SET CMP0003 OLD)
|
||||
|
||||
set(ROOT_PROJECT_NAME "Singularity" CACHE STRING
|
||||
"The root project/makefile/solution name. Defaults to Singularity.")
|
||||
@@ -27,7 +27,6 @@ include(Variables)
|
||||
|
||||
# Load versions now. Install locations need them.
|
||||
include(BuildVersion)
|
||||
|
||||
include(UnixInstall)
|
||||
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
|
||||
@@ -41,6 +40,9 @@ if(NOT STANDALONE)
|
||||
# We prepare prebuilt binaries when not building standalone.
|
||||
set(prepare_depends ${CMAKE_BINARY_DIR}/prepare/prebuilt)
|
||||
endif(NOT STANDALONE)
|
||||
if(WINDOWS)
|
||||
set(prepare_depends ${prepare_depends} copy_win_libs)
|
||||
endif(WINDOWS)
|
||||
add_custom_target(prepare DEPENDS ${prepare_depends})
|
||||
|
||||
add_subdirectory(cmake)
|
||||
@@ -107,3 +109,16 @@ add_custom_command(
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../install.xml
|
||||
${CMAKE_BINARY_DIR}/DownloadPrebuilt.cmake
|
||||
)
|
||||
|
||||
|
||||
if(WINDOWS)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/CopyWinLibs.cmake.in
|
||||
${CMAKE_BINARY_DIR}/CopyWinLibs.cmake @ONLY)
|
||||
add_custom_command(
|
||||
COMMENT "Copying prebuilt libraries to viewer executable directory"
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/CopyWinLibs
|
||||
COMMAND ${CMAKE_COMMAND} -DCUR_CONFIG:STRING=${CMAKE_CFG_INTDIR} -P ${CMAKE_BINARY_DIR}/CopyWinLibs.cmake
|
||||
DEPENDS ${CMAKE_BINARY_DIR}/prepare/prebuilt ${CMAKE_BINARY_DIR}/CopyWinLibs.cmake
|
||||
)
|
||||
add_custom_target(copy_win_libs DEPENDS ${CMAKE_BINARY_DIR}/CopyWinLibs)
|
||||
endif(WINDOWS)
|
||||
@@ -440,7 +440,7 @@ void AIStateMachine::multiplex(event_type event)
|
||||
// our need to run (by us having set need_run), so there is no need to run
|
||||
// ourselves.
|
||||
llassert(!mMultiplexMutex.isSelfLocked()); // We may never enter recursively!
|
||||
if (!mMultiplexMutex.tryLock())
|
||||
if (!mMultiplexMutex.try_lock())
|
||||
{
|
||||
Dout(dc::statemachine(mSMDebug), "Leaving because it is already being run [" << (void*)this << "]");
|
||||
return;
|
||||
@@ -762,7 +762,7 @@ void AIStateMachine::multiplex(event_type event)
|
||||
//=========================================
|
||||
|
||||
// Release the lock on mMultiplexMutex *first*, before releasing the lock on mState,
|
||||
// to avoid to ever call the tryLock() and fail, while this thread isn't still
|
||||
// to avoid to ever call the try_lock() and fail, while this thread isn't still
|
||||
// BEFORE the critical area of mState!
|
||||
|
||||
mMultiplexMutex.unlock();
|
||||
@@ -1262,7 +1262,7 @@ void AIStateMachine::abort(void)
|
||||
multiplex(insert_abort);
|
||||
}
|
||||
// Block until the current run finished.
|
||||
if (!mRunMutex.tryLock())
|
||||
if (!mRunMutex.try_lock())
|
||||
{
|
||||
llwarns << "AIStateMachine::abort() blocks because the statemachine is still executing code in another thread." << llendl;
|
||||
mRunMutex.lock();
|
||||
|
||||
@@ -45,11 +45,10 @@ if (WINDOWS)
|
||||
if (MSVC10)
|
||||
set(MSVC_DIR 10.0)
|
||||
set(MSVC_SUFFIX 100)
|
||||
elseif (MSVC12)
|
||||
set(MSVC_DIR 12.0)
|
||||
set(MSVC_SUFFIX 120)
|
||||
endif (MSVC10)
|
||||
if (MSVC11)
|
||||
set(MSVC_DIR 11.0)
|
||||
set(MSVC_SUFFIX 110)
|
||||
endif (MSVC11)
|
||||
|
||||
# Remove default /Zm1000 flag that cmake inserts
|
||||
string (REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
@@ -85,21 +84,27 @@ if (WINDOWS)
|
||||
/W3
|
||||
/c
|
||||
/Zc:forScope
|
||||
/Zc:wchar_t-
|
||||
/Zc:wchar_t-
|
||||
/nologo
|
||||
/Oy-
|
||||
)
|
||||
|
||||
# SSE2 is implied on win64
|
||||
if(WORD_SIZE EQUAL 32)
|
||||
add_definitions(/arch:SSE2)
|
||||
add_definitions(/arch:SSE2 /D_ATL_XP_TARGETING)
|
||||
else(WORD_SIZE EQUAL 32)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /wd4267 /wd4250 /wd4244")
|
||||
endif(WORD_SIZE EQUAL 32)
|
||||
|
||||
# configure win32 API for windows XP+ compatibility
|
||||
set(WINVER "0x0501" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)")
|
||||
add_definitions("/DWINVER=${WINVER}" "/D_WIN32_WINNT=${WINVER}")
|
||||
if (MSVC12)
|
||||
# configure win32 API for windows vista+ compatibility
|
||||
set(WINVER "0x0600" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)")
|
||||
add_definitions("/DWINVER=${WINVER}" "/D_WIN32_WINNT=${WINVER}")
|
||||
else (MSVC12)
|
||||
# configure win32 API for windows XP+ compatibility
|
||||
set(WINVER "0x0501" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)")
|
||||
add_definitions("/DWINVER=${WINVER}" "/D_WIN32_WINNT=${WINVER}")
|
||||
endif (MSVC12)
|
||||
|
||||
# Are we using the crummy Visual Studio KDU build workaround?
|
||||
if (NOT DISABLE_FATAL_WARNINGS)
|
||||
|
||||
@@ -14,25 +14,25 @@ else (STANDALONE)
|
||||
use_prebuilt_binary(apr_suite)
|
||||
if (WINDOWS)
|
||||
set(APR_LIBRARIES
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.lib
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.lib
|
||||
debug libapr-1.lib
|
||||
optimized libapr-1.lib
|
||||
)
|
||||
set(APRICONV_LIBRARIES
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapriconv-1.lib
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapriconv-1.lib
|
||||
debug libapriconv-1.lib
|
||||
optimized libapriconv-1.lib
|
||||
)
|
||||
set(APRUTIL_LIBRARIES
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.lib ${APRICONV_LIBRARIES}
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.lib ${APRICONV_LIBRARIES}
|
||||
debug libaprutil-1.lib
|
||||
optimized libaprutil-1.lib
|
||||
)
|
||||
elseif (DARWIN)
|
||||
set(APR_LIBRARIES
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.0.dylib
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.0.dylib
|
||||
debug libapr-1.0.dylib
|
||||
optimized libapr-1.0.dylib
|
||||
)
|
||||
set(APRUTIL_LIBRARIES
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.dylib
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.dylib
|
||||
set(APRUTIL_LIBRARIES
|
||||
debug libaprutil-1.dylib
|
||||
optimized libaprutil-1.dylib
|
||||
)
|
||||
set(APRICONV_LIBRARIES iconv)
|
||||
else (WINDOWS)
|
||||
@@ -40,7 +40,10 @@ else (STANDALONE)
|
||||
set(APRUTIL_LIBRARIES aprutil-1)
|
||||
set(APRICONV_LIBRARIES iconv)
|
||||
endif (WINDOWS)
|
||||
set(APR_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/apr-1)
|
||||
set(APR_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/include/apr-1
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/apr-1
|
||||
)
|
||||
|
||||
if (LINUX)
|
||||
list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES})
|
||||
|
||||
@@ -9,7 +9,10 @@ if (STANDALONE)
|
||||
pkg_check_modules(VORBISFILE REQUIRED vorbisfile)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(ogg-vorbis)
|
||||
set(VORBIS_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(VORBIS_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
set(VORBISENC_INCLUDE_DIRS ${VORBIS_INCLUDE_DIRS})
|
||||
set(VORBISFILE_INCLUDE_DIRS ${VORBIS_INCLUDE_DIRS})
|
||||
|
||||
|
||||
@@ -13,5 +13,8 @@ else (STANDALONE)
|
||||
else (LINUX)
|
||||
set(DB_LIBRARIES db-4.2)
|
||||
endif (LINUX)
|
||||
set(DB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(DB_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -11,7 +11,10 @@ if (STANDALONE)
|
||||
find_package(Boost 1.51.0 COMPONENTS date_time filesystem program_options regex system thread wave context)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(boost)
|
||||
set(Boost_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(Boost_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
set(Boost_VERSION "1.52")
|
||||
|
||||
if (WINDOWS)
|
||||
|
||||
@@ -38,11 +38,6 @@ if (WINDOWS)
|
||||
${CMAKE_SOURCE_DIR}/newview/res/viewerRes.rc.in
|
||||
${CMAKE_SOURCE_DIR}/newview/res/viewerRes.rc
|
||||
)
|
||||
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/newview/res/viewerRes_bc.rc.in
|
||||
${CMAKE_SOURCE_DIR}/newview/res/viewerRes_bc.rc
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
||||
if (DARWIN)
|
||||
@@ -75,13 +70,12 @@ if (LINUX)
|
||||
)
|
||||
endif (LINUX)
|
||||
|
||||
# Compose the version.
|
||||
set(viewer_VERSION "${vMAJOR}.${vMINOR}.${vPATCH}.${vBUILD}")
|
||||
if (viewer_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")
|
||||
message(STATUS "Version is ${viewer_VERSION}")
|
||||
else (viewer_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")
|
||||
message(FATAL_ERROR "Could not determine version (${viewer_VERSION})")
|
||||
endif (viewer_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")
|
||||
|
||||
# Report version to caller.
|
||||
#set(viewer_VERSION "${viewer_VERSION}" PARENT_SCOPE)
|
||||
# Compose the version.
|
||||
set(${ROOT_PROJECT_NAME}_VERSION "${vMAJOR}.${vMINOR}.${vPATCH}.${vBUILD}")
|
||||
if (${ROOT_PROJECT_NAME}_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")
|
||||
message(STATUS "Version is ${${ROOT_PROJECT_NAME}_VERSION}")
|
||||
else (${ROOT_PROJECT_NAME}_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")
|
||||
message(FATAL_ERROR "Could not determine version (${${ROOT_PROJECT_NAME}_VERSION})")
|
||||
endif (${ROOT_PROJECT_NAME}_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")
|
||||
|
||||
|
||||
@@ -13,12 +13,15 @@ else (STANDALONE)
|
||||
add_definitions("-DCARES_STATICLIB")
|
||||
set(CARES_LIBRARIES areslib)
|
||||
elseif (DARWIN)
|
||||
set(CARES_LIBRARIES
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libcares.a
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libcares.a
|
||||
set(CARES_LIBRARIES
|
||||
debug libcares.a
|
||||
optimized libcares.a
|
||||
)
|
||||
else (WINDOWS)
|
||||
set(CARES_LIBRARIES cares)
|
||||
endif (WINDOWS)
|
||||
set(CARES_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/ares)
|
||||
set(CARES_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include/ares
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/ares
|
||||
)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -29,8 +29,8 @@ set(cmake_SOURCE_FILES
|
||||
ELFIO.cmake
|
||||
EXPAT.cmake
|
||||
ExamplePlugin.cmake
|
||||
FMOD.cmake
|
||||
FMODEX.cmake
|
||||
FMODSTUDIO.cmake
|
||||
FindAPR.cmake
|
||||
FindBerkeleyDB.cmake
|
||||
FindCARes.cmake
|
||||
|
||||
@@ -18,5 +18,8 @@ else (STANDALONE)
|
||||
list(APPEND CURL_LIBRARIES idn)
|
||||
endif(LINUX AND WORD_SIZE EQUAL 64)
|
||||
endif (WINDOWS)
|
||||
set(CURL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(CURL_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
include(Prebuilt)
|
||||
include(Boost)
|
||||
|
||||
set(COLLADADOM_FIND_QUIETLY OFF)
|
||||
set(COLLADADOM_FIND_REQUIRED ON)
|
||||
@@ -19,16 +20,33 @@ else (STANDALONE)
|
||||
endif (NOT DARWIN AND NOT WINDOWS)
|
||||
|
||||
set(COLLADADOM_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/collada
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/collada/1.4
|
||||
)
|
||||
${LIBS_PREBUILT_DIR}/include/collada
|
||||
${LIBS_PREBUILT_DIR}/include/collada/1.4
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/collada
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/collada/1.4
|
||||
)
|
||||
|
||||
if (WINDOWS)
|
||||
add_definitions(-DDOM_DYNAMIC)
|
||||
set(COLLADADOM_LIBRARIES
|
||||
debug libcollada14dom22-d
|
||||
optimized libcollada14dom22
|
||||
if(MSVC12)
|
||||
use_prebuilt_binary(pcre)
|
||||
use_prebuilt_binary(libxml)
|
||||
set(COLLADADOM_LIBRARIES
|
||||
debug libcollada14dom23-sd
|
||||
optimized libcollada14dom23-s
|
||||
libxml2_a
|
||||
debug pcrecppd
|
||||
optimized pcrecpp
|
||||
debug pcred
|
||||
optimized pcre
|
||||
${BOOST_SYSTEM_LIBRARIES}
|
||||
)
|
||||
else(MSVC12)
|
||||
add_definitions(-DDOM_DYNAMIC)
|
||||
set(COLLADADOM_LIBRARIES
|
||||
debug libcollada14dom22-d
|
||||
optimized libcollada14dom22
|
||||
)
|
||||
endif(MSVC12)
|
||||
else (WINDOWS)
|
||||
set(COLLADADOM_LIBRARIES
|
||||
collada14dom
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Copies a binary back to the source directory
|
||||
|
||||
MACRO(COPY_BACK_TO_SOURCE target)
|
||||
GET_TARGET_PROPERTY(FROM ${target} LOCATION)
|
||||
SET(FROM $<TARGET_FILE:${target}>)
|
||||
SET(TO ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
#MESSAGE("TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${FROM} ${TO}")
|
||||
ADD_CUSTOM_COMMAND(
|
||||
|
||||
@@ -1,320 +0,0 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
# The copy_win_libs folder contains file lists and a script used to
|
||||
# copy dlls, exes and such needed to run the SecondLife from within
|
||||
# VisualStudio.
|
||||
|
||||
include(CMakeCopyIfDifferent)
|
||||
|
||||
if(WORD_SIZE EQUAL 32)
|
||||
set(debug_libs_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
|
||||
set(release_libs_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
|
||||
else(WORD_SIZE EQUAL 32)
|
||||
set(debug_libs_dir "${CMAKE_SOURCE_DIR}/../libraries/x86_64-win/lib/debug")
|
||||
set(release_libs_dir "${CMAKE_SOURCE_DIR}/../libraries/x86_64-win/lib/release")
|
||||
endif(WORD_SIZE EQUAL 32)
|
||||
|
||||
set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-win32")
|
||||
set(vivox_files
|
||||
ca-bundle.crt
|
||||
libsndfile-1.dll
|
||||
ortp.dll
|
||||
SLVoice.exe
|
||||
vivoxoal.dll
|
||||
vivoxplatform.dll
|
||||
vivoxsdk.dll
|
||||
zlib1.dll
|
||||
)
|
||||
copy_if_different(
|
||||
${vivox_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Debug"
|
||||
out_targets
|
||||
${vivox_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
|
||||
set(debug_src_dir "${debug_libs_dir}")
|
||||
set(debug_files
|
||||
libhunspell.dll
|
||||
libapr-1.dll
|
||||
libaprutil-1.dll
|
||||
libapriconv-1.dll
|
||||
libeay32.dll
|
||||
ssleay32.dll
|
||||
libcollada14dom22-d.dll
|
||||
glod.dll
|
||||
)
|
||||
|
||||
copy_if_different(
|
||||
${debug_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Debug"
|
||||
out_targets
|
||||
${debug_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
# Debug config runtime files required for the plugin test mule
|
||||
set(plugintest_debug_src_dir "${debug_libs_dir}")
|
||||
set(plugintest_debug_files
|
||||
libeay32.dll
|
||||
qtcored4.dll
|
||||
qtguid4.dll
|
||||
qtnetworkd4.dll
|
||||
qtopengld4.dll
|
||||
qtwebkitd4.dll
|
||||
ssleay32.dll
|
||||
)
|
||||
copy_if_different(
|
||||
${plugintest_debug_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Debug"
|
||||
out_targets
|
||||
${plugintest_debug_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
# Debug config runtime files required for the plugin test mule (Qt image format plugins)
|
||||
set(plugintest_debug_src_dir "${debug_libs_dir}/imageformats")
|
||||
set(plugintest_debug_files
|
||||
qgifd4.dll
|
||||
qicod4.dll
|
||||
qjpegd4.dll
|
||||
qmngd4.dll
|
||||
qsvgd4.dll
|
||||
qtiffd4.dll
|
||||
)
|
||||
copy_if_different(
|
||||
${plugintest_debug_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Debug/imageformats"
|
||||
out_targets
|
||||
${plugintest_debug_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${plugintest_debug_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/llplugin/imageformats"
|
||||
out_targets
|
||||
${plugintest_debug_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
# Release & ReleaseDebInfo config runtime files required for the plugin test mule
|
||||
set(plugintest_release_src_dir "${release_libs_dir}")
|
||||
set(plugintest_release_files
|
||||
libeay32.dll
|
||||
qtcore4.dll
|
||||
qtgui4.dll
|
||||
qtnetwork4.dll
|
||||
qtopengl4.dll
|
||||
qtwebkit4.dll
|
||||
ssleay32.dll
|
||||
)
|
||||
copy_if_different(
|
||||
${plugintest_release_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Release"
|
||||
out_targets
|
||||
${plugintest_release_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${plugintest_release_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/RelWithDebInfo"
|
||||
out_targets
|
||||
${plugintest_release_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
# Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins)
|
||||
set(plugintest_release_src_dir "${release_libs_dir}/imageformats")
|
||||
set(plugintest_release_files
|
||||
qgif4.dll
|
||||
qico4.dll
|
||||
qjpeg4.dll
|
||||
qmng4.dll
|
||||
qsvg4.dll
|
||||
qtiff4.dll
|
||||
)
|
||||
copy_if_different(
|
||||
${plugintest_release_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Release/imageformats"
|
||||
out_targets
|
||||
${plugintest_release_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${plugintest_release_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/RelWithDebInfo/imageformats"
|
||||
out_targets
|
||||
${plugintest_release_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${plugintest_release_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin/imageformats"
|
||||
out_targets
|
||||
${plugintest_release_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${plugintest_release_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin/imageformats"
|
||||
out_targets
|
||||
${plugintest_release_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
# Debug config runtime files required for the plugins
|
||||
set(plugins_debug_src_dir "${debug_libs_dir}")
|
||||
set(plugins_debug_files
|
||||
libeay32.dll
|
||||
qtcored4.dll
|
||||
qtguid4.dll
|
||||
qtnetworkd4.dll
|
||||
qtopengld4.dll
|
||||
qtwebkitd4.dll
|
||||
ssleay32.dll
|
||||
)
|
||||
copy_if_different(
|
||||
${plugins_debug_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Debug/llplugin"
|
||||
out_targets
|
||||
${plugins_debug_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
# Release & ReleaseDebInfo config runtime files required for the plugins
|
||||
set(plugins_release_src_dir "${release_libs_dir}")
|
||||
set(plugins_release_files
|
||||
libeay32.dll
|
||||
qtcore4.dll
|
||||
qtgui4.dll
|
||||
qtnetwork4.dll
|
||||
qtopengl4.dll
|
||||
qtwebkit4.dll
|
||||
ssleay32.dll
|
||||
)
|
||||
copy_if_different(
|
||||
${plugins_release_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin"
|
||||
out_targets
|
||||
${plugins_release_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${plugins_release_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin"
|
||||
out_targets
|
||||
${plugins_release_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
|
||||
set(release_src_dir "${release_libs_dir}")
|
||||
set(release_files
|
||||
libhunspell.dll
|
||||
libapr-1.dll
|
||||
libaprutil-1.dll
|
||||
libapriconv-1.dll
|
||||
libeay32.dll
|
||||
ssleay32.dll
|
||||
libcollada14dom22.dll
|
||||
glod.dll
|
||||
)
|
||||
|
||||
if(WORD_SIZE EQUAL 32)
|
||||
set(release_files ${release_files}
|
||||
libtcmalloc_minimal.dll
|
||||
)
|
||||
endif(WORD_SIZE EQUAL 32)
|
||||
|
||||
|
||||
if(FMODEX)
|
||||
if (WORD_SIZE EQUAL 32)
|
||||
set(fmodex_dll_file "fmodex.dll")
|
||||
else (WORD_SIZE EQUAL 32)
|
||||
set(fmodex_dll_file "fmodex64.dll")
|
||||
endif (WORD_SIZE EQUAL 32)
|
||||
|
||||
find_path(FMODEX_BINARY_DIR "${fmodex_dll_file}"
|
||||
"${release_src_dir}"
|
||||
"${FMODEX_SDK_DIR}/api"
|
||||
"${FMODEX_SDK_DIR}"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
if(FMODEX_BINARY_DIR)
|
||||
copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Release" out_targets "${fmodex_dll_file}")
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" out_targets "${fmodex_dll_file}")
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Debug" out_targets "${fmodex_dll_file}")
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
endif(FMODEX_BINARY_DIR)
|
||||
endif(FMODEX)
|
||||
|
||||
if(FMOD)
|
||||
find_path(FMOD_BINARY_DIR fmod.dll
|
||||
${release_src_dir}
|
||||
${FMOD_SDK_DIR}/api
|
||||
${FMOD_SDK_DIR}
|
||||
)
|
||||
|
||||
if(FMOD_BINARY_DIR)
|
||||
copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Release" out_targets fmod.dll)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" out_targets fmod.dll)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Debug" out_targets fmod.dll)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
else(FMOD_BINARY_DIR)
|
||||
list(APPEND release_files fmod.dll) #Required for compile. This will cause an error in copying binaries.
|
||||
endif(FMOD_BINARY_DIR)
|
||||
endif(FMOD)
|
||||
|
||||
copy_if_different(
|
||||
${release_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Release"
|
||||
out_targets
|
||||
${release_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${vivox_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Release"
|
||||
out_targets
|
||||
${vivox_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${release_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo"
|
||||
out_targets
|
||||
${release_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${vivox_src_dir}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo"
|
||||
out_targets
|
||||
${vivox_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
|
||||
add_custom_target(copy_win_libs ALL
|
||||
DEPENDS
|
||||
${all_targets}
|
||||
${release_appconfig_file}
|
||||
${relwithdebinfo_appconfig_file}
|
||||
${debug_appconfig_file}
|
||||
)
|
||||
add_dependencies(copy_win_libs prepare)
|
||||
|
||||
181
indra/cmake/CopyWinLibs.cmake.in
Normal file
181
indra/cmake/CopyWinLibs.cmake.in
Normal file
@@ -0,0 +1,181 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
# The copy_win_libs folder contains file lists and a script used to
|
||||
# copy dlls, exes and such needed to run the SecondLife from within
|
||||
# VisualStudio.
|
||||
|
||||
set(LIBS_PREBUILT_DIR "@LIBS_PREBUILT_DIR@")
|
||||
set(LIBS_PREBUILT_LEGACY_DIR "@LIBS_PREBUILT_LEGACY_DIR@")
|
||||
set(MSVC10 "@MSVC10@")
|
||||
set(WORD_SIZE "@WORD_SIZE@")
|
||||
|
||||
set(LIBS_RELEASE_DIR
|
||||
${LIBS_PREBUILT_DIR}/lib/release
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/lib/release
|
||||
)
|
||||
set(LIBS_DEBUG_DIR
|
||||
${LIBS_PREBUILT_DIR}/lib/debug
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/lib/debug
|
||||
)
|
||||
|
||||
function(copy_files paths names dest)
|
||||
string(FIND ${dest} ${CUR_CONFIG} idx)
|
||||
if(${idx} LESS 0)
|
||||
return()
|
||||
endif(${idx} LESS 0)
|
||||
foreach(f ${names})
|
||||
foreach(p ${paths})
|
||||
set(from_file "${p}/${f}")
|
||||
set(to_dest "${CMAKE_BINARY_DIR}/newview/${dest}/")
|
||||
if(EXISTS ${from_file})
|
||||
message("Copying ${from_file} to ${to_dest}")
|
||||
if(NOT EXISTS ${to_dest})
|
||||
execute_process(COMMAND md "${to_dest}")
|
||||
endif(NOT EXISTS ${to_dest})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${from_file}" "${to_dest}${f}" RESULT_VARIABLE result)
|
||||
if(${result})
|
||||
message(SEND_ERROR "Unsuccessful.")
|
||||
endif(${result})
|
||||
set(found 1)
|
||||
break()
|
||||
endif(EXISTS ${from_file})
|
||||
endforeach(p)
|
||||
if(NOT found)
|
||||
message(SEND_ERROR "Failed to find library: ${f}")
|
||||
endif(NOT found)
|
||||
endforeach(f)
|
||||
endfunction(copy_files)
|
||||
|
||||
set(vivox_files
|
||||
ca-bundle.crt
|
||||
libsndfile-1.dll
|
||||
ortp.dll
|
||||
SLVoice.exe
|
||||
vivoxoal.dll
|
||||
vivoxplatform.dll
|
||||
vivoxsdk.dll
|
||||
zlib1.dll
|
||||
)
|
||||
copy_files("${LIBS_RELEASE_DIR}" "${vivox_files}" "Release" )
|
||||
copy_files("${LIBS_RELEASE_DIR}" "${vivox_files}" "RelWithDebInfo")
|
||||
copy_files("${LIBS_DEBUG_DIR}" "${vivox_files}" "Debug")
|
||||
|
||||
set(release_files
|
||||
libhunspell.dll
|
||||
libapr-1.dll
|
||||
libaprutil-1.dll
|
||||
libapriconv-1.dll
|
||||
libeay32.dll
|
||||
ssleay32.dll
|
||||
glod.dll
|
||||
qtcore4.dll
|
||||
)
|
||||
copy_files("${LIBS_RELEASE_DIR}" "${release_files}" "Release")
|
||||
copy_files("${LIBS_RELEASE_DIR}" "${release_files}" "RelWithDebInfo")
|
||||
copy_files("${LIBS_DEBUG_DIR}" "${release_files}" "Debug")
|
||||
|
||||
if(MSVC10)
|
||||
copy_files("${LIBS_DEBUG_DIR}" "libcollada14dom22-d.dll" "Debug")
|
||||
endif(MSVC10)
|
||||
|
||||
if(WORD_SIZE EQUAL 32)
|
||||
set(release_files
|
||||
libcollada14dom22.dll
|
||||
libtcmalloc_minimal.dll
|
||||
)
|
||||
copy_files("${LIBS_RELEASE_DIR}" "${release_files}" "Release")
|
||||
copy_files("${LIBS_RELEASE_DIR}" "${release_files}" "RelWithDebInfo")
|
||||
endif(WORD_SIZE EQUAL 32)
|
||||
|
||||
set(plugins_release_files
|
||||
libeay32.dll
|
||||
qtcore4.dll
|
||||
qtgui4.dll
|
||||
qtnetwork4.dll
|
||||
qtopengl4.dll
|
||||
qtwebkit4.dll
|
||||
ssleay32.dll
|
||||
qtxmlpatterns4.dll
|
||||
)
|
||||
copy_files("${LIBS_RELEASE_DIR}" "${plugins_release_files}" "Release/llplugin")
|
||||
copy_files("${LIBS_RELEASE_DIR}" "${plugins_release_files}" "RelWithDebInfo/llplugin")
|
||||
if(0)
|
||||
copy_files("${LIBS_RELEASE_DIR}" "${plugin_release_files}" "../test_apps/llplugintest/Release")
|
||||
copy_files("${LIBS_RELEASE_DIR}" "${plugin_release_files}" "../test_apps/llplugintest/RelWithDebInfo")
|
||||
endif(0)
|
||||
|
||||
# Debug config runtime files required for the plugins
|
||||
set(plugins_debug_files
|
||||
libeay32.dll
|
||||
qtcored4.dll
|
||||
qtguid4.dll
|
||||
qtnetworkd4.dll
|
||||
qtopengld4.dll
|
||||
qtwebkitd4.dll
|
||||
ssleay32.dll
|
||||
qtxmlpatternsd4.dll
|
||||
)
|
||||
copy_files("${LIBS_DEBUG_DIR}" "${plugins_debug_files}" "Debug/llplugin")
|
||||
if(0)
|
||||
copy_files("${LIBS_DEBUG_DIR}" "${plugins_debug_files}" "../test_apps/llplugintest/Debug")
|
||||
endif(0)
|
||||
|
||||
# Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins)
|
||||
set(plugin_image_release_files
|
||||
qgif4.dll
|
||||
qico4.dll
|
||||
qjpeg4.dll
|
||||
qmng4.dll
|
||||
qsvg4.dll
|
||||
qtiff4.dll
|
||||
)
|
||||
copy_files("${LIBS_RELEASE_DIR}/imageformats" "${plugin_image_release_files}" "Release/llplugin/imageformats")
|
||||
copy_files("${LIBS_RELEASE_DIR}/imageformats" "${plugin_image_release_files}" "RelWithDebInfo/llplugin/imageformats")
|
||||
if(0)
|
||||
copy_files("${LIBS_RELEASE_DIR}/imageformats" "${plugin_image_release_files}" "../test_apps/llplugintest/imageformats/Release")
|
||||
copy_files("${LIBS_RELEASE_DIR}/imageformats" "${plugin_image_release_files}" "../test_apps/llplugintest/imageformats/RelWithDebInfo")
|
||||
endif(0)
|
||||
|
||||
|
||||
# Debug config runtime files required for the plugin test mule (Qt image format plugins)
|
||||
set(plugin_image_debug_files
|
||||
qgifd4.dll
|
||||
qicod4.dll
|
||||
qjpegd4.dll
|
||||
qmngd4.dll
|
||||
qsvgd4.dll
|
||||
qtiffd4.dll
|
||||
)
|
||||
copy_files("${LIBS_DEBUG_DIR}/imageformats" "${plugin_image_debug_files}" "Debug/llplugin/imageformats")
|
||||
if(0)
|
||||
copy_files("${LIBS_DEBUG_DIR}/imageformats" "${plugin_image_debug_files}" "../test_apps/llplugintest/imageformats/Debug")
|
||||
endif(0)
|
||||
|
||||
# Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins)
|
||||
set(plugin_codec_release_files
|
||||
qcncodecs4.dll
|
||||
qjpcodecs4.dll
|
||||
qkrcodecs4.dll
|
||||
qtwcodecs4.dll
|
||||
)
|
||||
copy_files("${LIBS_RELEASE_DIR}/codecs" "${plugin_codec_release_files}" "Release/llplugin/codecs")
|
||||
copy_files("${LIBS_RELEASE_DIR}/codecs" "${plugin_codec_release_files}" "RelWithDebInfo/llplugin/codecs")
|
||||
if(0)
|
||||
copy_files("${LIBS_RELEASE_DIR}/codecs" "${plugin_codec_release_files}" "../test_apps/llplugintest/codecs/Release")
|
||||
copy_files("${LIBS_RELEASE_DIR}/codecs" "${plugin_codec_release_files}" "../test_apps/llplugintest/codecs/RelWithDebInfo")
|
||||
endif(0)
|
||||
|
||||
# Debug config runtime files required for the plugin test mule (Qt image format plugins)
|
||||
set(plugin_codec_debug_files
|
||||
qcncodecsd4.dll
|
||||
qjpcodecsd4.dll
|
||||
qkrcodecsd4.dll
|
||||
qtwcodecsd4.dll
|
||||
)
|
||||
copy_files("${LIBS_DEBUG_DIR}/codecs" "${plugin_codec_debug_files}" "Debug/llplugin/codecs")
|
||||
if(0)
|
||||
copy_files("${LIBS_DEBUG_DIR}/codecs" "${plugin_codec_debug_files}" "../test_apps/llplugintest/codecs/Debug")
|
||||
endif(0)
|
||||
|
||||
|
||||
|
||||
@@ -10,8 +10,9 @@ elseif (LINUX)
|
||||
use_prebuilt_binary(dbusglib)
|
||||
set(DBUSGLIB_FOUND ON FORCE BOOL)
|
||||
set(DBUSGLIB_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/dbus
|
||||
)
|
||||
${LIBS_PREBUILT_DIR}/include/dbus
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/dbus
|
||||
)
|
||||
# We don't need to explicitly link against dbus-glib itself, because
|
||||
# the viewer probes for the system's copy at runtime.
|
||||
set(DBUSGLIB_LIBRARIES
|
||||
|
||||
@@ -11,25 +11,32 @@ if (WINDOWS)
|
||||
set (DIRECTX_ARCHITECTURE x86)
|
||||
endif (WORD_SIZE EQUAL 32)
|
||||
|
||||
SET(program_files $ENV{ProgramW6432})
|
||||
if(NOT program_files)
|
||||
SET(program_files $ENV{ProgramFiles})
|
||||
endif(NOT program_files)
|
||||
SET(program_files_x86 "ProgramFiles(x86)")
|
||||
SET(program_files_x86 $ENV{${program_files_x86}})
|
||||
|
||||
find_path(DIRECTX_ROOT_DIR Include/dxdiag.h
|
||||
PATHS
|
||||
"$ENV{DXSDK_DIR}"
|
||||
"$ENV{ProgramFiles}/Microsoft DirectX SDK (June 2010)"
|
||||
"$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (June 2010)"
|
||||
"$ENV{ProgramFiles}/Microsoft DirectX SDK (February 2010)"
|
||||
"$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (February 2010)"
|
||||
"$ENV{ProgramFiles}/Microsoft DirectX SDK (March 2009)"
|
||||
"$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (March 2009)"
|
||||
"$ENV{ProgramFiles}/Microsoft DirectX SDK (August 2008)"
|
||||
"$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (August 2008)"
|
||||
"$ENV{ProgramFiles}/Microsoft DirectX SDK (June 2008)"
|
||||
"$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (June 2008)"
|
||||
"$ENV{ProgramFiles}/Microsoft DirectX SDK (March 2008)"
|
||||
"$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (March 2008)"
|
||||
"$ENV{ProgramFiles}/Microsoft DirectX SDK (November 2007)"
|
||||
"$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (November 2007)"
|
||||
"$ENV{ProgramFiles}/Microsoft DirectX SDK (August 2007)"
|
||||
"$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (August 2007)"
|
||||
"${program_files}/Microsoft DirectX SDK (June 2010)"
|
||||
"${program_files_x86}/Microsoft DirectX SDK (June 2010)"
|
||||
"${program_files}/Microsoft DirectX SDK (February 2010)"
|
||||
"${program_files_x86}/Microsoft DirectX SDK (February 2010)"
|
||||
"${program_files}/Microsoft DirectX SDK (March 2009)"
|
||||
"${program_files_x86}/Microsoft DirectX SDK (March 2009)"
|
||||
"${program_files}/Microsoft DirectX SDK (August 2008)"
|
||||
"${program_files_x86}/Microsoft DirectX SDK (August 2008)"
|
||||
"${program_files}/Microsoft DirectX SDK (June 2008)"
|
||||
"${program_files_x86}/Microsoft DirectX SDK (June 2008)"
|
||||
"${program_files}/Microsoft DirectX SDK (March 2008)"
|
||||
"${program_files_x86}/Microsoft DirectX SDK (March 2008)"
|
||||
"${program_files}/Microsoft DirectX SDK (November 2007)"
|
||||
"${program_files_x86}/Microsoft DirectX SDK (November 2007)"
|
||||
"${program_files}/Microsoft DirectX SDK (August 2007)"
|
||||
"${program_files_x86}/Microsoft DirectX SDK (August 2007)"
|
||||
)
|
||||
|
||||
if (DIRECTX_ROOT_DIR)
|
||||
@@ -38,10 +45,10 @@ if (WINDOWS)
|
||||
else (DIRECTX_ROOT_DIR)
|
||||
find_path (WIN_KIT_ROOT_DIR Include/um/windows.h
|
||||
PATHS
|
||||
"$ENV{ProgramFiles}/Windows Kits/8.1"
|
||||
"$ENV{ProgramFiles(x86)}/Windows Kits/8.1"
|
||||
"$ENV{ProgramFiles}/Windows Kits/8.0"
|
||||
"$ENV{ProgramFiles(x86)}/Windows Kits/8.0"
|
||||
"${program_files}/Windows Kits/8.1"
|
||||
"${program_files_x86}/Windows Kits/8.1"
|
||||
"${program_files}/Windows Kits/8.0"
|
||||
"${program_files_x86}/Windows Kits/8.0"
|
||||
)
|
||||
|
||||
find_path (WIN_KIT_LIB_DIR dxguid.lib
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# The top-level CMakeLists.txt configures packages and tool locations.
|
||||
set(packages "@PREBUILT_PACKAGES@")
|
||||
set(python "@PYTHON_EXECUTABLE@")
|
||||
set(install_dir "@CMAKE_SOURCE_DIR@/..")
|
||||
set(install_dir "@CMAKE_BINARY_DIR@/packages")
|
||||
set(scp "@SCP_EXECUTABLE@")
|
||||
set(scripts_dir "@SCRIPTS_DIR@")
|
||||
set(sentinel_dir "@CMAKE_BINARY_DIR@/prepare")
|
||||
@@ -20,7 +20,7 @@ foreach(package ${packages})
|
||||
# This package is missing or out of date.
|
||||
message(STATUS "Obtaining${proprietary_message} prebuilt '${package}'")
|
||||
execute_process(
|
||||
COMMAND ${python} install.py -p${prebuilt_type} --install-dir=${install_dir} ${scp_option} ${package}
|
||||
COMMAND ${python} install.py -p${prebuilt_type} --install-dir=${install_dir} --installed-manifest=${install_dir}/installed.xml ${scp_option} ${package}
|
||||
WORKING_DIRECTORY ${scripts_dir}
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
|
||||
@@ -8,7 +8,10 @@ if (STANDALONE)
|
||||
elseif (LINUX)
|
||||
use_prebuilt_binary(elfio)
|
||||
set(ELFIO_LIBRARIES ELFIO)
|
||||
set(ELFIO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(ELFIO_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
set(ELFIO_FOUND "YES")
|
||||
endif (STANDALONE)
|
||||
|
||||
|
||||
@@ -9,9 +9,16 @@ if (STANDALONE)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(expat)
|
||||
if (WINDOWS)
|
||||
set(EXPAT_LIBRARIES libexpatMT)
|
||||
if (MSVC12)
|
||||
set(EXPAT_LIBRARIES expat)
|
||||
else (MSVC12)
|
||||
set(EXPAT_LIBRARIES libexpatMT)
|
||||
endif (MSVC12)
|
||||
else (WINDOWS)
|
||||
set(EXPAT_LIBRARIES expat)
|
||||
endif (WINDOWS)
|
||||
set(EXPAT_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(EXPAT_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
include(Linking)
|
||||
|
||||
if(INSTALL_PROPRIETARY)
|
||||
include(Prebuilt)
|
||||
use_prebuilt_binary(fmod)
|
||||
endif(INSTALL_PROPRIETARY)
|
||||
|
||||
find_library(FMOD_LIBRARY
|
||||
NAMES fmod fmodvc fmod-3.75
|
||||
PATHS
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}
|
||||
)
|
||||
|
||||
if (NOT FMOD_LIBRARY)
|
||||
set(FMOD_SDK_DIR CACHE PATH "Path to the FMOD SDK.")
|
||||
if (FMOD_SDK_DIR)
|
||||
find_library(FMOD_LIBRARY
|
||||
NAMES fmodvc fmod-3.75 fmod
|
||||
PATHS
|
||||
${FMOD_SDK_DIR}/api/lib
|
||||
${FMOD_SDK_DIR}/api
|
||||
${FMOD_SDK_DIR}/lib
|
||||
${FMOD_SDK_DIR}
|
||||
)
|
||||
endif (FMOD_SDK_DIR)
|
||||
endif (NOT FMOD_LIBRARY)
|
||||
|
||||
find_path(FMOD_INCLUDE_DIR fmod.h
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include
|
||||
${FMOD_SDK_DIR}/api/inc
|
||||
${FMOD_SDK_DIR}/inc
|
||||
${FMOD_SDK_DIR}
|
||||
)
|
||||
|
||||
if (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
|
||||
set(FMOD ON CACHE BOOL "Use closed source FMOD sound library.")
|
||||
else (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
|
||||
set(FMOD_LIBRARY "")
|
||||
set(FMOD_INCLUDE_DIR "")
|
||||
if (FMOD)
|
||||
message(STATUS "No support for FMOD audio (need to set FMOD_SDK_DIR?)")
|
||||
endif (FMOD)
|
||||
set(FMOD OFF CACHE BOOL "Use closed source FMOD sound library.")
|
||||
endif (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
|
||||
|
||||
if (FMOD)
|
||||
message(STATUS "Building with FMOD audio support")
|
||||
endif (FMOD)
|
||||
@@ -2,81 +2,115 @@
|
||||
|
||||
include(Linking)
|
||||
|
||||
if (NOT FMODEX_LIBRARY)
|
||||
set(FMODEX_SDK_DIR CACHE PATH "Path to the FMOD Ex SDK.")
|
||||
if (FMODEX_SDK_DIR)
|
||||
if(WORD_SIZE EQUAL 32)
|
||||
find_library(FMODEX_LIBRARY
|
||||
fmodex_vc fmodexL_vc fmodex fmodexL
|
||||
PATHS
|
||||
"${FMODEX_SDK_DIR}/api/lib"
|
||||
"${FMODEX_SDK_DIR}/api"
|
||||
"${FMODEX_SDK_DIR}/lib"
|
||||
"${FMODEX_SDK_DIR}"
|
||||
)
|
||||
elseif(WORD_SIZE EQUAL 64)
|
||||
find_library(FMODEX_LIBRARY
|
||||
fmodex64_vc fmodexL64_vc fmodex64 fmodexL64
|
||||
PATHS
|
||||
"${FMODEX_SDK_DIR}/api/lib"
|
||||
"${FMODEX_SDK_DIR}/api"
|
||||
"${FMODEX_SDK_DIR}/lib"
|
||||
"${FMODEX_SDK_DIR}"
|
||||
)
|
||||
endif(WORD_SIZE EQUAL 32)
|
||||
endif(FMODEX_SDK_DIR)
|
||||
if(WINDOWS AND NOT FMODEX_SDK_DIR)
|
||||
GET_FILENAME_COMPONENT(FMODEX_PROG_DIR [HKEY_CURRENT_USER\\Software\\FMOD\ Programmers\ API\ Windows] ABSOLUTE CACHE)
|
||||
if(WORD_SIZE EQUAL 32)
|
||||
find_library(FMODEX_LIBRARY
|
||||
fmodex_vc fmodexL_vc
|
||||
PATHS
|
||||
"${FMODEX_PROG_DIR}/api/lib"
|
||||
"${FMODEX_PROG_DIR}/api"
|
||||
"${FMODEX_PROG_DIR}"
|
||||
)
|
||||
else(WORD_SIZE EQUAL 32)
|
||||
find_library(FMODEX_LIBRARY
|
||||
fmodex64_vc fmodexL64_vc
|
||||
PATHS
|
||||
"${FMODEX_PROG_DIR}/api/lib"
|
||||
"${FMODEX_PROG_DIR}/api"
|
||||
"${FMODEX_PROG_DIR}"
|
||||
)
|
||||
endif(WORD_SIZE EQUAL 32)
|
||||
if(FMODEX_LIBRARY)
|
||||
message(STATUS "Found fmodex in ${FMODEX_PROG_DIR}")
|
||||
set(FMODEX_SDK_DIR "${FMODEX_PROG_DIR}")
|
||||
set(FMODEX_SDK_DIR "${FMODEX_PROG_DIR}" CACHE PATH "Path to the FMOD Ex SDK." FORCE)
|
||||
endif(FMODEX_LIBRARY)
|
||||
endif(WINDOWS AND NOT FMODEX_SDK_DIR)
|
||||
endif (NOT FMODEX_LIBRARY)
|
||||
if (FMODEX AND FMODSTUDIO)
|
||||
message( FATAL_ERROR "You can not enable two FMOD variants at the same time." )
|
||||
endif (FMODEX AND FMODSTUDIO)
|
||||
|
||||
find_path(FMODEX_INCLUDE_DIR fmod.hpp
|
||||
"${LIBS_PREBUILT_DIR}/include/fmodex"
|
||||
"${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/fmodex"
|
||||
"${FMODEX_SDK_DIR}/api/inc"
|
||||
"${FMODEX_SDK_DIR}/inc"
|
||||
"${FMODEX_SDK_DIR}"
|
||||
)
|
||||
unset(FMOD_LIBRARY_RELEASE CACHE)
|
||||
unset(FMOD_LIBRARY_DEBUG CACHE)
|
||||
unset(FMOD_INCLUDE_DIR CACHE)
|
||||
|
||||
if(DARWIN)
|
||||
set(FMODEX_ORIG_LIBRARY "${FMODEX_LIBRARY}")
|
||||
set(FMODEX_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/libfmodex.dylib")
|
||||
endif(DARWIN)
|
||||
set(FMOD_EXTERNAL_LIB OFF)
|
||||
|
||||
if (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
|
||||
set(FMODEX ON CACHE BOOL "Use closed source FMOD Ex sound library.")
|
||||
else (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
|
||||
set(FMODEX_LIBRARY "")
|
||||
set(FMODEX_INCLUDE_DIR "")
|
||||
if (FMODEX)
|
||||
message(STATUS "No support for FMOD Ex audio (need to set FMODEX_SDK_DIR?)")
|
||||
endif (FMODEX)
|
||||
set(FMODEX OFF CACHE BOOL "Use closed source FMOD Ex sound library.")
|
||||
if(STANDALONE OR WINDOWS)
|
||||
if (NOT FMODEX_SDK_DIR AND WINDOWS)
|
||||
GET_FILENAME_COMPONENT(REG_DIR [HKEY_CURRENT_USER\\Software\\FMOD\ Programmers\ API\ Windows] ABSOLUTE)
|
||||
set(FMODEX_SDK_DIR ${REG_DIR} CACHE PATH "Path to the FMOD Ex SDK." FORCE)
|
||||
endif (NOT FMODEX_SDK_DIR AND WINDOWS)
|
||||
if(NOT FMODEX_SDK_DIR AND STANDALONE)
|
||||
message(FATAL_ERROR "FMODEX_SDK_DIR not set!")
|
||||
endif(NOT FMODEX_SDK_DIR AND STANDALONE)
|
||||
endif(STANDALONE OR WINDOWS)
|
||||
|
||||
if(FMODEX_SDK_DIR)
|
||||
set(fmod_lib_paths "${FMODEX_SDK_DIR}/api" "${FMODEX_SDK_DIR}/api/lib" )
|
||||
set(fmod_inc_paths "${FMODEX_SDK_DIR}/api/inc")
|
||||
|
||||
if(WINDOWS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES_OLD ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .dll)
|
||||
endif(WINDOWS)
|
||||
if(WORD_SIZE EQUAL 64)
|
||||
find_library(FMOD_LIBRARY_RELEASE fmodex64 PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
find_library(FMOD_LIBRARY_DEBUG fmodexL64 PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
else(WORD_SIZE EQUAL 64)#Check if CMAKE_FIND_LIBRARY_PREFIXES is set to 'lib' for darwin.
|
||||
find_library(FMOD_LIBRARY_RELEASE fmodex PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
find_library(FMOD_LIBRARY_DEBUG fmodexL PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
endif(WORD_SIZE EQUAL 64)
|
||||
if(WINDOWS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_OLD})
|
||||
if(WORD_SIZE EQUAL 64)
|
||||
find_library(FMOD_LINK_LIBRARY_RELEASE fmodex64_vc PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
find_library(FMOD_LINK_LIBRARY_DEBUG fmodexL64_vc PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
else(WORD_SIZE EQUAL 64)#Check if CMAKE_FIND_LIBRARY_PREFIXES is set to 'lib' for darwin.
|
||||
find_library(FMOD_LINK_LIBRARY_RELEASE fmodex_vc PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
find_library(FMOD_LINK_LIBRARY_DEBUG fmodexL_vc PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
endif(WORD_SIZE EQUAL 64)
|
||||
else(WINDOWS)
|
||||
set(FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE})
|
||||
set(FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG})
|
||||
endif(WINDOWS)
|
||||
find_path(FMOD_INCLUDE_DIR fmod.hpp ${fmod_inc_paths})
|
||||
if(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR)
|
||||
if(STANDALONE)
|
||||
message(FATAL_ERROR "Provided FMODEX_SDK_DIR path not found '{$FMODEX_SDK_DIR}'")
|
||||
else(STANDALONE)
|
||||
message(STATUS "Provided FMODEX_SDK_DIR path not found '${FMODEX_SDK_DIR}'. Falling back to prebuilts")
|
||||
endif(STANDALONE)
|
||||
else(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR)
|
||||
message(STATUS "Using system-provided FMOD Ex Libraries")
|
||||
set(FMOD_EXTERNAL_LIB ON)
|
||||
endif(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR)
|
||||
endif (FMODEX_SDK_DIR)
|
||||
|
||||
if (NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR)
|
||||
if(WINDOWS)
|
||||
set(lib_suffix .dll)
|
||||
elseif(DARWIN)
|
||||
set(lib_suffix .dylib)
|
||||
else(WINDOWS)
|
||||
set(lib_suffix .so)
|
||||
endif(WINDOWS)
|
||||
if(WINDOWS)
|
||||
if(WORD_SIZE EQUAL 64)
|
||||
set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/fmodex64${lib_suffix})
|
||||
set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/fmodexL64${lib_suffix})
|
||||
else(WORD_SIZE EQUAL 64)
|
||||
set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/fmodex${lib_suffix})
|
||||
set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/fmodexL${lib_suffix})
|
||||
endif(WORD_SIZE EQUAL 64)
|
||||
else(WINDOWS)
|
||||
if(WORD_SIZE EQUAL 64)
|
||||
set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/libfmodex64${lib_suffix})
|
||||
set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/libfmodex64L${lib_suffix})
|
||||
else(WORD_SIZE EQUAL 64)
|
||||
set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/libfmodex${lib_suffix})
|
||||
set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/libfmodexL${lib_suffix})
|
||||
endif(WORD_SIZE EQUAL 64)
|
||||
endif(WINDOWS)
|
||||
set(FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE})
|
||||
set(FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG})
|
||||
if(WINDOWS)
|
||||
string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE})
|
||||
string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG})
|
||||
endif(WINDOWS)
|
||||
use_prebuilt_binary(fmodex)
|
||||
set(FMOD_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/include/fmodex)
|
||||
endif(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR)
|
||||
|
||||
if(FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR)
|
||||
set(FMOD ON)
|
||||
if (NOT FMOD_LIBRARY_DEBUG) #Use release library in debug configuration if debug library is absent.
|
||||
set(FMOD_LIBRARY_DEBUG ${FMOD_LIBRARY_RELEASE})
|
||||
endif (NOT FMOD_LIBRARY_DEBUG)
|
||||
else (FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR)
|
||||
message(STATUS "No support for FMOD EX audio (need to set FMODEX_SDK_DIR?)")
|
||||
set(FMOD OFF)
|
||||
set(FMODEX OFF)
|
||||
endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
|
||||
endif (FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR)
|
||||
|
||||
if (FMODEX)
|
||||
if (FMOD)
|
||||
message(STATUS "Building with FMOD Ex audio support")
|
||||
endif (FMODEX)
|
||||
set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX")
|
||||
endif (FMOD)
|
||||
|
||||
112
indra/cmake/FMODSTUDIO.cmake
Normal file
112
indra/cmake/FMODSTUDIO.cmake
Normal file
@@ -0,0 +1,112 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
include(Linking)
|
||||
|
||||
if (FMODEX AND FMODSTUDIO)
|
||||
message( FATAL_ERROR "You can not enable two FMOD variants at the same time." )
|
||||
endif (FMODEX AND FMODSTUDIO)
|
||||
|
||||
unset(FMOD_LIBRARY_RELEASE CACHE)
|
||||
unset(FMOD_LIBRARY_DEBUG CACHE)
|
||||
unset(FMOD_INCLUDE_DIR CACHE)
|
||||
|
||||
set(FMOD_EXTERNAL_LIB OFF)
|
||||
|
||||
if(STANDALONE OR WINDOWS)
|
||||
if (NOT FMODSTUDIO_SDK_DIR AND WINDOWS)
|
||||
#GET_FILENAME_COMPONENT(REG_DIR [HKEY_CURRENT_USER\\Software\\FMOD\ Studio\ API\ Windows] ABSOLUTE)
|
||||
#set(FMODSTUDIO_SDK_DIR ${REG_DIR} CACHE PATH "Path to the FMOD Studio SDK." FORCE)
|
||||
endif (NOT FMODSTUDIO_SDK_DIR AND WINDOWS)
|
||||
if(NOT FMODSTUDIO_SDK_DIR AND STANDALONE)
|
||||
message(FATAL_ERROR "FMODSTUDIO_SDK_DIR not set!")
|
||||
endif(NOT FMODSTUDIO_SDK_DIR AND STANDALONE)
|
||||
endif(STANDALONE OR WINDOWS)
|
||||
|
||||
if(FMODSTUDIO_SDK_DIR)
|
||||
if(LINUX AND WORD_SIZE EQUAL 32)
|
||||
set(fmod_lib_paths "${FMODSTUDIO_SDK_DIR}/api/lowlevel/lib/x86" )
|
||||
elseif(LINUX)
|
||||
set(fmod_lib_paths "${FMODSTUDIO_SDK_DIR}/api/lowlevel/lib/x86_64")
|
||||
else(LINUX AND WORD_SIZE EQUAL 32)
|
||||
set(fmod_lib_paths "${FMODSTUDIO_SDK_DIR}/api/lowlevel/lib")
|
||||
endif(LINUX AND WORD_SIZE EQUAL 32)
|
||||
set(fmod_inc_paths "${FMODSTUDIO_SDK_DIR}/api/lowlevel/inc")
|
||||
|
||||
if(WINDOWS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES_OLD ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .dll)
|
||||
endif(WINDOWS)
|
||||
if(WORD_SIZE EQUAL 64 AND WINDOWS)
|
||||
find_library(FMOD_LIBRARY_RELEASE fmod64 PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
find_library(FMOD_LIBRARY_DEBUG fmodL64 PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
else(WORD_SIZE EQUAL 64 AND WINDOWS)#Check if CMAKE_FIND_LIBRARY_PREFIXES is set to 'lib' for darwin.
|
||||
find_library(FMOD_LIBRARY_RELEASE fmod PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
find_library(FMOD_LIBRARY_DEBUG fmodL PATHS ${fmod_lib_paths} NO_DEFAULT_PATH)
|
||||
endif(WORD_SIZE EQUAL 64 AND WINDOWS)
|
||||
if(WINDOWS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_OLD})
|
||||
string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE})
|
||||
string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG})
|
||||
else(WINDOWS)
|
||||
set(FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE})
|
||||
set(FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG})
|
||||
endif(WINDOWS)
|
||||
find_path(FMOD_INCLUDE_DIR fmod.hpp ${fmod_inc_paths})
|
||||
if(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR)
|
||||
if(STANDALONE)
|
||||
message(FATAL_ERROR "Provided FMODSTUDIO_SDK_DIR path not found '{$FMODSTUDIO_SDK_DIR}'")
|
||||
else(STANDALONE)
|
||||
message(STATUS "Provided FMODSTUDIO_SDK_DIR path not found '${FMODSTUDIO_SDK_DIR}'. Falling back to prebuilts")
|
||||
endif(STANDALONE)
|
||||
else(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR)
|
||||
message(STATUS "Using system-provided FMOD Studio Libraries")
|
||||
set(FMOD_EXTERNAL_LIB ON)
|
||||
endif(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR)
|
||||
endif (FMODSTUDIO_SDK_DIR)
|
||||
|
||||
if (NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR)
|
||||
if(WINDOWS)
|
||||
set(lib_suffix .dll)
|
||||
elseif(DARWIN)
|
||||
set(lib_suffix .dylib)
|
||||
else(WINDOWS)
|
||||
set(lib_suffix .so)
|
||||
endif(WINDOWS)
|
||||
if(WINDOWS)
|
||||
if(WORD_SIZE EQUAL 64)
|
||||
set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/fmod64${lib_suffix})
|
||||
set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/fmodL64${lib_suffix})
|
||||
else(WORD_SIZE EQUAL 64)
|
||||
set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/fmod${lib_suffix})
|
||||
set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/fmodL${lib_suffix})
|
||||
endif(WORD_SIZE EQUAL 64)
|
||||
else(WINDOWS)
|
||||
set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/libfmod${lib_suffix})
|
||||
set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/libfmodL${lib_suffix})
|
||||
endif(WINDOWS)
|
||||
set(FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE})
|
||||
set(FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG})
|
||||
if(WINDOWS)
|
||||
string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE})
|
||||
string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG})
|
||||
endif(WINDOWS)
|
||||
use_prebuilt_binary(fmodstudio)
|
||||
set(FMOD_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/include/fmodstudio)
|
||||
endif(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR)
|
||||
|
||||
if(FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR)
|
||||
set(FMOD ON)
|
||||
if (NOT FMOD_LIBRARY_DEBUG) #Use release library in debug configuration if debug library is absent.
|
||||
set(FMOD_LIBRARY_DEBUG ${FMOD_LIBRARY_RELEASE})
|
||||
endif (NOT FMOD_LIBRARY_DEBUG)
|
||||
else (FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR)
|
||||
message(STATUS "No support for FMOD Studio audio (need to set FMODSTUDIO_SDK_DIR?)")
|
||||
set(FMOD OFF)
|
||||
set(FMODSTUDIO OFF)
|
||||
endif (FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR)
|
||||
|
||||
if (FMOD)
|
||||
message(STATUS "Building with FMOD Studio audio support")
|
||||
set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODSTUDIO")
|
||||
endif (FMOD)
|
||||
@@ -7,12 +7,17 @@ if (STANDALONE)
|
||||
pkg_check_modules(FREETYPE REQUIRED freetype2)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(freetype)
|
||||
if (LINUX)
|
||||
if(MSVC12)
|
||||
set(FREETYPE_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
else (LINUX)
|
||||
set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
endif (LINUX)
|
||||
${LIBS_PREBUILT_DIR}/include/freetype2
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/freetype2
|
||||
)
|
||||
else(MSVC12)
|
||||
set(FREETYPE_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
endif (MSVC12)
|
||||
|
||||
set(FREETYPE_LIBRARIES freetype)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -8,6 +8,9 @@ if (STANDALONE)
|
||||
include(FindGLOD)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(GLOD)
|
||||
set(GLOD_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(GLOD_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
set(GLOD_LIBRARIES glod)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -16,10 +16,13 @@ else (STANDALONE)
|
||||
set(GSTREAMER010_FOUND ON FORCE BOOL)
|
||||
set(GSTREAMER010_PLUGINS_BASE_FOUND ON FORCE BOOL)
|
||||
set(GSTREAMER010_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gstreamer-0.10
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2
|
||||
)
|
||||
${LIBS_PREBUILT_DIR}/include/gstreamer-0.10
|
||||
${LIBS_PREBUILT_DIR}/includeg/lib-2.0
|
||||
${LIBS_PREBUILT_DIR}/include/libxml2
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/gstreamer-0.10
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/glib-2.0
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/libxml2
|
||||
)
|
||||
|
||||
endif (STANDALONE)
|
||||
|
||||
|
||||
@@ -17,5 +17,10 @@ else (STANDALONE)
|
||||
endif (WINDOWS)
|
||||
# yes, this does look dumb, no, it's not incorrect
|
||||
# I think it's incorrect: the second one should go --Aleric
|
||||
set(BREAKPAD_INCLUDE_DIRECTORIES "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/google_breakpad" "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/google_breakpad/google_breakpad")
|
||||
set(BREAKPAD_INCLUDE_DIRECTORIES
|
||||
${LIBS_PREBUILT_DIR}/include/google_breakpad
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/google_breakpad
|
||||
${LIBS_PREBUILT_DIR}/include/google_breakpad/google_breakpad
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/google_breakpad/google_breakpad
|
||||
)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -25,7 +25,9 @@ else (STANDALONE)
|
||||
set(TCMALLOC_LIBRARIES tcmalloc_minimal)
|
||||
endif()
|
||||
set(GOOGLE_PERFTOOLS_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
endif (LINUX)
|
||||
endif (STANDALONE)
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@ if (STANDALONE)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(hunspell)
|
||||
|
||||
set(HUNSPELL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/hunspell)
|
||||
set(HUNSPELL_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/include/hunspell
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/hunspell
|
||||
)
|
||||
|
||||
if (LINUX OR DARWIN)
|
||||
set(HUNSPELL_LIBRARY hunspell-1.3)
|
||||
|
||||
@@ -13,11 +13,14 @@ else (STANDALONE)
|
||||
set(JPEG_LIBRARIES jpeg)
|
||||
elseif (DARWIN)
|
||||
set(JPEG_LIBRARIES
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libjpeg.a
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libjpeg.a
|
||||
debug libjpeg.a
|
||||
optimized libjpeg.a
|
||||
)
|
||||
elseif (WINDOWS)
|
||||
set(JPEG_LIBRARIES jpeglib)
|
||||
endif (LINUX)
|
||||
set(JPEG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(JPEG_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -10,13 +10,22 @@ if (STANDALONE)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(jsoncpp)
|
||||
if (WINDOWS)
|
||||
set(JSONCPP_LIBRARIES
|
||||
debug json_vc${MSVC_SUFFIX}d
|
||||
optimized json_vc${MSVC_SUFFIX})
|
||||
if(MSVC12)
|
||||
set(JSONCPP_LIBRARIES
|
||||
debug json_vc${MSVC_SUFFIX}debug_libmt.lib
|
||||
optimized json_vc${MSVC_SUFFIX}_libmt)
|
||||
else(MSVC12)
|
||||
set(JSONCPP_LIBRARIES
|
||||
debug json_vc${MSVC_SUFFIX}d
|
||||
optimized json_vc${MSVC_SUFFIX})
|
||||
endif(MSVC12)
|
||||
elseif (DARWIN)
|
||||
set(JSONCPP_LIBRARIES json_linux-gcc-4.0.1_libmt)
|
||||
elseif (LINUX)
|
||||
set(JSONCPP_LIBRARIES jsoncpp)
|
||||
endif (WINDOWS)
|
||||
set(JSONCPP_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/jsoncpp)
|
||||
set(JSONCPP_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/include/jsoncpp
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/jsoncpp
|
||||
)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -87,7 +87,7 @@ MACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files)
|
||||
${libraries}
|
||||
)
|
||||
|
||||
GET_TARGET_PROPERTY(TEST_EXE ${name}_test LOCATION)
|
||||
SET(TEST_EXE $<TARGET_FILE:${name}_test>)
|
||||
SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}_test_ok.txt)
|
||||
|
||||
IF ("${wrapper}" STREQUAL "")
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
# ll_deploy_sharedlibs_command
|
||||
# target_exe: the cmake target of the executable for which the shared libs will be deployed.
|
||||
macro(ll_deploy_sharedlibs_command target_exe)
|
||||
get_target_property(TARGET_LOCATION ${target_exe} LOCATION)
|
||||
get_filename_component(OUTPUT_PATH ${TARGET_LOCATION} PATH)
|
||||
SET(OUTPUT_PATH $<TARGET_FILE:${target_exe}>)
|
||||
|
||||
if(DARWIN)
|
||||
SET_TEST_PATH(SEARCH_DIRS)
|
||||
get_target_property(IS_BUNDLE ${target_exe} MACOSX_BUNDLE)
|
||||
if(IS_BUNDLE)
|
||||
# If its a bundle the exe is not in the target location, this should find it.
|
||||
get_filename_component(TARGET_FILE ${TARGET_LOCATION} NAME)
|
||||
set(OUTPUT_PATH ${TARGET_LOCATION}.app/Contents/MacOS)
|
||||
set(TARGET_LOCATION ${OUTPUT_PATH}/${TARGET_FILE})
|
||||
set(OUTPUT_PATH ${OUTPUT_PATH}/../Resources)
|
||||
endif(IS_BUNDLE)
|
||||
elseif(WINDOWS)
|
||||
@@ -26,7 +22,7 @@ macro(ll_deploy_sharedlibs_command target_exe)
|
||||
TARGET ${target_exe} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS
|
||||
"-DBIN_NAME=\"${TARGET_LOCATION}\""
|
||||
"-DBIN_NAME=\"$<TARGET_FILE:${target_exe}>\""
|
||||
"-DSEARCH_DIRS=\"${SEARCH_DIRS}\""
|
||||
"-DDST_PATH=\"${OUTPUT_PATH}\""
|
||||
"-P"
|
||||
@@ -42,7 +38,8 @@ macro(ll_stage_sharedlib DSO_TARGET)
|
||||
# Also this directory is shared with RunBuildTest.cmake, y'know, for the tests.
|
||||
set_target_properties(${DSO_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${SHARED_LIB_STAGING_DIR})
|
||||
if(NOT WINDOWS)
|
||||
get_target_property(DSO_PATH ${DSO_TARGET} LOCATION)
|
||||
|
||||
SET(DSO_PATH $<TARGET_FILE:${DSO_TARGET}>)
|
||||
get_filename_component(DSO_FILE ${DSO_PATH} NAME)
|
||||
if(DARWIN)
|
||||
set(SHARED_LIB_STAGING_DIR_CONFIG ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources)
|
||||
|
||||
@@ -17,7 +17,10 @@ else (STANDALONE)
|
||||
use_prebuilt_binary(mesa)
|
||||
use_prebuilt_binary(SDL)
|
||||
set (SDL_FOUND TRUE)
|
||||
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR})
|
||||
set (SDL_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
if(WORD_SIZE EQUAL 64)
|
||||
set (SDL_LIBRARY SDL)
|
||||
else(WORD_SIZE EQUAL 64)
|
||||
|
||||
@@ -5,26 +5,35 @@ set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES")
|
||||
include(Variables)
|
||||
|
||||
if (NOT STANDALONE)
|
||||
set(ARCH_PREBUILT_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib)
|
||||
set(ARCH_PREBUILT_DIRS_RELEASE ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/release)
|
||||
set(ARCH_PREBUILT_DIRS_DEBUG ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/debug)
|
||||
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
|
||||
endif(CMAKE_BUILD_TYPE)
|
||||
|
||||
if(WINDOWS OR ${CMAKE_GENERATOR} MATCHES "Xcode")
|
||||
# the cmake xcode and VS generators implicitly append ${CMAKE_CFG_INTDIR} to the library paths for us
|
||||
# fortunately both windows and darwin are case insensitive filesystems so this works.
|
||||
set(ARCH_PREBUILT_LINK_DIRS "${ARCH_PREBUILT_DIRS}")
|
||||
set(ARCH_PREBUILT_LINK_DIRS
|
||||
${LIBS_PREBUILT_DIR}/lib
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/lib
|
||||
)
|
||||
else(WINDOWS OR ${CMAKE_GENERATOR} MATCHES "Xcode")
|
||||
# else block is for linux and any other makefile based generators
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
|
||||
set(ARCH_PREBUILT_LINK_DIRS ${ARCH_PREBUILT_DIRS}/${CMAKE_BUILD_TYPE_LOWER})
|
||||
set(ARCH_PREBUILT_LINK_DIRS
|
||||
${LIBS_PREBUILT_DIR}/lib/${CMAKE_BUILD_TYPE_LOWER}
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/lib/${CMAKE_BUILD_TYPE_LOWER}
|
||||
)
|
||||
endif(WINDOWS OR ${CMAKE_GENERATOR} MATCHES "Xcode")
|
||||
|
||||
if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release")
|
||||
if (NOT "${CMAKE_BUILD_TYPE_LOWER}" STREQUAL "release")
|
||||
# When we're building something other than Release, append the
|
||||
# packages/lib/release directory to deal with autobuild packages that don't
|
||||
# provide (e.g.) lib/debug libraries.
|
||||
list(APPEND ARCH_PREBUILT_LINK_DIRS ${ARCH_PREBUILT_DIRS_RELEASE})
|
||||
endif (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release")
|
||||
list(APPEND ARCH_PREBUILT_LINK_DIRS
|
||||
${LIBS_PREBUILT_DIR}/lib/release
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/lib/release
|
||||
)
|
||||
endif (NOT "${CMAKE_BUILD_TYPE_LOWER}" STREQUAL "release")
|
||||
endif (NOT STANDALONE)
|
||||
|
||||
link_directories(${ARCH_PREBUILT_LINK_DIRS})
|
||||
@@ -37,7 +46,7 @@ else (LINUX)
|
||||
set(PTHREAD_LIBRARY "")
|
||||
endif (LINUX)
|
||||
|
||||
if (WINDOWS)
|
||||
if (WINDOWS)
|
||||
set(WINDOWS_LIBRARIES
|
||||
advapi32
|
||||
shell32
|
||||
|
||||
@@ -15,7 +15,10 @@ else (STANDALONE)
|
||||
set(NDOF_LIBRARY ndofdev)
|
||||
endif (WINDOWS)
|
||||
|
||||
set(NDOF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/ndofdev)
|
||||
set(NDOF_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/include/ndofdev
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/ndofdev
|
||||
)
|
||||
set(NDOF_FOUND 1)
|
||||
endif (STANDALONE)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
include(Linking)
|
||||
include(Prebuilt)
|
||||
|
||||
if(NOT FMOD)
|
||||
if (LINUX)
|
||||
set(OPENAL ON CACHE BOOL "Enable OpenAL")
|
||||
else (LINUX)
|
||||
@@ -21,9 +22,14 @@ if (OPENAL)
|
||||
openal
|
||||
alut
|
||||
)
|
||||
set(OPENAL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(OPENAL_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
endif (OPENAL)
|
||||
|
||||
if (OPENAL)
|
||||
message(STATUS "Building with OpenAL audio support")
|
||||
set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL")
|
||||
endif (OPENAL)
|
||||
endif(NOT FMOD)
|
||||
|
||||
@@ -3,5 +3,8 @@ include(Prebuilt)
|
||||
|
||||
if (NOT (STANDALONE OR DARWIN))
|
||||
use_prebuilt_binary(glext)
|
||||
set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(GLEXT_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
endif (NOT (STANDALONE OR DARWIN))
|
||||
|
||||
@@ -13,9 +13,14 @@ else (STANDALONE OR USE_SYSTEM_OPENSSL)
|
||||
else (WINDOWS)
|
||||
set(OPENSSL_LIBRARIES ssl)
|
||||
endif (WINDOWS)
|
||||
set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(OPENSSL_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
endif (STANDALONE OR USE_SYSTEM_OPENSSL)
|
||||
|
||||
if (LINUX OR DARWIN)
|
||||
if (LINUX)
|
||||
set(CRYPTO_LIBRARIES crypto dl)
|
||||
elseif (DARWIN)
|
||||
set(CRYPTO_LIBRARIES crypto)
|
||||
endif (LINUX OR DARWIN)
|
||||
endif (LINUX)
|
||||
|
||||
@@ -9,11 +9,42 @@ if (STANDALONE)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(libpng)
|
||||
if (WINDOWS)
|
||||
set(PNG_LIBRARIES libpng15)
|
||||
if(MSVC12)
|
||||
set(PNG_LIBRARIES libpng16)
|
||||
else(MSVC12)
|
||||
set(PNG_LIBRARIES libpng15)
|
||||
endif(MSVC12)
|
||||
elseif(DARWIN)
|
||||
set(PNG_LIBRARIES png15)
|
||||
else(LINUX)
|
||||
set(PNG_LIBRARIES png15)
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 4) # Singu TODO: update png
|
||||
set(PNG_LIBRARIES png15)
|
||||
else ()
|
||||
#
|
||||
# When we have updated static libraries in competition with older
|
||||
# shared libraries and we want the former to win, we need to do some
|
||||
# extra work. The *_PRELOAD_ARCHIVES settings are invoked early
|
||||
# and will pull in the entire archive to the binary giving it
|
||||
# priority in symbol resolution. Beware of cmake moving the
|
||||
# achive load itself to another place on the link command line. If
|
||||
# that happens, you can try something like -Wl,-lpng16 here to hide
|
||||
# the archive. Also be aware that the linker will not tolerate a
|
||||
# second whole-archive load of the archive. See viewer's
|
||||
# CMakeLists.txt for more information.
|
||||
#
|
||||
set(PNG_PRELOAD_ARCHIVES -Wl,--whole-archive png16 -Wl,--no-whole-archive)
|
||||
set(PNG_LIBRARIES png16)
|
||||
endif ()
|
||||
endif()
|
||||
set(PNG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/)
|
||||
if (WINDOWS)
|
||||
set(PNG_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include/${PNG_LIBRARIES}
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/${PNG_LIBRARIES}
|
||||
)
|
||||
else (WINDOWS)
|
||||
set(PNG_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include/lib${PNG_LIBRARIES}
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/lib${PNG_LIBRARIES}
|
||||
)
|
||||
endif (WINDOWS)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -13,8 +13,9 @@ if (PULSEAUDIO)
|
||||
use_prebuilt_binary(pulseaudio)
|
||||
set(PULSEAUDIO_FOUND ON FORCE BOOL)
|
||||
set(PULSEAUDIO_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include
|
||||
)
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
# We don't need to explicitly link against pulseaudio itself, because
|
||||
# the viewer probes for the system's copy at runtime.
|
||||
set(PULSEAUDIO_LIBRARIES
|
||||
|
||||
@@ -9,18 +9,29 @@ if (DARWIN)
|
||||
include(CMakeFindFrameworks)
|
||||
find_library(QUICKTIME_LIBRARY QuickTime)
|
||||
elseif (WINDOWS AND WORD_SIZE EQUAL 32)
|
||||
set(QUICKTIME_SDK_DIR "$ENV{PROGRAMFILES}/QuickTime SDK"
|
||||
SET(program_files "ProgramFiles(x86)")
|
||||
SET(program_files $ENV{${program_files}})
|
||||
if(NOT program_files)
|
||||
SET(program_files $ENV{ProgramW6432})
|
||||
endif(NOT program_files)
|
||||
if(NOT program_files)
|
||||
SET(program_files $ENV{ProgramFiles})
|
||||
endif(NOT program_files)
|
||||
|
||||
set(QUICKTIME_SDK_DIR "${program_files}/QuickTime SDK"
|
||||
CACHE PATH "Location of the QuickTime SDK.")
|
||||
|
||||
find_library(DEBUG_QUICKTIME_LIBRARY qtmlclient
|
||||
PATHS
|
||||
${ARCH_PREBUILT_DIRS_DEBUG}
|
||||
${LIBS_PREBUILT_DIR}/lib/debug
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/lib/debug
|
||||
"${QUICKTIME_SDK_DIR}\\libraries"
|
||||
)
|
||||
|
||||
find_library(RELEASE_QUICKTIME_LIBRARY qtmlclient
|
||||
PATHS
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}
|
||||
${LIBS_PREBUILT_DIR}/lib/release
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/lib/release
|
||||
"${QUICKTIME_SDK_DIR}\\libraries"
|
||||
)
|
||||
|
||||
@@ -33,7 +44,8 @@ elseif (WINDOWS AND WORD_SIZE EQUAL 32)
|
||||
endif (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
|
||||
|
||||
include_directories(
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/quicktime
|
||||
${LIBS_PREBUILT_DIR}/include/quicktime
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/quicktime
|
||||
"${QUICKTIME_SDK_DIR}\\CIncludes"
|
||||
)
|
||||
endif (DARWIN)
|
||||
|
||||
@@ -55,12 +55,18 @@ else (STANDALONE)
|
||||
endif (LINUX)
|
||||
|
||||
include_directories (
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/cairo
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/pixman-1
|
||||
${LIBS_PREBUILT_DIR}/packages/include
|
||||
${LIBS_PREBUILT_DIR}/packages/include/cairo
|
||||
${LIBS_PREBUILT_DIR}/packages/include/pixman-1
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/cairo
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/pixman-1
|
||||
)
|
||||
foreach(include ${${LL_ARCH}_INCLUDES})
|
||||
include_directories(${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/${include})
|
||||
include_directories(
|
||||
${LIBS_PREBUILT_DIR}/include/${include}
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/${include}
|
||||
)
|
||||
endforeach(include)
|
||||
endif (STANDALONE)
|
||||
|
||||
|
||||
@@ -11,6 +11,6 @@ if (INSTALL)
|
||||
set(APP_BIN_DIR bin)
|
||||
endif(NOT APP_BIN_DIR)
|
||||
if(NOT APP_SHARE_DIR)
|
||||
set(APP_SHARE_DIR share/secondlife-${viewer_VERSION})
|
||||
set(APP_SHARE_DIR share/secondlife-${${ROOT_PROJECT_NAME}_VERSION})
|
||||
endif(NOT APP_SHARE_DIR)
|
||||
endif (INSTALL)
|
||||
|
||||
@@ -32,9 +32,6 @@ set(DISABLE_TCMALLOC OFF CACHE BOOL "Disable linkage of TCMalloc. (64bit builds
|
||||
set(LL_TESTS OFF CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation)")
|
||||
set(DISABLE_FATAL_WARNINGS TRUE CACHE BOOL "Set this to FALSE to enable fatal warnings.")
|
||||
|
||||
set(LIBS_PREBUILT_DIR ${CMAKE_SOURCE_DIR}/../libraries CACHE PATH
|
||||
"Location of prebuilt libraries.")
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(WINDOWS ON BOOL FORCE)
|
||||
if (WORD_SIZE EQUAL 32)
|
||||
@@ -154,6 +151,12 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(LL_ARCH_DIR universal-darwin)
|
||||
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
|
||||
set(LIBS_PREBUILT_DIR ${CMAKE_BINARY_DIR}/packages CACHE PATH
|
||||
"Location of prebuilt libraries.")
|
||||
|
||||
set(LIBS_PREBUILT_LEGACY_DIR ${CMAKE_BINARY_DIR}/packages/libraries/${LL_ARCH_DIR} CACHE PATH
|
||||
"Legacy location of prebuilt libraries.")
|
||||
|
||||
if (WINDOWS AND WORD_SIZE EQUAL 32)
|
||||
set(PREBUILT_TYPE windows)
|
||||
elseif (WINDOWS AND WORD_SIZE EQUAL 64)
|
||||
|
||||
@@ -32,8 +32,8 @@ if (WINDOWS)
|
||||
)
|
||||
elseif (DARWIN)
|
||||
set(WEBKIT_PLUGIN_LIBRARIES
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libllqtwebkit.dylib
|
||||
debug libllqtwebkit.dylib
|
||||
optimized libllqtwebkit.dylib
|
||||
)
|
||||
elseif (LINUX)
|
||||
if (STANDALONE)
|
||||
@@ -50,7 +50,6 @@ elseif (LINUX)
|
||||
ssl
|
||||
# qgif
|
||||
# qjpeg
|
||||
jscore
|
||||
jpeg
|
||||
fontconfig
|
||||
X11
|
||||
@@ -58,5 +57,8 @@ elseif (LINUX)
|
||||
Xext
|
||||
GL
|
||||
)
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 4) # Singu TODO: update webkit
|
||||
set(WEBKIT_PLUGIN_LIBRARIES ${WEBKIT_PLUGIN_LIBRARIES} jscore)
|
||||
endif (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
endif (STANDALONE)
|
||||
endif (WINDOWS)
|
||||
|
||||
@@ -9,5 +9,8 @@ if (STANDALONE)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(xmlrpc-epi)
|
||||
set(XMLRPCEPI_LIBRARIES xmlrpc-epi)
|
||||
set(XMLRPCEPI_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
set(XMLRPCEPI_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include
|
||||
)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -17,6 +17,9 @@ else (STANDALONE)
|
||||
set(ZLIB_LIBRARIES z)
|
||||
endif (WINDOWS)
|
||||
if (WINDOWS OR LINUX)
|
||||
set(ZLIB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/zlib)
|
||||
set(ZLIB_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include/zlib
|
||||
${LIBS_PREBUILT_LEGACY_DIR}/include/zlib
|
||||
)
|
||||
endif (WINDOWS OR LINUX)
|
||||
endif (STANDALONE)
|
||||
|
||||
159
indra/develop.py
159
indra/develop.py
@@ -41,6 +41,7 @@ import shutil
|
||||
import socket
|
||||
import sys
|
||||
import commands
|
||||
import shlex
|
||||
|
||||
class CommandError(Exception):
|
||||
pass
|
||||
@@ -111,11 +112,15 @@ class PlatformSetup(object):
|
||||
|
||||
def build_dirs(self):
|
||||
'''Return the top-level directories in which builds occur.
|
||||
|
||||
This can return more than one directory, e.g. if doing a
|
||||
32-bit viewer and server build on Linux.'''
|
||||
|
||||
return ['build-' + self.platform()]
|
||||
if(os.path.basename(os.path.normpath(os.getcwd())) == 'indra'):
|
||||
prefix = '../'
|
||||
else:
|
||||
prefix = ''
|
||||
|
||||
return [prefix+'build-' + self.platform()]
|
||||
|
||||
def cmake_commandline(self, src_dir, build_dir, opts, simple):
|
||||
'''Return the command line to run cmake with.'''
|
||||
@@ -275,9 +280,7 @@ class LinuxSetup(UnixSetup):
|
||||
return 'linux'
|
||||
|
||||
def build_dirs(self):
|
||||
platform_build = '%s-%s' % (self.platform(), self.build_type.lower())
|
||||
|
||||
return ['viewer-' + platform_build]
|
||||
return [PlatformSetup.build_dirs(self)[0]+'-'+self.build_type.lower()]
|
||||
|
||||
def cmake_commandline(self, src_dir, build_dir, opts, simple):
|
||||
args = dict(
|
||||
@@ -399,6 +402,12 @@ class DarwinSetup(UnixSetup):
|
||||
else:
|
||||
return UnixSetup.arch(self)
|
||||
|
||||
def build_dirs(self):
|
||||
if(self.generator == 'Xcode'):
|
||||
return PlatformSetup.build_dirs(self)
|
||||
else:
|
||||
return [PlatformSetup.build_dirs(self)[0]+'-'+self.build_type.lower()]
|
||||
|
||||
def cmake_commandline(self, src_dir, build_dir, opts, simple):
|
||||
args = dict(
|
||||
dir=src_dir,
|
||||
@@ -408,15 +417,17 @@ class DarwinSetup(UnixSetup):
|
||||
word_size=self.word_size,
|
||||
unattended=self.unattended,
|
||||
project_name=self.project_name,
|
||||
universal=self.universal,
|
||||
type=self.build_type.upper(),
|
||||
universal='',
|
||||
type='',
|
||||
)
|
||||
if(self.generator != 'Xcode'):
|
||||
args['type'] = '-DCMAKE_BUILD_TYPE=%s' % self.build_type.upper()
|
||||
if self.universal == 'ON':
|
||||
args['universal'] = '-DCMAKE_OSX_ARCHITECTURES:STRING=\'i386;ppc\''
|
||||
#if simple:
|
||||
# return 'cmake %(opts)s %(dir)r' % args
|
||||
return ('cmake -G %(generator)r '
|
||||
'-DCMAKE_BUILD_TYPE:STRING=%(type)s '
|
||||
'%(type)s '
|
||||
'-DSTANDALONE:BOOL=%(standalone)s '
|
||||
'-DUNATTENDED:BOOL=%(unattended)s '
|
||||
'-DWORD_SIZE:STRING=%(word_size)s '
|
||||
@@ -425,6 +436,18 @@ class DarwinSetup(UnixSetup):
|
||||
'%(opts)s %(dir)r' % args)
|
||||
|
||||
def run_build(self, opts, targets):
|
||||
if(self.generator != 'Xcode'):
|
||||
if targets:
|
||||
targets = ' '.join(targets)
|
||||
else:
|
||||
targets = 'all'
|
||||
|
||||
for d in self.build_dirs():
|
||||
cmd = 'make -C %r %s %s' % (d, ' '.join(opts), targets)
|
||||
print 'Running %r' % cmd
|
||||
self.run(cmd)
|
||||
return
|
||||
|
||||
cwd = getcwd()
|
||||
if targets:
|
||||
targets = ' '.join(['-target ' + repr(t) for t in targets])
|
||||
@@ -447,14 +470,14 @@ class WindowsSetup(PlatformSetup):
|
||||
'gen' : r'Visual Studio 10',
|
||||
'ver' : r'10.0'
|
||||
},
|
||||
'vc110' : {
|
||||
'gen' : r'Visual Studio 11',
|
||||
'ver' : r'11.0'
|
||||
'vc120' : {
|
||||
'gen' : r'Visual Studio 12',
|
||||
'ver' : r'12.0'
|
||||
}
|
||||
}
|
||||
|
||||
gens['vs2010'] = gens['vc100']
|
||||
gens['vs2012'] = gens['vc110']
|
||||
gens['vs2013'] = gens['vc120']
|
||||
|
||||
search_path = r'C:\windows'
|
||||
exe_suffixes = ('.exe', '.bat', '.com')
|
||||
@@ -497,14 +520,24 @@ class WindowsSetup(PlatformSetup):
|
||||
|
||||
generator = property(_get_generator, _set_generator)
|
||||
|
||||
def get_gen_str(self, gen):
|
||||
if gen is None:
|
||||
gen = self._generator
|
||||
return self.gens[gen.lower()]['ver']
|
||||
|
||||
def os(self):
|
||||
return 'win32'
|
||||
|
||||
def build_dirs(self):
|
||||
if self.word_size == 64:
|
||||
return ['build-' + self.generator + '-Win64']
|
||||
if(os.path.basename(os.path.normpath(os.getcwd())) == 'indra'):
|
||||
prefix = '../'
|
||||
else:
|
||||
return ['build-' + self.generator]
|
||||
prefix = ''
|
||||
|
||||
if self.word_size == 64:
|
||||
return [prefix+'build-' + self.generator + '-Win64']
|
||||
else:
|
||||
return [prefix+'build-' + self.generator]
|
||||
|
||||
def cmake_commandline(self, src_dir, build_dir, opts, simple):
|
||||
args = dict(
|
||||
@@ -525,7 +558,7 @@ class WindowsSetup(PlatformSetup):
|
||||
'-DSTANDALONE:BOOL=%(standalone)s '
|
||||
'-DUNATTENDED:BOOL=%(unattended)s '
|
||||
'-DWORD_SIZE:STRING=%(word_size)s '
|
||||
'-DROOT_PROJECT_NAME:STRING=%(project_name)s '
|
||||
'-DROOT_PROJECT_NAME:STRING=\"%(project_name)s\" '
|
||||
'%(opts)s "%(dir)s"' % args)
|
||||
|
||||
def get_HKLM_registry_value(self, key_str, value_str):
|
||||
@@ -537,34 +570,53 @@ class WindowsSetup(PlatformSetup):
|
||||
return value
|
||||
|
||||
def find_visual_studio(self, gen=None):
|
||||
if gen is None:
|
||||
gen = self._generator
|
||||
gen = gen.lower()
|
||||
gen = self.get_gen_str(gen)
|
||||
value_str = (r'EnvironmentDirectory')
|
||||
key_str = (r'SOFTWARE\Microsoft\VisualStudio\%s\Setup\VS' %
|
||||
self.gens[gen]['ver'])
|
||||
gen)
|
||||
print ('Reading VS environment from HKEY_LOCAL_MACHINE\%s\%s' %
|
||||
(key_str, value_str))
|
||||
try:
|
||||
return self.get_HKLM_registry_value(key_str, value_str)
|
||||
except WindowsError, err:
|
||||
key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' %
|
||||
self.gens[gen]['ver'])
|
||||
gen)
|
||||
|
||||
try:
|
||||
return self.get_HKLM_registry_value(key_str, value_str)
|
||||
except:
|
||||
print >> sys.stderr, "Didn't find ", self.gens[gen]['gen']
|
||||
return ''
|
||||
|
||||
|
||||
def find_msbuild(self, gen=None):
|
||||
gen = self.get_gen_str(gen)
|
||||
|
||||
key_str = (r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0')
|
||||
|
||||
print ('Checking MSBuild support for vs ver = %s' % gen)
|
||||
if not self.get_HKLM_registry_value(key_str+'\\'+gen, "VCTargetsPath"):
|
||||
return (None, None)
|
||||
print ('Reading MSBuild location from HKEY_LOCAL_MACHINE\%s\MSBuildToolsPath' %
|
||||
key_str)
|
||||
print key_str
|
||||
try:
|
||||
return (self.get_HKLM_registry_value(key_str, 'MSBuildToolsPath'), gen)
|
||||
except WindowsError, err:
|
||||
key_str = (r'SOFTWARE\Wow6432Node\Microsoft\MSBuild\ToolsVersions\%s' %
|
||||
gen)
|
||||
|
||||
try:
|
||||
return (self.get_HKLM_registry_value(key_str, 'MSBuildToolsPath'), gen)
|
||||
except WindowsError, err:
|
||||
print 'Didn\'t find msbuild'
|
||||
return (None, None)
|
||||
|
||||
def find_visual_studio_express(self, gen=None):
|
||||
if gen is None:
|
||||
gen = self._generator
|
||||
gen = gen.lower()
|
||||
gen = self.get_gen_str(gen)
|
||||
try:
|
||||
import _winreg
|
||||
key_str = (r'SOFTWARE\Microsoft\VCEXpress\%s\Setup\VC' %
|
||||
self.gens[gen]['ver'])
|
||||
gen)
|
||||
value_str = (r'ProductDir')
|
||||
print ('Reading VS environment from HKEY_LOCAL_MACHINE\%s\%s' %
|
||||
(key_str, value_str))
|
||||
@@ -576,17 +628,15 @@ class WindowsSetup(PlatformSetup):
|
||||
print 'Found: %s' % value
|
||||
return value
|
||||
except WindowsError, err:
|
||||
print >> sys.stderr, "Didn't find ", self.gens[gen]['gen']
|
||||
print >> sys.stderr, "Didn't find ", gen
|
||||
return ''
|
||||
|
||||
def find_visual_studio_express_single(self, gen=None):
|
||||
if gen is None:
|
||||
gen = self._generator
|
||||
gen = gen.lower()
|
||||
gen = self.get_gen_str(gen)
|
||||
try:
|
||||
import _winreg
|
||||
key_str = (r'SOFTWARE\Microsoft\VCEXpress\%s_Config\Setup\VC' %
|
||||
self.gens[gen]['ver'])
|
||||
gen)
|
||||
value_str = (r'ProductDir')
|
||||
print ('Reading VS environment from HKEY_CURRENT_USER\%s\%s' %
|
||||
(key_str, value_str))
|
||||
@@ -598,7 +648,7 @@ class WindowsSetup(PlatformSetup):
|
||||
print 'Found: %s' % value
|
||||
return value
|
||||
except WindowsError, err:
|
||||
print >> sys.stderr, "Didn't find ", self.gens[gen]['gen']
|
||||
print >> sys.stderr, "Didn't find ", gen
|
||||
return ''
|
||||
|
||||
def get_build_cmd(self):
|
||||
@@ -607,7 +657,7 @@ class WindowsSetup(PlatformSetup):
|
||||
if self.gens[self.generator]['ver'] in [ r'8.0', r'9.0' ]:
|
||||
config = '\"%s|Win32\"' % config
|
||||
|
||||
return "buildconsole %s.sln /build %s" % (self.project_name, config)
|
||||
return "buildconsole \"%s.sln\" /build %s" % (self.project_name, config), None
|
||||
environment = self.find_visual_studio()
|
||||
if environment == '':
|
||||
environment = self.find_visual_studio_express()
|
||||
@@ -622,16 +672,23 @@ class WindowsSetup(PlatformSetup):
|
||||
print >> sys.stderr, "\nPlease see https://wiki.secondlife.com/wiki/Microsoft_Visual_Studio#Extra_steps_for_Visual_Studio_Express_editions for Visual Studio Express specific information"
|
||||
exit(0)
|
||||
|
||||
msbuild_dir, tool_ver = self.find_msbuild()
|
||||
|
||||
if msbuild_dir is not None and tool_ver is not None:
|
||||
return ('\"%smsbuild.exe\" \"%s.sln\" /p:configuration=%s /p:VisualStudioVersion=%s' %
|
||||
(msbuild_dir, self.project_name, self.build_type, tool_ver)), True
|
||||
|
||||
# devenv.com is CLI friendly, devenv.exe... not so much.
|
||||
return ('"%sdevenv.com" %s.sln /build %s' %
|
||||
(self.find_visual_studio(), self.project_name, self.build_type))
|
||||
return ('"%sdevenv.com" \"%s.sln\" /build %s' %
|
||||
(self.find_visual_studio(), self.project_name, self.build_type)), None
|
||||
|
||||
def run(self, command, name=None):
|
||||
'''Run a program. If the program fails, raise an exception.'''
|
||||
ret = os.system(command)
|
||||
ret = os.system('\"'+command+'\"')
|
||||
if ret:
|
||||
if name is None:
|
||||
name = command.split(None, 1)[0]
|
||||
name = os.path.normpath(shlex.split(command.encode('utf8'),posix=False)[0].strip('"'))
|
||||
|
||||
path = self.find_in_path(name)
|
||||
if not path:
|
||||
ret = 'was not found'
|
||||
@@ -657,10 +714,15 @@ class WindowsSetup(PlatformSetup):
|
||||
if prev_build == self.build_type:
|
||||
# Only run vstool if the build type has changed.
|
||||
continue
|
||||
vstool_cmd = (os.path.join('tools','vstool','VSTool.exe') +
|
||||
' --solution ' +
|
||||
os.path.join(build_dir,'Singularity.sln') +
|
||||
' --config ' + self.build_type +
|
||||
|
||||
if(os.path.basename(os.path.normpath(os.getcwd())) == 'indra'):
|
||||
tool_path = os.path.join('tools','vstool','VSTool.exe')
|
||||
else:
|
||||
tool_path = os.path.join('indra','tools','vstool','VSTool.exe')
|
||||
vstool_cmd = (tool_path +
|
||||
' --solution \"' +
|
||||
os.path.join(build_dir,'%s.sln' % self.project_name) +
|
||||
'\" --config ' + self.build_type +
|
||||
' --startup secondlife-bin')
|
||||
print 'Running vstool %r in %r' % (vstool_cmd, getcwd())
|
||||
self.run(vstool_cmd)
|
||||
@@ -668,16 +730,21 @@ class WindowsSetup(PlatformSetup):
|
||||
|
||||
def run_build(self, opts, targets):
|
||||
cwd = getcwd()
|
||||
build_cmd = self.get_build_cmd()
|
||||
build_cmd, msbuild = self.get_build_cmd()
|
||||
|
||||
for d in self.build_dirs():
|
||||
try:
|
||||
os.chdir(d)
|
||||
if targets:
|
||||
for t in targets:
|
||||
cmd = '%s /project %s %s' % (build_cmd, t, ' '.join(opts))
|
||||
if msbuild:
|
||||
cmd = '%s /target:%s %s' % (build_cmd, ';'.join(targets), ' '.join(opts))
|
||||
print 'Running build(targets) %r in %r' % (cmd, d)
|
||||
self.run(cmd)
|
||||
else:
|
||||
for t in targets:
|
||||
cmd = '%s /project %s %s' % (build_cmd, t, ' '.join(opts))
|
||||
print 'Running build(targets) %r in %r' % (cmd, d)
|
||||
self.run(cmd)
|
||||
else:
|
||||
cmd = '%s %s' % (build_cmd, ' '.join(opts))
|
||||
print 'Running build %r in %r' % (cmd, d)
|
||||
@@ -748,10 +815,12 @@ Commands:
|
||||
Command-options for "configure":
|
||||
We use cmake variables to change the build configuration.
|
||||
-DPACKAGE:BOOL=ON Create "package" target to make installers
|
||||
-DLOCALIZESETUP:BOOL=ON Create one win_setup target per supported language
|
||||
-DLL_TESTS:BOOL=OFF Don't generate unit test projects
|
||||
-DEXAMPLEPLUGIN:BOOL=OFF Don't generate example plugin project
|
||||
-DDISABLE_TCMALLOC:BOOL=ON Disable linkage of TCMalloc. (64bit builds automatically disable TCMalloc)
|
||||
-DRELEASE_CRASH_REPORTING:BOOL=ON Enable Google Breakpad crash reporting
|
||||
-DFMODSTUDIO:BOOL=ON Use FMOD Studio audio libraries
|
||||
-DFMODEX:BOOL=ON Use FMOD Ex audio libraries
|
||||
|
||||
Examples:
|
||||
Set up a Visual Studio 2010 project with "package" target:
|
||||
|
||||
@@ -2,19 +2,24 @@
|
||||
@file __init__.py
|
||||
@brief Initialization file for the indra module.
|
||||
|
||||
$LicenseInfo:firstyear=2006&license=internal$
|
||||
$LicenseInfo:firstyear=2006&license=viewerlgpl$
|
||||
Second Life Viewer Source Code
|
||||
Copyright (C) 2006-2010, Linden Research, Inc.
|
||||
|
||||
Copyright (c) 2006-2009, Linden Research, Inc.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation;
|
||||
version 2.1 of the License only.
|
||||
|
||||
The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
|
||||
this source code is governed by the Linden Lab Source Code Disclosure
|
||||
Agreement ("Agreement") previously entered between you and Linden
|
||||
Lab. By accessing, using, copying, modifying or distributing this
|
||||
software, you acknowledge that you have been informed of your
|
||||
obligations under the Agreement and agree to abide by those obligations.
|
||||
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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
COMPLETENESS OR PERFORMANCE.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
#!/usr/bin/python
|
||||
##
|
||||
## $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
## Second Life Viewer Source Code
|
||||
## Copyright (C) 2011, Linden Research, Inc.
|
||||
##
|
||||
## This library is free software; you can redistribute it and/or
|
||||
## modify it under the terms of the GNU Lesser General Public
|
||||
## License as published by the Free Software Foundation;
|
||||
## version 2.1 of the License only.
|
||||
##
|
||||
## 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
|
||||
## Lesser General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU Lesser General Public
|
||||
## License along with this library; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
## $/LicenseInfo$
|
||||
from indra.base import llsd, lluuid
|
||||
from datetime import datetime
|
||||
import cllsd
|
||||
@@ -10,7 +32,7 @@ values = (
|
||||
'&<>',
|
||||
u'\u81acj',
|
||||
llsd.uri('http://foo<'),
|
||||
lluuid.LLUUID(),
|
||||
lluuid.UUID(),
|
||||
llsd.LLSD(['thing']),
|
||||
1,
|
||||
myint(31337),
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
"""\
|
||||
@file lllog.py
|
||||
@brief Logging for event processing
|
||||
|
||||
$LicenseInfo:firstyear=2008&license=mit$
|
||||
|
||||
Copyright (c) 2008-2009, Linden Research, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
from indra.base.llsd import format_notation
|
||||
|
||||
try:
|
||||
import syslog
|
||||
except ImportError:
|
||||
# Windows
|
||||
import sys
|
||||
|
||||
class syslog(object):
|
||||
_logfp = sys.stderr
|
||||
|
||||
def syslog(msg):
|
||||
_logfp.write(msg)
|
||||
if not msg.endswith('\n'):
|
||||
_logfp.write('\n')
|
||||
|
||||
syslog = staticmethod(syslog)
|
||||
|
||||
class Logger(object):
|
||||
def __init__(self, name='indra'):
|
||||
self._sequence = 0
|
||||
try:
|
||||
syslog.openlog(name, syslog.LOG_CONS | syslog.LOG_PID,
|
||||
syslog.LOG_LOCAL0)
|
||||
except AttributeError:
|
||||
# No syslog module on Windows
|
||||
pass
|
||||
|
||||
def next(self):
|
||||
self._sequence += 1
|
||||
return self._sequence
|
||||
|
||||
def log(self, msg, llsd):
|
||||
payload = 'INFO: log: LLLOGMESSAGE (%d) %s %s' % (self.next(), msg,
|
||||
format_notation(llsd))
|
||||
syslog.syslog(payload)
|
||||
|
||||
_logger = None
|
||||
|
||||
def log(msg, llsd):
|
||||
global _logger
|
||||
if _logger is None:
|
||||
_logger = Logger()
|
||||
_logger.log(msg, llsd)
|
||||
@@ -72,8 +72,11 @@ BOOL_FALSE = ('0', '0.0', 'false', '')
|
||||
|
||||
|
||||
def format_datestr(v):
|
||||
""" Formats a datetime object into the string format shared by xml and notation serializations."""
|
||||
return v.isoformat() + 'Z'
|
||||
""" Formats a datetime or date object into the string format shared by xml and notation serializations."""
|
||||
if hasattr(v, 'microsecond'):
|
||||
return v.isoformat() + 'Z'
|
||||
else:
|
||||
return v.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
|
||||
def parse_datestr(datestr):
|
||||
"""Parses a datetime object from the string format shared by xml and notation serializations."""
|
||||
@@ -183,6 +186,7 @@ class LLSDXMLFormatter(object):
|
||||
unicode : self.STRING,
|
||||
uri : self.URI,
|
||||
datetime.datetime : self.DATE,
|
||||
datetime.date : self.DATE,
|
||||
list : self.ARRAY,
|
||||
tuple : self.ARRAY,
|
||||
types.GeneratorType : self.ARRAY,
|
||||
@@ -234,7 +238,7 @@ class LLSDXMLFormatter(object):
|
||||
def MAP(self, v):
|
||||
return self.elt(
|
||||
'map',
|
||||
''.join(["%s%s" % (self.elt('key', key), self.generate(value))
|
||||
''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value))
|
||||
for key, value in v.items()]))
|
||||
|
||||
typeof = type
|
||||
@@ -347,6 +351,7 @@ class LLSDNotationFormatter(object):
|
||||
unicode : self.STRING,
|
||||
uri : self.URI,
|
||||
datetime.datetime : self.DATE,
|
||||
datetime.date : self.DATE,
|
||||
list : self.ARRAY,
|
||||
tuple : self.ARRAY,
|
||||
types.GeneratorType : self.ARRAY,
|
||||
@@ -924,12 +929,13 @@ def _format_binary_recurse(something):
|
||||
(type(something), something))
|
||||
|
||||
|
||||
def parse_binary(something):
|
||||
header = '<?llsd/binary?>\n'
|
||||
if not something.startswith(header):
|
||||
raise LLSDParseError('LLSD binary encoding header not found')
|
||||
return LLSDBinaryParser().parse(something[len(header):])
|
||||
|
||||
def parse_binary(binary):
|
||||
if binary.startswith('<?llsd/binary?>'):
|
||||
just_binary = binary.split('\n', 1)[1]
|
||||
else:
|
||||
just_binary = binary
|
||||
return LLSDBinaryParser().parse(just_binary)
|
||||
|
||||
def parse_xml(something):
|
||||
try:
|
||||
return to_python(fromstring(something)[0])
|
||||
|
||||
@@ -28,13 +28,12 @@ $/LicenseInfo$
|
||||
|
||||
import random, socket, string, time, re
|
||||
import uuid
|
||||
|
||||
# *HACK: Necessary for python 2.4. Consider replacing this code wart
|
||||
# after python >=2.5 has deployed everywhere. 2009-10-05
|
||||
try:
|
||||
# Python 2.6
|
||||
from hashlib import md5
|
||||
except ImportError:
|
||||
from md5 import md5
|
||||
# Python 2.5 and earlier
|
||||
from md5 import new as md5
|
||||
|
||||
def _int2binstr(i,l):
|
||||
s=''
|
||||
@@ -73,7 +72,7 @@ class UUID(object):
|
||||
ip = ''
|
||||
try:
|
||||
ip = socket.gethostbyname(socket.gethostname())
|
||||
except(socket.gaierror):
|
||||
except(socket.gaierror, socket.error):
|
||||
# no ip address, so just default to somewhere in 10.x.x.x
|
||||
ip = '10'
|
||||
for i in range(3):
|
||||
@@ -164,7 +163,7 @@ class UUID(object):
|
||||
def setFromMemoryDump(self, gdb_string):
|
||||
"""
|
||||
We expect to get gdb_string as four hex units. eg:
|
||||
0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
|
||||
0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
|
||||
Which will be translated to:
|
||||
db547d14-1b3f4bc3-9b984f71-d22f890a
|
||||
Returns self.
|
||||
@@ -188,7 +187,7 @@ class UUID(object):
|
||||
def getAsString(self):
|
||||
"""
|
||||
Return a different string representation of the form
|
||||
AAAAAAAA-AAAABBBB-BBBBBBBB-BBCCCCCC (a 128-bit number in hex)
|
||||
AAAAAAAA-AAAABBBB-BBBBBBBB-BBCCCCCC (a 128-bit number in hex)
|
||||
where A=network address, B=timestamp, C=random.
|
||||
"""
|
||||
i1 = _binstr2int(self._bits[0:4])
|
||||
@@ -234,7 +233,7 @@ NULL = UUID()
|
||||
def printTranslatedMemory(four_hex_uints):
|
||||
"""
|
||||
We expect to get the string as four hex units. eg:
|
||||
0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
|
||||
0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
|
||||
Which will be translated to:
|
||||
db547d14-1b3f4bc3-9b984f71-d22f890a
|
||||
"""
|
||||
|
||||
@@ -29,25 +29,93 @@ $/LicenseInfo$
|
||||
"""
|
||||
|
||||
import sys
|
||||
from indra.base import llsd
|
||||
try:
|
||||
import syslog
|
||||
except ImportError:
|
||||
# Windows
|
||||
import sys
|
||||
class syslog(object):
|
||||
# wrap to a lame syslog for windows
|
||||
_logfp = sys.stderr
|
||||
def syslog(msg):
|
||||
_logfp.write(msg)
|
||||
if not msg.endswith('\n'):
|
||||
_logfp.write('\n')
|
||||
syslog = staticmethod(syslog)
|
||||
|
||||
_sequence_id = 0
|
||||
from indra.base.llsd import format_notation
|
||||
|
||||
def record_metrics(table, stats, dest=None):
|
||||
def record_metrics(table, stats):
|
||||
"Write a standard metrics log"
|
||||
_log("LLMETRICS", table, stats, dest)
|
||||
_log("LLMETRICS", table, stats)
|
||||
|
||||
def record_event(table, data, dest=None):
|
||||
def record_event(table, data):
|
||||
"Write a standard logmessage log"
|
||||
_log("LLLOGMESSAGE", table, data, dest)
|
||||
_log("LLLOGMESSAGE", table, data)
|
||||
|
||||
def _log(header, table, data, dest):
|
||||
def set_destination(dest):
|
||||
"""Set the destination of metrics logs for this process.
|
||||
|
||||
If you do not call this function prior to calling a logging
|
||||
method, that function will open sys.stdout as a destination.
|
||||
Attempts to set dest to None will throw a RuntimeError.
|
||||
@param dest a file-like object which will be the destination for logs."""
|
||||
if dest is None:
|
||||
# do this check here in case sys.stdout changes at some
|
||||
# point. as a default parameter, it will never be
|
||||
# re-evaluated.
|
||||
dest = sys.stdout
|
||||
raise RuntimeError("Attempt to unset metrics destination.")
|
||||
global _destination
|
||||
_destination = dest
|
||||
|
||||
def destination():
|
||||
"""Get the destination of the metrics logs for this process.
|
||||
Returns None if no destination is set"""
|
||||
global _destination
|
||||
return _destination
|
||||
|
||||
class SysLogger(object):
|
||||
"A file-like object which writes to syslog."
|
||||
def __init__(self, ident='indra', logopt = None, facility = None):
|
||||
try:
|
||||
if logopt is None:
|
||||
logopt = syslog.LOG_CONS | syslog.LOG_PID
|
||||
if facility is None:
|
||||
facility = syslog.LOG_LOCAL0
|
||||
syslog.openlog(ident, logopt, facility)
|
||||
import atexit
|
||||
atexit.register(syslog.closelog)
|
||||
except AttributeError:
|
||||
# No syslog module on Windows
|
||||
pass
|
||||
|
||||
def write(str):
|
||||
syslog.syslog(str)
|
||||
write = staticmethod(write)
|
||||
|
||||
def flush():
|
||||
pass
|
||||
flush = staticmethod(flush)
|
||||
|
||||
#
|
||||
# internal API
|
||||
#
|
||||
_sequence_id = 0
|
||||
_destination = None
|
||||
|
||||
def _next_id():
|
||||
global _sequence_id
|
||||
print >>dest, header, "(" + str(_sequence_id) + ")",
|
||||
print >>dest, table, llsd.format_notation(data)
|
||||
next = _sequence_id
|
||||
_sequence_id += 1
|
||||
return next
|
||||
|
||||
def _dest():
|
||||
global _destination
|
||||
if _destination is None:
|
||||
# this default behavior is documented in the metrics functions above.
|
||||
_destination = sys.stdout
|
||||
return _destination
|
||||
|
||||
def _log(header, table, data):
|
||||
log_line = "%s (%d) %s %s" \
|
||||
% (header, _next_id(), table, format_notation(data))
|
||||
dest = _dest()
|
||||
dest.write(log_line)
|
||||
dest.flush()
|
||||
|
||||
@@ -39,6 +39,12 @@ except:
|
||||
pass
|
||||
|
||||
_g_builder = None
|
||||
def _builder():
|
||||
global _g_builder
|
||||
if _g_builder is None:
|
||||
_g_builder = ServiceBuilder()
|
||||
return _g_builder
|
||||
|
||||
def build(name, context={}, **kwargs):
|
||||
""" Convenience method for using a global, singleton, service builder. Pass arguments either via a dict or via python keyword arguments, or both!
|
||||
|
||||
@@ -56,6 +62,11 @@ def build(name, context={}, **kwargs):
|
||||
_g_builder = ServiceBuilder()
|
||||
return _g_builder.buildServiceURL(name, context, **kwargs)
|
||||
|
||||
def build_path(name, context={}, **kwargs):
|
||||
context = context.copy() # shouldn't modify the caller's dictionary
|
||||
context.update(kwargs)
|
||||
return _builder().buildPath(name, context)
|
||||
|
||||
class ServiceBuilder(object):
|
||||
def __init__(self, services_definition = services_config):
|
||||
"""\
|
||||
@@ -73,12 +84,21 @@ class ServiceBuilder(object):
|
||||
continue
|
||||
if isinstance(service_builder, dict):
|
||||
# We will be constructing several builders
|
||||
for name, builder in service_builder.items():
|
||||
for name, builder in service_builder.iteritems():
|
||||
full_builder_name = service['name'] + '-' + name
|
||||
self.builders[full_builder_name] = builder
|
||||
else:
|
||||
self.builders[service['name']] = service_builder
|
||||
|
||||
def buildPath(self, name, context):
|
||||
"""\
|
||||
@brief given the environment on construction, return a service path.
|
||||
@param name The name of the service.
|
||||
@param context A dict of name value lookups for the service.
|
||||
@returns Returns the
|
||||
"""
|
||||
return russ.format(self.builders[name], context)
|
||||
|
||||
def buildServiceURL(self, name, context={}, **kwargs):
|
||||
"""\
|
||||
@brief given the environment on construction, return a service URL.
|
||||
@@ -108,7 +128,7 @@ def on_in(query_name, host_key, schema_key):
|
||||
@param schema_key Logical name of destination schema. Will
|
||||
be looked up in indra.xml.
|
||||
"""
|
||||
host_name = config.get(host_key)
|
||||
schema_name = config.get(schema_key)
|
||||
return '/'.join( ('on', host_name, 'in', schema_name, query_name.lstrip('/')) )
|
||||
return "on/config:%s/in/config:%s/%s" % (host_key.strip('/'),
|
||||
schema_key.strip('/'),
|
||||
query_name.lstrip('/'))
|
||||
|
||||
|
||||
@@ -1,3 +1,32 @@
|
||||
"""\
|
||||
@file siesta.py
|
||||
@brief A tiny llsd based RESTful web services framework
|
||||
|
||||
$LicenseInfo:firstyear=2008&license=mit$
|
||||
|
||||
Copyright (c) 2008, Linden Research, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
from indra.base import config
|
||||
from indra.base import llsd
|
||||
from webob import exc
|
||||
import webob
|
||||
@@ -37,11 +66,11 @@ def mime_type(content_type):
|
||||
return content_type.split(';', 1)[0].strip().lower()
|
||||
|
||||
class BodyLLSD(object):
|
||||
'''Give a webob Request or Response an llsd property.
|
||||
'''Give a webob Request or Response an llsd based "content" property.
|
||||
|
||||
Getting the llsd property parses the body, and caches the result.
|
||||
Getting the content property parses the body, and caches the result.
|
||||
|
||||
Setting the llsd property formats a payload, and the body property
|
||||
Setting the content property formats a payload, and the body property
|
||||
is set.'''
|
||||
|
||||
def _llsd__get(self):
|
||||
@@ -80,7 +109,7 @@ class BodyLLSD(object):
|
||||
if hasattr(self, '_llsd'):
|
||||
del self._llsd
|
||||
|
||||
llsd = property(_llsd__get, _llsd__set, _llsd__del)
|
||||
content = property(_llsd__get, _llsd__set, _llsd__del)
|
||||
|
||||
|
||||
class Response(webob.Response, BodyLLSD):
|
||||
@@ -114,10 +143,10 @@ class Request(webob.Request, BodyLLSD):
|
||||
|
||||
Sensible content type and accept headers are used by default.
|
||||
|
||||
Setting the llsd property also sets the body. Getting the llsd
|
||||
Setting the content property also sets the body. Getting the content
|
||||
property parses the body if necessary.
|
||||
|
||||
If you set the body property directly, the llsd property will be
|
||||
If you set the body property directly, the content property will be
|
||||
deleted.'''
|
||||
|
||||
default_content_type = 'application/llsd+xml'
|
||||
@@ -149,11 +178,11 @@ class Request(webob.Request, BodyLLSD):
|
||||
body = property(webob.Request._body__get, _body__set,
|
||||
webob.Request._body__del, webob.Request._body__get.__doc__)
|
||||
|
||||
def create_response(self, llsd=None, status='200 OK',
|
||||
def create_response(self, content=None, status='200 OK',
|
||||
conditional_response=webob.NoDefault):
|
||||
resp = self.ResponseClass(status=status, request=self,
|
||||
conditional_response=conditional_response)
|
||||
resp.llsd = llsd
|
||||
resp.content = content
|
||||
return resp
|
||||
|
||||
def curl(self):
|
||||
@@ -196,12 +225,18 @@ llsd_formatters = {
|
||||
'application/xml': llsd.format_xml,
|
||||
}
|
||||
|
||||
formatter_qualities = (
|
||||
('application/llsd+xml', 1.0),
|
||||
('application/llsd+notation', 0.5),
|
||||
('application/llsd+binary', 0.4),
|
||||
('application/xml', 0.3),
|
||||
('application/json', 0.2),
|
||||
)
|
||||
|
||||
def formatter_for_mime_type(mime_type):
|
||||
'''Return a formatter that encodes to the given MIME type.
|
||||
|
||||
The result is a pair of function and MIME type.'''
|
||||
|
||||
try:
|
||||
return llsd_formatters[mime_type], mime_type
|
||||
except KeyError:
|
||||
@@ -214,21 +249,19 @@ def formatter_for_request(req):
|
||||
'''Return a formatter that encodes to the preferred type of the client.
|
||||
|
||||
The result is a pair of function and actual MIME type.'''
|
||||
|
||||
for ctype in req.accept.best_matches('application/llsd+xml'):
|
||||
try:
|
||||
return llsd_formatters[ctype], ctype
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
ctype = req.accept.best_match(formatter_qualities)
|
||||
try:
|
||||
return llsd_formatters[ctype], ctype
|
||||
except KeyError:
|
||||
raise exc.HTTPNotAcceptable().exception
|
||||
|
||||
|
||||
def wsgi_adapter(func, environ, start_response):
|
||||
'''Adapt a Siesta callable to act as a WSGI application.'''
|
||||
|
||||
# Process the request as appropriate.
|
||||
try:
|
||||
req = Request(environ)
|
||||
#print req.urlvars
|
||||
resp = func(req, **req.urlvars)
|
||||
if not isinstance(resp, webob.Response):
|
||||
try:
|
||||
@@ -281,7 +314,8 @@ def llsd_class(cls):
|
||||
allowed = [m for m in http11_methods
|
||||
if hasattr(instance, 'handle_' + m.lower())]
|
||||
raise exc.HTTPMethodNotAllowed(
|
||||
headers={'Allowed': ', '.join(allowed)}).exception
|
||||
headers={'Allow': ', '.join(allowed)}).exception
|
||||
#print "kwargs: ", kwargs
|
||||
return handler(req, **kwargs)
|
||||
|
||||
def replacement(environ, start_response):
|
||||
@@ -336,7 +370,7 @@ def curl(reqs):
|
||||
|
||||
route_re = re.compile(r'''
|
||||
\{ # exact character "{"
|
||||
(\w+) # variable name (restricted to a-z, 0-9, _)
|
||||
(\w*) # "config" or variable (restricted to a-z, 0-9, _)
|
||||
(?:([:~])([^}]+))? # optional :type or ~regex part
|
||||
\} # exact character "}"
|
||||
''', re.VERBOSE)
|
||||
@@ -344,27 +378,37 @@ route_re = re.compile(r'''
|
||||
predefined_regexps = {
|
||||
'uuid': r'[a-f0-9][a-f0-9-]{31,35}',
|
||||
'int': r'\d+',
|
||||
'host': r'[a-z0-9][a-z0-9\-\.]*',
|
||||
}
|
||||
|
||||
def compile_route(route):
|
||||
fp = StringIO()
|
||||
last_pos = 0
|
||||
for match in route_re.finditer(route):
|
||||
#print "matches: ", match.groups()
|
||||
fp.write(re.escape(route[last_pos:match.start()]))
|
||||
var_name = match.group(1)
|
||||
sep = match.group(2)
|
||||
expr = match.group(3)
|
||||
if expr:
|
||||
if sep == ':':
|
||||
expr = predefined_regexps[expr]
|
||||
# otherwise, treat what follows '~' as a regexp
|
||||
if var_name == 'config':
|
||||
expr = re.escape(str(config.get(var_name)))
|
||||
else:
|
||||
expr = '[^/]+'
|
||||
expr = '(?P<%s>%s)' % (var_name, expr)
|
||||
if expr:
|
||||
if sep == ':':
|
||||
expr = predefined_regexps[expr]
|
||||
# otherwise, treat what follows '~' as a regexp
|
||||
else:
|
||||
expr = '[^/]+'
|
||||
if var_name != '':
|
||||
expr = '(?P<%s>%s)' % (var_name, expr)
|
||||
else:
|
||||
expr = '(%s)' % (expr,)
|
||||
fp.write(expr)
|
||||
last_pos = match.end()
|
||||
fp.write(re.escape(route[last_pos:]))
|
||||
return '^%s$' % fp.getvalue()
|
||||
compiled_route = '^%s$' % fp.getvalue()
|
||||
#print route, "->", compiled_route
|
||||
return compiled_route
|
||||
|
||||
class Router(object):
|
||||
'''WSGI routing class. Parses a URL and hands off a request to
|
||||
@@ -372,21 +416,43 @@ class Router(object):
|
||||
responds with a 404.'''
|
||||
|
||||
def __init__(self):
|
||||
self.routes = []
|
||||
self.paths = []
|
||||
self._new_routes = []
|
||||
self._routes = []
|
||||
self._paths = []
|
||||
|
||||
def add(self, route, app, methods=None):
|
||||
self.paths.append(route)
|
||||
self.routes.append((re.compile(compile_route(route)), app,
|
||||
methods and dict.fromkeys(methods)))
|
||||
self._new_routes.append((route, app, methods))
|
||||
|
||||
def _create_routes(self):
|
||||
for route, app, methods in self._new_routes:
|
||||
self._paths.append(route)
|
||||
self._routes.append(
|
||||
(re.compile(compile_route(route)),
|
||||
app,
|
||||
methods and dict.fromkeys(methods)))
|
||||
self._new_routes = []
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
# load up the config from the config file. Only needs to be
|
||||
# done once per interpreter. This is the entry point of all
|
||||
# siesta applications, so this is where we trap it.
|
||||
_conf = config.get_config()
|
||||
if _conf is None:
|
||||
import os.path
|
||||
fname = os.path.join(
|
||||
environ.get('ll.config_dir', '/local/linden/etc'),
|
||||
'indra.xml')
|
||||
config.load(fname)
|
||||
|
||||
# proceed with handling the request
|
||||
self._create_routes()
|
||||
path_info = environ['PATH_INFO']
|
||||
request_method = environ['REQUEST_METHOD']
|
||||
allowed = []
|
||||
for regex, app, methods in self.routes:
|
||||
for regex, app, methods in self._routes:
|
||||
m = regex.match(path_info)
|
||||
if m:
|
||||
#print "groupdict:",m.groupdict()
|
||||
if not methods or request_method in methods:
|
||||
environ['paste.urlvars'] = m.groupdict()
|
||||
return app(environ, start_response)
|
||||
@@ -396,7 +462,7 @@ class Router(object):
|
||||
allowed = dict.fromkeys(allows).keys()
|
||||
allowed.sort()
|
||||
resp = exc.HTTPMethodNotAllowed(
|
||||
headers={'Allowed': ', '.join(allowed)})
|
||||
headers={'Allow': ', '.join(allowed)})
|
||||
else:
|
||||
resp = exc.HTTPNotFound()
|
||||
return resp(environ, start_response)
|
||||
|
||||
@@ -280,13 +280,14 @@ class LLManifest(object):
|
||||
self.file_list = []
|
||||
self.excludes = []
|
||||
self.actions = []
|
||||
self.src_prefix = [args['source']]
|
||||
self.artwork_prefix = [args['artwork']]
|
||||
self.build_prefix = [args['build']]
|
||||
self.dst_prefix = [args['dest']]
|
||||
self.src_prefix = list([args['source']])
|
||||
self.artwork_prefix = list([args['artwork']])
|
||||
self.build_prefix = list([args['build']])
|
||||
self.alt_build_prefix = list([args['build']])
|
||||
self.dst_prefix = list([args['dest']])
|
||||
self.created_paths = []
|
||||
self.package_name = "Unknown"
|
||||
|
||||
|
||||
def default_grid(self):
|
||||
return self.args.get('grid', None) == ''
|
||||
def default_channel(self):
|
||||
@@ -310,7 +311,7 @@ class LLManifest(object):
|
||||
in the file list by path()."""
|
||||
self.excludes.append(glob)
|
||||
|
||||
def prefix(self, src='', build=None, dst=None):
|
||||
def prefix(self, src='', build=None, dst=None, alt_build=None):
|
||||
""" Pushes a prefix onto the stack. Until end_prefix is
|
||||
called, all relevant method calls (esp. to path()) will prefix
|
||||
paths with the entire prefix stack. Source and destination
|
||||
@@ -321,10 +322,15 @@ class LLManifest(object):
|
||||
dst = src
|
||||
if build is None:
|
||||
build = src
|
||||
if alt_build is None:
|
||||
alt_build = build
|
||||
|
||||
self.src_prefix.append(src)
|
||||
self.artwork_prefix.append(src)
|
||||
self.build_prefix.append(build)
|
||||
self.dst_prefix.append(dst)
|
||||
self.alt_build_prefix.append(alt_build)
|
||||
|
||||
return True # so that you can wrap it in an if to get indentation
|
||||
|
||||
def end_prefix(self, descr=None):
|
||||
@@ -337,25 +343,30 @@ class LLManifest(object):
|
||||
src = self.src_prefix.pop()
|
||||
artwork = self.artwork_prefix.pop()
|
||||
build = self.build_prefix.pop()
|
||||
alt_build_prefix = self.alt_build_prefix.pop()
|
||||
dst = self.dst_prefix.pop()
|
||||
if descr and not(src == descr or build == descr or dst == descr):
|
||||
raise ValueError, "End prefix '" + descr + "' didn't match '" +src+ "' or '" +dst + "'"
|
||||
|
||||
def get_src_prefix(self):
|
||||
""" Returns the current source prefix."""
|
||||
return os.path.join(*self.src_prefix)
|
||||
return os.path.relpath(os.path.normpath(os.path.join(*self.src_prefix)))
|
||||
|
||||
def get_artwork_prefix(self):
|
||||
""" Returns the current artwork prefix."""
|
||||
return os.path.join(*self.artwork_prefix)
|
||||
return os.path.relpath(os.path.normpath(os.path.join(*self.artwork_prefix)))
|
||||
|
||||
def get_build_prefix(self):
|
||||
""" Returns the current build prefix."""
|
||||
return os.path.join(*self.build_prefix)
|
||||
return os.path.relpath(os.path.normpath(os.path.join(*self.build_prefix)))
|
||||
|
||||
def get_alt_build_prefix(self):
|
||||
""" Returns the current alternate source prefix."""
|
||||
return os.path.relpath(os.path.normpath(os.path.join(*self.alt_build_prefix)))
|
||||
|
||||
def get_dst_prefix(self):
|
||||
""" Returns the current destination prefix."""
|
||||
return os.path.join(*self.dst_prefix)
|
||||
return os.path.relpath(os.path.normpath(os.path.join(*self.dst_prefix)))
|
||||
|
||||
def src_path_of(self, relpath):
|
||||
"""Returns the full path to a file or directory specified
|
||||
@@ -372,22 +383,6 @@ class LLManifest(object):
|
||||
relative to the destination directory."""
|
||||
return os.path.join(self.get_dst_prefix(), relpath)
|
||||
|
||||
def ensure_src_dir(self, reldir):
|
||||
"""Construct the path for a directory relative to the
|
||||
source path, and ensures that it exists. Returns the
|
||||
full path."""
|
||||
path = os.path.join(self.get_src_prefix(), reldir)
|
||||
self.cmakedirs(path)
|
||||
return path
|
||||
|
||||
def ensure_dst_dir(self, reldir):
|
||||
"""Construct the path for a directory relative to the
|
||||
destination path, and ensures that it exists. Returns the
|
||||
full path."""
|
||||
path = os.path.join(self.get_dst_prefix(), reldir)
|
||||
self.cmakedirs(path)
|
||||
return path
|
||||
|
||||
def run_command(self, command):
|
||||
""" Runs an external command, and returns the output. Raises
|
||||
an exception if the command reurns a nonzero status code. For
|
||||
@@ -484,29 +479,30 @@ class LLManifest(object):
|
||||
if method is not None:
|
||||
method(src, dst)
|
||||
self.file_list.append([src, dst])
|
||||
return 1
|
||||
return [dst]
|
||||
else:
|
||||
sys.stdout.write(" (excluding %r, %r)" % (src, dst))
|
||||
sys.stdout.flush()
|
||||
return 0
|
||||
return []
|
||||
|
||||
def process_directory(self, src, dst):
|
||||
if not self.includes(src, dst):
|
||||
sys.stdout.write(" (excluding %r, %r)" % (src, dst))
|
||||
sys.stdout.flush()
|
||||
return 0
|
||||
return []
|
||||
names = os.listdir(src)
|
||||
self.cmakedirs(dst)
|
||||
errors = []
|
||||
found_files = []
|
||||
count = 0
|
||||
for name in names:
|
||||
srcname = os.path.join(src, name)
|
||||
dstname = os.path.join(dst, name)
|
||||
if os.path.isdir(srcname):
|
||||
count += self.process_directory(srcname, dstname)
|
||||
found_files.extend(self.process_directory(srcname, dstname))
|
||||
else:
|
||||
count += self.process_file(srcname, dstname)
|
||||
return count
|
||||
found_files.extend(self.process_file(srcname, dstname))
|
||||
return found_files
|
||||
|
||||
def includes(self, src, dst):
|
||||
if src:
|
||||
@@ -586,25 +582,11 @@ class LLManifest(object):
|
||||
if os.path.exists(f):
|
||||
return f
|
||||
# didn't find it, return last item in list
|
||||
if len(list) > 0:
|
||||
if list:
|
||||
return list[-1]
|
||||
else:
|
||||
return None
|
||||
|
||||
def contents_of_tar(self, src_tar, dst_dir):
|
||||
""" Extracts the contents of the tarfile (specified
|
||||
relative to the source prefix) into the directory
|
||||
specified relative to the destination directory."""
|
||||
self.check_file_exists(src_tar)
|
||||
tf = tarfile.open(self.src_path_of(src_tar), 'r')
|
||||
for member in tf.getmembers():
|
||||
tf.extract(member, self.ensure_dst_dir(dst_dir))
|
||||
# TODO get actions working on these dudes, perhaps we should extract to a temporary directory and then process_directory on it?
|
||||
self.file_list.append([src_tar,
|
||||
self.dst_path_of(os.path.join(dst_dir,member.name))])
|
||||
tf.close()
|
||||
|
||||
|
||||
def wildcard_regex(self, src_glob, dst_glob):
|
||||
src_re = re.escape(src_glob)
|
||||
src_re = src_re.replace('\*', '([-a-zA-Z0-9._ ]*)')
|
||||
@@ -615,12 +597,6 @@ class LLManifest(object):
|
||||
i = i+1
|
||||
return re.compile(src_re), dst_temp
|
||||
|
||||
def check_file_exists(self, path):
|
||||
if not os.path.exists(path) and not os.path.islink(path):
|
||||
raise RuntimeError("Path %s doesn't exist" % (
|
||||
os.path.normpath(os.path.join(os.getcwd(), path)),))
|
||||
|
||||
|
||||
wildcard_pattern = re.compile('\*')
|
||||
def expand_globs(self, src, dst):
|
||||
src_list = glob.glob(src)
|
||||
@@ -630,40 +606,61 @@ class LLManifest(object):
|
||||
d = src_re.sub(d_template, s.replace('\\', '/'))
|
||||
yield os.path.normpath(s), os.path.normpath(d)
|
||||
|
||||
def path2basename(self, path, file):
|
||||
"""
|
||||
It is a common idiom to write:
|
||||
self.path(os.path.join(somedir, somefile), somefile)
|
||||
|
||||
So instead you can write:
|
||||
self.path2basename(somedir, somefile)
|
||||
|
||||
Note that this is NOT the same as:
|
||||
self.path(os.path.join(somedir, somefile))
|
||||
|
||||
which is the same as:
|
||||
temppath = os.path.join(somedir, somefile)
|
||||
self.path(temppath, temppath)
|
||||
"""
|
||||
return self.path(os.path.join(path, file), file)
|
||||
|
||||
def path(self, src, dst=None):
|
||||
sys.stdout.write("Processing %s => %s ... " % (src, dst))
|
||||
sys.stdout.flush()
|
||||
if src == None:
|
||||
raise RuntimeError("No source file, dst is " + dst)
|
||||
if dst == None:
|
||||
dst = src
|
||||
dst = os.path.join(self.get_dst_prefix(), dst)
|
||||
sys.stdout.write("Processing %s => %s ... " % (src, dst))
|
||||
count = 0
|
||||
is_glob = False
|
||||
found_files = []
|
||||
|
||||
# look under each prefix for matching paths
|
||||
paths = set([os.path.join(self.get_src_prefix(), src),
|
||||
os.path.join(self.get_artwork_prefix(), src),
|
||||
os.path.join(self.get_build_prefix(), src)])
|
||||
# look under each prefix for matching paths. Paths are normalized so './../blah' will match '../blah/../blah/'
|
||||
paths = set([os.path.normpath(os.path.join(self.get_src_prefix(), src)),
|
||||
os.path.normpath(os.path.join(self.get_artwork_prefix(), src)),
|
||||
os.path.normpath(os.path.join(self.get_build_prefix(), src)),
|
||||
os.path.normpath(os.path.join(self.get_alt_build_prefix(), src))]
|
||||
)
|
||||
for path in paths:
|
||||
if self.wildcard_pattern.search(path):
|
||||
is_glob = True
|
||||
for s,d in self.expand_globs(path, dst):
|
||||
assert(s != d)
|
||||
count += self.process_file(s, d)
|
||||
found_files.extend(self.process_file(s, d))
|
||||
else:
|
||||
# if it's a directory, recurse through it
|
||||
if os.path.isdir(path):
|
||||
count += self.process_directory(path, dst)
|
||||
found_files.extend(self.process_directory(path, dst))
|
||||
elif os.path.exists(path):
|
||||
count += self.process_file(path, dst)
|
||||
found_files.extend(self.process_file(path, dst))
|
||||
|
||||
# if we're specifying a single path (not a glob),
|
||||
# we should error out if it doesn't exist
|
||||
if count == 0 and not is_glob:
|
||||
if not found_files and not is_glob:
|
||||
raise RuntimeError("No files match %s\n" % str(paths))
|
||||
|
||||
print "%d files" % count
|
||||
print "%d files" % len(found_files)
|
||||
return found_files
|
||||
|
||||
def do(self, *actions):
|
||||
self.actions = actions
|
||||
|
||||
@@ -1,4 +1,28 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
"""\
|
||||
@file llperformance.py
|
||||
|
||||
$LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
Second Life Viewer Source Code
|
||||
Copyright (C) 2010-2011, Linden Research, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation;
|
||||
version 2.1 of the License only.
|
||||
|
||||
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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
# ------------------------------------------------
|
||||
# Sim metrics utility functions.
|
||||
|
||||
@@ -90,6 +90,17 @@ all the output, and get the result.
|
||||
child.tochild.close()
|
||||
result = child.poll()
|
||||
if result != -1:
|
||||
# At this point, the child process has exited and result
|
||||
# is the return value from the process. Between the time
|
||||
# we called select() and poll() the process may have
|
||||
# exited so read all the data left on the child process
|
||||
# stdout and stderr.
|
||||
last = child.fromchild.read()
|
||||
if last:
|
||||
out.append(last)
|
||||
last = child.childerr.read()
|
||||
if last:
|
||||
err.append(last)
|
||||
child.tochild.close()
|
||||
child.fromchild.close()
|
||||
child.childerr.close()
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
"""@file llversion.py
|
||||
@brief Utility for parsing llcommon/llversion${server}.h
|
||||
for the version string and channel string
|
||||
Utility that parses svn info for branch and revision
|
||||
|
||||
$LicenseInfo:firstyear=2006&license=mit$
|
||||
|
||||
Copyright (c) 2006-2009, Linden Research, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
import re, sys, os, commands
|
||||
|
||||
# Methods for gathering version information from
|
||||
# llversionviewer.h and llversionserver.h
|
||||
|
||||
def get_src_root():
|
||||
indra_lib_python_indra_path = os.path.dirname(__file__)
|
||||
return os.path.abspath(os.path.realpath(indra_lib_python_indra_path + "/../../../../../"))
|
||||
|
||||
def get_version_file_contents(version_type):
|
||||
filepath = get_src_root() + '/indra/llcommon/llversion%s.h' % version_type
|
||||
file = open(filepath,"r")
|
||||
file_str = file.read()
|
||||
file.close()
|
||||
return file_str
|
||||
|
||||
def get_version(version_type):
|
||||
file_str = get_version_file_contents(version_type)
|
||||
m = re.search('const S32 LL_VERSION_MAJOR = (\d+);', file_str)
|
||||
VER_MAJOR = m.group(1)
|
||||
m = re.search('const S32 LL_VERSION_MINOR = (\d+);', file_str)
|
||||
VER_MINOR = m.group(1)
|
||||
m = re.search('const S32 LL_VERSION_PATCH = (\d+);', file_str)
|
||||
VER_PATCH = m.group(1)
|
||||
m = re.search('const S32 LL_VERSION_BUILD = (\d+);', file_str)
|
||||
VER_BUILD = m.group(1)
|
||||
version = "%(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s" % locals()
|
||||
return version
|
||||
|
||||
def get_channel(version_type):
|
||||
file_str = get_version_file_contents(version_type)
|
||||
m = re.search('const char \* const LL_CHANNEL = "(.+)";', file_str)
|
||||
return m.group(1)
|
||||
|
||||
def get_viewer_version():
|
||||
return get_version('viewer')
|
||||
|
||||
def get_server_version():
|
||||
return get_version('server')
|
||||
|
||||
def get_viewer_channel():
|
||||
return get_channel('viewer')
|
||||
|
||||
def get_server_channel():
|
||||
return get_channel('server')
|
||||
|
||||
# Methods for gathering subversion information
|
||||
def get_svn_status_matching(regular_expression):
|
||||
# Get the subversion info from the working source tree
|
||||
status, output = commands.getstatusoutput('svn info %s' % get_src_root())
|
||||
m = regular_expression.search(output)
|
||||
if not m:
|
||||
print "Failed to parse svn info output, resultfollows:"
|
||||
print output
|
||||
raise Exception, "No matching svn status in "+src_root
|
||||
return m.group(1)
|
||||
|
||||
def get_svn_branch():
|
||||
branch_re = re.compile('URL: (\S+)')
|
||||
return get_svn_status_matching(branch_re)
|
||||
|
||||
def get_svn_revision():
|
||||
last_rev_re = re.compile('Last Changed Rev: (\d+)')
|
||||
return get_svn_status_matching(last_rev_re)
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ from indra.base import llsd
|
||||
from indra.base import config
|
||||
|
||||
DEBUG = False
|
||||
|
||||
NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
|
||||
NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
|
||||
|
||||
@@ -52,6 +51,11 @@ def _init_g_named_manager(sql_dir = None):
|
||||
|
||||
This function is intended entirely for testing purposes,
|
||||
because it's tricky to control the config from inside a test."""
|
||||
global NQ_FILE_SUFFIX
|
||||
NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
|
||||
global NQ_FILE_SUFFIX_LEN
|
||||
NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
|
||||
|
||||
if sql_dir is None:
|
||||
sql_dir = config.get('named-query-base-dir')
|
||||
|
||||
@@ -65,11 +69,11 @@ def _init_g_named_manager(sql_dir = None):
|
||||
_g_named_manager = NamedQueryManager(
|
||||
os.path.abspath(os.path.realpath(sql_dir)))
|
||||
|
||||
def get(name):
|
||||
def get(name, schema = None):
|
||||
"Get the named query object to be used to perform queries"
|
||||
if _g_named_manager is None:
|
||||
_init_g_named_manager()
|
||||
return _g_named_manager.get(name)
|
||||
return _g_named_manager.get(name).for_schema(schema)
|
||||
|
||||
def sql(connection, name, params):
|
||||
# use module-global NamedQuery object to perform default substitution
|
||||
@@ -280,7 +284,10 @@ class NamedQuery(object):
|
||||
|
||||
So, we need a vendor (or extention) for LIKE_STRING. Anyone
|
||||
want to write it?"""
|
||||
utf8_value = unicode(value, "utf-8")
|
||||
if isinstance(value, unicode):
|
||||
utf8_value = value
|
||||
else:
|
||||
utf8_value = unicode(value, "utf-8")
|
||||
esc_list = []
|
||||
remove_chars = set(u"%_")
|
||||
for glyph in utf8_value:
|
||||
@@ -317,6 +324,8 @@ class NamedQuery(object):
|
||||
|
||||
def for_schema(self, db_name):
|
||||
"Look trough the alternates and return the correct query"
|
||||
if db_name is None:
|
||||
return self
|
||||
try:
|
||||
return self._alternative[db_name]
|
||||
except KeyError, e:
|
||||
@@ -341,21 +350,21 @@ class NamedQuery(object):
|
||||
cursor = connection.cursor(MySQLdb.cursors.DictCursor)
|
||||
else:
|
||||
cursor = connection.cursor()
|
||||
|
||||
statement = self.sql(connection, params)
|
||||
|
||||
full_query, params = self._construct_sql(params)
|
||||
if DEBUG:
|
||||
print "SQL:", statement
|
||||
rows = cursor.execute(statement)
|
||||
|
||||
print "SQL:", self.sql(connection, params)
|
||||
rows = cursor.execute(full_query, params)
|
||||
|
||||
# *NOTE: the expect_rows argument is a very cheesy way to get some
|
||||
# validation on the result set. If you want to add more expectation
|
||||
# logic, do something more object-oriented and flexible. Or use an ORM.
|
||||
# logic, do something more object-oriented and flexible. Or use an ORM.
|
||||
if(self._return_as_map):
|
||||
expect_rows = 1
|
||||
if expect_rows is not None and rows != expect_rows:
|
||||
cursor.close()
|
||||
raise ExpectationFailed("Statement expected %s rows, got %s. Sql: %s" % (
|
||||
expect_rows, rows, statement))
|
||||
raise ExpectationFailed("Statement expected %s rows, got %s. Sql: '%s' %s" % (
|
||||
expect_rows, rows, full_query, params))
|
||||
|
||||
# convert to dicts manually if we're not using a dictcursor
|
||||
if use_dictcursor:
|
||||
@@ -381,11 +390,9 @@ class NamedQuery(object):
|
||||
return result_set[0]
|
||||
return result_set
|
||||
|
||||
def sql(self, connection, params):
|
||||
""" Generates an SQL statement from the named query document
|
||||
and a dictionary of parameters.
|
||||
|
||||
"""
|
||||
def _construct_sql(self, params):
|
||||
""" Returns a query string and a dictionary of parameters,
|
||||
suitable for directly passing to the execute() method."""
|
||||
self.refresh()
|
||||
|
||||
# build the query from the options available and the params
|
||||
@@ -431,10 +438,23 @@ class NamedQuery(object):
|
||||
new_params[self._build_integer_key(key)] = int(params[key])
|
||||
params.update(new_params)
|
||||
|
||||
return full_query, params
|
||||
|
||||
def sql(self, connection, params):
|
||||
""" Generates an SQL statement from the named query document
|
||||
and a dictionary of parameters.
|
||||
|
||||
*NOTE: Only use for debugging, because it uses the
|
||||
non-standard MySQLdb 'literal' method.
|
||||
"""
|
||||
if not DEBUG:
|
||||
import warnings
|
||||
warnings.warn("Don't use named_query.sql() when not debugging. Used on %s" % self._location)
|
||||
# do substitution using the mysql (non-standard) 'literal'
|
||||
# function to do the escaping.
|
||||
sql = full_query % connection.literal(params)
|
||||
return sql
|
||||
full_query, params = self._construct_sql(params)
|
||||
return full_query % connection.literal(params)
|
||||
|
||||
|
||||
def refresh(self):
|
||||
""" Refresh self from the file on the filesystem.
|
||||
|
||||
@@ -3,20 +3,27 @@
|
||||
@file simperf_oprof_interface.py
|
||||
@brief Manage OProfile data collection on a host
|
||||
|
||||
$LicenseInfo:firstyear=2008&license=internal$
|
||||
$LicenseInfo:firstyear=2008&license=mit$
|
||||
|
||||
Copyright (c) 2008-2009, Linden Research, Inc.
|
||||
|
||||
The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
|
||||
this source code is governed by the Linden Lab Source Code Disclosure
|
||||
Agreement ("Agreement") previously entered between you and Linden
|
||||
Lab. By accessing, using, copying, modifying or distributing this
|
||||
software, you acknowledge that you have been informed of your
|
||||
obligations under the Agreement and agree to abide by those obligations.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
COMPLETENESS OR PERFORMANCE.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,4 +1,31 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
"""\
|
||||
@file simperf_proc_interface.py
|
||||
@brief Utility to extract log messages from *.<pid>.llsd files containing performance statistics.
|
||||
|
||||
$LicenseInfo:firstyear=2008&license=mit$
|
||||
|
||||
Copyright (c) 2008-2009, Linden Research, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Utility to extract log messages from *.<pid>.llsd
|
||||
|
||||
146
indra/lib/python/indra/util/test_win32_manifest.py
Normal file
146
indra/lib/python/indra/util/test_win32_manifest.py
Normal file
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env python
|
||||
"""\
|
||||
@file test_win32_manifest.py
|
||||
@brief Test an assembly binding version and uniqueness in a windows dll or exe.
|
||||
|
||||
$LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
Second Life Viewer Source Code
|
||||
Copyright (C) 2009-2011, Linden Research, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation;
|
||||
version 2.1 of the License only.
|
||||
|
||||
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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
import sys, os
|
||||
import tempfile
|
||||
from xml.dom.minidom import parse
|
||||
|
||||
class AssemblyTestException(Exception):
|
||||
pass
|
||||
|
||||
class NoManifestException(AssemblyTestException):
|
||||
pass
|
||||
|
||||
class MultipleBindingsException(AssemblyTestException):
|
||||
pass
|
||||
|
||||
class UnexpectedVersionException(AssemblyTestException):
|
||||
pass
|
||||
|
||||
class NoMatchingAssemblyException(AssemblyTestException):
|
||||
pass
|
||||
|
||||
def get_HKLM_registry_value(key_str, value_str):
|
||||
import _winreg
|
||||
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
|
||||
key = _winreg.OpenKey(reg, key_str)
|
||||
value = _winreg.QueryValueEx(key, value_str)[0]
|
||||
#print 'Found: %s' % value
|
||||
return value
|
||||
|
||||
def find_vc_dir():
|
||||
supported_versions = (r'8.0', r'9.0')
|
||||
supported_products = (r'VisualStudio', r'VCExpress')
|
||||
value_str = (r'ProductDir')
|
||||
|
||||
for product in supported_products:
|
||||
for version in supported_versions:
|
||||
key_str = (r'SOFTWARE\Microsoft\%s\%s\Setup\VC' %
|
||||
(product, version))
|
||||
try:
|
||||
return get_HKLM_registry_value(key_str, value_str)
|
||||
except WindowsError, err:
|
||||
x64_key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' %
|
||||
version)
|
||||
try:
|
||||
return get_HKLM_registry_value(x64_key_str, value_str)
|
||||
except:
|
||||
print >> sys.stderr, "Didn't find MS %s version %s " % (product,version)
|
||||
|
||||
raise
|
||||
|
||||
def find_mt_path():
|
||||
vc_dir = find_vc_dir()
|
||||
mt_path = '\"%sbin\\mt.exe\"' % vc_dir
|
||||
return mt_path
|
||||
|
||||
def test_assembly_binding(src_filename, assembly_name, assembly_ver):
|
||||
print "checking %s dependency %s..." % (src_filename, assembly_name)
|
||||
|
||||
(tmp_file_fd, tmp_file_name) = tempfile.mkstemp(suffix='.xml')
|
||||
tmp_file = os.fdopen(tmp_file_fd)
|
||||
tmp_file.close()
|
||||
|
||||
mt_path = find_mt_path()
|
||||
resource_id = ""
|
||||
if os.path.splitext(src_filename)[1].lower() == ".dll":
|
||||
resource_id = ";#2"
|
||||
system_call = '%s -nologo -inputresource:%s%s -out:%s > NUL' % (mt_path, src_filename, resource_id, tmp_file_name)
|
||||
print "Executing: %s" % system_call
|
||||
mt_result = os.system(system_call)
|
||||
if mt_result == 31:
|
||||
print "No manifest found in %s" % src_filename
|
||||
raise NoManifestException()
|
||||
|
||||
manifest_dom = parse(tmp_file_name)
|
||||
nodes = manifest_dom.getElementsByTagName('assemblyIdentity')
|
||||
|
||||
versions = list()
|
||||
for node in nodes:
|
||||
if node.getAttribute('name') == assembly_name:
|
||||
versions.append(node.getAttribute('version'))
|
||||
|
||||
if len(versions) == 0:
|
||||
print "No matching assemblies found in %s" % src_filename
|
||||
raise NoMatchingAssemblyException()
|
||||
|
||||
elif len(versions) > 1:
|
||||
print "Multiple bindings to %s found:" % assembly_name
|
||||
print versions
|
||||
print
|
||||
raise MultipleBindingsException(versions)
|
||||
|
||||
elif versions[0] != assembly_ver:
|
||||
print "Unexpected version found for %s:" % assembly_name
|
||||
print "Wanted %s, found %s" % (assembly_ver, versions[0])
|
||||
print
|
||||
raise UnexpectedVersionException(assembly_ver, versions[0])
|
||||
|
||||
os.remove(tmp_file_name)
|
||||
|
||||
print "SUCCESS: %s OK!" % src_filename
|
||||
print
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print
|
||||
print "Running test_win32_manifest.py..."
|
||||
|
||||
usage = 'test_win32_manfest <srcFileName> <assemblyName> <assemblyVersion>'
|
||||
|
||||
try:
|
||||
src_filename = sys.argv[1]
|
||||
assembly_name = sys.argv[2]
|
||||
assembly_ver = sys.argv[3]
|
||||
except:
|
||||
print "Usage:"
|
||||
print usage
|
||||
print
|
||||
raise
|
||||
|
||||
test_assembly_binding(src_filename, assembly_name, assembly_ver)
|
||||
|
||||
|
||||
@@ -45,13 +45,6 @@ Typical usage:
|
||||
|
||||
This module works with Python 2.3 or higher."""
|
||||
|
||||
# *HACK: Necessary for python 2.4. Consider replacing this code wart
|
||||
# after python >=2.5 has deployed everywhere. 2009-10-05
|
||||
try:
|
||||
from hashlib import md5
|
||||
except ImportError:
|
||||
from md5 import md5
|
||||
|
||||
__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
|
||||
__date__ = '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-')
|
||||
__version__ = '$Revision: 1.30 $'.split()[1]
|
||||
@@ -453,6 +446,13 @@ def uuid1(node=None, clock_seq=None):
|
||||
|
||||
def uuid3(namespace, name):
|
||||
"""Generate a UUID from the MD5 hash of a namespace UUID and a name."""
|
||||
try:
|
||||
# Python 2.6
|
||||
from hashlib import md5
|
||||
except ImportError:
|
||||
# Python 2.5 and earlier
|
||||
from md5 import new as md5
|
||||
|
||||
hash = md5(namespace.bytes + name).digest()
|
||||
return UUID(bytes=hash[:16], version=3)
|
||||
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
#include <assert.h>
|
||||
#include <limits>
|
||||
#include "hacdManifoldMesh.h"
|
||||
|
||||
#if _MSC_VER >= 1800
|
||||
#include <algorithm>
|
||||
#endif
|
||||
namespace HACD
|
||||
{
|
||||
bool BBox::Raycast(const Vec3<Float> & origin, const Vec3<Float> & dir, Float & distMin) const
|
||||
|
||||
@@ -182,9 +182,6 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
|
||||
}
|
||||
|
||||
mIsBuilt = FALSE;
|
||||
|
||||
mNumCollisionVolumes = 0;
|
||||
mCollisionVolumes = NULL;
|
||||
}
|
||||
|
||||
// virtual
|
||||
@@ -294,7 +291,7 @@ LLAvatarAppearance::~LLAvatarAppearance()
|
||||
mJointMap.clear();
|
||||
|
||||
clearSkeleton();
|
||||
deleteAndClearArray(mCollisionVolumes);
|
||||
clearCollisionVolumes();
|
||||
|
||||
std::for_each(mPolyMeshes.begin(), mPolyMeshes.end(), DeletePairedPointer());
|
||||
mPolyMeshes.clear();
|
||||
@@ -575,12 +572,12 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
|
||||
}
|
||||
else // collision volume
|
||||
{
|
||||
if (volume_num >= (S32)mNumCollisionVolumes)
|
||||
if (volume_num >= (S32)mCollisionVolumes.size())
|
||||
{
|
||||
llwarns << "Too many bones" << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
joint = (&mCollisionVolumes[volume_num]);
|
||||
joint = (mCollisionVolumes[volume_num]);
|
||||
joint->setName( info->mName );
|
||||
}
|
||||
|
||||
@@ -1250,12 +1247,12 @@ LLVector3 LLAvatarAppearance::getVolumePos(S32 joint_index, LLVector3& volume_of
|
||||
return LLVector3::zero;
|
||||
}
|
||||
|
||||
if (joint_index > mNumCollisionVolumes)
|
||||
if (joint_index > (S32)mCollisionVolumes.size())
|
||||
{
|
||||
return LLVector3::zero;
|
||||
}
|
||||
|
||||
return mCollisionVolumes[joint_index].getVolumePos(volume_offset);
|
||||
return mCollisionVolumes[joint_index]->getVolumePos(volume_offset);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1266,12 +1263,12 @@ LLJoint* LLAvatarAppearance::findCollisionVolume(U32 volume_id)
|
||||
//SNOW-488: As mNumCollisionVolumes is a S32 and we are casting from a U32 to a S32
|
||||
//to compare we also need to be sure of the wrap around case producing (S32) <0
|
||||
//or in terms of the U32 an out of bounds index in the array.
|
||||
if ((S32)volume_id > mNumCollisionVolumes || (S32)volume_id<0)
|
||||
if ((S32)volume_id > (S32)mCollisionVolumes.size() || (S32)volume_id<0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &mCollisionVolumes[volume_id];
|
||||
return mCollisionVolumes[volume_id];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1279,9 +1276,9 @@ LLJoint* LLAvatarAppearance::findCollisionVolume(U32 volume_id)
|
||||
//-----------------------------------------------------------------------------
|
||||
S32 LLAvatarAppearance::getCollisionVolumeID(std::string &name)
|
||||
{
|
||||
for (S32 i = 0; i < mNumCollisionVolumes; i++)
|
||||
for (S32 i = 0; i < (S32)mCollisionVolumes.size(); i++)
|
||||
{
|
||||
if (mCollisionVolumes[i].getName() == name)
|
||||
if (mCollisionVolumes[i]->getName() == name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
@@ -1530,21 +1527,34 @@ LLTexLayerSet* LLAvatarAppearance::getAvatarLayerSet(EBakedTextureIndex baked_in
|
||||
return mBakedTextureDatas[baked_index].mTexLayerSet;
|
||||
}
|
||||
|
||||
void LLAvatarAppearance::clearCollisionVolumes()
|
||||
{
|
||||
std::for_each(mCollisionVolumes.begin(), mCollisionVolumes.end(),
|
||||
DeletePointer());
|
||||
mCollisionVolumes.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// allocateCollisionVolumes()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num )
|
||||
{
|
||||
deleteAndClearArray(mCollisionVolumes);
|
||||
mNumCollisionVolumes = 0;
|
||||
mCollisionVolumes.reserve(num);
|
||||
|
||||
mCollisionVolumes = new LLAvatarJointCollisionVolume[num];
|
||||
if (!mCollisionVolumes)
|
||||
LLAvatarJointCollisionVolume* cv;
|
||||
for (U32 i = 0; i < num; ++i)
|
||||
{
|
||||
return FALSE;
|
||||
cv = new LLAvatarJointCollisionVolume();
|
||||
if (cv)
|
||||
{
|
||||
mCollisionVolumes.push_back(cv);
|
||||
}
|
||||
else
|
||||
{
|
||||
clearCollisionVolumes();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mNumCollisionVolumes = num;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -337,9 +337,9 @@ protected:
|
||||
// Collision volumes
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
S32 mNumCollisionVolumes;
|
||||
LLAvatarJointCollisionVolume* mCollisionVolumes;
|
||||
std::vector<LLAvatarJointCollisionVolume*> mCollisionVolumes;
|
||||
protected:
|
||||
void clearCollisionVolumes();
|
||||
BOOL allocateCollisionVolumes(U32 num);
|
||||
|
||||
/** Physics
|
||||
|
||||
@@ -127,6 +127,16 @@ public:
|
||||
LLAvatarJointCollisionVolume();
|
||||
virtual ~LLAvatarJointCollisionVolume() {};
|
||||
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
|
||||
/*virtual*/ BOOL inheritScale() { return TRUE; }
|
||||
/*virtual*/ U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE );
|
||||
|
||||
|
||||
@@ -647,11 +647,11 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
|
||||
for (iter = getInfo()->mVolumeInfoList.begin(); iter != getInfo()->mVolumeInfoList.end(); iter++)
|
||||
{
|
||||
LLPolyVolumeMorphInfo *volume_info = &(*iter);
|
||||
for (S32 i = 0; i < avatarp->mNumCollisionVolumes; i++)
|
||||
for (S32 i = 0; i < (S32)avatarp->mCollisionVolumes.size(); i++)
|
||||
{
|
||||
if (avatarp->mCollisionVolumes[i].getName() == volume_info->mName)
|
||||
if (avatarp->mCollisionVolumes[i]->getName() == volume_info->mName)
|
||||
{
|
||||
mVolumeMorphs.push_back(LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i],
|
||||
mVolumeMorphs.push_back(LLPolyVolumeMorph(avatarp->mCollisionVolumes[i],
|
||||
volume_info->mScale,
|
||||
volume_info->mPos));
|
||||
break;
|
||||
|
||||
@@ -163,6 +163,16 @@ public:
|
||||
LLPolyMorphTarget(LLPolyMesh *poly_mesh);
|
||||
~LLPolyMorphTarget();
|
||||
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
|
||||
// Special: These functions are overridden by child classes
|
||||
LLPolyMorphTargetInfo* getInfo() const { return (LLPolyMorphTargetInfo*)mInfo; }
|
||||
// This sets mInfo and calls initialization functions
|
||||
|
||||
@@ -5,25 +5,21 @@ project(llaudio)
|
||||
include(00-Common)
|
||||
include(Audio)
|
||||
include(LLAudio)
|
||||
if (FMODSTUDIO)
|
||||
include(FMODSTUDIO)
|
||||
endif (FMODSTUDIO)
|
||||
if (FMODEX)
|
||||
include(FMODEX)
|
||||
set(FMOD OFF)
|
||||
endif (FMODEX)
|
||||
if (NOT FMODEX)
|
||||
include(FMOD)
|
||||
endif (NOT FMODEX)
|
||||
include(OPENAL)
|
||||
include(LLCommon)
|
||||
include(LLMath)
|
||||
include(LLMessage)
|
||||
include(LLVFS)
|
||||
|
||||
if (FMODEX)
|
||||
include_directories(${FMODEX_INCLUDE_DIR})
|
||||
endif(FMODEX)
|
||||
if(FMOD)
|
||||
if (FMOD)
|
||||
include_directories(${FMOD_INCLUDE_DIR})
|
||||
endif (FMOD)
|
||||
endif(FMOD)
|
||||
|
||||
include_directories(
|
||||
${LLAUDIO_INCLUDE_DIRS}
|
||||
@@ -58,6 +54,20 @@ set(llaudio_HEADER_FILES
|
||||
llwindgen.h
|
||||
)
|
||||
|
||||
if (FMODSTUDIO)
|
||||
list(APPEND llaudio_SOURCE_FILES
|
||||
llaudioengine_fmodstudio.cpp
|
||||
lllistener_fmodstudio.cpp
|
||||
llstreamingaudio_fmodstudio.cpp
|
||||
)
|
||||
|
||||
list(APPEND llaudio_HEADER_FILES
|
||||
llaudioengine_fmodstudio.h
|
||||
lllistener_fmodstudio.h
|
||||
llstreamingaudio_fmodstudio.h
|
||||
)
|
||||
endif (FMODSTUDIO)
|
||||
|
||||
if (FMODEX)
|
||||
list(APPEND llaudio_SOURCE_FILES
|
||||
llaudioengine_fmodex.cpp
|
||||
@@ -71,26 +81,6 @@ if (FMODEX)
|
||||
llstreamingaudio_fmodex.h
|
||||
)
|
||||
endif (FMODEX)
|
||||
if (FMOD)
|
||||
list(APPEND llaudio_SOURCE_FILES
|
||||
llaudioengine_fmod.cpp
|
||||
lllistener_fmod.cpp
|
||||
llstreamingaudio_fmod.cpp
|
||||
)
|
||||
|
||||
list(APPEND llaudio_HEADER_FILES
|
||||
llaudioengine_fmod.h
|
||||
lllistener_fmod.h
|
||||
llstreamingaudio_fmod.h
|
||||
)
|
||||
|
||||
if (LINUX)
|
||||
if (${CXX_VERSION} MATCHES "4.[23]")
|
||||
set_source_files_properties(llaudioengine_fmod.cpp
|
||||
COMPILE_FLAGS -Wno-error=write-strings)
|
||||
endif (${CXX_VERSION} MATCHES "4.[23]")
|
||||
endif (LINUX)
|
||||
endif (FMOD)
|
||||
|
||||
if (OPENAL)
|
||||
list(APPEND llaudio_SOURCE_FILES
|
||||
|
||||
@@ -174,6 +174,9 @@ void LLAudioEngine::shutdown()
|
||||
delete mBuffers[i];
|
||||
mBuffers[i] = NULL;
|
||||
}
|
||||
|
||||
delete mStreamingAudioImpl;
|
||||
mStreamingAudioImpl = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,789 +0,0 @@
|
||||
/**
|
||||
* @file audioengine_fmod.cpp
|
||||
* @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 3D implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llstreamingaudio.h"
|
||||
#include "llstreamingaudio_fmod.h"
|
||||
|
||||
#include "llaudioengine_fmod.h"
|
||||
#include "lllistener_fmod.h"
|
||||
|
||||
#include "llerror.h"
|
||||
#include "llmath.h"
|
||||
#include "llrand.h"
|
||||
|
||||
#include "fmod.h"
|
||||
#include "fmod_errors.h"
|
||||
#include "lldir.h"
|
||||
#include "llapr.h"
|
||||
|
||||
#include "sound_ids.h"
|
||||
|
||||
|
||||
extern "C" {
|
||||
void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata);
|
||||
}
|
||||
|
||||
|
||||
LLAudioEngine_FMOD::LLAudioEngine_FMOD()
|
||||
{
|
||||
mInited = false;
|
||||
mWindGen = NULL;
|
||||
mWindDSP = NULL;
|
||||
}
|
||||
|
||||
|
||||
LLAudioEngine_FMOD::~LLAudioEngine_FMOD()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
|
||||
{
|
||||
LLAudioEngine::init(num_channels, userdata);
|
||||
|
||||
// Reserve one extra channel for the http stream.
|
||||
if (!FSOUND_SetMinHardwareChannels(num_channels + 1))
|
||||
{
|
||||
LL_WARNS("AppInit") << "FMOD::init[0](), error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
|
||||
}
|
||||
|
||||
LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() initializing FMOD" << LL_ENDL;
|
||||
|
||||
F32 version = FSOUND_GetVersion();
|
||||
if (version < FMOD_VERSION)
|
||||
{
|
||||
LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version
|
||||
<< ")! You should be using FMOD " << FMOD_VERSION << LL_ENDL;
|
||||
//return false;
|
||||
}
|
||||
|
||||
U32 fmod_flags = 0x0;
|
||||
|
||||
#if LL_WINDOWS
|
||||
// Windows needs to know which window is frontmost.
|
||||
// This must be called before FSOUND_Init() per the FMOD docs.
|
||||
// This could be used to let FMOD handle muting when we lose focus,
|
||||
// but we don't actually want to do that because we want to distinguish
|
||||
// between minimized and not-focused states.
|
||||
if (!FSOUND_SetHWND(userdata))
|
||||
{
|
||||
LL_WARNS("AppInit") << "Error setting FMOD window: "
|
||||
<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
// Play audio when we don't have focus.
|
||||
// (For example, IM client on top of us.)
|
||||
// This means we also try to play audio when minimized,
|
||||
// so we manually handle muting in that case. JC
|
||||
fmod_flags |= FSOUND_INIT_GLOBALFOCUS;
|
||||
fmod_flags |= FSOUND_INIT_DSOUND_HRTF_FULL;
|
||||
#endif
|
||||
|
||||
#if LL_LINUX
|
||||
// initialize the FMOD engine
|
||||
|
||||
// This is a hack to use only FMOD's basic FPU mixer
|
||||
// when the LL_VALGRIND environmental variable is set,
|
||||
// otherwise valgrind will fall over on FMOD's MMX detection
|
||||
if (getenv("LL_VALGRIND")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_INFOS("AppInit") << "Pacifying valgrind in FMOD init." << LL_ENDL;
|
||||
FSOUND_SetMixer(FSOUND_MIXER_QUALITY_FPU);
|
||||
}
|
||||
|
||||
// If we don't set an output method, Linux FMOD always
|
||||
// decides on OSS and fails otherwise. So we'll manually
|
||||
// try ESD, then OSS, then ALSA.
|
||||
// Why this order? See SL-13250, but in short, OSS emulated
|
||||
// on top of ALSA is ironically more reliable than raw ALSA.
|
||||
// Ack, and ESD has more reliable failure modes - but has worse
|
||||
// latency - than all of them, so wins for now.
|
||||
bool audio_ok = false;
|
||||
|
||||
if (!audio_ok)
|
||||
{
|
||||
if (NULL == getenv("LL_BAD_FMOD_ESD")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL;
|
||||
if(FSOUND_SetOutput(FSOUND_OUTPUT_ESD) &&
|
||||
FSOUND_Init(44100, num_channels, fmod_flags))
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY"
|
||||
<< LL_ENDL;
|
||||
audio_ok = true;
|
||||
} else {
|
||||
LL_WARNS("AppInit") << "ESD audio output FAILED to initialize: "
|
||||
<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
|
||||
}
|
||||
} else {
|
||||
LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
if (!audio_ok)
|
||||
{
|
||||
if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL;
|
||||
if(FSOUND_SetOutput(FSOUND_OUTPUT_OSS) &&
|
||||
FSOUND_Init(44100, num_channels, fmod_flags))
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL;
|
||||
audio_ok = true;
|
||||
} else {
|
||||
LL_WARNS("AppInit") << "OSS audio output FAILED to initialize: "
|
||||
<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
|
||||
}
|
||||
} else {
|
||||
LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
if (!audio_ok)
|
||||
{
|
||||
if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
|
||||
if(FSOUND_SetOutput(FSOUND_OUTPUT_ALSA) &&
|
||||
FSOUND_Init(44100, num_channels, fmod_flags))
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL;
|
||||
audio_ok = true;
|
||||
} else {
|
||||
LL_WARNS("AppInit") << "ALSA audio output FAILED to initialize: "
|
||||
<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
|
||||
}
|
||||
} else {
|
||||
LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
if (!audio_ok)
|
||||
{
|
||||
LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// On Linux, FMOD causes a SIGPIPE for some netstream error
|
||||
// conditions (an FMOD bug); ignore SIGPIPE so it doesn't crash us.
|
||||
// NOW FIXED in FMOD 3.x since 2006-10-01.
|
||||
//signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
// We're interested in logging which output method we
|
||||
// ended up with, for QA purposes.
|
||||
switch (FSOUND_GetOutput())
|
||||
{
|
||||
case FSOUND_OUTPUT_NOSOUND: LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
|
||||
case FSOUND_OUTPUT_OSS: LL_DEBUGS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
|
||||
case FSOUND_OUTPUT_ESD: LL_DEBUGS("AppInit") << "Audio output: ESD" << LL_ENDL; break;
|
||||
case FSOUND_OUTPUT_ALSA: LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
|
||||
default: LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
|
||||
};
|
||||
|
||||
#else // LL_LINUX
|
||||
|
||||
// initialize the FMOD engine
|
||||
if (!FSOUND_Init(44100, num_channels, fmod_flags))
|
||||
{
|
||||
LL_WARNS("AppInit") << "Error initializing FMOD: "
|
||||
<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// set up our favourite FMOD-native streaming audio implementation if none has already been added
|
||||
if (!getStreamingAudioImpl()) // no existing implementation added
|
||||
setStreamingAudioImpl(new LLStreamingAudio_FMOD());
|
||||
|
||||
LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL;
|
||||
|
||||
mInited = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string LLAudioEngine_FMOD::getDriverName(bool verbose)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
F32 version = FSOUND_GetVersion();
|
||||
return llformat("FMOD version %f", version);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "FMOD";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLAudioEngine_FMOD::allocateListener(void)
|
||||
{
|
||||
mListenerp = (LLListener *) new LLListener_FMOD();
|
||||
if (!mListenerp)
|
||||
{
|
||||
llwarns << "Listener creation failed" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLAudioEngine_FMOD::shutdown()
|
||||
{
|
||||
if (mWindDSP)
|
||||
{
|
||||
FSOUND_DSP_SetActive(mWindDSP,false);
|
||||
FSOUND_DSP_Free(mWindDSP);
|
||||
}
|
||||
|
||||
stopInternetStream();
|
||||
|
||||
LLAudioEngine::shutdown();
|
||||
|
||||
llinfos << "LLAudioEngine_FMOD::shutdown() closing FMOD" << llendl;
|
||||
FSOUND_Close();
|
||||
llinfos << "LLAudioEngine_FMOD::shutdown() done closing FMOD" << llendl;
|
||||
|
||||
delete mListenerp;
|
||||
mListenerp = NULL;
|
||||
}
|
||||
|
||||
|
||||
LLAudioBuffer * LLAudioEngine_FMOD::createBuffer()
|
||||
{
|
||||
return new LLAudioBufferFMOD();
|
||||
}
|
||||
|
||||
|
||||
LLAudioChannel * LLAudioEngine_FMOD::createChannel()
|
||||
{
|
||||
return new LLAudioChannelFMOD();
|
||||
}
|
||||
|
||||
|
||||
bool LLAudioEngine_FMOD::initWind()
|
||||
{
|
||||
if (!mWindGen)
|
||||
{
|
||||
bool enable;
|
||||
|
||||
switch (FSOUND_GetMixer())
|
||||
{
|
||||
case FSOUND_MIXER_MMXP5:
|
||||
case FSOUND_MIXER_MMXP6:
|
||||
case FSOUND_MIXER_QUALITY_MMXP5:
|
||||
case FSOUND_MIXER_QUALITY_MMXP6:
|
||||
enable = (typeid(MIXBUFFERFORMAT) == typeid(S16));
|
||||
break;
|
||||
case FSOUND_MIXER_BLENDMODE:
|
||||
enable = (typeid(MIXBUFFERFORMAT) == typeid(S32));
|
||||
break;
|
||||
case FSOUND_MIXER_QUALITY_FPU:
|
||||
enable = (typeid(MIXBUFFERFORMAT) == typeid(F32));
|
||||
break;
|
||||
default:
|
||||
// FSOUND_GetMixer() does not return a valid mixer type on Darwin
|
||||
LL_INFOS("AppInit") << "Unknown FMOD mixer type, assuming default" << LL_ENDL;
|
||||
enable = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
{
|
||||
mWindGen = new LLWindGen<MIXBUFFERFORMAT>(FSOUND_GetOutputRate());
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("AppInit") << "Incompatible FMOD mixer type, wind noise disabled" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
mNextWindUpdate = 0.0;
|
||||
|
||||
if (mWindGen && !mWindDSP)
|
||||
{
|
||||
mWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen);
|
||||
}
|
||||
if (mWindDSP)
|
||||
{
|
||||
FSOUND_DSP_SetActive(mWindDSP, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioEngine_FMOD::cleanupWind()
|
||||
{
|
||||
if (mWindDSP)
|
||||
{
|
||||
FSOUND_DSP_SetActive(mWindDSP, false);
|
||||
FSOUND_DSP_Free(mWindDSP);
|
||||
mWindDSP = NULL;
|
||||
}
|
||||
|
||||
delete mWindGen;
|
||||
mWindGen = NULL;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec, F32 camera_height_above_water)
|
||||
{
|
||||
LLVector3 wind_pos;
|
||||
F64 pitch;
|
||||
F64 center_freq;
|
||||
|
||||
if (!mEnableWind)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
|
||||
{
|
||||
|
||||
// wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up)
|
||||
// need to convert this to the conventional orientation DS3D and OpenAL use
|
||||
// where +X = right, +Y = up, +Z = backwards
|
||||
|
||||
wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
|
||||
|
||||
// cerr << "Wind update" << endl;
|
||||
|
||||
pitch = 1.0 + mapWindVecToPitch(wind_vec);
|
||||
center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
|
||||
|
||||
mWindGen->mTargetFreq = (F32)center_freq;
|
||||
mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
|
||||
mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
//-----------------------------------------------------------------------
|
||||
void LLAudioEngine_FMOD::setSourceMinDistance(U16 source_num, F64 distance)
|
||||
{
|
||||
if (!mInited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mBuffer[source_num])
|
||||
{
|
||||
mMinDistance[source_num] = (F32) distance;
|
||||
if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num]))
|
||||
{
|
||||
llwarns << "FMOD::setSourceMinDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLAudioEngine_FMOD::setSourceMaxDistance(U16 source_num, F64 distance)
|
||||
{
|
||||
if (!mInited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mBuffer[source_num])
|
||||
{
|
||||
mMaxDistance[source_num] = (F32) distance;
|
||||
if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num]))
|
||||
{
|
||||
llwarns << "FMOD::setSourceMaxDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLAudioEngine_FMOD::get3DParams(S32 source_num, S32 *volume, S32 *freq, S32 *inside, S32 *outside, LLVector3 *orient, S32 *out_volume, F32 *min_dist, F32 *max_dist)
|
||||
{
|
||||
*volume = 0;
|
||||
*freq = 0;
|
||||
*inside = 0;
|
||||
*outside = 0;
|
||||
*orient = LLVector3::zero;
|
||||
*out_volume = 0;
|
||||
*min_dist = 0.f;
|
||||
*max_dist = 0.f;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLAudioEngine_FMOD::setInternalGain(F32 gain)
|
||||
{
|
||||
if (!mInited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gain = llclamp( gain, 0.0f, 1.0f );
|
||||
FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) );
|
||||
|
||||
LLStreamingAudioInterface *saimpl = getStreamingAudioImpl();
|
||||
if ( saimpl )
|
||||
{
|
||||
// fmod likes its streaming audio channel gain re-asserted after
|
||||
// master volume change.
|
||||
saimpl->setGain(saimpl->getGain());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LLAudioChannelFMOD implementation
|
||||
//
|
||||
|
||||
LLAudioChannelFMOD::LLAudioChannelFMOD() : LLAudioChannel(), mChannelID(0), mLastSamplePos(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LLAudioChannelFMOD::~LLAudioChannelFMOD()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
||||
bool LLAudioChannelFMOD::updateBuffer()
|
||||
{
|
||||
if (LLAudioChannel::updateBuffer())
|
||||
{
|
||||
// Base class update returned true, which means that we need to actually
|
||||
// set up the channel for a different buffer.
|
||||
|
||||
LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer();
|
||||
|
||||
// Grab the FMOD sample associated with the buffer
|
||||
FSOUND_SAMPLE *samplep = bufferp->getSample();
|
||||
if (!samplep)
|
||||
{
|
||||
// This is bad, there should ALWAYS be a sample associated with a legit
|
||||
// buffer.
|
||||
llerrs << "No FMOD sample!" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Actually play the sound. Start it off paused so we can do all the necessary
|
||||
// setup.
|
||||
mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), true);
|
||||
|
||||
//llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl;
|
||||
}
|
||||
|
||||
// If we have a source for the channel, we need to update its gain.
|
||||
if (mCurrentSourcep)
|
||||
{
|
||||
// SJB: warnings can spam and hurt framerate, disabling
|
||||
if (!FSOUND_SetVolume(mChannelID, llround(getSecondaryGain() * mCurrentSourcep->getGain() * 255.0f)))
|
||||
{
|
||||
// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
|
||||
}
|
||||
|
||||
if (!FSOUND_SetLoopMode(mChannelID, mCurrentSourcep->isLoop() ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF))
|
||||
{
|
||||
// llwarns << "Channel " << mChannelID << "Source ID: " << mCurrentSourcep->getID()
|
||||
// << " at " << mCurrentSourcep->getPositionGlobal() << llendl;
|
||||
// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMOD::update3DPosition()
|
||||
{
|
||||
if (!mChannelID)
|
||||
{
|
||||
// We're not actually a live channel (i.e., we're not playing back anything)
|
||||
return;
|
||||
}
|
||||
|
||||
LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentBufferp;
|
||||
if (!bufferp)
|
||||
{
|
||||
// We don't have a buffer associated with us (should really have been picked up
|
||||
// by the above if.
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCurrentSourcep->isAmbient())
|
||||
{
|
||||
// Ambient sound, don't need to do any positional updates.
|
||||
bufferp->set3DMode(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Localized sound. Update the position and velocity of the sound.
|
||||
bufferp->set3DMode(true);
|
||||
|
||||
LLVector3 float_pos;
|
||||
float_pos.setVec(mCurrentSourcep->getPositionGlobal());
|
||||
if (!FSOUND_3D_SetAttributes(mChannelID, float_pos.mV, mCurrentSourcep->getVelocity().mV))
|
||||
{
|
||||
LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::update3DPosition error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMOD::updateLoop()
|
||||
{
|
||||
if (!mChannelID)
|
||||
{
|
||||
// May want to clear up the loop/sample counters.
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Hack: We keep track of whether we looped or not by seeing when the
|
||||
// sample position looks like it's going backwards. Not reliable; may
|
||||
// yield false negatives.
|
||||
//
|
||||
U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID);
|
||||
if (cur_pos < (U32)mLastSamplePos)
|
||||
{
|
||||
mLoopedThisFrame = true;
|
||||
}
|
||||
mLastSamplePos = cur_pos;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMOD::cleanup()
|
||||
{
|
||||
LLAudioChannel::cleanup();
|
||||
if (!mChannelID)
|
||||
{
|
||||
//llinfos << "Aborting cleanup with no channelID." << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
//llinfos << "Cleaning up channel: " << mChannelID << llendl;
|
||||
if (!FSOUND_StopSound(mChannelID))
|
||||
{
|
||||
LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::cleanup error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
|
||||
}
|
||||
|
||||
mChannelID = 0;
|
||||
mLastSamplePos = 0;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMOD::play()
|
||||
{
|
||||
if (!mChannelID)
|
||||
{
|
||||
llwarns << "Playing without a channelID, aborting" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!FSOUND_IsPaused(mChannelID))
|
||||
{
|
||||
FSOUND_SetPaused(mChannelID, true);
|
||||
FSOUND_SetCurrentPosition(mChannelID, 0);
|
||||
}
|
||||
|
||||
if (!FSOUND_SetPaused(mChannelID, false))
|
||||
{
|
||||
llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
|
||||
}
|
||||
getSource()->setPlayedOnce(true);
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMOD::playSynced(LLAudioChannel *channelp)
|
||||
{
|
||||
LLAudioChannelFMOD *fmod_channelp = (LLAudioChannelFMOD*)channelp;
|
||||
if (!(fmod_channelp->mChannelID && mChannelID))
|
||||
{
|
||||
// Don't have channels allocated to both the master and the slave
|
||||
return;
|
||||
}
|
||||
|
||||
U32 position = FSOUND_GetCurrentPosition(fmod_channelp->mChannelID) % mCurrentBufferp->getLength();
|
||||
// Try to match the position of our sync master
|
||||
if (!FSOUND_SetCurrentPosition(mChannelID, position))
|
||||
{
|
||||
llwarns << "LLAudioChannelFMOD::playSynced unable to set current position" << llendl;
|
||||
}
|
||||
|
||||
// Start us playing
|
||||
play();
|
||||
}
|
||||
|
||||
|
||||
bool LLAudioChannelFMOD::isPlaying()
|
||||
{
|
||||
if (!mChannelID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// LLAudioBufferFMOD implementation
|
||||
//
|
||||
|
||||
|
||||
LLAudioBufferFMOD::LLAudioBufferFMOD() : LLAudioBuffer()
|
||||
{
|
||||
mSamplep = NULL;
|
||||
}
|
||||
|
||||
|
||||
LLAudioBufferFMOD::~LLAudioBufferFMOD()
|
||||
{
|
||||
if (mSamplep)
|
||||
{
|
||||
// Clean up the associated FMOD sample if it exists.
|
||||
FSOUND_Sample_Free(mSamplep);
|
||||
mSamplep = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLAudioBufferFMOD::loadWAV(const std::string& filename)
|
||||
{
|
||||
// Try to open a wav file from disk. This will eventually go away, as we don't
|
||||
// really want to block doing this.
|
||||
if (filename.empty())
|
||||
{
|
||||
// invalid filename, abort.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!LLAPRFile::isExist(filename, LL_APR_RPB))
|
||||
{
|
||||
// File not found, abort.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mSamplep)
|
||||
{
|
||||
// If there's already something loaded in this buffer, clean it up.
|
||||
FSOUND_Sample_Free(mSamplep);
|
||||
mSamplep = NULL;
|
||||
}
|
||||
|
||||
// Load up the wav file into an fmod sample
|
||||
#if LL_WINDOWS
|
||||
// MikeS. - Loading the sound file manually and then handing it over to FMOD,
|
||||
// since FMOD uses posix IO internally,
|
||||
// which doesn't work with unicode file paths.
|
||||
LLFILE* sound_file = LLFile::fopen(filename,"rb"); /* Flawfinder: ignore */
|
||||
if (sound_file)
|
||||
{
|
||||
fseek(sound_file,0,SEEK_END);
|
||||
U32 file_length = ftell(sound_file); //Find the length of the file by seeking to the end and getting the offset
|
||||
size_t read_count;
|
||||
fseek(sound_file,0,SEEK_SET); //Seek back to the beginning
|
||||
char* buffer = new char[file_length];
|
||||
llassert(buffer);
|
||||
read_count = fread((void*)buffer,file_length,1,sound_file);//Load it..
|
||||
if(ferror(sound_file)==0 && (read_count == 1)){//No read error, and we got 1 chunk of our size...
|
||||
unsigned int mode_flags = FSOUND_LOOP_NORMAL | FSOUND_LOADMEMORY;
|
||||
//FSOUND_16BITS | FSOUND_MONO | FSOUND_LOADMEMORY | FSOUND_LOOP_NORMAL;
|
||||
mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, mode_flags , 0, file_length);
|
||||
}
|
||||
delete[] buffer;
|
||||
fclose(sound_file);
|
||||
}
|
||||
#else
|
||||
mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, filename.c_str(), FSOUND_LOOP_NORMAL, 0, 0);
|
||||
#endif
|
||||
|
||||
if (!mSamplep)
|
||||
{
|
||||
// We failed to load the file for some reason.
|
||||
llwarns << "Could not load data '" << filename << "': "
|
||||
<< FMOD_ErrorString(FSOUND_GetError()) << llendl;
|
||||
|
||||
//
|
||||
// If we EVER want to load wav files provided by end users, we need
|
||||
// to rethink this!
|
||||
//
|
||||
// file is probably corrupt - remove it.
|
||||
LLFile::remove(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Everything went well, return true
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
U32 LLAudioBufferFMOD::getLength()
|
||||
{
|
||||
if (!mSamplep)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return FSOUND_Sample_GetLength(mSamplep);
|
||||
}
|
||||
|
||||
|
||||
void LLAudioBufferFMOD::set3DMode(bool use3d)
|
||||
{
|
||||
U16 current_mode = FSOUND_Sample_GetMode(mSamplep);
|
||||
|
||||
if (use3d)
|
||||
{
|
||||
if (!FSOUND_Sample_SetMode(mSamplep, (current_mode & (~FSOUND_2D))))
|
||||
{
|
||||
llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!FSOUND_Sample_SetMode(mSamplep, current_mode | FSOUND_2D))
|
||||
{
|
||||
llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata)
|
||||
{
|
||||
// originalbuffer = fmod's original mixbuffer.
|
||||
// newbuffer = the buffer passed from the previous DSP unit.
|
||||
// length = length in samples at this mix time.
|
||||
// userdata = user parameter passed through in FSOUND_DSP_Create.
|
||||
|
||||
LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *windgen =
|
||||
(LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *)userdata;
|
||||
|
||||
newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length);
|
||||
|
||||
return newbuffer;
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/**
|
||||
* @file audioengine_fmod.h
|
||||
* @brief Definition of LLAudioEngine class abstracting the audio
|
||||
* support as a FMOD 3D implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_AUDIOENGINE_FMOD_H
|
||||
#define LL_AUDIOENGINE_FMOD_H
|
||||
|
||||
#include "llaudioengine.h"
|
||||
#include "lllistener_fmod.h"
|
||||
#include "llwindgen.h"
|
||||
|
||||
#include "fmod.h"
|
||||
|
||||
class LLAudioStreamManagerFMOD;
|
||||
|
||||
class LLAudioEngine_FMOD : public LLAudioEngine
|
||||
{
|
||||
public:
|
||||
LLAudioEngine_FMOD();
|
||||
virtual ~LLAudioEngine_FMOD();
|
||||
|
||||
// initialization/startup/shutdown
|
||||
virtual bool init(const S32 num_channels, void *user_data);
|
||||
virtual std::string getDriverName(bool verbose);
|
||||
virtual void allocateListener();
|
||||
|
||||
virtual void shutdown();
|
||||
|
||||
/*virtual*/ bool initWind();
|
||||
/*virtual*/ void cleanupWind();
|
||||
|
||||
/*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water);
|
||||
|
||||
#if LL_DARWIN
|
||||
typedef S32 MIXBUFFERFORMAT;
|
||||
#else
|
||||
typedef S16 MIXBUFFERFORMAT;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to.
|
||||
/*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel.
|
||||
|
||||
/*virtual*/ void setInternalGain(F32 gain);
|
||||
protected:
|
||||
static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata);
|
||||
|
||||
//F32 mMinDistance[MAX_BUFFERS];
|
||||
//F32 mMaxDistance[MAX_BUFFERS];
|
||||
|
||||
bool mInited;
|
||||
|
||||
// On Windows, userdata is the HWND of the application window.
|
||||
void* mUserData;
|
||||
|
||||
LLWindGen<MIXBUFFERFORMAT> *mWindGen;
|
||||
FSOUND_DSPUNIT *mWindDSP;
|
||||
};
|
||||
|
||||
|
||||
class LLAudioChannelFMOD : public LLAudioChannel
|
||||
{
|
||||
public:
|
||||
LLAudioChannelFMOD();
|
||||
virtual ~LLAudioChannelFMOD();
|
||||
|
||||
protected:
|
||||
/*virtual*/ void play();
|
||||
/*virtual*/ void playSynced(LLAudioChannel *channelp);
|
||||
/*virtual*/ void cleanup();
|
||||
/*virtual*/ bool isPlaying();
|
||||
|
||||
/*virtual*/ bool updateBuffer();
|
||||
/*virtual*/ void update3DPosition();
|
||||
/*virtual*/ void updateLoop();
|
||||
|
||||
protected:
|
||||
int mChannelID;
|
||||
S32 mLastSamplePos;
|
||||
};
|
||||
|
||||
|
||||
class LLAudioBufferFMOD : public LLAudioBuffer
|
||||
{
|
||||
public:
|
||||
LLAudioBufferFMOD();
|
||||
virtual ~LLAudioBufferFMOD();
|
||||
|
||||
/*virtual*/ bool loadWAV(const std::string& filename);
|
||||
/*virtual*/ U32 getLength();
|
||||
friend class LLAudioChannelFMOD;
|
||||
|
||||
void set3DMode(bool use3d);
|
||||
protected:
|
||||
FSOUND_SAMPLE *getSample() { return mSamplep; }
|
||||
protected:
|
||||
FSOUND_SAMPLE *mSamplep;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_AUDIOENGINE_FMOD_H
|
||||
@@ -285,7 +285,7 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
U32 version;
|
||||
U32 version = 0;
|
||||
FMOD_RESULT result;
|
||||
|
||||
LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL;
|
||||
@@ -321,10 +321,6 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
if(mEnableProfiler)
|
||||
{
|
||||
fmod_flags |= FMOD_INIT_ENABLE_PROFILE;
|
||||
mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]);
|
||||
mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]);
|
||||
mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]);
|
||||
mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]);
|
||||
}
|
||||
|
||||
#if LL_LINUX
|
||||
@@ -335,7 +331,7 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
if (NULL == getenv("LL_BAD_FMOD_PULSEAUDIO")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL;
|
||||
if(mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK &&
|
||||
if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO)) == FMOD_OK &&
|
||||
(result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL;
|
||||
@@ -356,7 +352,7 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
|
||||
if(mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK &&
|
||||
if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA)) == FMOD_OK &&
|
||||
(result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL;
|
||||
@@ -377,7 +373,7 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL;
|
||||
if(mSystem->setOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK &&
|
||||
if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_OSS)) == FMOD_OK &&
|
||||
(result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL;
|
||||
@@ -402,20 +398,22 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
// We're interested in logging which output method we
|
||||
// ended up with, for QA purposes.
|
||||
FMOD_OUTPUTTYPE output_type;
|
||||
mSystem->getOutput(&output_type);
|
||||
switch (output_type)
|
||||
if(!Check_FMOD_Error(mSystem->getOutput(&output_type), "FMOD::System::getOutput"))
|
||||
{
|
||||
case FMOD_OUTPUTTYPE_NOSOUND:
|
||||
LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_PULSEAUDIO:
|
||||
LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_ALSA:
|
||||
LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_OSS:
|
||||
LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
|
||||
default:
|
||||
LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
|
||||
};
|
||||
switch (output_type)
|
||||
{
|
||||
case FMOD_OUTPUTTYPE_NOSOUND:
|
||||
LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_PULSEAUDIO:
|
||||
LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_ALSA:
|
||||
LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_OSS:
|
||||
LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
|
||||
default:
|
||||
LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
|
||||
};
|
||||
}
|
||||
#else // LL_LINUX
|
||||
|
||||
// initialize the FMOD engine
|
||||
@@ -437,6 +435,14 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (mEnableProfiler)
|
||||
{
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]), "FMOD::System::createChannelGroup");
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]), "FMOD::System::createChannelGroup");
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]), "FMOD::System::createChannelGroup");
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]), "FMOD::System::createChannelGroup");
|
||||
}
|
||||
|
||||
// set up our favourite FMOD-native streaming audio implementation if none has already been added
|
||||
if (!getStreamingAudioImpl()) // no existing implementation added
|
||||
setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem));
|
||||
@@ -447,35 +453,40 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
unsigned int r_bufferlength;
|
||||
char r_name[256];
|
||||
FMOD_SPEAKERMODE speaker_mode;
|
||||
mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers);
|
||||
mSystem->getSoftwareFormat(&r_samplerate, NULL, &r_channels, NULL, NULL, &r_bits);
|
||||
mSystem->getDriverInfo(0, r_name, 255, 0);
|
||||
mSystem->getSpeakerMode(&speaker_mode);
|
||||
std::string speaker_mode_str = "unknown";
|
||||
switch(speaker_mode)
|
||||
if (!Check_FMOD_Error(mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers), "FMOD::System::getDSPBufferSize") &&
|
||||
!Check_FMOD_Error(mSystem->getSoftwareFormat(&r_samplerate, NULL, &r_channels, NULL, NULL, &r_bits), "FMOD::System::getSoftwareFormat") &&
|
||||
!Check_FMOD_Error(mSystem->getDriverInfo(0, r_name, 255, 0), "FMOD::System::getDriverInfo") &&
|
||||
!Check_FMOD_Error(mSystem->getSpeakerMode(&speaker_mode), "FMOD::System::getSpeakerMode"))
|
||||
{
|
||||
#define SPEAKER_MODE_CASE(MODE) case MODE: speaker_mode_str = #MODE; break;
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_RAW)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_MONO)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_STEREO)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_QUAD)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_SURROUND)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_5POINT1)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_7POINT1)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_SRS5_1_MATRIX)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_MYEARS)
|
||||
default:;
|
||||
#undef SPEAKER_MODE_CASE
|
||||
std::string speaker_mode_str = "unknown";
|
||||
switch(speaker_mode)
|
||||
{
|
||||
#define SPEAKER_MODE_CASE(MODE) case MODE: speaker_mode_str = #MODE; break;
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_RAW)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_MONO)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_STEREO)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_QUAD)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_SURROUND)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_5POINT1)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_7POINT1)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_SRS5_1_MATRIX)
|
||||
SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_MYEARS)
|
||||
default:;
|
||||
#undef SPEAKER_MODE_CASE
|
||||
}
|
||||
|
||||
r_name[255] = '\0';
|
||||
int latency = 1000.0 * r_bufferlength * r_numbuffers /r_samplerate;
|
||||
|
||||
LL_INFOS("AppInit") << "FMOD device: "<< r_name << "\n"
|
||||
<< "Output mode: "<< speaker_mode_str << "\n"
|
||||
<< "FMOD Ex parameters: " << r_samplerate << " Hz * " << r_channels << " * " <<r_bits <<" bit\n"
|
||||
<< "\tbuffer " << r_bufferlength << " * " << r_numbuffers << " (" << latency <<"ms)" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("AppInit") << "Failed to retrieve FMOD device info!" << LL_ENDL;
|
||||
}
|
||||
|
||||
r_name[255] = '\0';
|
||||
int latency = 1000.0 * r_bufferlength * r_numbuffers /r_samplerate;
|
||||
|
||||
LL_INFOS("AppInit") << "FMOD device: "<< r_name << "\n"
|
||||
<< "Output mode: "<< speaker_mode_str << "\n"
|
||||
<< "FMOD Ex parameters: " << r_samplerate << " Hz * " << r_channels << " * " <<r_bits <<" bit\n"
|
||||
<< "\tbuffer " << r_bufferlength << " * " << r_numbuffers << " (" << latency <<"ms)" << LL_ENDL;
|
||||
|
||||
mInited = true;
|
||||
|
||||
return true;
|
||||
@@ -509,8 +520,6 @@ void LLAudioEngine_FMODEX::allocateListener(void)
|
||||
|
||||
void LLAudioEngine_FMODEX::shutdown()
|
||||
{
|
||||
stopInternetStream();
|
||||
|
||||
LL_INFOS("AudioImpl") << "About to LLAudioEngine::shutdown()" << LL_ENDL;
|
||||
LLAudioEngine::shutdown();
|
||||
|
||||
@@ -518,9 +527,9 @@ void LLAudioEngine_FMODEX::shutdown()
|
||||
if ( mSystem ) // speculative fix for MAINT-2657
|
||||
{
|
||||
LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() Requesting FMOD Ex system closure" << LL_ENDL;
|
||||
mSystem->close();
|
||||
Check_FMOD_Error(mSystem->close(), "FMOD::System::close");
|
||||
LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() Requesting FMOD Ex system release" << LL_ENDL;
|
||||
mSystem->release();
|
||||
Check_FMOD_Error(mSystem->release(), "FMOD::System::release");
|
||||
}
|
||||
LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << LL_ENDL;
|
||||
|
||||
@@ -544,30 +553,27 @@ bool LLAudioEngine_FMODEX::initWind()
|
||||
{
|
||||
mNextWindUpdate = 0.0;
|
||||
|
||||
if (!mWindDSP)
|
||||
{
|
||||
FMOD_DSP_DESCRIPTION dspdesc;
|
||||
memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Set everything to zero
|
||||
strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name)); //Set name to "Wind Unit"
|
||||
dspdesc.channels=2;
|
||||
dspdesc.read = &windCallback; //Assign callback.
|
||||
if(Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP"))
|
||||
return false;
|
||||
cleanupWind();
|
||||
|
||||
if(mWindGen)
|
||||
delete mWindGen;
|
||||
|
||||
FMOD_DSP_DESCRIPTION dspdesc;
|
||||
memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Set everything to zero
|
||||
strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name)); //Set name to "Wind Unit"
|
||||
dspdesc.channels=2;
|
||||
dspdesc.read = &windCallback; //Assign callback.
|
||||
if(Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP") || !mWindDSP)
|
||||
return false;
|
||||
|
||||
float frequency = 44100;
|
||||
mWindDSP->getDefaults(&frequency,0,0,0);
|
||||
float frequency = 44100;
|
||||
if (!Check_FMOD_Error(mWindDSP->getDefaults(&frequency,0,0,0), "FMOD::DSP::getDefaults"))
|
||||
{
|
||||
mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency);
|
||||
mWindDSP->setUserData((void*)mWindGen);
|
||||
if (!Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData") &&
|
||||
!Check_FMOD_Error(mSystem->playDSP(FMOD_CHANNEL_FREE, mWindDSP, false, 0), "FMOD::System::playDSP"))
|
||||
return true; //Success
|
||||
}
|
||||
|
||||
if (mWindDSP)
|
||||
{
|
||||
mSystem->playDSP(FMOD_CHANNEL_FREE, mWindDSP, false, 0);
|
||||
return true;
|
||||
}
|
||||
cleanupWind();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -576,8 +582,8 @@ void LLAudioEngine_FMODEX::cleanupWind()
|
||||
{
|
||||
if (mWindDSP)
|
||||
{
|
||||
mWindDSP->remove();
|
||||
mWindDSP->release();
|
||||
Check_FMOD_Error(mWindDSP->remove(), "FMOD::DSP::remove");
|
||||
Check_FMOD_Error(mWindDSP->release(), "FMOD::DSP::release");
|
||||
mWindDSP = NULL;
|
||||
}
|
||||
|
||||
@@ -629,8 +635,8 @@ void LLAudioEngine_FMODEX::setInternalGain(F32 gain)
|
||||
gain = llclamp( gain, 0.0f, 1.0f );
|
||||
|
||||
FMOD::ChannelGroup *master_group;
|
||||
mSystem->getMasterChannelGroup(&master_group);
|
||||
|
||||
if(Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup"))
|
||||
return;
|
||||
master_group->setVolume(gain);
|
||||
|
||||
LLStreamingAudioInterface *saimpl = getStreamingAudioImpl();
|
||||
@@ -1013,10 +1019,9 @@ FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *originalbu
|
||||
FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance;
|
||||
|
||||
thisdsp->getUserData((void **)&windgen);
|
||||
S32 channels, configwidth, configheight;
|
||||
thisdsp->getInfo(0, 0, &channels, &configwidth, &configheight);
|
||||
|
||||
windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length);
|
||||
if (windgen)
|
||||
windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length);
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#define LL_AUDIOENGINE_FMODEX_H
|
||||
|
||||
#include "llaudioengine.h"
|
||||
#include "lllistener_fmod.h"
|
||||
#include "lllistener_fmodex.h"
|
||||
#include "llwindgen.h"
|
||||
|
||||
//Stubs
|
||||
|
||||
1002
indra/llaudio/llaudioengine_fmodstudio.cpp
Normal file
1002
indra/llaudio/llaudioengine_fmodstudio.cpp
Normal file
File diff suppressed because it is too large
Load Diff
139
indra/llaudio/llaudioengine_fmodstudio.h
Normal file
139
indra/llaudio/llaudioengine_fmodstudio.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* @file audioengine_FMODSTUDIO.h
|
||||
* @brief Definition of LLAudioEngine class abstracting the audio
|
||||
* support as a FMOD Studio 3D implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2002-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_AUDIOENGINE_FMODSTUDIO_H
|
||||
#define LL_AUDIOENGINE_FMODSTUDIO_H
|
||||
|
||||
#include "llaudioengine.h"
|
||||
#include "lllistener_fmodstudio.h"
|
||||
#include "llwindgen.h"
|
||||
|
||||
//Stubs
|
||||
class LLAudioStreamManagerFMODSTUDIO;
|
||||
namespace FMOD
|
||||
{
|
||||
class System;
|
||||
class Channel;
|
||||
class ChannelGroup;
|
||||
class Sound;
|
||||
class DSP;
|
||||
}
|
||||
|
||||
//Interfaces
|
||||
class LLAudioEngine_FMODSTUDIO : public LLAudioEngine
|
||||
{
|
||||
public:
|
||||
LLAudioEngine_FMODSTUDIO(bool enable_profiler, bool verbose_debugging);
|
||||
virtual ~LLAudioEngine_FMODSTUDIO();
|
||||
|
||||
// initialization/startup/shutdown
|
||||
virtual bool init(const S32 num_channels, void *user_data);
|
||||
virtual std::string getDriverName(bool verbose);
|
||||
virtual void allocateListener();
|
||||
|
||||
virtual void shutdown();
|
||||
|
||||
/*virtual*/ bool initWind();
|
||||
/*virtual*/ void cleanupWind();
|
||||
|
||||
/*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water);
|
||||
|
||||
typedef F32 MIXBUFFERFORMAT;
|
||||
|
||||
FMOD::System *getSystem() const {return mSystem;}
|
||||
protected:
|
||||
/*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to.
|
||||
/*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel.
|
||||
|
||||
/*virtual*/ void setInternalGain(F32 gain);
|
||||
|
||||
bool mInited;
|
||||
|
||||
LLWindGen<MIXBUFFERFORMAT> *mWindGen;
|
||||
|
||||
FMOD::DSP *mWindDSP;
|
||||
FMOD::System *mSystem;
|
||||
bool mEnableProfiler;
|
||||
|
||||
public:
|
||||
static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT];
|
||||
};
|
||||
|
||||
|
||||
class LLAudioChannelFMODSTUDIO : public LLAudioChannel
|
||||
{
|
||||
public:
|
||||
LLAudioChannelFMODSTUDIO(FMOD::System *audioengine);
|
||||
virtual ~LLAudioChannelFMODSTUDIO();
|
||||
void onRelease();
|
||||
protected:
|
||||
/*virtual*/ void play();
|
||||
/*virtual*/ void playSynced(LLAudioChannel *channelp);
|
||||
/*virtual*/ void cleanup();
|
||||
/*virtual*/ bool isPlaying();
|
||||
|
||||
/*virtual*/ bool updateBuffer();
|
||||
/*virtual*/ void update3DPosition();
|
||||
/*virtual*/ void updateLoop();
|
||||
|
||||
void set3DMode(bool use3d);
|
||||
protected:
|
||||
FMOD::System *getSystem() const {return mSystemp;}
|
||||
FMOD::System *mSystemp;
|
||||
FMOD::Channel *mChannelp;
|
||||
S32 mLastSamplePos;
|
||||
|
||||
friend class CFMODSoundChecks;
|
||||
};
|
||||
|
||||
|
||||
class LLAudioBufferFMODSTUDIO : public LLAudioBuffer
|
||||
{
|
||||
public:
|
||||
LLAudioBufferFMODSTUDIO(FMOD::System *audioengine);
|
||||
virtual ~LLAudioBufferFMODSTUDIO();
|
||||
|
||||
/*virtual*/ bool loadWAV(const std::string& filename);
|
||||
/*virtual*/ U32 getLength();
|
||||
friend class LLAudioChannelFMODSTUDIO;
|
||||
protected:
|
||||
FMOD::System *getSystem() const {return mSystemp;}
|
||||
FMOD::System *mSystemp;
|
||||
FMOD::Sound *getSound() const{ return mSoundp; }
|
||||
FMOD::Sound *mSoundp;
|
||||
|
||||
friend class CFMODSoundChecks;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_AUDIOENGINE_FMODSTUDIO_H
|
||||
@@ -1,125 +0,0 @@
|
||||
/**
|
||||
* @file listener_fmod.cpp
|
||||
* @brief implementation of LISTENER class abstracting the audio
|
||||
* support as a FMOD 3D implementation (windows only)
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llaudioengine.h"
|
||||
#include "lllistener_fmod.h"
|
||||
#include "fmod.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener_FMOD::LLListener_FMOD()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener_FMOD::~LLListener_FMOD()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMOD::init(void)
|
||||
{
|
||||
// do inherited
|
||||
LLListener::init();
|
||||
mDopplerFactor = 1.0f;
|
||||
mRolloffFactor = 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMOD::translate(LLVector3 offset)
|
||||
{
|
||||
LLListener::translate(offset);
|
||||
|
||||
FSOUND_3D_Listener_SetAttributes(mPosition.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMOD::setPosition(LLVector3 pos)
|
||||
{
|
||||
LLListener::setPosition(pos);
|
||||
|
||||
FSOUND_3D_Listener_SetAttributes(pos.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMOD::setVelocity(LLVector3 vel)
|
||||
{
|
||||
LLListener::setVelocity(vel);
|
||||
|
||||
FSOUND_3D_Listener_SetAttributes(NULL, vel.mV, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMOD::orient(LLVector3 up, LLVector3 at)
|
||||
{
|
||||
LLListener::orient(up, at);
|
||||
|
||||
// Welcome to the transition between right and left
|
||||
// (coordinate systems, that is)
|
||||
// Leaving the at vector alone results in a L/R reversal
|
||||
// since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed
|
||||
at = -at;
|
||||
|
||||
FSOUND_3D_Listener_SetAttributes(NULL, NULL, at.mV[0],at.mV[1],at.mV[2], up.mV[0],up.mV[1],up.mV[2]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMOD::commitDeferredChanges()
|
||||
{
|
||||
FSOUND_Update();
|
||||
}
|
||||
|
||||
|
||||
void LLListener_FMOD::setRolloffFactor(F32 factor)
|
||||
{
|
||||
mRolloffFactor = factor;
|
||||
FSOUND_3D_SetRolloffFactor(factor);
|
||||
}
|
||||
|
||||
|
||||
F32 LLListener_FMOD::getRolloffFactor()
|
||||
{
|
||||
return mRolloffFactor;
|
||||
}
|
||||
|
||||
|
||||
void LLListener_FMOD::setDopplerFactor(F32 factor)
|
||||
{
|
||||
mDopplerFactor = factor;
|
||||
FSOUND_3D_SetDopplerFactor(factor);
|
||||
}
|
||||
|
||||
|
||||
F32 LLListener_FMOD::getDopplerFactor()
|
||||
{
|
||||
return mDopplerFactor;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* @file listener_fmod.h
|
||||
* @brief Description of LISTENER class abstracting the audio support
|
||||
* as an FMOD 3D implementation (windows and Linux)
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LISTENER_FMOD_H
|
||||
#define LL_LISTENER_FMOD_H
|
||||
|
||||
#include "lllistener.h"
|
||||
|
||||
class LLListener_FMOD : public LLListener
|
||||
{
|
||||
public:
|
||||
LLListener_FMOD();
|
||||
virtual ~LLListener_FMOD();
|
||||
virtual void init();
|
||||
|
||||
virtual void translate(LLVector3 offset);
|
||||
virtual void setPosition(LLVector3 pos);
|
||||
virtual void setVelocity(LLVector3 vel);
|
||||
virtual void orient(LLVector3 up, LLVector3 at);
|
||||
virtual void commitDeferredChanges();
|
||||
|
||||
virtual void setDopplerFactor(F32 factor);
|
||||
virtual F32 getDopplerFactor();
|
||||
virtual void setRolloffFactor(F32 factor);
|
||||
virtual F32 getRolloffFactor();
|
||||
|
||||
protected:
|
||||
F32 mDopplerFactor;
|
||||
F32 mRolloffFactor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
135
indra/llaudio/lllistener_fmodstudio.cpp
Normal file
135
indra/llaudio/lllistener_fmodstudio.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* @file listener_fmodstudio.cpp
|
||||
* @brief implementation of LISTENER class abstracting the audio
|
||||
* support as a FMOD 3D implementation (windows only)
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2002-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llaudioengine.h"
|
||||
#include "lllistener_fmodstudio.h"
|
||||
#include "fmod.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system)
|
||||
{
|
||||
mSystem = system;
|
||||
init();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener_FMODSTUDIO::~LLListener_FMODSTUDIO()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::init(void)
|
||||
{
|
||||
// do inherited
|
||||
LLListener::init();
|
||||
mDopplerFactor = 1.0f;
|
||||
mRolloffFactor = 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::translate(LLVector3 offset)
|
||||
{
|
||||
LLListener::translate(offset);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::setPosition(LLVector3 pos)
|
||||
{
|
||||
LLListener::setPosition(pos);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::setVelocity(LLVector3 vel)
|
||||
{
|
||||
LLListener::setVelocity(vel);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::orient(LLVector3 up, LLVector3 at)
|
||||
{
|
||||
LLListener::orient(up, at);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::commitDeferredChanges()
|
||||
{
|
||||
mSystem->update();
|
||||
}
|
||||
|
||||
|
||||
void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor)
|
||||
{
|
||||
//An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment.
|
||||
//Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well.
|
||||
//In short: Changing the position ticks a dirtyflag inside fmodstudio, which makes it not skip 3D processing next update call.
|
||||
if(mRolloffFactor != factor)
|
||||
{
|
||||
LLVector3 pos = mVelocity - LLVector3(0.f,0.f,.1f);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL, NULL);
|
||||
}
|
||||
mRolloffFactor = factor;
|
||||
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
|
||||
}
|
||||
|
||||
|
||||
F32 LLListener_FMODSTUDIO::getRolloffFactor()
|
||||
{
|
||||
return mRolloffFactor;
|
||||
}
|
||||
|
||||
|
||||
void LLListener_FMODSTUDIO::setDopplerFactor(F32 factor)
|
||||
{
|
||||
mDopplerFactor = factor;
|
||||
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
|
||||
}
|
||||
|
||||
|
||||
F32 LLListener_FMODSTUDIO::getDopplerFactor()
|
||||
{
|
||||
return mDopplerFactor;
|
||||
}
|
||||
|
||||
|
||||
71
indra/llaudio/lllistener_fmodstudio.h
Normal file
71
indra/llaudio/lllistener_fmodstudio.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file listener_fmodstudio.h
|
||||
* @brief Description of LISTENER class abstracting the audio support
|
||||
* as an FMOD Studio 3D implementation (windows and Linux)
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2002-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LISTENER_FMODSTUDIO_H
|
||||
#define LL_LISTENER_FMODSTUDIO_H
|
||||
|
||||
#include "lllistener.h"
|
||||
|
||||
//Stubs
|
||||
namespace FMOD
|
||||
{
|
||||
class System;
|
||||
}
|
||||
|
||||
//Interfaces
|
||||
class LLListener_FMODSTUDIO : public LLListener
|
||||
{
|
||||
public:
|
||||
LLListener_FMODSTUDIO(FMOD::System *system);
|
||||
virtual ~LLListener_FMODSTUDIO();
|
||||
virtual void init();
|
||||
|
||||
virtual void translate(LLVector3 offset);
|
||||
virtual void setPosition(LLVector3 pos);
|
||||
virtual void setVelocity(LLVector3 vel);
|
||||
virtual void orient(LLVector3 up, LLVector3 at);
|
||||
virtual void commitDeferredChanges();
|
||||
|
||||
virtual void setDopplerFactor(F32 factor);
|
||||
virtual F32 getDopplerFactor();
|
||||
virtual void setRolloffFactor(F32 factor);
|
||||
virtual F32 getRolloffFactor();
|
||||
protected:
|
||||
FMOD::System *mSystem;
|
||||
F32 mDopplerFactor;
|
||||
F32 mRolloffFactor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,385 +0,0 @@
|
||||
/**
|
||||
* @file streamingaudio_fmod.cpp
|
||||
* @brief LLStreamingAudio_FMOD implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llmath.h"
|
||||
|
||||
#include "fmod.h"
|
||||
#include "fmod_errors.h"
|
||||
|
||||
#include "llstreamingaudio_fmod.h"
|
||||
|
||||
|
||||
class LLAudioStreamManagerFMOD
|
||||
{
|
||||
public:
|
||||
LLAudioStreamManagerFMOD(const std::string& url);
|
||||
int startStream();
|
||||
bool stopStream(); // Returns true if the stream was successfully stopped.
|
||||
bool ready();
|
||||
|
||||
const std::string& getURL() { return mInternetStreamURL; }
|
||||
|
||||
int getOpenState();
|
||||
|
||||
FSOUND_STREAM* getStream() { return mInternetStream; }
|
||||
protected:
|
||||
FSOUND_STREAM* mInternetStream;
|
||||
bool mReady;
|
||||
|
||||
std::string mInternetStreamURL;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Internet Streaming
|
||||
//---------------------------------------------------------------------------
|
||||
LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() :
|
||||
mCurrentInternetStreamp(NULL),
|
||||
mFMODInternetStreamChannel(-1),
|
||||
mGain(1.0f),
|
||||
mMetaData(NULL)
|
||||
{
|
||||
// Number of milliseconds of audio to buffer for the audio card.
|
||||
// Must be larger than the usual Second Life frame stutter time.
|
||||
FSOUND_Stream_SetBufferSize(200);
|
||||
|
||||
// Here's where we set the size of the network buffer and some buffering
|
||||
// parameters. In this case we want a network buffer of 16k, we want it
|
||||
// to prebuffer 40% of that when we first connect, and we want it
|
||||
// to rebuffer 80% of that whenever we encounter a buffer underrun.
|
||||
|
||||
// Leave the net buffer properties at the default.
|
||||
//FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80);
|
||||
}
|
||||
|
||||
|
||||
LLStreamingAudio_FMOD::~LLStreamingAudio_FMOD()
|
||||
{
|
||||
// nothing interesting/safe to do.
|
||||
}
|
||||
|
||||
signed char F_CALLBACKAPI MetaDataCallback(char *name, char *value, void *userdata)
|
||||
{
|
||||
std::string szName(name);
|
||||
if(szName == "TITLE" || szName=="TIT2" || szName=="Title")
|
||||
(*(LLSD*)userdata)["TITLE"] = value;
|
||||
if(szName == "ARTIST" || szName=="TPE1" || szName =="WM/AlbumTitle")
|
||||
(*(LLSD*)userdata)["ARTIST"] = value;
|
||||
else
|
||||
(*(LLSD*)userdata)[std::string(name)] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMOD::start(const std::string& url)
|
||||
{
|
||||
//if (!mInited)
|
||||
//{
|
||||
// llwarns << "startInternetStream before audio initialized" << llendl;
|
||||
// return;
|
||||
//}
|
||||
|
||||
// "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
|
||||
stop();
|
||||
|
||||
if (!url.empty())
|
||||
{
|
||||
llinfos << "Starting internet stream: " << url << llendl;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMOD(url);
|
||||
mURL = url;
|
||||
if(mCurrentInternetStreamp->getStream())
|
||||
{
|
||||
mMetaData = new LLSD;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << "Set internet stream to null" << llendl;
|
||||
mURL.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLStreamingAudio_FMOD::update()
|
||||
{
|
||||
// Kill dead internet streams, if possible
|
||||
std::list<LLAudioStreamManagerFMOD *>::iterator iter;
|
||||
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
|
||||
{
|
||||
LLAudioStreamManagerFMOD *streamp = *iter;
|
||||
if (streamp->stopStream())
|
||||
{
|
||||
llinfos << "Closed dead stream" << llendl;
|
||||
delete streamp;
|
||||
mDeadStreams.erase(iter++);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't do anything if there are no streams playing
|
||||
if (!mCurrentInternetStreamp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int open_state = mCurrentInternetStreamp->getOpenState();
|
||||
|
||||
if (!open_state)
|
||||
{
|
||||
// Stream is live
|
||||
|
||||
// start the stream if it's ready
|
||||
if (mFMODInternetStreamChannel < 0)
|
||||
{
|
||||
mFMODInternetStreamChannel = mCurrentInternetStreamp->startStream();
|
||||
|
||||
if (mFMODInternetStreamChannel != -1)
|
||||
{
|
||||
// Reset volume to previously set volume
|
||||
setGain(getGain());
|
||||
FSOUND_SetPaused(mFMODInternetStreamChannel, false);
|
||||
if(mCurrentInternetStreamp->getStream() && mMetaData)
|
||||
{
|
||||
FSOUND_Stream_Net_SetMetadataCallback(mCurrentInternetStreamp->getStream(),&MetaDataCallback, mMetaData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(open_state)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
// success
|
||||
break;
|
||||
case -1:
|
||||
// stream handle is invalid
|
||||
llwarns << "InternetStream - invalid handle" << llendl;
|
||||
stop();
|
||||
return;
|
||||
case -2:
|
||||
// opening
|
||||
break;
|
||||
case -3:
|
||||
// failed to open, file not found, perhaps
|
||||
llwarns << "InternetStream - failed to open" << llendl;
|
||||
stop();
|
||||
return;
|
||||
case -4:
|
||||
// connecting
|
||||
break;
|
||||
case -5:
|
||||
// buffering
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMOD::stop()
|
||||
{
|
||||
if(mMetaData)
|
||||
{
|
||||
if(mCurrentInternetStreamp && mCurrentInternetStreamp->getStream())
|
||||
FSOUND_Stream_Net_SetMetadataCallback(mCurrentInternetStreamp->getStream(),NULL,NULL);
|
||||
delete mMetaData;
|
||||
mMetaData = NULL;
|
||||
}
|
||||
if (mFMODInternetStreamChannel != -1)
|
||||
{
|
||||
FSOUND_SetPaused(mFMODInternetStreamChannel, true);
|
||||
FSOUND_SetPriority(mFMODInternetStreamChannel, 0);
|
||||
mFMODInternetStreamChannel = -1;
|
||||
}
|
||||
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
llinfos << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << llendl;
|
||||
if (mCurrentInternetStreamp->stopStream())
|
||||
{
|
||||
delete mCurrentInternetStreamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << llendl;
|
||||
mDeadStreams.push_back(mCurrentInternetStreamp);
|
||||
}
|
||||
mCurrentInternetStreamp = NULL;
|
||||
//mURL.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMOD::pause(int pauseopt)
|
||||
{
|
||||
if (pauseopt < 0)
|
||||
{
|
||||
pauseopt = mCurrentInternetStreamp ? 1 : 0;
|
||||
}
|
||||
|
||||
if (pauseopt)
|
||||
{
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
start(getURL());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// A stream is "playing" if it has been requested to start. That
|
||||
// doesn't necessarily mean audio is coming out of the speakers.
|
||||
int LLStreamingAudio_FMOD::isPlaying()
|
||||
{
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
return 1; // Active and playing
|
||||
}
|
||||
else if (!mURL.empty())
|
||||
{
|
||||
return 2; // "Paused"
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
F32 LLStreamingAudio_FMOD::getGain()
|
||||
{
|
||||
return mGain;
|
||||
}
|
||||
|
||||
|
||||
std::string LLStreamingAudio_FMOD::getURL()
|
||||
{
|
||||
return mURL;
|
||||
}
|
||||
|
||||
|
||||
void LLStreamingAudio_FMOD::setGain(F32 vol)
|
||||
{
|
||||
mGain = vol;
|
||||
|
||||
if (mFMODInternetStreamChannel != -1)
|
||||
{
|
||||
vol = llclamp(vol * vol, 0.f, 1.f);
|
||||
int vol_int = llround(vol * 255.f);
|
||||
FSOUND_SetVolumeAbsolute(mFMODInternetStreamChannel, vol_int);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// manager of possibly-multiple internet audio streams
|
||||
|
||||
LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) :
|
||||
mInternetStream(NULL),
|
||||
mReady(false)
|
||||
{
|
||||
mInternetStreamURL = url;
|
||||
mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0);
|
||||
if (!mInternetStream)
|
||||
{
|
||||
llwarns << "Couldn't open fmod stream, error "
|
||||
<< FMOD_ErrorString(FSOUND_GetError())
|
||||
<< llendl;
|
||||
mReady = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mReady = true;
|
||||
}
|
||||
|
||||
int LLAudioStreamManagerFMOD::startStream()
|
||||
{
|
||||
// We need a live and opened stream before we try and play it.
|
||||
if (!mInternetStream || getOpenState())
|
||||
{
|
||||
llwarns << "No internet stream to start playing!" << llendl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Make sure the stream is set to 2D mode.
|
||||
FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D);
|
||||
|
||||
return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true);
|
||||
}
|
||||
|
||||
bool LLAudioStreamManagerFMOD::stopStream()
|
||||
{
|
||||
if (mInternetStream)
|
||||
{
|
||||
int read_percent = 0;
|
||||
int status = 0;
|
||||
int bitrate = 0;
|
||||
unsigned int flags = 0x0;
|
||||
FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags);
|
||||
|
||||
bool close = true;
|
||||
switch (status)
|
||||
{
|
||||
case FSOUND_STREAM_NET_CONNECTING:
|
||||
close = false;
|
||||
break;
|
||||
case FSOUND_STREAM_NET_NOTCONNECTED:
|
||||
case FSOUND_STREAM_NET_BUFFERING:
|
||||
case FSOUND_STREAM_NET_READY:
|
||||
case FSOUND_STREAM_NET_ERROR:
|
||||
default:
|
||||
close = true;
|
||||
}
|
||||
|
||||
if (close)
|
||||
{
|
||||
FSOUND_Stream_Close(mInternetStream);
|
||||
mInternetStream = NULL;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int LLAudioStreamManagerFMOD::getOpenState()
|
||||
{
|
||||
int open_state = FSOUND_Stream_GetOpenState(mInternetStream);
|
||||
return open_state;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/**
|
||||
* @file streamingaudio_fmod.h
|
||||
* @author Tofu Linden
|
||||
* @brief Definition of LLStreamingAudio_FMOD implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_STREAMINGAUDIO_FMOD_H
|
||||
#define LL_STREAMINGAUDIO_FMOD_H
|
||||
|
||||
#include "stdtypes.h" // from llcommon
|
||||
|
||||
#include "llstreamingaudio.h"
|
||||
|
||||
class LLAudioStreamManagerFMOD;
|
||||
|
||||
class LLStreamingAudio_FMOD : public LLStreamingAudioInterface
|
||||
{
|
||||
public:
|
||||
LLStreamingAudio_FMOD();
|
||||
/*virtual*/ ~LLStreamingAudio_FMOD();
|
||||
|
||||
/*virtual*/ void start(const std::string& url);
|
||||
/*virtual*/ void stop();
|
||||
/*virtual*/ void pause(int pause);
|
||||
/*virtual*/ void update();
|
||||
/*virtual*/ int isPlaying();
|
||||
/*virtual*/ void setGain(F32 vol);
|
||||
/*virtual*/ F32 getGain();
|
||||
/*virtual*/ std::string getURL();
|
||||
|
||||
/*virtual*/ bool supportsMetaData(){return true;}
|
||||
/*virtual*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not playing.
|
||||
/*virtual*/ bool supportsWaveData(){return false;}
|
||||
/*virtual*/ bool getWaveData(float* arr, S32 count, S32 stride = 1){return false;}
|
||||
private:
|
||||
LLAudioStreamManagerFMOD *mCurrentInternetStreamp;
|
||||
int mFMODInternetStreamChannel;
|
||||
std::list<LLAudioStreamManagerFMOD *> mDeadStreams;
|
||||
|
||||
std::string mURL;
|
||||
F32 mGain;
|
||||
|
||||
LLSD *mMetaData;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_STREAMINGAUDIO_FMOD_H
|
||||
@@ -39,6 +39,13 @@
|
||||
|
||||
#include "llstreamingaudio_fmodex.h"
|
||||
|
||||
inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
|
||||
{
|
||||
if (result == FMOD_OK)
|
||||
return false;
|
||||
LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
class LLAudioStreamManagerFMODEX
|
||||
{
|
||||
@@ -50,7 +57,7 @@ public:
|
||||
|
||||
const std::string& getURL() { return mInternetStreamURL; }
|
||||
|
||||
FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL);
|
||||
FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL);
|
||||
protected:
|
||||
FMOD::System* mSystem;
|
||||
FMOD::Channel* mStreamChannel;
|
||||
@@ -72,11 +79,14 @@ LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) :
|
||||
mGain(1.0f),
|
||||
mMetaData(NULL)
|
||||
{
|
||||
FMOD_RESULT result;
|
||||
|
||||
// Number of milliseconds of audio to buffer for the audio card.
|
||||
// Must be larger than the usual Second Life frame stutter time.
|
||||
const U32 buffer_seconds = 10; //sec
|
||||
const U32 estimated_bitrate = 128; //kbit/sec
|
||||
mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
|
||||
result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
|
||||
Check_FMOD_Error(result, "FMOD::System::setStreamBufferSize");
|
||||
|
||||
// Here's where we set the size of the network buffer and some buffering
|
||||
// parameters. In this case we want a network buffer of 16k, we want it
|
||||
@@ -90,7 +100,13 @@ LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) :
|
||||
|
||||
LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX()
|
||||
{
|
||||
// nothing interesting/safe to do.
|
||||
stop();
|
||||
for (U32 i = 0; i < 100; ++i)
|
||||
{
|
||||
if (releaseDeadStreams())
|
||||
break;
|
||||
ms_sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,27 +143,49 @@ void LLStreamingAudio_FMODEX::start(const std::string& url)
|
||||
}
|
||||
}
|
||||
|
||||
enum utf_endian_type_t
|
||||
{
|
||||
UTF16LE,
|
||||
UTF16BE,
|
||||
UTF16
|
||||
};
|
||||
|
||||
std::string utf16input_to_utf8(char* input, U32 len, utf_endian_type_t type)
|
||||
{
|
||||
if (type == UTF16)
|
||||
{
|
||||
type = UTF16BE; //Default
|
||||
if (len > 2)
|
||||
{
|
||||
//Parse and strip BOM.
|
||||
if ((input[0] == 0xFE && input[1] == 0xFF) ||
|
||||
(input[0] == 0xFF && input[1] == 0xFE))
|
||||
{
|
||||
input += 2;
|
||||
len -= 2;
|
||||
type = input[0] == 0xFE ? UTF16BE : UTF16LE;
|
||||
}
|
||||
}
|
||||
}
|
||||
llutf16string out_16((U16*)input, len / 2);
|
||||
if (len % 2)
|
||||
{
|
||||
out_16.push_back((input)[len - 1] << 8);
|
||||
}
|
||||
if (type == UTF16BE)
|
||||
{
|
||||
for (llutf16string::iterator i = out_16.begin(); i < out_16.end(); ++i)
|
||||
{
|
||||
llutf16string::value_type v = *i;
|
||||
*i = ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8);
|
||||
}
|
||||
}
|
||||
return utf16str_to_utf8str(out_16);
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODEX::update()
|
||||
{
|
||||
// Kill dead internet streams, if possible
|
||||
std::list<LLAudioStreamManagerFMODEX *>::iterator iter;
|
||||
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
|
||||
{
|
||||
LLAudioStreamManagerFMODEX *streamp = *iter;
|
||||
if (streamp->stopStream())
|
||||
{
|
||||
llinfos << "Closed dead stream" << llendl;
|
||||
delete streamp;
|
||||
mDeadStreams.erase(iter++);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
if(!mDeadStreams.empty())
|
||||
if (!releaseDeadStreams())
|
||||
{
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
return;
|
||||
@@ -172,9 +210,15 @@ void LLStreamingAudio_FMODEX::update()
|
||||
unsigned int progress;
|
||||
bool starving;
|
||||
bool diskbusy;
|
||||
FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy);
|
||||
FMOD_OPENSTATE open_state;
|
||||
FMOD_RESULT res = mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy);
|
||||
|
||||
if (open_state == FMOD_OPENSTATE_READY)
|
||||
if (res != FMOD_OK || open_state == FMOD_OPENSTATE_ERROR)
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
else if (open_state == FMOD_OPENSTATE_READY)
|
||||
{
|
||||
// Stream is live
|
||||
|
||||
@@ -184,14 +228,9 @@ void LLStreamingAudio_FMODEX::update()
|
||||
{
|
||||
// Reset volume to previously set volume
|
||||
setGain(getGain());
|
||||
mFMODInternetStreamChannelp->setPaused(false);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
else if(open_state == FMOD_OPENSTATE_ERROR)
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if(mFMODInternetStreamChannelp)
|
||||
{
|
||||
@@ -216,23 +255,27 @@ void LLStreamingAudio_FMODEX::update()
|
||||
switch(tag.type) //Crappy tag translate table.
|
||||
{
|
||||
case(FMOD_TAGTYPE_ID3V2):
|
||||
if(name == "TIT2") name = "TITLE";
|
||||
if (!LLStringUtil::compareInsensitive(name, "TIT2")) name = "TITLE";
|
||||
else if(name == "TPE1") name = "ARTIST";
|
||||
break;
|
||||
case(FMOD_TAGTYPE_ASF):
|
||||
if(name == "Title") name = "TITLE";
|
||||
else if(name == "WM/AlbumArtist") name = "ARTIST";
|
||||
if (!LLStringUtil::compareInsensitive(name, "Title")) name = "TITLE";
|
||||
else if (!LLStringUtil::compareInsensitive(name, "WM/AlbumArtist")) name = "ARTIST";
|
||||
break;
|
||||
case(FMOD_TAGTYPE_FMOD):
|
||||
if (!strcmp(tag.name, "Sample Rate Change"))
|
||||
if (!LLStringUtil::compareInsensitive(name, "Sample Rate Change"))
|
||||
{
|
||||
llinfos << "Stream forced changing sample rate to " << *((float *)tag.data) << llendl;
|
||||
mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data));
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)), "FMOD::Channel::setFrequency");
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
if (!LLStringUtil::compareInsensitive(name, "TITLE") ||
|
||||
!LLStringUtil::compareInsensitive(name, "ARTIST"))
|
||||
LLStringUtil::toUpper(name);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(tag.datatype)
|
||||
{
|
||||
case(FMOD_TAGDATATYPE_INT):
|
||||
@@ -246,25 +289,40 @@ void LLStreamingAudio_FMODEX::update()
|
||||
case(FMOD_TAGDATATYPE_STRING):
|
||||
{
|
||||
std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen));
|
||||
if (out.length() && out[out.size() - 1] == 0)
|
||||
out.erase(out.size() - 1);
|
||||
(*mMetaData)[name]=out;
|
||||
llinfos << tag.name << ": " << out << llendl;
|
||||
llinfos << tag.name << "(RAW): " << out << llendl;
|
||||
}
|
||||
break;
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF8) :
|
||||
{
|
||||
U8 offs = 0;
|
||||
if (tag.datalen > 3 && ((char*)tag.data)[0] == 0xEF && ((char*)tag.data)[1] == 0xBB && ((char*)tag.data)[2] == 0xBF)
|
||||
offs = 3;
|
||||
std::string out((char*)tag.data + offs, tag.datalen - offs);
|
||||
if (out.length() && out[out.size() - 1] == 0)
|
||||
out.erase(out.size() - 1);
|
||||
(*mMetaData)[name] = out;
|
||||
llinfos << tag.name << "(UTF8): " << out << llendl;
|
||||
}
|
||||
break;
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF16):
|
||||
{
|
||||
std::string out((char*)tag.data,tag.datalen);
|
||||
(*mMetaData)[std::string(tag.name)]=out;
|
||||
llinfos << tag.name << ": " << out << llendl;
|
||||
std::string out = utf16input_to_utf8((char*)tag.data, tag.datalen, UTF16);
|
||||
if (out.length() && out[out.size() - 1] == 0)
|
||||
out.erase(out.size() - 1);
|
||||
(*mMetaData)[name] = out;
|
||||
llinfos << tag.name << "(UTF16): " << out << llendl;
|
||||
}
|
||||
break;
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF16BE):
|
||||
{
|
||||
std::string out((char*)tag.data,tag.datalen);
|
||||
U16* buf = (U16*)out.c_str();
|
||||
for(U32 j = 0; j < out.size()/2; ++j)
|
||||
(((buf[j] & 0xff)<<8) | ((buf[j] & 0xff00)>>8));
|
||||
(*mMetaData)[std::string(tag.name)]=out;
|
||||
llinfos << tag.name << ": " << out << llendl;
|
||||
std::string out = utf16input_to_utf8((char*)tag.data, tag.datalen, UTF16BE);
|
||||
if (out.length() && out[out.size() - 1] == 0)
|
||||
out.erase(out.size() - 1);
|
||||
(*mMetaData)[name] = out;
|
||||
llinfos << tag.name << "(UTF16BE): " << out << llendl;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
@@ -274,18 +332,17 @@ void LLStreamingAudio_FMODEX::update()
|
||||
if(starving)
|
||||
{
|
||||
bool paused = false;
|
||||
mFMODInternetStreamChannelp->getPaused(&paused);
|
||||
if(!paused)
|
||||
if (mFMODInternetStreamChannelp->getPaused(&paused) == FMOD_OK && !paused)
|
||||
{
|
||||
llinfos << "Stream starvation detected! Pausing stream until buffer nearly full." << llendl;
|
||||
llinfos << " (diskbusy="<<diskbusy<<")" << llendl;
|
||||
llinfos << " (progress="<<progress<<")" << llendl;
|
||||
mFMODInternetStreamChannelp->setPaused(true);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
else if(progress > 80)
|
||||
{
|
||||
mFMODInternetStreamChannelp->setPaused(false);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -302,8 +359,8 @@ void LLStreamingAudio_FMODEX::stop()
|
||||
}
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
mFMODInternetStreamChannelp->setPaused(true);
|
||||
mFMODInternetStreamChannelp->setPriority(0);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority");
|
||||
mFMODInternetStreamChannelp = NULL;
|
||||
}
|
||||
|
||||
@@ -384,7 +441,7 @@ void LLStreamingAudio_FMODEX::setGain(F32 vol)
|
||||
{
|
||||
vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here?
|
||||
|
||||
mFMODInternetStreamChannelp->setVolume(vol);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,8 +451,8 @@ void LLStreamingAudio_FMODEX::setGain(F32 vol)
|
||||
return false;
|
||||
|
||||
bool muted=false;
|
||||
mFMODInternetStreamChannelp->getMute(&muted);
|
||||
if(muted)
|
||||
FMOD_RESULT res = mFMODInternetStreamChannelp->getMute(&muted);
|
||||
if(res != FMOD_OK || muted)
|
||||
return false;
|
||||
|
||||
static std::vector<float> local_array(count); //Have to have an extra buffer to mix channels. Bleh.
|
||||
@@ -448,7 +505,8 @@ LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, con
|
||||
FMOD::Channel *LLAudioStreamManagerFMODEX::startStream()
|
||||
{
|
||||
// We need a live and opened stream before we try and play it.
|
||||
if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY)
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (getOpenState(open_state) != FMOD_OK || open_state != FMOD_OPENSTATE_READY)
|
||||
{
|
||||
llwarns << "No internet stream to start playing!" << llendl;
|
||||
return NULL;
|
||||
@@ -457,7 +515,7 @@ FMOD::Channel *LLAudioStreamManagerFMODEX::startStream()
|
||||
if(mStreamChannel)
|
||||
return mStreamChannel; //Already have a channel for this stream.
|
||||
|
||||
mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel);
|
||||
Check_FMOD_Error(mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel), "FMOD::System::playSound");
|
||||
return mStreamChannel;
|
||||
}
|
||||
|
||||
@@ -466,17 +524,17 @@ bool LLAudioStreamManagerFMODEX::stopStream()
|
||||
if (mInternetStream)
|
||||
{
|
||||
bool close = true;
|
||||
switch (getOpenState())
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (getOpenState(open_state) == FMOD_OK)
|
||||
{
|
||||
case FMOD_OPENSTATE_CONNECTING:
|
||||
close = false;
|
||||
break;
|
||||
/*case FSOUND_STREAM_NET_NOTCONNECTED:
|
||||
case FSOUND_STREAM_NET_BUFFERING:
|
||||
case FSOUND_STREAM_NET_READY:
|
||||
case FSOUND_STREAM_NET_ERROR:*/
|
||||
default:
|
||||
close = true;
|
||||
switch (open_state)
|
||||
{
|
||||
case FMOD_OPENSTATE_CONNECTING:
|
||||
close = false;
|
||||
break;
|
||||
default:
|
||||
close = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (close && mInternetStream->release() == FMOD_OK)
|
||||
@@ -496,19 +554,43 @@ bool LLAudioStreamManagerFMODEX::stopStream()
|
||||
}
|
||||
}
|
||||
|
||||
FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy)
|
||||
FMOD_RESULT LLAudioStreamManagerFMODEX::getOpenState(FMOD_OPENSTATE& state, unsigned int* percentbuffered, bool* starving, bool* diskbusy)
|
||||
{
|
||||
FMOD_OPENSTATE state;
|
||||
mInternetStream->getOpenState(&state,percentbuffered,starving,diskbusy);
|
||||
return state;
|
||||
if (!mInternetStream)
|
||||
return FMOD_ERR_INVALID_HANDLE;
|
||||
FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
|
||||
Check_FMOD_Error(result, "FMOD::Sound::getOpenState");
|
||||
return result;
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)
|
||||
{
|
||||
mSystem->setStreamBufferSize(streambuffertime/1000*128*128, FMOD_TIMEUNIT_RAWBYTES);
|
||||
Check_FMOD_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
|
||||
FMOD_ADVANCEDSETTINGS settings;
|
||||
memset(&settings,0,sizeof(settings));
|
||||
settings.cbsize=sizeof(settings);
|
||||
settings.defaultDecodeBufferSize = decodebuffertime;//ms
|
||||
mSystem->setAdvancedSettings(&settings);
|
||||
Check_FMOD_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings");
|
||||
}
|
||||
|
||||
bool LLStreamingAudio_FMODEX::releaseDeadStreams()
|
||||
{
|
||||
// Kill dead internet streams, if possible
|
||||
std::list<LLAudioStreamManagerFMODEX *>::iterator iter;
|
||||
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
|
||||
{
|
||||
LLAudioStreamManagerFMODEX *streamp = *iter;
|
||||
if (streamp->stopStream())
|
||||
{
|
||||
llinfos << "Closed dead stream" << llendl;
|
||||
delete streamp;
|
||||
mDeadStreams.erase(iter++);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
return mDeadStreams.empty();
|
||||
}
|
||||
@@ -70,6 +70,8 @@ class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface
|
||||
/*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
|
||||
/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
|
||||
private:
|
||||
bool releaseDeadStreams();
|
||||
|
||||
FMOD::System *mSystem;
|
||||
|
||||
LLAudioStreamManagerFMODEX *mCurrentInternetStreamp;
|
||||
|
||||
675
indra/llaudio/llstreamingaudio_fmodstudio.cpp
Normal file
675
indra/llaudio/llstreamingaudio_fmodstudio.cpp
Normal file
@@ -0,0 +1,675 @@
|
||||
/**
|
||||
* @file streamingaudio_fmodstudio.cpp
|
||||
* @brief LLStreamingAudio_FMODSTUDIO implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llmath.h"
|
||||
#include "llthread.h"
|
||||
|
||||
#include "fmod.hpp"
|
||||
#include "fmod_errors.h"
|
||||
|
||||
#include "llstreamingaudio_fmodstudio.h"
|
||||
|
||||
inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
|
||||
{
|
||||
if (result == FMOD_OK)
|
||||
return false;
|
||||
LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
class LLAudioStreamManagerFMODSTUDIO
|
||||
{
|
||||
public:
|
||||
LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url);
|
||||
FMOD::Channel* startStream();
|
||||
bool stopStream(); // Returns true if the stream was successfully stopped.
|
||||
bool ready();
|
||||
|
||||
const std::string& getURL() { return mInternetStreamURL; }
|
||||
|
||||
FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL);
|
||||
protected:
|
||||
FMOD::System* mSystem;
|
||||
FMOD::Channel* mStreamChannel;
|
||||
FMOD::Sound* mInternetStream;
|
||||
FMOD::ChannelGroup* mChannelGroup;
|
||||
bool mReady;
|
||||
|
||||
std::string mInternetStreamURL;
|
||||
};
|
||||
|
||||
LLGlobalMutex gWaveDataMutex; //Just to be extra strict.
|
||||
const U32 WAVE_BUFFER_SIZE = 1024;
|
||||
U32 gWaveBufferMinSize = 0;
|
||||
F32 gWaveDataBuffer[WAVE_BUFFER_SIZE] = { 0.f };
|
||||
U32 gWaveDataBufferSize = 0;
|
||||
|
||||
FMOD_RESULT F_CALLBACK waveDataCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels)
|
||||
{
|
||||
if (!length || !inchannels)
|
||||
return FMOD_OK;
|
||||
memcpy(outbuffer, inbuffer, length * inchannels * sizeof(float));
|
||||
|
||||
static std::vector<F32> local_buf;
|
||||
if (local_buf.size() < length)
|
||||
local_buf.resize(length, 0.f);
|
||||
|
||||
for (U32 i = 0; i < length; ++i)
|
||||
{
|
||||
F32 total = 0.f;
|
||||
for (S32 j = 0; j < inchannels; ++j)
|
||||
{
|
||||
total += inbuffer[i*inchannels + j];
|
||||
}
|
||||
local_buf[i] = total / inchannels;
|
||||
}
|
||||
|
||||
{
|
||||
LLMutexLock lock(gWaveDataMutex);
|
||||
|
||||
for (U32 i = length; i > 0; --i)
|
||||
{
|
||||
if (++gWaveDataBufferSize > WAVE_BUFFER_SIZE)
|
||||
{
|
||||
if (gWaveBufferMinSize)
|
||||
memcpy(gWaveDataBuffer + WAVE_BUFFER_SIZE - gWaveBufferMinSize, gWaveDataBuffer, gWaveBufferMinSize * sizeof(float));
|
||||
gWaveDataBufferSize = 1 + gWaveBufferMinSize;
|
||||
}
|
||||
gWaveDataBuffer[WAVE_BUFFER_SIZE - gWaveDataBufferSize] = local_buf[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Internet Streaming
|
||||
//---------------------------------------------------------------------------
|
||||
LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) :
|
||||
mSystem(system),
|
||||
mCurrentInternetStreamp(NULL),
|
||||
mFMODInternetStreamChannelp(NULL),
|
||||
mGain(1.0f),
|
||||
mMetaData(NULL),
|
||||
mStreamGroup(NULL),
|
||||
mStreamDSP(NULL)
|
||||
{
|
||||
FMOD_RESULT result;
|
||||
|
||||
// Number of milliseconds of audio to buffer for the audio card.
|
||||
// Must be larger than the usual Second Life frame stutter time.
|
||||
const U32 buffer_seconds = 10; //sec
|
||||
const U32 estimated_bitrate = 128; //kbit/sec
|
||||
result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
|
||||
Check_FMOD_Error(result, "FMOD::System::setStreamBufferSize");
|
||||
|
||||
// Here's where we set the size of the network buffer and some buffering
|
||||
// parameters. In this case we want a network buffer of 16k, we want it
|
||||
// to prebuffer 40% of that when we first connect, and we want it
|
||||
// to rebuffer 80% of that whenever we encounter a buffer underrun.
|
||||
|
||||
// Leave the net buffer properties at the default.
|
||||
//FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80);
|
||||
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("stream", &mStreamGroup), "FMOD::System::createChannelGroup");
|
||||
|
||||
FMOD_DSP_DESCRIPTION dspdesc;
|
||||
memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Zero out everything
|
||||
dspdesc.pluginsdkversion = FMOD_PLUGIN_SDK_VERSION;
|
||||
strncpy(dspdesc.name, "Waveform", sizeof(dspdesc.name));
|
||||
dspdesc.numoutputbuffers = 1;
|
||||
dspdesc.read = &waveDataCallback; //Assign callback.
|
||||
|
||||
Check_FMOD_Error(system->createDSP(&dspdesc, &mStreamDSP), "FMOD::System::createDSP");
|
||||
}
|
||||
|
||||
|
||||
LLStreamingAudio_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO()
|
||||
{
|
||||
stop();
|
||||
for (U32 i = 0; i < 100; ++i)
|
||||
{
|
||||
if (releaseDeadStreams())
|
||||
break;
|
||||
ms_sleep(10);
|
||||
}
|
||||
|
||||
cleanupWaveData();
|
||||
}
|
||||
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::start(const std::string& url)
|
||||
{
|
||||
//if (!mInited)
|
||||
//{
|
||||
// llwarns << "startInternetStream before audio initialized" << llendl;
|
||||
// return;
|
||||
//}
|
||||
|
||||
// "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
|
||||
stop();
|
||||
|
||||
if (!url.empty())
|
||||
{
|
||||
if(mDeadStreams.empty())
|
||||
{
|
||||
llinfos << "Starting internet stream: " << url << llendl;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, url);
|
||||
mURL = url;
|
||||
mMetaData = new LLSD;
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << "Deferring stream load until buffer release: " << url << llendl;
|
||||
mPendingURL = url;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << "Set internet stream to null" << llendl;
|
||||
mURL.clear();
|
||||
}
|
||||
}
|
||||
|
||||
enum utf_endian_type_t
|
||||
{
|
||||
UTF16LE,
|
||||
UTF16BE,
|
||||
UTF16
|
||||
};
|
||||
|
||||
std::string utf16input_to_utf8(char* input, U32 len, utf_endian_type_t type)
|
||||
{
|
||||
if (type == UTF16)
|
||||
{
|
||||
type = UTF16BE; //Default
|
||||
if (len > 2)
|
||||
{
|
||||
//Parse and strip BOM.
|
||||
if ((input[0] == 0xFE && input[1] == 0xFF) ||
|
||||
(input[0] == 0xFF && input[1] == 0xFE))
|
||||
{
|
||||
input += 2;
|
||||
len -= 2;
|
||||
type = input[0] == 0xFE ? UTF16BE : UTF16LE;
|
||||
}
|
||||
}
|
||||
}
|
||||
llutf16string out_16((U16*)input, len / 2);
|
||||
if (len % 2)
|
||||
{
|
||||
out_16.push_back((input)[len - 1] << 8);
|
||||
}
|
||||
if (type == UTF16BE)
|
||||
{
|
||||
for (llutf16string::iterator i = out_16.begin(); i < out_16.end(); ++i)
|
||||
{
|
||||
llutf16string::value_type v = *i;
|
||||
*i = ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8);
|
||||
}
|
||||
}
|
||||
return utf16str_to_utf8str(out_16);
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::update()
|
||||
{
|
||||
if (!releaseDeadStreams())
|
||||
{
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!mPendingURL.empty())
|
||||
{
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
llinfos << "Starting internet stream: " << mPendingURL << llendl;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem,mStreamGroup, mPendingURL);
|
||||
mURL = mPendingURL;
|
||||
mMetaData = new LLSD;
|
||||
mPendingURL.clear();
|
||||
}
|
||||
|
||||
// Don't do anything if there are no streams playing
|
||||
if (!mCurrentInternetStreamp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int progress;
|
||||
bool starving;
|
||||
bool diskbusy;
|
||||
FMOD_OPENSTATE open_state;
|
||||
FMOD_RESULT result = mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy);
|
||||
|
||||
if (result != FMOD_OK || open_state == FMOD_OPENSTATE_ERROR)
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
else if (open_state == FMOD_OPENSTATE_READY)
|
||||
{
|
||||
// Stream is live
|
||||
|
||||
// start the stream if it's ready
|
||||
if (!mFMODInternetStreamChannelp &&
|
||||
(mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))
|
||||
{
|
||||
// Reset volume to previously set volume
|
||||
setGain(getGain());
|
||||
if (mStreamDSP)
|
||||
{
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->addDSP(FMOD_CHANNELCONTROL_DSP_TAIL, mStreamDSP), "FMOD::Channel::addDSP");
|
||||
}
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(mFMODInternetStreamChannelp)
|
||||
{
|
||||
if(!mMetaData)
|
||||
mMetaData = new LLSD;
|
||||
|
||||
FMOD::Sound *sound = NULL;
|
||||
|
||||
if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound)
|
||||
{
|
||||
FMOD_TAG tag;
|
||||
S32 tagcount, dirtytagcount;
|
||||
if(sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount)
|
||||
{
|
||||
mMetaData->clear();
|
||||
|
||||
for(S32 i = 0; i < tagcount; ++i)
|
||||
{
|
||||
if(sound->getTag(NULL, i, &tag)!=FMOD_OK)
|
||||
continue;
|
||||
std::string name = tag.name;
|
||||
switch(tag.type) //Crappy tag translate table.
|
||||
{
|
||||
case(FMOD_TAGTYPE_ID3V2):
|
||||
if (!LLStringUtil::compareInsensitive(name, "TIT2")) name = "TITLE";
|
||||
else if(name == "TPE1") name = "ARTIST";
|
||||
break;
|
||||
case(FMOD_TAGTYPE_ASF):
|
||||
if (!LLStringUtil::compareInsensitive(name, "Title")) name = "TITLE";
|
||||
else if (!LLStringUtil::compareInsensitive(name, "WM/AlbumArtist")) name = "ARTIST";
|
||||
break;
|
||||
case(FMOD_TAGTYPE_FMOD):
|
||||
if (!LLStringUtil::compareInsensitive(name, "Sample Rate Change"))
|
||||
{
|
||||
llinfos << "Stream forced changing sample rate to " << *((float *)tag.data) << llendl;
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)), "FMOD::Channel::setFrequency");
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
if (!LLStringUtil::compareInsensitive(name, "TITLE") ||
|
||||
!LLStringUtil::compareInsensitive(name, "ARTIST"))
|
||||
LLStringUtil::toUpper(name);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(tag.datatype)
|
||||
{
|
||||
case(FMOD_TAGDATATYPE_INT):
|
||||
(*mMetaData)[name]=*(LLSD::Integer*)(tag.data);
|
||||
llinfos << tag.name << ": " << *(int*)(tag.data) << llendl;
|
||||
break;
|
||||
case(FMOD_TAGDATATYPE_FLOAT):
|
||||
(*mMetaData)[name]=*(LLSD::Float*)(tag.data);
|
||||
llinfos << tag.name << ": " << *(float*)(tag.data) << llendl;
|
||||
break;
|
||||
case(FMOD_TAGDATATYPE_STRING):
|
||||
{
|
||||
std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen));
|
||||
if (out.length() && out[out.size() - 1] == 0)
|
||||
out.erase(out.size() - 1);
|
||||
(*mMetaData)[name]=out;
|
||||
llinfos << tag.name << "(RAW): " << out << llendl;
|
||||
}
|
||||
break;
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF8) :
|
||||
{
|
||||
U8 offs = 0;
|
||||
if (tag.datalen > 3 && ((char*)tag.data)[0] == 0xEF && ((char*)tag.data)[1] == 0xBB && ((char*)tag.data)[2] == 0xBF)
|
||||
offs = 3;
|
||||
std::string out((char*)tag.data + offs, tag.datalen - offs);
|
||||
if (out.length() && out[out.size() - 1] == 0)
|
||||
out.erase(out.size() - 1);
|
||||
(*mMetaData)[name] = out;
|
||||
llinfos << tag.name << "(UTF8): " << out << llendl;
|
||||
}
|
||||
break;
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF16):
|
||||
{
|
||||
std::string out = utf16input_to_utf8((char*)tag.data, tag.datalen, UTF16);
|
||||
if (out.length() && out[out.size() - 1] == 0)
|
||||
out.erase(out.size() - 1);
|
||||
(*mMetaData)[name] = out;
|
||||
llinfos << tag.name << "(UTF16): " << out << llendl;
|
||||
}
|
||||
break;
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF16BE):
|
||||
{
|
||||
std::string out = utf16input_to_utf8((char*)tag.data, tag.datalen, UTF16BE);
|
||||
if (out.length() && out[out.size() - 1] == 0)
|
||||
out.erase(out.size() - 1);
|
||||
(*mMetaData)[name] = out;
|
||||
llinfos << tag.name << "(UTF16BE): " << out << llendl;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(starving)
|
||||
{
|
||||
bool paused = false;
|
||||
if (mFMODInternetStreamChannelp->getPaused(&paused) == FMOD_OK && !paused)
|
||||
{
|
||||
llinfos << "Stream starvation detected! Pausing stream until buffer nearly full." << llendl;
|
||||
llinfos << " (diskbusy="<<diskbusy<<")" << llendl;
|
||||
llinfos << " (progress="<<progress<<")" << llendl;
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
else if(progress > 80)
|
||||
{
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::stop()
|
||||
{
|
||||
mPendingURL.clear();
|
||||
|
||||
if(mMetaData)
|
||||
{
|
||||
delete mMetaData;
|
||||
mMetaData = NULL;
|
||||
}
|
||||
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority");
|
||||
if (mStreamDSP)
|
||||
{
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->removeDSP(mStreamDSP), "FMOD::Channel::removeDSP");
|
||||
}
|
||||
mFMODInternetStreamChannelp = NULL;
|
||||
}
|
||||
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
llinfos << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << llendl;
|
||||
if (mCurrentInternetStreamp->stopStream())
|
||||
{
|
||||
delete mCurrentInternetStreamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << llendl;
|
||||
mDeadStreams.push_back(mCurrentInternetStreamp);
|
||||
}
|
||||
mCurrentInternetStreamp = NULL;
|
||||
//mURL.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::pause(int pauseopt)
|
||||
{
|
||||
if (pauseopt < 0)
|
||||
{
|
||||
pauseopt = mCurrentInternetStreamp ? 1 : 0;
|
||||
}
|
||||
|
||||
if (pauseopt)
|
||||
{
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
start(getURL());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// A stream is "playing" if it has been requested to start. That
|
||||
// doesn't necessarily mean audio is coming out of the speakers.
|
||||
int LLStreamingAudio_FMODSTUDIO::isPlaying()
|
||||
{
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
return 1; // Active and playing
|
||||
}
|
||||
else if (!mURL.empty() || !mPendingURL.empty())
|
||||
{
|
||||
return 2; // "Paused"
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
F32 LLStreamingAudio_FMODSTUDIO::getGain()
|
||||
{
|
||||
return mGain;
|
||||
}
|
||||
|
||||
|
||||
std::string LLStreamingAudio_FMODSTUDIO::getURL()
|
||||
{
|
||||
return mURL;
|
||||
}
|
||||
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol)
|
||||
{
|
||||
mGain = vol;
|
||||
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here?
|
||||
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume");
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/ bool LLStreamingAudio_FMODSTUDIO::getWaveData(float* arr, S32 count, S32 stride/*=1*/)
|
||||
{
|
||||
if (count > (WAVE_BUFFER_SIZE / 2))
|
||||
LL_ERRS("AudioImpl") << "Count=" << count << " exceeds WAVE_BUFFER_SIZE/2=" << WAVE_BUFFER_SIZE << LL_ENDL;
|
||||
|
||||
if(!mFMODInternetStreamChannelp || !mCurrentInternetStreamp)
|
||||
return false;
|
||||
|
||||
bool muted = false;
|
||||
FMOD_RESULT res = mFMODInternetStreamChannelp->getMute(&muted);
|
||||
if(res != FMOD_OK || muted)
|
||||
return false;
|
||||
{
|
||||
U32 buff_size;
|
||||
{
|
||||
LLMutexLock lock(gWaveDataMutex);
|
||||
gWaveBufferMinSize = count;
|
||||
buff_size = gWaveDataBufferSize;
|
||||
if (!buff_size)
|
||||
return false;
|
||||
memcpy(arr, gWaveDataBuffer + WAVE_BUFFER_SIZE - buff_size, llmin(U32(count), buff_size) * sizeof(float));
|
||||
}
|
||||
if (buff_size < U32(count))
|
||||
memset(arr + buff_size, 0, (count - buff_size) * sizeof(float));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// manager of possibly-multiple internet audio streams
|
||||
|
||||
LLAudioStreamManagerFMODSTUDIO::LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url) :
|
||||
mSystem(system),
|
||||
mStreamChannel(NULL),
|
||||
mInternetStream(NULL),
|
||||
mChannelGroup(group),
|
||||
mReady(false)
|
||||
{
|
||||
mInternetStreamURL = url;
|
||||
|
||||
FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream);
|
||||
|
||||
if (result!= FMOD_OK)
|
||||
{
|
||||
llwarns << "Couldn't open fmod stream, error "
|
||||
<< FMOD_ErrorString(result)
|
||||
<< llendl;
|
||||
mReady = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mReady = true;
|
||||
}
|
||||
|
||||
FMOD::Channel *LLAudioStreamManagerFMODSTUDIO::startStream()
|
||||
{
|
||||
// We need a live and opened stream before we try and play it.
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (getOpenState(open_state) != FMOD_OK || open_state != FMOD_OPENSTATE_READY)
|
||||
{
|
||||
llwarns << "No internet stream to start playing!" << llendl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mStreamChannel)
|
||||
return mStreamChannel; //Already have a channel for this stream.
|
||||
|
||||
Check_FMOD_Error(mSystem->playSound(mInternetStream, mChannelGroup, true, &mStreamChannel), "FMOD::System::playSound");
|
||||
return mStreamChannel;
|
||||
}
|
||||
|
||||
bool LLAudioStreamManagerFMODSTUDIO::stopStream()
|
||||
{
|
||||
if (mInternetStream)
|
||||
{
|
||||
bool close = true;
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (getOpenState(open_state) == FMOD_OK)
|
||||
{
|
||||
switch (open_state)
|
||||
{
|
||||
case FMOD_OPENSTATE_CONNECTING:
|
||||
close = false;
|
||||
break;
|
||||
default:
|
||||
close = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (close && mInternetStream->release() == FMOD_OK)
|
||||
{
|
||||
mStreamChannel = NULL;
|
||||
mInternetStream = NULL;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
FMOD_RESULT LLAudioStreamManagerFMODSTUDIO::getOpenState(FMOD_OPENSTATE& state, unsigned int* percentbuffered, bool* starving, bool* diskbusy)
|
||||
{
|
||||
if (!mInternetStream)
|
||||
return FMOD_ERR_INVALID_HANDLE;
|
||||
FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
|
||||
Check_FMOD_Error(result, "FMOD::Sound::getOpenState");
|
||||
return result;
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)
|
||||
{
|
||||
Check_FMOD_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
|
||||
FMOD_ADVANCEDSETTINGS settings;
|
||||
memset(&settings,0,sizeof(settings));
|
||||
settings.cbSize=sizeof(settings);
|
||||
settings.defaultDecodeBufferSize = decodebuffertime;//ms
|
||||
Check_FMOD_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings");
|
||||
}
|
||||
|
||||
bool LLStreamingAudio_FMODSTUDIO::releaseDeadStreams()
|
||||
{
|
||||
// Kill dead internet streams, if possible
|
||||
std::list<LLAudioStreamManagerFMODSTUDIO *>::iterator iter;
|
||||
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
|
||||
{
|
||||
LLAudioStreamManagerFMODSTUDIO *streamp = *iter;
|
||||
if (streamp->stopStream())
|
||||
{
|
||||
llinfos << "Closed dead stream" << llendl;
|
||||
delete streamp;
|
||||
mDeadStreams.erase(iter++);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
return mDeadStreams.empty();
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::cleanupWaveData()
|
||||
{
|
||||
if (mStreamGroup)
|
||||
{
|
||||
Check_FMOD_Error(mStreamGroup->release(), "FMOD::ChannelGroup::release");
|
||||
mStreamGroup = NULL;
|
||||
}
|
||||
|
||||
if(mStreamDSP)
|
||||
Check_FMOD_Error(mStreamDSP->release(), "FMOD::DSP::release");
|
||||
mStreamDSP = NULL;
|
||||
}
|
||||
97
indra/llaudio/llstreamingaudio_fmodstudio.h
Normal file
97
indra/llaudio/llstreamingaudio_fmodstudio.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @file streamingaudio_fmodstudio.h
|
||||
* @author Tofu Linden
|
||||
* @brief Definition of LLStreamingAudio_FMODSTUDIO implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_STREAMINGAUDIO_FMODSTUDIO_H
|
||||
#define LL_STREAMINGAUDIO_FMODSTUDIO_H
|
||||
|
||||
#include "stdtypes.h" // from llcommon
|
||||
|
||||
#include "llstreamingaudio.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
//Stubs
|
||||
class LLAudioStreamManagerFMODSTUDIO;
|
||||
namespace FMOD
|
||||
{
|
||||
class System;
|
||||
class Channel;
|
||||
class ChannelGroup;
|
||||
class ChannelGroup;
|
||||
class DSP;
|
||||
}
|
||||
|
||||
//Interfaces
|
||||
class LLStreamingAudio_FMODSTUDIO : public LLStreamingAudioInterface
|
||||
{
|
||||
public:
|
||||
LLStreamingAudio_FMODSTUDIO(FMOD::System *system);
|
||||
/*virtual*/ ~LLStreamingAudio_FMODSTUDIO();
|
||||
|
||||
/*virtual*/ void start(const std::string& url);
|
||||
/*virtual*/ void stop();
|
||||
/*virtual*/ void pause(int pause);
|
||||
/*virtual*/ void update();
|
||||
/*virtual*/ int isPlaying();
|
||||
/*virtual*/ void setGain(F32 vol);
|
||||
/*virtual*/ F32 getGain();
|
||||
/*virtual*/ std::string getURL();
|
||||
|
||||
/*virtual*/ bool supportsMetaData(){return true;}
|
||||
/*virtual*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not playing.
|
||||
/*virtual*/ bool supportsWaveData(){return true;}
|
||||
/*virtual*/ bool getWaveData(float* arr, S32 count, S32 stride = 1);
|
||||
/*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
|
||||
/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
|
||||
|
||||
private:
|
||||
bool releaseDeadStreams();
|
||||
void cleanupWaveData();
|
||||
|
||||
FMOD::System *mSystem;
|
||||
|
||||
LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp;
|
||||
FMOD::Channel *mFMODInternetStreamChannelp;
|
||||
std::list<LLAudioStreamManagerFMODSTUDIO *> mDeadStreams;
|
||||
|
||||
std::string mURL;
|
||||
std::string mPendingURL;
|
||||
F32 mGain;
|
||||
|
||||
LLSD *mMetaData;
|
||||
|
||||
FMOD::ChannelGroup* mStreamGroup;
|
||||
FMOD::DSP* mStreamDSP;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_STREAMINGAUDIO_FMOD_H
|
||||
@@ -58,6 +58,16 @@ public:
|
||||
// Destructor
|
||||
virtual ~LLEditingMotion();
|
||||
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// functions to support MotionController and MotionRegistry
|
||||
|
||||
@@ -1111,7 +1111,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
|
||||
|
||||
LLVector3 source_to_target = target_pos - keyframe_source_pos;
|
||||
|
||||
S32 max_iteration_count = llround(clamp_rescale(
|
||||
S32 max_iteration_count = llmath::llround(clamp_rescale(
|
||||
mCharacter->getPixelArea(),
|
||||
MAX_PIXEL_AREA_CONSTRAINTS,
|
||||
MIN_PIXEL_AREA_CONSTRAINTS,
|
||||
|
||||
@@ -53,6 +53,16 @@ public:
|
||||
// Destructor
|
||||
virtual ~LLKeyframeStandMotion();
|
||||
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// functions to support MotionController and MotionRegistry
|
||||
|
||||
@@ -876,12 +876,12 @@ void LLMotionController::updateMotions(bool force_update)
|
||||
|
||||
//<singu>
|
||||
// This old code is nonsense.
|
||||
//S32 quantum_count = llmax(0, llround((update_time - time_interval) / mTimeStep)) + 1;
|
||||
//S32 quantum_count = llmax(0, llmath::llround((update_time - time_interval) / mTimeStep)) + 1;
|
||||
// (update_time - time_interval) / mTimeStep is an integer! We need llround to get rid of floating point errors, not llfloor.
|
||||
// Moreover, just rounding off to the nearest integer with llround(update_time / mTimeStep) makes a lot more sense:
|
||||
// Moreover, just rounding off to the nearest integer with llmath::llround(update_time / mTimeStep) makes a lot more sense:
|
||||
// it is the best we can do to get as close to what we should draw as possible.
|
||||
// However, mAnimTime may only be incremented; therefore make sure of that with the llmax.
|
||||
S32 quantum_count = llmax(llround(update_time / mTimeStep), llceil(mAnimTime / mTimeStep));
|
||||
S32 quantum_count = llmax(llmath::llround(update_time / mTimeStep), llceil(mAnimTime / mTimeStep));
|
||||
//</singu>
|
||||
if (quantum_count == mTimeStepCount)
|
||||
{
|
||||
|
||||
@@ -96,6 +96,16 @@ protected:
|
||||
public:
|
||||
LLJointStateBlender();
|
||||
~LLJointStateBlender();
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
|
||||
void blendJointStates(BOOL apply_now = TRUE);
|
||||
BOOL addJointState(const LLPointer<LLJointState>& joint_state, S32 priority, BOOL additive_blend);
|
||||
void interpolate(F32 u);
|
||||
|
||||
@@ -31,7 +31,6 @@ set(llcommon_SOURCE_FILES
|
||||
llapr.cpp
|
||||
llaprpool.cpp
|
||||
llassettype.cpp
|
||||
llavatarname.cpp
|
||||
llbase32.cpp
|
||||
llbase64.cpp
|
||||
llcommon.cpp
|
||||
@@ -56,7 +55,6 @@ set(llcommon_SOURCE_FILES
|
||||
llfile.cpp
|
||||
llfindlocale.cpp
|
||||
llfixedbuffer.cpp
|
||||
llfoldertype.cpp
|
||||
llformat.cpp
|
||||
llframetimer.cpp
|
||||
llheartbeat.cpp
|
||||
@@ -135,7 +133,6 @@ set(llcommon_HEADER_FILES
|
||||
llassoclist.h
|
||||
llatomic.h
|
||||
llavatarconstants.h
|
||||
llavatarname.h
|
||||
llbase32.h
|
||||
llbase64.h
|
||||
llboost.h
|
||||
@@ -177,7 +174,6 @@ set(llcommon_HEADER_FILES
|
||||
llfile.h
|
||||
llfindlocale.h
|
||||
llfixedbuffer.h
|
||||
llfoldertype.h
|
||||
llformat.h
|
||||
llframetimer.h
|
||||
llhandle.h
|
||||
@@ -284,6 +280,8 @@ target_link_libraries(
|
||||
${WINDOWS_LIBRARIES}
|
||||
${Boost_CONTEXT_LIBRARY}
|
||||
${Boost_REGEX_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${CORESERVICES_LIBRARY}
|
||||
)
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ static F64 const NEVER = 1e16; // 317 million years.
|
||||
|
||||
F64 AIFrameTimer::sNextExpiration;
|
||||
AIFrameTimer::timer_list_type AIFrameTimer::sTimerList;
|
||||
LLMutex AIFrameTimer::sMutex;
|
||||
LLGlobalMutex AIFrameTimer::sMutex;
|
||||
|
||||
// Notes on thread-safety of AIRunningFrameTimer (continued from aiframetimer.h)
|
||||
//
|
||||
@@ -80,11 +80,10 @@ LLMutex AIFrameTimer::sMutex;
|
||||
void AIFrameTimer::create(F64 expiration, signal_type::slot_type const& slot)
|
||||
{
|
||||
AIRunningFrameTimer new_timer(expiration, this);
|
||||
sMutex.lock();
|
||||
LLMutexLock lock(sMutex);
|
||||
llassert(mHandle.mRunningTimer == sTimerList.end()); // Create may only be called when the timer isn't already running.
|
||||
mHandle.init(sTimerList.insert(new_timer), slot);
|
||||
sNextExpiration = sTimerList.begin()->expiration();
|
||||
sMutex.unlock();
|
||||
}
|
||||
|
||||
void AIFrameTimer::cancel(void)
|
||||
@@ -95,18 +94,19 @@ void AIFrameTimer::cancel(void)
|
||||
// mHandle.mMutex lock), we start with trying to obtain
|
||||
// it here and as such wait till the callback function
|
||||
// returned.
|
||||
mHandle.mMutex.lock();
|
||||
mHandle.mMutex.lock();
|
||||
// Next we have to grab this lock in order to stop
|
||||
// AIFrameTimer::handleExpiration from even entering
|
||||
// in the case we manage to get it first.
|
||||
sMutex.lock();
|
||||
if (mHandle.mRunningTimer != sTimerList.end())
|
||||
{
|
||||
sTimerList.erase(mHandle.mRunningTimer);
|
||||
mHandle.mRunningTimer = sTimerList.end();
|
||||
sNextExpiration = sTimerList.empty() ? NEVER : sTimerList.begin()->expiration();
|
||||
LLMutexLock lock(sMutex);
|
||||
if (mHandle.mRunningTimer != sTimerList.end())
|
||||
{
|
||||
sTimerList.erase(mHandle.mRunningTimer);
|
||||
mHandle.mRunningTimer = sTimerList.end();
|
||||
sNextExpiration = sTimerList.empty() ? NEVER : sTimerList.begin()->expiration();
|
||||
}
|
||||
}
|
||||
sMutex.unlock();
|
||||
mHandle.mMutex.unlock();
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ void AIFrameTimer::handleExpiration(F64 current_frame_time)
|
||||
//
|
||||
// Note that if the other thread actually obtained the sMutex then we
|
||||
// can't be here: this is still inside the critical area of sMutex.
|
||||
if (handle.mMutex.tryLock()) // If this fails then another thread is in the process of cancelling this timer, so do nothing.
|
||||
if (handle.mMutex.try_lock()) // If this fails then another thread is in the process of cancelling this timer, so do nothing.
|
||||
{
|
||||
sMutex.unlock();
|
||||
running_timer->do_callback(); // May not throw exceptions.
|
||||
|
||||
@@ -96,7 +96,7 @@ class LL_COMMON_API AIFrameTimer
|
||||
|
||||
typedef std::multiset<AIRunningFrameTimer> timer_list_type;
|
||||
|
||||
static LLMutex sMutex; // Mutex for the two global variables below.
|
||||
static LLGlobalMutex sMutex; // Mutex for the two global variables below.
|
||||
static timer_list_type sTimerList; // List with all running timers.
|
||||
static F64 sNextExpiration; // Cache of smallest value in sTimerList.
|
||||
friend class LLFrameTimer; // Access to sNextExpiration.
|
||||
|
||||
@@ -239,7 +239,7 @@ protected:
|
||||
|
||||
// For use by AIThreadSafeDC
|
||||
AIThreadSafe(void) { }
|
||||
AIThreadSafe(LLAPRPool& parent) : mRWLock(parent) { }
|
||||
MUTEX_POOL(AIThreadSafe(LLAPRPool& parent) : mRWLock(parent){ })
|
||||
|
||||
public:
|
||||
// Only for use by AITHREADSAFE, see below.
|
||||
@@ -473,7 +473,7 @@ protected:
|
||||
friend struct AIRegisteredStateMachinesList;
|
||||
// For use by AIThreadSafeSimpleDC and AIRegisteredStateMachinesList.
|
||||
AIThreadSafeSimple(void) { }
|
||||
AIThreadSafeSimple(LLAPRPool& parent) : mMutex(parent) { }
|
||||
MUTEX_POOL(AIThreadSafeSimple(LLAPRPool& parent) : mMutex(parent) { })
|
||||
|
||||
public:
|
||||
// Only for use by AITHREADSAFESIMPLE, see below.
|
||||
@@ -551,7 +551,7 @@ public:
|
||||
|
||||
protected:
|
||||
// For use by AIThreadSafeSimpleDCRootPool
|
||||
AIThreadSafeSimpleDC(LLAPRRootPool& parent) : AIThreadSafeSimple<T, MUTEX>(parent) { new (AIThreadSafeSimple<T, MUTEX>::ptr()) T; }
|
||||
AIThreadSafeSimpleDC(LLAPRRootPool& parent) : AIThreadSafeSimple<T, MUTEX>(MUTEX_POOL(parent)) { new (AIThreadSafeSimple<T, MUTEX>::ptr()) T; }
|
||||
};
|
||||
|
||||
// Helper class for AIThreadSafeSimpleDCRootPool to assure initialization of
|
||||
@@ -585,7 +585,7 @@ public:
|
||||
// as opposed to allocated from the current threads root pool.
|
||||
AIThreadSafeSimpleDCRootPool(void) :
|
||||
AIThreadSafeSimpleDCRootPool_pbase(),
|
||||
AIThreadSafeSimpleDC<T>(mRootPool) { }
|
||||
AIThreadSafeSimpleDC<T>(MUTEX_POOL(mRootPool)) { }
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -66,6 +66,7 @@ bool windows_post_minidump_callback(const wchar_t* dump_path,
|
||||
#else
|
||||
# include <signal.h>
|
||||
# include <unistd.h> // for fork()
|
||||
# include "apr_signal.h" // for apr_signal_description_get(int signum)
|
||||
void setup_signals();
|
||||
void default_unix_signal_handler(int signum, siginfo_t *info, void *);
|
||||
|
||||
@@ -385,12 +386,12 @@ void LLApp::setupErrorHandling()
|
||||
// installing the handler.
|
||||
installHandler = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(installHandler && (mExceptionHandler == 0))
|
||||
{
|
||||
mExceptionHandler = new google_breakpad::ExceptionHandler(mDumpPath, clear_CrashLoggerReserve_callback, &unix_post_minidump_callback, 0, true, 0);
|
||||
}
|
||||
#endif
|
||||
#elif LL_LINUX
|
||||
if(installHandler && (mExceptionHandler == 0))
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user