Merge with trunk
commit
30ff6cabd6
|
|
@ -44,6 +44,7 @@ Aleric Inglewood
|
|||
VWR-10001
|
||||
VWR-10759
|
||||
VWR-10837
|
||||
VWR-13996
|
||||
Ales Beaumont
|
||||
VWR-9352
|
||||
Alissa Sabre
|
||||
|
|
@ -275,6 +276,9 @@ Jacek Antonelli
|
|||
VWR-597
|
||||
VWR-2054
|
||||
VWR-2448
|
||||
VWR-2896
|
||||
VWR-2947
|
||||
VWR-2948
|
||||
VWR-3605
|
||||
JB Kraft
|
||||
VWR-5283
|
||||
|
|
|
|||
|
|
@ -377,7 +377,23 @@
|
|||
<key>trusted-sender</key>
|
||||
<boolean>true</boolean>
|
||||
</map>
|
||||
|
||||
<key>ParcelMediaURLFilter</key>
|
||||
<map>
|
||||
<key>flavor</key>
|
||||
<string>llsd</string>
|
||||
<key>trusted-sender</key>
|
||||
<boolean>false</boolean>
|
||||
</map>
|
||||
|
||||
<key>ParcelNavigateMedia</key>
|
||||
<map>
|
||||
<key>flavor</key>
|
||||
<string>llsd</string>
|
||||
<key>trusted-sender</key>
|
||||
<boolean>false</boolean>
|
||||
</map>
|
||||
|
||||
<key>ParcelObjectOwnersReply</key>
|
||||
<map>
|
||||
<key>flavor</key>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
# -*- cmake -*-
|
||||
|
||||
# cmake_minimum_required should appear before any
|
||||
|
|
@ -42,7 +43,6 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llimage)
|
|||
add_subdirectory(${LIBS_OPEN_PREFIX}llimagej2coj)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llinventory)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llmath)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llmedia)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llmessage)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llrender)
|
||||
|
|
@ -63,11 +63,22 @@ endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
|
|||
add_custom_target(viewer)
|
||||
if (VIEWER)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llui)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llxuixml)
|
||||
|
||||
# viewer media plugins
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
|
||||
|
||||
# llplugin testbed code (is this the right way to include it?)
|
||||
if (NOT LINUX)
|
||||
add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest)
|
||||
endif (NOT LINUX)
|
||||
|
||||
if (LINUX)
|
||||
add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
|
||||
add_dependencies(viewer linux-crash-logger-strip-target)
|
||||
add_subdirectory(${VIEWER_PREFIX}linux_updater)
|
||||
add_dependencies(viewer linux-crash-logger-strip-target linux-updater)
|
||||
elseif (DARWIN)
|
||||
add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
|
||||
add_subdirectory(${VIEWER_PREFIX}mac_updater)
|
||||
|
|
@ -110,3 +121,7 @@ if (SERVER)
|
|||
add_subdirectory(${SERVER_PREFIX}tools)
|
||||
endif (WINDOWS)
|
||||
endif (SERVER)
|
||||
|
||||
# Define after the custom viewer and server targets are created so individual
|
||||
# apps can add themselves as dependencies
|
||||
add_subdirectory(${INTEGRATION_TESTS_PREFIX}integration_tests)
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ endif (DARWIN)
|
|||
|
||||
|
||||
if (LINUX OR DARWIN)
|
||||
set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor")
|
||||
set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor -Woverloaded-virtual")
|
||||
|
||||
if (NOT GCC_DISABLE_FATAL_WARNINGS)
|
||||
set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")
|
||||
|
|
@ -227,7 +227,6 @@ else (STANDALONE)
|
|||
glib-2.0
|
||||
gstreamer-0.10
|
||||
gtk-2.0
|
||||
llfreetype2
|
||||
pango-1.0
|
||||
)
|
||||
endif (STANDALONE)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ set(cmake_SOURCE_FILES
|
|||
FindXmlRpcEpi.cmake
|
||||
FMOD.cmake
|
||||
FreeType.cmake
|
||||
GStreamer.cmake
|
||||
GStreamer010Plugin.cmake
|
||||
GooglePerfTools.cmake
|
||||
JPEG.cmake
|
||||
LLAddBuildTest.cmake
|
||||
|
|
@ -48,8 +48,8 @@ set(cmake_SOURCE_FILES
|
|||
LLInventory.cmake
|
||||
LLKDU.cmake
|
||||
LLMath.cmake
|
||||
LLMedia.cmake
|
||||
LLMessage.cmake
|
||||
LLPlugin.cmake
|
||||
LLPrimitive.cmake
|
||||
LLRender.cmake
|
||||
LLScene.cmake
|
||||
|
|
@ -60,7 +60,6 @@ set(cmake_SOURCE_FILES
|
|||
LScript.cmake
|
||||
Linking.cmake
|
||||
MonoEmbed.cmake
|
||||
Mozlib.cmake
|
||||
MySQL.cmake
|
||||
NDOF.cmake
|
||||
OPENAL.cmake
|
||||
|
|
@ -70,7 +69,6 @@ set(cmake_SOURCE_FILES
|
|||
PNG.cmake
|
||||
Python.cmake
|
||||
Prebuilt.cmake
|
||||
QuickTime.cmake
|
||||
RunBuildTest.cmake
|
||||
TemplateCheck.cmake
|
||||
Tut.cmake
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
if (STANDALONE)
|
||||
include(FindPkgConfig)
|
||||
|
||||
pkg_check_modules(GSTREAMER010 REQUIRED gstreamer-0.10)
|
||||
pkg_check_modules(GSTREAMER010_PLUGINS_BASE REQUIRED gstreamer-plugins-base-0.10)
|
||||
elseif (LINUX)
|
||||
use_prebuilt_binary(gstreamer)
|
||||
# possible libxml should have its own .cmake file instead
|
||||
use_prebuilt_binary(libxml)
|
||||
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
|
||||
)
|
||||
# We don't need to explicitly link against gstreamer itself, because
|
||||
# LLMediaImplGStreamer probes for the system's copy at runtime.
|
||||
set(GSTREAMER010_LIBRARIES
|
||||
gobject-2.0
|
||||
gmodule-2.0
|
||||
dl
|
||||
gthread-2.0
|
||||
rt
|
||||
glib-2.0
|
||||
)
|
||||
endif (STANDALONE)
|
||||
|
||||
if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND)
|
||||
set(GSTREAMER010 ON CACHE BOOL "Build with GStreamer-0.10 streaming media support.")
|
||||
endif (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND)
|
||||
|
||||
if (GSTREAMER010)
|
||||
add_definitions(-DLL_GSTREAMER010_ENABLED=1)
|
||||
endif (GSTREAMER010)
|
||||
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# -*- cmake -*-
|
||||
include(Linking)
|
||||
include(Prebuilt)
|
||||
|
||||
if (STANDALONE)
|
||||
set(GLUI OFF CACHE BOOL
|
||||
"GLUI support for the llplugin/llmedia test apps.")
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(glui)
|
||||
set(GLUI ON CACHE BOOL
|
||||
"GLUI support for the llplugin/llmedia test apps.")
|
||||
endif (STANDALONE)
|
||||
|
||||
if (LINUX)
|
||||
set(GLUI ON CACHE BOOL
|
||||
"llplugin media apps HACK for Linux.")
|
||||
endif (LINUX)
|
||||
|
||||
if (DARWIN OR LINUX)
|
||||
set(GLUI_LIBRARY
|
||||
glui)
|
||||
endif (DARWIN OR LINUX)
|
||||
|
||||
if (WINDOWS)
|
||||
set(GLUI_LIBRARY
|
||||
debug glui32.lib
|
||||
optimized glui32.lib)
|
||||
endif (WINDOWS)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# -*- cmake -*-
|
||||
include(Linking)
|
||||
include(Prebuilt)
|
||||
|
||||
if (WINDOWS)
|
||||
use_prebuilt_binary(freeglut)
|
||||
set(GLUT_LIBRARY
|
||||
debug freeglut_static.lib
|
||||
optimized freeglut_static.lib)
|
||||
endif (WINDOWS)
|
||||
|
||||
if (LINUX)
|
||||
FIND_LIBRARY(GLUT_LIBRARY glut)
|
||||
endif (LINUX)
|
||||
|
||||
if (DARWIN)
|
||||
include(CMakeFindFrameworks)
|
||||
find_library(GLUT_LIBRARY GLUT)
|
||||
endif (DARWIN)
|
||||
|
|
@ -6,9 +6,11 @@ if (STANDALONE)
|
|||
else (STANDALONE)
|
||||
use_prebuilt_binary(google)
|
||||
if (WINDOWS)
|
||||
use_prebuilt_binary(google-perftools)
|
||||
set(TCMALLOC_LIBRARIES
|
||||
debug libtcmalloc_minimal-debug
|
||||
optimized libtcmalloc_minimal-debug)
|
||||
optimized libtcmalloc_minimal)
|
||||
set(GOOGLE_PERFTOOLS_FOUND "YES")
|
||||
endif (WINDOWS)
|
||||
if (LINUX)
|
||||
set(TCMALLOC_LIBRARIES tcmalloc)
|
||||
|
|
@ -27,6 +29,10 @@ endif (GOOGLE_PERFTOOLS_FOUND)
|
|||
# XXX Disable temporarily, until we have compilation issues on 64-bit
|
||||
# Etch sorted.
|
||||
set(USE_GOOGLE_PERFTOOLS OFF)
|
||||
if (WINDOWS)
|
||||
# *TODO -reenable this once we get server usage sorted out
|
||||
#set(USE_GOOGLE_PERFTOOLS ON)
|
||||
endif (WINDOWS)
|
||||
|
||||
if (USE_GOOGLE_PERFTOOLS)
|
||||
set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1)
|
||||
|
|
|
|||
|
|
@ -157,3 +157,79 @@ INCLUDE(GoogleMock)
|
|||
ADD_DEPENDENCIES(${project} ${project}_tests)
|
||||
ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS)
|
||||
|
||||
FUNCTION(LL_ADD_INTEGRATION_TEST
|
||||
testname
|
||||
additional_source_files
|
||||
library_dependencies
|
||||
# variable args
|
||||
)
|
||||
if(TEST_DEBUG)
|
||||
message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on")
|
||||
endif(TEST_DEBUG)
|
||||
|
||||
SET(source_files
|
||||
tests/${testname}_test.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/test.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/lltut.cpp
|
||||
${additional_source_files}
|
||||
)
|
||||
|
||||
SET(libraries
|
||||
${library_dependencies}
|
||||
${PTHREAD_LIBRARY}
|
||||
)
|
||||
|
||||
# Add test executable build target
|
||||
if(TEST_DEBUG)
|
||||
message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})")
|
||||
endif(TEST_DEBUG)
|
||||
ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
|
||||
|
||||
# Add link deps to the executable
|
||||
if(TEST_DEBUG)
|
||||
message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})")
|
||||
endif(TEST_DEBUG)
|
||||
TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})
|
||||
|
||||
# Create the test running command
|
||||
SET(test_command ${ARGN})
|
||||
GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION)
|
||||
LIST(FIND test_command "{}" test_exe_pos)
|
||||
IF(test_exe_pos LESS 0)
|
||||
# The {} marker means "the full pathname of the test executable."
|
||||
# test_exe_pos -1 means we didn't find it -- so append the test executable
|
||||
# name to $ARGN, the variable part of the arg list. This is convenient
|
||||
# shorthand for both straightforward execution of the test program (empty
|
||||
# $ARGN) and for running a "wrapper" program of some kind accepting the
|
||||
# pathname of the test program as the last of its args. You need specify
|
||||
# {} only if the test program's pathname isn't the last argument in the
|
||||
# desired command line.
|
||||
LIST(APPEND test_command "${TEST_EXE}")
|
||||
ELSE (test_exe_pos LESS 0)
|
||||
# Found {} marker at test_exe_pos. Remove the {}...
|
||||
LIST(REMOVE_AT test_command test_exe_pos)
|
||||
# ...and replace it with the actual name of the test executable.
|
||||
LIST(INSERT test_command test_exe_pos "${TEST_EXE}")
|
||||
ENDIF (test_exe_pos LESS 0)
|
||||
|
||||
SET(TEST_SCRIPT_CMD
|
||||
${CMAKE_COMMAND}
|
||||
-DLD_LIBRARY_PATH=${ARCH_PREBUILT_DIRS}:/usr/lib
|
||||
-DTEST_CMD:STRING="${test_command}"
|
||||
-P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake
|
||||
)
|
||||
|
||||
if(TEST_DEBUG)
|
||||
message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}")
|
||||
endif(TEST_DEBUG)
|
||||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
TARGET INTEGRATION_TEST_${testname}
|
||||
POST_BUILD
|
||||
COMMAND ${TEST_SCRIPT_CMD}
|
||||
)
|
||||
|
||||
# Use CTEST? Not sure how to yet...
|
||||
# ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD})
|
||||
|
||||
ENDFUNCTION(LL_ADD_INTEGRATION_TEST)
|
||||
|
|
@ -4,6 +4,7 @@ include(APR)
|
|||
include(Boost)
|
||||
include(EXPAT)
|
||||
include(ZLIB)
|
||||
include(GooglePerfTools)
|
||||
|
||||
set(LLCOMMON_INCLUDE_DIRS
|
||||
${LIBS_OPEN_DIR}/llcommon
|
||||
|
|
@ -13,3 +14,6 @@ set(LLCOMMON_INCLUDE_DIRS
|
|||
)
|
||||
|
||||
set(LLCOMMON_LIBRARIES llcommon)
|
||||
|
||||
add_definitions(${TCMALLOC_FLAG})
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
|
||||
set(LLPLUGIN_INCLUDE_DIRS
|
||||
${LIBS_OPEN_DIR}/llplugin
|
||||
)
|
||||
|
||||
set(LLPLUGIN_LIBRARIES llplugin)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
set(LLXUIXML_INCLUDE_DIRS
|
||||
${LIBS_OPEN_DIR}/llxuixml
|
||||
)
|
||||
|
||||
set(LLXUIXML_LIBRARIES llxuixml)
|
||||
|
|
@ -42,6 +42,7 @@ if (WINDOWS)
|
|||
wldap32
|
||||
gdi32
|
||||
user32
|
||||
dbghelp
|
||||
)
|
||||
else (WINDOWS)
|
||||
set(WINDOWS_LIBRARIES "")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
|
||||
set(MEDIA_PLUGIN_BASE_INCLUDE_DIRS
|
||||
${LIBS_OPEN_DIR}/media_plugins/base/
|
||||
)
|
||||
|
||||
set(MEDIA_PLUGIN_BASE_LIBRARIES media_plugin_base)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
if (WINDOWS)
|
||||
set(PLUGIN_API_WINDOWS_LIBRARIES
|
||||
wsock32
|
||||
ws2_32
|
||||
psapi
|
||||
netapi32
|
||||
advapi32
|
||||
user32
|
||||
)
|
||||
else (WINDOWS)
|
||||
set(PLUGIN_API_WINDOWS_LIBRARIES "")
|
||||
endif (WINDOWS)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
if(INSTALL_PROPRIETARY)
|
||||
include(Prebuilt)
|
||||
use_prebuilt_binary(quicktime)
|
||||
endif(INSTALL_PROPRIETARY)
|
||||
|
||||
if (DARWIN)
|
||||
include(CMakeFindFrameworks)
|
||||
find_library(QUICKTIME_LIBRARY QuickTime)
|
||||
elseif (WINDOWS)
|
||||
set(QUICKTIME_SDK_DIR "$ENV{PROGRAMFILES}/QuickTime SDK"
|
||||
CACHE PATH "Location of the QuickTime SDK.")
|
||||
|
||||
find_library(DEBUG_QUICKTIME_LIBRARY qtmlclient
|
||||
PATHS
|
||||
${ARCH_PREBUILT_DIRS_DEBUG}
|
||||
"${QUICKTIME_SDK_DIR}\\libraries"
|
||||
)
|
||||
|
||||
find_library(RELEASE_QUICKTIME_LIBRARY qtmlclient
|
||||
PATHS
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}
|
||||
"${QUICKTIME_SDK_DIR}\\libraries"
|
||||
)
|
||||
|
||||
if (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
|
||||
set(QUICKTIME_LIBRARY
|
||||
optimized ${RELEASE_QUICKTIME_LIBRARY}
|
||||
debug ${DEBUG_QUICKTIME_LIBRARY}
|
||||
)
|
||||
|
||||
endif (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
|
||||
|
||||
include_directories(
|
||||
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/quicktime
|
||||
"${QUICKTIME_SDK_DIR}\\CIncludes"
|
||||
)
|
||||
endif (DARWIN)
|
||||
|
||||
mark_as_advanced(QUICKTIME_LIBRARY)
|
||||
|
||||
if (QUICKTIME_LIBRARY)
|
||||
set(QUICKTIME ON CACHE BOOL "Build with QuickTime streaming media support.")
|
||||
endif (QUICKTIME_LIBRARY)
|
||||
|
||||
|
|
@ -23,6 +23,7 @@ set(LIBS_SERVER_PREFIX)
|
|||
set(SCRIPTS_PREFIX ../scripts)
|
||||
set(SERVER_PREFIX)
|
||||
set(VIEWER_PREFIX)
|
||||
set(INTEGRATION_TESTS_PREFIX)
|
||||
|
||||
set(LIBS_CLOSED_DIR ${CMAKE_SOURCE_DIR}/${LIBS_CLOSED_PREFIX})
|
||||
set(LIBS_OPEN_DIR ${CMAKE_SOURCE_DIR}/${LIBS_OPEN_PREFIX})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
# -*- cmake -*-
|
||||
include(Linking)
|
||||
include(Prebuilt)
|
||||
|
||||
if (STANDALONE)
|
||||
set(WEBKITLIBPLUGIN OFF CACHE BOOL
|
||||
"WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(llqtwebkit)
|
||||
set(WEBKITLIBPLUGIN ON CACHE BOOL
|
||||
"WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
|
||||
endif (STANDALONE)
|
||||
|
||||
if (WINDOWS)
|
||||
set(WEBKIT_PLUGIN_LIBRARIES
|
||||
debug llqtwebkitd
|
||||
debug QtWebKitd4
|
||||
debug QtOpenGLd4
|
||||
debug QtNetworkd4
|
||||
debug QtGuid4
|
||||
debug QtCored4
|
||||
debug qtmaind
|
||||
optimized llqtwebkit
|
||||
optimized QtWebKit4
|
||||
optimized QtOpenGL4
|
||||
optimized QtNetwork4
|
||||
optimized QtGui4
|
||||
optimized QtCore4
|
||||
optimized qtmain
|
||||
)
|
||||
elseif (DARWIN)
|
||||
set(WEBKIT_PLUGIN_LIBRARIES
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib
|
||||
debug ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib
|
||||
)
|
||||
elseif (LINUX)
|
||||
set(WEBKIT_PLUGIN_LIBRARIES
|
||||
llqtwebkit
|
||||
|
||||
qgif
|
||||
# qico
|
||||
qjpeg
|
||||
# qpng
|
||||
# qtiff
|
||||
# qsvg
|
||||
|
||||
# QtSvg
|
||||
QtWebKit
|
||||
QtOpenGL
|
||||
QtNetwork
|
||||
QtGui
|
||||
QtCore
|
||||
|
||||
fontconfig
|
||||
X11
|
||||
Xrender
|
||||
GL
|
||||
|
||||
# sqlite3
|
||||
# Xi
|
||||
# SM
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
|
@ -76,6 +76,7 @@ class PlatformSetup(object):
|
|||
build_type = build_types['relwithdebinfo']
|
||||
standalone = 'OFF'
|
||||
unattended = 'OFF'
|
||||
universal = 'OFF'
|
||||
project_name = 'SecondLife'
|
||||
distcc = True
|
||||
cmake_opts = []
|
||||
|
|
@ -419,7 +420,7 @@ class DarwinSetup(UnixSetup):
|
|||
return 'darwin'
|
||||
|
||||
def arch(self):
|
||||
if self.unattended == 'ON':
|
||||
if self.universal == 'ON':
|
||||
return 'universal'
|
||||
else:
|
||||
return UnixSetup.arch(self)
|
||||
|
|
@ -433,11 +434,12 @@ class DarwinSetup(UnixSetup):
|
|||
word_size=self.word_size,
|
||||
unattended=self.unattended,
|
||||
project_name=self.project_name,
|
||||
universal='',
|
||||
universal=self.universal,
|
||||
type=self.build_type.upper(),
|
||||
)
|
||||
if self.unattended == 'ON':
|
||||
if self.universal == 'ON':
|
||||
args['universal'] = '-DCMAKE_OSX_ARCHITECTURES:STRING=\'i386;ppc\''
|
||||
pass
|
||||
#if simple:
|
||||
# return 'cmake %(opts)s %(dir)r' % args
|
||||
return ('cmake -G %(generator)r '
|
||||
|
|
@ -676,6 +678,7 @@ Options:
|
|||
--standalone build standalone, without Linden prebuild libraries
|
||||
--unattended build unattended, do not invoke any tools requiring
|
||||
a human response
|
||||
--universal build a universal binary on Mac OS X (unsupported)
|
||||
-t | --type=NAME build type ("Debug", "Release", or "RelWithDebInfo")
|
||||
-m32 | -m64 build architecture (32-bit or 64-bit)
|
||||
-N | --no-distcc disable use of distcc
|
||||
|
|
@ -721,7 +724,7 @@ def main(arguments):
|
|||
opts, args = getopt.getopt(
|
||||
arguments,
|
||||
'?hNt:p:G:m:',
|
||||
['help', 'standalone', 'no-distcc', 'unattended', 'type=', 'incredibuild', 'generator=', 'project='])
|
||||
['help', 'standalone', 'no-distcc', 'unattended', 'universal', 'type=', 'incredibuild', 'generator=', 'project='])
|
||||
except getopt.GetoptError, err:
|
||||
print >> sys.stderr, 'Error:', err
|
||||
print >> sys.stderr, """
|
||||
|
|
@ -738,6 +741,8 @@ For example: develop.py configure -DSERVER:BOOL=OFF"""
|
|||
setup.standalone = 'ON'
|
||||
elif o in ('--unattended',):
|
||||
setup.unattended = 'ON'
|
||||
elif o in ('--universal',):
|
||||
setup.universal = 'ON'
|
||||
elif o in ('-m',):
|
||||
if a in ('32', '64'):
|
||||
setup.word_size = int(a)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
add_subdirectory(llui_libtest)
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
# Only set this up for viewer builds, because the llui library is most closely
|
||||
# related to the viewer
|
||||
if (VIEWER)
|
||||
|
||||
project (llui_libtest)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLImage)
|
||||
include(LLImageJ2COJ) # ugh, needed for images
|
||||
include(LLMath)
|
||||
include(LLRender)
|
||||
include(LLWindow)
|
||||
include(LLUI)
|
||||
include(LLVFS) # ugh, needed for LLDir
|
||||
include(LLXML)
|
||||
include(LLXUIXML)
|
||||
include(Linking)
|
||||
# include(Tut)
|
||||
|
||||
include_directories(
|
||||
${FREETYPE_INCLUDE_DIRS}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLIMAGE_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLRENDER_INCLUDE_DIRS}
|
||||
${LLUI_INCLUDE_DIRS}
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
${LLWINDOW_INCLUDE_DIRS}
|
||||
${LLXML_INCLUDE_DIRS}
|
||||
${LLXUIXML_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(llui_libtest_SOURCE_FILES
|
||||
llui_libtest.cpp
|
||||
llwidgetreg.cpp
|
||||
)
|
||||
|
||||
set(llui_libtest_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
llui_libtest.h
|
||||
llwidgetreg.h
|
||||
)
|
||||
|
||||
set_source_files_properties(${llui_libtest_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
list(APPEND llui_libtest_SOURCE_FILES ${llui_libtest_HEADER_FILES})
|
||||
|
||||
add_executable(llui_libtest ${llui_libtest_SOURCE_FILES})
|
||||
|
||||
# Link with OS-specific libraries for LLWindow dependency
|
||||
if (DARWIN)
|
||||
find_library(COCOA_LIBRARY Cocoa)
|
||||
set(OS_LIBRARIES ${COCOA_LIBRARY})
|
||||
elseif (WINDOWS)
|
||||
set(OS_LIBRARIES ${WINDOWS_LIBRARIES})
|
||||
elseif (LINUX)
|
||||
set(OS_LIBRARIES)
|
||||
else (DARWIN)
|
||||
message(FATAL_ERROR "unknown platform")
|
||||
endif (DARWIN)
|
||||
|
||||
# Libraries on which this library depends, needed for Linux builds
|
||||
# Sort by high-level to low-level
|
||||
target_link_libraries(llui_libtest
|
||||
llui
|
||||
${OS_LIBRARIES}
|
||||
${GOOGLE_PERFTOOLS_LIBRARIES}
|
||||
)
|
||||
|
||||
if (WINDOWS)
|
||||
set_target_properties(llui_libtest
|
||||
PROPERTIES
|
||||
LINK_FLAGS "/NODEFAULTLIB:LIBCMT"
|
||||
LINK_FLAGS_DEBUG "/NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBCMTD"
|
||||
)
|
||||
|
||||
# Copy over OpenJPEG.dll
|
||||
# *NOTE: On Windows with VS2005, only the first comment prints
|
||||
set(OPENJPEG_RELEASE
|
||||
"${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/openjpeg.dll")
|
||||
add_custom_command( TARGET llui_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${OPENJPEG_RELEASE} ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Copying OpenJPEG DLLs to binary directory"
|
||||
)
|
||||
set(OPENJPEG_DEBUG
|
||||
"${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/openjpegd.dll")
|
||||
add_custom_command( TARGET llui_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${OPENJPEG_DEBUG} ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
||||
# Ensure people working on the viewer don't break this library
|
||||
# *NOTE: This could be removed, or only built by Parabuild, if the build
|
||||
# and link times become too long. JC
|
||||
add_dependencies(viewer llui_libtest)
|
||||
|
||||
endif (VIEWER)
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
/**
|
||||
* @file llui_libtest.cpp
|
||||
* @brief Integration test for the LLUI library
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&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 "llui_libtest.h"
|
||||
|
||||
// project includes
|
||||
#include "llwidgetreg.h"
|
||||
|
||||
// linden library includes
|
||||
#include "llcontrol.h" // LLControlGroup
|
||||
#include "lldir.h"
|
||||
#include "llerrorcontrol.h"
|
||||
#include "llfloater.h"
|
||||
#include "llfontfreetype.h"
|
||||
#include "llfontgl.h"
|
||||
#include "lltransutil.h"
|
||||
#include "llui.h"
|
||||
#include "lluictrlfactory.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// *TODO: switch to using TUT
|
||||
// *TODO: teach Parabuild about this program, run automatically after full builds
|
||||
|
||||
// I believe these must be globals, not stack variables. JC
|
||||
LLControlGroup gSavedSettings("Global"); // saved at end of session
|
||||
LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session
|
||||
LLControlGroup gWarningSettings("Warnings"); // persists ignored dialogs/warnings
|
||||
|
||||
// We can't create LLImageGL objects because we have no window or rendering
|
||||
// context. Provide enough of an LLUIImage to test the LLUI library without
|
||||
// an underlying image.
|
||||
class TestUIImage : public LLUIImage
|
||||
{
|
||||
public:
|
||||
TestUIImage()
|
||||
: LLUIImage( std::string(), NULL ) // NULL ImageGL, don't deref!
|
||||
{ }
|
||||
|
||||
/*virtual*/ S32 getWidth() const
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
/*virtual*/ S32 getHeight() const
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class LLTexture ;
|
||||
// We need to supply dummy images
|
||||
class TestImageProvider : public LLImageProviderInterface
|
||||
{
|
||||
public:
|
||||
/*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name)
|
||||
{
|
||||
return makeImage();
|
||||
}
|
||||
|
||||
/*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id)
|
||||
{
|
||||
return makeImage();
|
||||
}
|
||||
|
||||
/*virtual*/ void cleanUp()
|
||||
{
|
||||
}
|
||||
|
||||
LLPointer<LLUIImage> makeImage()
|
||||
{
|
||||
LLPointer<LLTexture> image_gl;
|
||||
LLPointer<LLUIImage> image = new TestUIImage(); //LLUIImage( std::string(), image_gl);
|
||||
mImageList.push_back(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
public:
|
||||
// Unclear if we need this, hold on to one copy of each image we make
|
||||
std::vector<LLPointer<LLUIImage> > mImageList;
|
||||
};
|
||||
TestImageProvider gTestImageProvider;
|
||||
|
||||
static std::string get_xui_dir()
|
||||
{
|
||||
std::string delim = gDirUtilp->getDirDelimiter();
|
||||
return gDirUtilp->getSkinBaseDir() + delim + "default" + delim + "xui" + delim;
|
||||
}
|
||||
|
||||
void init_llui()
|
||||
{
|
||||
// Font lookup needs directory support
|
||||
#if LL_DARWIN
|
||||
const char* newview_path = "../../../../newview";
|
||||
#else
|
||||
const char* newview_path = "../../../newview";
|
||||
#endif
|
||||
gDirUtilp->initAppDirs("SecondLife", newview_path);
|
||||
gDirUtilp->setSkinFolder("default");
|
||||
|
||||
// colors are no longer stored in a LLControlGroup file
|
||||
LLUIColorTable::instance().loadFromSettings();
|
||||
|
||||
std::string config_filename = gDirUtilp->getExpandedFilename(
|
||||
LL_PATH_APP_SETTINGS, "settings.xml");
|
||||
gSavedSettings.loadFromFile(config_filename);
|
||||
|
||||
// See LLAppViewer::init()
|
||||
LLUI::settings_map_t settings;
|
||||
settings["config"] = &gSavedSettings;
|
||||
settings["ignores"] = &gWarningSettings;
|
||||
settings["floater"] = &gSavedSettings;
|
||||
settings["account"] = &gSavedPerAccountSettings;
|
||||
|
||||
// Don't use real images as we don't have a GL context
|
||||
LLUI::initClass(settings, &gTestImageProvider);
|
||||
|
||||
const bool no_register_widgets = false;
|
||||
LLWidgetReg::initClass( no_register_widgets );
|
||||
|
||||
// Unclear if this is needed
|
||||
LLUI::setupPaths();
|
||||
// Otherwise we get translation warnings when setting up floaters
|
||||
// (tooltips for buttons)
|
||||
std::set<std::string> default_args;
|
||||
LLTransUtil::parseStrings("strings.xml", default_args);
|
||||
LLTransUtil::parseLanguageStrings("language_settings.xml");
|
||||
LLFontManager::initClass();
|
||||
|
||||
// Creating widgets apparently requires fonts to be initialized,
|
||||
// otherwise it crashes.
|
||||
LLFontGL::initClass(96.f, 1.f, 1.f,
|
||||
gDirUtilp->getAppRODataDir(),
|
||||
LLUI::getXUIPaths(),
|
||||
false ); // don't create gl textures
|
||||
|
||||
LLFloaterView::Params fvparams;
|
||||
fvparams.name("Floater View");
|
||||
fvparams.rect( LLRect(0,480,640,0) );
|
||||
fvparams.mouse_opaque(false);
|
||||
fvparams.follows.flags(FOLLOWS_ALL);
|
||||
fvparams.tab_stop(false);
|
||||
gFloaterView = LLUICtrlFactory::create<LLFloaterView> (fvparams);
|
||||
}
|
||||
|
||||
void export_test_floaters()
|
||||
{
|
||||
// Convert all test floaters to new XML format
|
||||
std::string delim = gDirUtilp->getDirDelimiter();
|
||||
std::string xui_dir = get_xui_dir() + "en" + delim;
|
||||
std::string filename;
|
||||
while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename, false))
|
||||
{
|
||||
if (filename.find("_new.xml") != std::string::npos)
|
||||
{
|
||||
// don't re-export other test floaters
|
||||
continue;
|
||||
}
|
||||
llinfos << "Converting " << filename << llendl;
|
||||
// Build a floater and output new attributes
|
||||
LLXMLNodePtr output_node = new LLXMLNode();
|
||||
LLFloater* floater = new LLFloater(LLSD());
|
||||
LLUICtrlFactory::getInstance()->buildFloater(floater,
|
||||
filename,
|
||||
// FALSE, // don't open floater
|
||||
output_node);
|
||||
std::string out_filename = xui_dir + filename;
|
||||
std::string::size_type extension_pos = out_filename.rfind(".xml");
|
||||
out_filename.resize(extension_pos);
|
||||
out_filename += "_new.xml";
|
||||
|
||||
llinfos << "Output: " << out_filename << llendl;
|
||||
LLFILE* floater_file = LLFile::fopen(out_filename.c_str(), "w");
|
||||
LLXMLNode::writeHeaderToFile(floater_file);
|
||||
output_node->writeToFile(floater_file);
|
||||
fclose(floater_file);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Must init LLError for llerrs to actually cause errors.
|
||||
LLError::initForApplication(".");
|
||||
|
||||
init_llui();
|
||||
|
||||
export_test_floaters();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* @file llui_libtest.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&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 LLUI_LIBTEST_H
|
||||
#define LLUI_LIBTEST_H
|
||||
|
||||
// TODO
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* @file llwidgetreg.cpp
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&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 "llwidgetreg.h"
|
||||
|
||||
#include "llbutton.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llcontainerview.h"
|
||||
#include "lliconctrl.h"
|
||||
#include "llmenugl.h"
|
||||
#include "llmultislider.h"
|
||||
#include "llmultisliderctrl.h"
|
||||
#include "llprogressbar.h"
|
||||
#include "llradiogroup.h"
|
||||
#include "llsearcheditor.h"
|
||||
#include "llscrollcontainer.h"
|
||||
#include "llscrollingpanellist.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "llslider.h"
|
||||
#include "llsliderctrl.h"
|
||||
#include "llspinctrl.h"
|
||||
#include "llstatview.h"
|
||||
#include "lltabcontainer.h"
|
||||
#include "lltextbox.h"
|
||||
#include "lltexteditor.h"
|
||||
#include "llflyoutbutton.h"
|
||||
#include "llfiltereditor.h"
|
||||
#include "lllayoutstack.h"
|
||||
|
||||
void LLWidgetReg::initClass(bool register_widgets)
|
||||
{
|
||||
// Only need to register if the Windows linker has optimized away the
|
||||
// references to the object files.
|
||||
if (register_widgets)
|
||||
{
|
||||
LLDefaultChildRegistry::Register<LLButton> button("button");
|
||||
LLDefaultChildRegistry::Register<LLCheckBoxCtrl> check_box("check_box");
|
||||
LLDefaultChildRegistry::Register<LLComboBox> combo_box("combo_box");
|
||||
LLDefaultChildRegistry::Register<LLFilterEditor> filter_editor("filter_editor");
|
||||
LLDefaultChildRegistry::Register<LLFlyoutButton> flyout_button("flyout_button");
|
||||
LLDefaultChildRegistry::Register<LLContainerView> container_view("container_view");
|
||||
LLDefaultChildRegistry::Register<LLIconCtrl> icon("icon");
|
||||
LLDefaultChildRegistry::Register<LLLineEditor> line_editor("line_editor");
|
||||
LLDefaultChildRegistry::Register<LLMenuItemSeparatorGL> menu_item_separator("menu_item_separator");
|
||||
LLDefaultChildRegistry::Register<LLMenuItemCallGL> menu_item_call_gl("menu_item_call");
|
||||
LLDefaultChildRegistry::Register<LLMenuItemCheckGL> menu_item_check_gl("menu_item_check");
|
||||
LLDefaultChildRegistry::Register<LLMenuGL> menu("menu");
|
||||
LLDefaultChildRegistry::Register<LLMenuBarGL> menu_bar("menu_bar");
|
||||
LLDefaultChildRegistry::Register<LLContextMenu> context_menu("context_menu");
|
||||
LLDefaultChildRegistry::Register<LLMultiSlider> multi_slider_bar("multi_slider_bar");
|
||||
LLDefaultChildRegistry::Register<LLMultiSliderCtrl> multi_slider("multi_slider");
|
||||
LLDefaultChildRegistry::Register<LLPanel> panel("panel", &LLPanel::fromXML);
|
||||
LLDefaultChildRegistry::Register<LLLayoutStack> layout_stack("layout_stack", &LLLayoutStack::fromXML);
|
||||
LLDefaultChildRegistry::Register<LLProgressBar> progress_bar("progress_bar");
|
||||
LLDefaultChildRegistry::Register<LLRadioGroup> radio_group("radio_group");
|
||||
LLDefaultChildRegistry::Register<LLRadioCtrl> radio_item("radio_item");
|
||||
LLDefaultChildRegistry::Register<LLSearchEditor> search_editor("search_editor");
|
||||
LLDefaultChildRegistry::Register<LLScrollContainer> scroll_container("scroll_container");
|
||||
LLDefaultChildRegistry::Register<LLScrollingPanelList> scrolling_panel_list("scrolling_panel_list");
|
||||
LLDefaultChildRegistry::Register<LLScrollListCtrl> scroll_list("scroll_list");
|
||||
LLDefaultChildRegistry::Register<LLSlider> slider_bar("slider_bar");
|
||||
LLDefaultChildRegistry::Register<LLSliderCtrl> slider("slider");
|
||||
LLDefaultChildRegistry::Register<LLSpinCtrl> spinner("spinner");
|
||||
LLDefaultChildRegistry::Register<LLStatBar> stat_bar("stat_bar");
|
||||
//LLDefaultChildRegistry::Register<LLPlaceHolderPanel> placeholder("placeholder");
|
||||
LLDefaultChildRegistry::Register<LLTabContainer> tab_container("tab_container");
|
||||
LLDefaultChildRegistry::Register<LLTextBox> text("text");
|
||||
LLDefaultChildRegistry::Register<LLTextEditor> simple_text_editor("simple_text_editor");
|
||||
LLDefaultChildRegistry::Register<LLUICtrl> ui_ctrl("ui_ctrl");
|
||||
LLDefaultChildRegistry::Register<LLStatView> stat_view("stat_view");
|
||||
//LLDefaultChildRegistry::Register<LLUICtrlLocate> locate("locate");
|
||||
//LLDefaultChildRegistry::Register<LLUICtrlLocate> pad("pad");
|
||||
LLDefaultChildRegistry::Register<LLViewBorder> view_border("view_border");
|
||||
}
|
||||
|
||||
// *HACK: Usually this is registered as a viewer text editor
|
||||
LLDefaultChildRegistry::Register<LLTextEditor> text_editor("text_editor");
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file llwidgetreg.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&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 LLWIDGETREG_H
|
||||
#define LLWIDGETREG_H
|
||||
|
||||
// Register all widgets with the builder registry.
|
||||
// Useful on Windows where linker discards all references to the
|
||||
// static LLDefaultChildRegistry::Register<> calls.
|
||||
class LLWidgetReg
|
||||
{
|
||||
public:
|
||||
static void initClass(bool register_widgets);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
project(linux_updater)
|
||||
|
||||
include(00-Common)
|
||||
include(CURL)
|
||||
include(CARes)
|
||||
include(OpenSSL)
|
||||
include(UI)
|
||||
include(LLCommon)
|
||||
include(LLVFS)
|
||||
include(LLXML)
|
||||
include(LLXUIXML)
|
||||
include(Linking)
|
||||
|
||||
include_directories(
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
${LLXML_INCLUDE_DIRS}
|
||||
${LLXUIXML_INCLUDE_DIRS}
|
||||
${CURL_INCLUDE_DIRS}
|
||||
${CARES_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
${UI_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(linux_updater_SOURCE_FILES linux_updater.cpp)
|
||||
|
||||
set(linux_updater_HEADER_FILES CMakeLists.txt)
|
||||
|
||||
set_source_files_properties(${linux_updater_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILES_ONLY TRUE)
|
||||
|
||||
list(APPEND linux_updater_SOURCE_FILES ${linux_updater_HEADER_FILES})
|
||||
|
||||
add_executable(linux-updater ${linux_updater_SOURCE_FILES})
|
||||
|
||||
target_link_libraries(linux-updater
|
||||
${CURL_LIBRARIES}
|
||||
${CARES_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CRYPTO_LIBRARIES}
|
||||
${UI_LIBRARIES}
|
||||
${LLXML_LIBRARIES}
|
||||
${LLXUIXML_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT linux-updater-stripped
|
||||
COMMAND strip
|
||||
ARGS --strip-debug -o linux-updater-stripped linux-updater
|
||||
DEPENDS linux-updater
|
||||
)
|
||||
|
||||
add_custom_target(linux-updater-strip-target ALL
|
||||
DEPENDS linux-updater-stripped)
|
||||
|
|
@ -0,0 +1,818 @@
|
|||
/**
|
||||
* @file linux_updater.cpp
|
||||
* @author Kyle Ambroff <ambroff@lindenlab.com>, Tofu Linden
|
||||
* @brief Viewer update program for unix platforms that support GTK+
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2008, 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 <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llerrorcontrol.h"
|
||||
#include "llfile.h"
|
||||
#include "lldir.h"
|
||||
#include "llxmlnode.h"
|
||||
#include "lltrans.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
extern "C" {
|
||||
#include <gtk/gtk.h>
|
||||
}
|
||||
|
||||
const guint UPDATE_PROGRESS_TIMEOUT = 100;
|
||||
const guint UPDATE_PROGRESS_TEXT_TIMEOUT = 1000;
|
||||
const guint ROTATE_IMAGE_TIMEOUT = 8000;
|
||||
|
||||
typedef struct _updater_app_state {
|
||||
std::string app_name;
|
||||
std::string url;
|
||||
std::string image_dir;
|
||||
std::string dest_dir;
|
||||
std::string strings_dirs;
|
||||
std::string strings_file;
|
||||
|
||||
GtkWidget *window;
|
||||
GtkWidget *progress_bar;
|
||||
GtkWidget *image;
|
||||
|
||||
double progress_value;
|
||||
bool activity_mode;
|
||||
|
||||
guint image_rotation_timeout_id;
|
||||
guint progress_update_timeout_id;
|
||||
guint update_progress_text_timeout_id;
|
||||
|
||||
bool failure;
|
||||
} UpdaterAppState;
|
||||
|
||||
// List of entries from strings.xml to always replace
|
||||
static std::set<std::string> default_trans_args;
|
||||
void init_default_trans_args()
|
||||
{
|
||||
default_trans_args.insert("SECOND_LIFE"); // World
|
||||
default_trans_args.insert("SECOND_LIFE_VIEWER");
|
||||
default_trans_args.insert("SECOND_LIFE_GRID");
|
||||
default_trans_args.insert("SECOND_LIFE_SUPPORT");
|
||||
}
|
||||
|
||||
bool translate_init(std::string comma_delim_path_list,
|
||||
std::string base_xml_name)
|
||||
{
|
||||
init_default_trans_args();
|
||||
|
||||
// extract paths string vector from comma-delimited flat string
|
||||
std::vector<std::string> paths;
|
||||
LLStringUtil::getTokens(comma_delim_path_list, paths); // split over ','
|
||||
|
||||
// suck the translation xml files into memory
|
||||
LLXMLNodePtr root;
|
||||
bool success = LLXMLNode::getLayeredXMLNode(base_xml_name, root, paths);
|
||||
if (!success)
|
||||
{
|
||||
// couldn't load string table XML
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get those strings out of the XML
|
||||
LLTrans::parseStrings(root, default_trans_args);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void updater_app_ui_init(void);
|
||||
void updater_app_quit(UpdaterAppState *app_state);
|
||||
void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state);
|
||||
std::string next_image_filename(std::string& image_path);
|
||||
void display_error(GtkWidget *parent, std::string title, std::string message);
|
||||
BOOL install_package(std::string package_file, std::string destination);
|
||||
BOOL spawn_viewer(UpdaterAppState *app_state);
|
||||
|
||||
extern "C" {
|
||||
void on_window_closed(GtkWidget *sender, gpointer state);
|
||||
gpointer worker_thread_cb(gpointer *data);
|
||||
int download_progress_cb(gpointer data, double t, double d, double utotal, double ulnow);
|
||||
gboolean rotate_image_cb(gpointer data);
|
||||
gboolean progress_update_timeout(gpointer data);
|
||||
gboolean update_progress_text_timeout(gpointer data);
|
||||
}
|
||||
|
||||
void updater_app_ui_init(UpdaterAppState *app_state)
|
||||
{
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *summary_label;
|
||||
GtkWidget *description_label;
|
||||
GtkWidget *frame;
|
||||
|
||||
llassert(app_state != NULL);
|
||||
|
||||
// set up window and main container
|
||||
std::string window_title = LLTrans::getString("UpdaterWindowTitle");
|
||||
app_state->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title(GTK_WINDOW(app_state->window),
|
||||
window_title.c_str());
|
||||
gtk_window_set_resizable(GTK_WINDOW(app_state->window), FALSE);
|
||||
gtk_window_set_position(GTK_WINDOW(app_state->window),
|
||||
GTK_WIN_POS_CENTER_ALWAYS);
|
||||
|
||||
gtk_container_set_border_width(GTK_CONTAINER(app_state->window), 12);
|
||||
g_signal_connect(G_OBJECT(app_state->window), "delete-event",
|
||||
G_CALLBACK(on_window_closed), app_state);
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 6);
|
||||
gtk_container_add(GTK_CONTAINER(app_state->window), vbox);
|
||||
|
||||
// set top label
|
||||
std::ostringstream label_ostr;
|
||||
label_ostr << "<big><b>"
|
||||
<< LLTrans::getString("UpdaterNowUpdating")
|
||||
<< "</b></big>";
|
||||
|
||||
summary_label = gtk_label_new(NULL);
|
||||
gtk_label_set_use_markup(GTK_LABEL(summary_label), TRUE);
|
||||
gtk_label_set_markup(GTK_LABEL(summary_label),
|
||||
label_ostr.str().c_str());
|
||||
gtk_misc_set_alignment(GTK_MISC(summary_label), 0, 0.5);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), summary_label, FALSE, FALSE, 0);
|
||||
|
||||
// create the description label
|
||||
description_label = gtk_label_new(LLTrans::getString("UpdaterUpdatingDescriptive").c_str());
|
||||
gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE);
|
||||
gtk_misc_set_alignment(GTK_MISC(description_label), 0, 0.5);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), description_label, FALSE, FALSE, 0);
|
||||
|
||||
// If an image path has been set, load the background images
|
||||
if (!app_state->image_dir.empty()) {
|
||||
frame = gtk_frame_new(NULL);
|
||||
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
|
||||
|
||||
// load the first image
|
||||
app_state->image = gtk_image_new_from_file
|
||||
(next_image_filename(app_state->image_dir).c_str());
|
||||
gtk_widget_set_size_request(app_state->image, 340, 310);
|
||||
gtk_container_add(GTK_CONTAINER(frame), app_state->image);
|
||||
|
||||
// rotate the images every 5 seconds
|
||||
app_state->image_rotation_timeout_id = g_timeout_add
|
||||
(ROTATE_IMAGE_TIMEOUT, rotate_image_cb, app_state);
|
||||
}
|
||||
|
||||
// set up progress bar, and update it roughly every 1/10 of a second
|
||||
app_state->progress_bar = gtk_progress_bar_new();
|
||||
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar),
|
||||
LLTrans::getString("UpdaterProgressBarTextWithEllipses").c_str());
|
||||
gtk_box_pack_start(GTK_BOX(vbox),
|
||||
app_state->progress_bar, FALSE, TRUE, 0);
|
||||
app_state->progress_update_timeout_id = g_timeout_add
|
||||
(UPDATE_PROGRESS_TIMEOUT, progress_update_timeout, app_state);
|
||||
app_state->update_progress_text_timeout_id = g_timeout_add
|
||||
(UPDATE_PROGRESS_TEXT_TIMEOUT, update_progress_text_timeout, app_state);
|
||||
|
||||
gtk_widget_show_all(app_state->window);
|
||||
}
|
||||
|
||||
gboolean rotate_image_cb(gpointer data)
|
||||
{
|
||||
UpdaterAppState *app_state;
|
||||
std::string filename;
|
||||
|
||||
llassert(data != NULL);
|
||||
app_state = (UpdaterAppState *) data;
|
||||
|
||||
filename = next_image_filename(app_state->image_dir);
|
||||
|
||||
gdk_threads_enter();
|
||||
gtk_image_set_from_file(GTK_IMAGE(app_state->image), filename.c_str());
|
||||
gdk_threads_leave();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
std::string next_image_filename(std::string& image_path)
|
||||
{
|
||||
std::string image_filename;
|
||||
gDirUtilp->getNextFileInDir(image_path, "/*.jpg", image_filename, true);
|
||||
return image_path + "/" + image_filename;
|
||||
}
|
||||
|
||||
void on_window_closed(GtkWidget *sender, gpointer data)
|
||||
{
|
||||
UpdaterAppState *app_state;
|
||||
|
||||
llassert(data != NULL);
|
||||
app_state = (UpdaterAppState *) data;
|
||||
|
||||
updater_app_quit(app_state);
|
||||
}
|
||||
|
||||
void updater_app_quit(UpdaterAppState *app_state)
|
||||
{
|
||||
if (app_state != NULL)
|
||||
{
|
||||
g_source_remove(app_state->progress_update_timeout_id);
|
||||
|
||||
if (!app_state->image_dir.empty())
|
||||
{
|
||||
g_source_remove(app_state->image_rotation_timeout_id);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
void display_error(GtkWidget *parent, std::string title, std::string message)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_message_dialog_new(GTK_WINDOW(parent),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
"%s", message.c_str());
|
||||
gtk_window_set_title(GTK_WINDOW(dialog), title.c_str());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
gpointer worker_thread_cb(gpointer data)
|
||||
{
|
||||
UpdaterAppState *app_state;
|
||||
CURL *curl;
|
||||
CURLcode result;
|
||||
FILE *package_file;
|
||||
GError *error = NULL;
|
||||
char *tmp_filename = NULL;
|
||||
int fd;
|
||||
|
||||
//g_return_val_if_fail (data != NULL, NULL);
|
||||
app_state = (UpdaterAppState *) data;
|
||||
|
||||
try {
|
||||
// create temporary file to store the package.
|
||||
fd = g_file_open_tmp
|
||||
("secondlife-update-XXXXXX", &tmp_filename, &error);
|
||||
if (error != NULL)
|
||||
{
|
||||
llerrs << "Unable to create temporary file: "
|
||||
<< error->message
|
||||
<< llendl;
|
||||
|
||||
g_error_free(error);
|
||||
throw 0;
|
||||
}
|
||||
|
||||
package_file = fdopen(fd, "wb");
|
||||
if (package_file == NULL)
|
||||
{
|
||||
llerrs << "Failed to create temporary file: "
|
||||
<< tmp_filename
|
||||
<< llendl;
|
||||
|
||||
gdk_threads_enter();
|
||||
display_error(app_state->window,
|
||||
LLTrans::getString("UpdaterFailDownloadTitle"),
|
||||
LLTrans::getString("UpdaterFailUpdateDescriptive"));
|
||||
gdk_threads_leave();
|
||||
throw 0;
|
||||
}
|
||||
|
||||
// initialize curl and start downloading the package
|
||||
llinfos << "Downloading package: " << app_state->url << llendl;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if (curl == NULL)
|
||||
{
|
||||
llerrs << "Failed to initialize libcurl" << llendl;
|
||||
|
||||
gdk_threads_enter();
|
||||
display_error(app_state->window,
|
||||
LLTrans::getString("UpdaterFailDownloadTitle"),
|
||||
LLTrans::getString("UpdaterFailUpdateDescriptive"));
|
||||
gdk_threads_leave();
|
||||
throw 0;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
|
||||
&download_progress_cb);
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state);
|
||||
|
||||
result = curl_easy_perform(curl);
|
||||
fclose(package_file);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (result)
|
||||
{
|
||||
llerrs << "Failed to download update: "
|
||||
<< app_state->url
|
||||
<< llendl;
|
||||
|
||||
gdk_threads_enter();
|
||||
display_error(app_state->window,
|
||||
LLTrans::getString("UpdaterFailDownloadTitle"),
|
||||
LLTrans::getString("UpdaterFailUpdateDescriptive"));
|
||||
gdk_threads_leave();
|
||||
|
||||
throw 0;
|
||||
}
|
||||
|
||||
// now pulse the progres bar back and forth while the package is
|
||||
// being unpacked
|
||||
gdk_threads_enter();
|
||||
std::string installing_msg = LLTrans::getString("UpdaterNowInstalling");
|
||||
gtk_progress_bar_set_text(
|
||||
GTK_PROGRESS_BAR(app_state->progress_bar),
|
||||
installing_msg.c_str());
|
||||
app_state->activity_mode = TRUE;
|
||||
gdk_threads_leave();
|
||||
|
||||
// *TODO: if the destination is not writable, terminate this
|
||||
// thread and show file chooser?
|
||||
if (!install_package(tmp_filename, app_state->dest_dir))
|
||||
{
|
||||
llwarns << "Failed to install package to destination: "
|
||||
<< app_state->dest_dir
|
||||
<< llendl;
|
||||
|
||||
gdk_threads_enter();
|
||||
display_error(app_state->window,
|
||||
LLTrans::getString("UpdaterFailInstallTitle"),
|
||||
LLTrans::getString("UpdaterFailUpdateDescriptive"));
|
||||
//"Failed to update " + app_state->app_name,
|
||||
gdk_threads_leave();
|
||||
throw 0;
|
||||
}
|
||||
|
||||
// try to spawn the new viewer
|
||||
if (!spawn_viewer(app_state))
|
||||
{
|
||||
llwarns << "Viewer was not installed properly in : "
|
||||
<< app_state->dest_dir
|
||||
<< llendl;
|
||||
|
||||
gdk_threads_enter();
|
||||
display_error(app_state->window,
|
||||
LLTrans::getString("UpdaterFailStartTitle"),
|
||||
LLTrans::getString("UpdaterFailUpdateDescriptive"));
|
||||
gdk_threads_leave();
|
||||
throw 0;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
app_state->failure = TRUE;
|
||||
}
|
||||
|
||||
// FIXME: delete package file also if delete-event is raised on window
|
||||
if (tmp_filename != NULL)
|
||||
{
|
||||
if (gDirUtilp->fileExists(tmp_filename))
|
||||
{
|
||||
LLFile::remove(tmp_filename);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_threads_enter();
|
||||
updater_app_quit(app_state);
|
||||
gdk_threads_leave();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
gboolean less_anal_gspawnsync(gchar **argv,
|
||||
gchar **stderr_output,
|
||||
gint *child_exit_status,
|
||||
GError **spawn_error)
|
||||
{
|
||||
// store current SIGCHLD handler if there is one, replace with default
|
||||
// handler to make glib happy
|
||||
struct sigaction sigchld_backup;
|
||||
struct sigaction sigchld_appease_glib;
|
||||
sigchld_appease_glib.sa_handler = SIG_DFL;
|
||||
sigemptyset(&sigchld_appease_glib.sa_mask);
|
||||
sigchld_appease_glib.sa_flags = 0;
|
||||
sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup);
|
||||
|
||||
gboolean rtn = g_spawn_sync(NULL,
|
||||
argv,
|
||||
NULL,
|
||||
(GSpawnFlags) (G_SPAWN_STDOUT_TO_DEV_NULL),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
stderr_output,
|
||||
child_exit_status,
|
||||
spawn_error);
|
||||
|
||||
// restore SIGCHLD handler
|
||||
sigaction(SIGCHLD, &sigchld_backup, NULL);
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
// perform a rename, or perform a (prompted) root rename if that fails
|
||||
int
|
||||
rename_with_sudo_fallback(const std::string& filename, const std::string& newname)
|
||||
{
|
||||
int rtncode = ::rename(filename.c_str(), newname.c_str());
|
||||
lldebugs << "rename result is: " << rtncode << " / " << errno << llendl;
|
||||
if (rtncode && (EACCES == errno || EPERM == errno || EXDEV == errno))
|
||||
{
|
||||
llinfos << "Permission problem in rename, or moving between different mount points. Retrying as a mv under a sudo." << llendl;
|
||||
// failed due to permissions, try again as a gksudo or kdesu mv wrapper hack
|
||||
char *sudo_cmd = NULL;
|
||||
sudo_cmd = g_find_program_in_path("gksudo");
|
||||
if (!sudo_cmd)
|
||||
{
|
||||
sudo_cmd = g_find_program_in_path("kdesu");
|
||||
}
|
||||
if (sudo_cmd)
|
||||
{
|
||||
char *mv_cmd = NULL;
|
||||
mv_cmd = g_find_program_in_path("mv");
|
||||
if (mv_cmd)
|
||||
{
|
||||
char *src_string_copy = g_strdup(filename.c_str());
|
||||
char *dst_string_copy = g_strdup(newname.c_str());
|
||||
char* argv[] =
|
||||
{
|
||||
sudo_cmd,
|
||||
mv_cmd,
|
||||
src_string_copy,
|
||||
dst_string_copy,
|
||||
NULL
|
||||
};
|
||||
|
||||
gchar *stderr_output = NULL;
|
||||
gint child_exit_status = 0;
|
||||
GError *spawn_error = NULL;
|
||||
if (!less_anal_gspawnsync(argv, &stderr_output,
|
||||
&child_exit_status, &spawn_error))
|
||||
{
|
||||
llwarns << "Failed to spawn child process: "
|
||||
<< spawn_error->message
|
||||
<< llendl;
|
||||
}
|
||||
else if (child_exit_status)
|
||||
{
|
||||
llwarns << "mv command failed: "
|
||||
<< (stderr_output ? stderr_output : "(no reason given)")
|
||||
<< llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// everything looks good, clear the error code
|
||||
rtncode = 0;
|
||||
}
|
||||
|
||||
g_free(src_string_copy);
|
||||
g_free(dst_string_copy);
|
||||
if (spawn_error) g_error_free(spawn_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rtncode;
|
||||
}
|
||||
|
||||
gboolean install_package(std::string package_file, std::string destination)
|
||||
{
|
||||
char *tar_cmd = NULL;
|
||||
std::ostringstream command;
|
||||
|
||||
// Find the absolute path to the 'tar' command.
|
||||
tar_cmd = g_find_program_in_path("tar");
|
||||
if (!tar_cmd)
|
||||
{
|
||||
llerrs << "`tar' was not found in $PATH" << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
llinfos << "Found tar command: " << tar_cmd << llendl;
|
||||
|
||||
// Unpack the tarball in a temporary place first, then move it to
|
||||
// its final destination
|
||||
std::string tmp_dest_dir = gDirUtilp->getTempFilename();
|
||||
if (LLFile::mkdir(tmp_dest_dir, 0744))
|
||||
{
|
||||
llerrs << "Failed to create directory: "
|
||||
<< destination
|
||||
<< llendl;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char *package_file_string_copy = g_strdup(package_file.c_str());
|
||||
char *tmp_dest_dir_string_copy = g_strdup(tmp_dest_dir.c_str());
|
||||
gchar *argv[8] = {
|
||||
tar_cmd,
|
||||
const_cast<gchar*>("--strip"), const_cast<gchar*>("1"),
|
||||
const_cast<gchar*>("-xjf"),
|
||||
package_file_string_copy,
|
||||
const_cast<gchar*>("-C"), tmp_dest_dir_string_copy,
|
||||
NULL,
|
||||
};
|
||||
|
||||
llinfos << "Untarring package: " << package_file << llendl;
|
||||
|
||||
// store current SIGCHLD handler if there is one, replace with default
|
||||
// handler to make glib happy
|
||||
struct sigaction sigchld_backup;
|
||||
struct sigaction sigchld_appease_glib;
|
||||
sigchld_appease_glib.sa_handler = SIG_DFL;
|
||||
sigemptyset(&sigchld_appease_glib.sa_mask);
|
||||
sigchld_appease_glib.sa_flags = 0;
|
||||
sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup);
|
||||
|
||||
gchar *stderr_output = NULL;
|
||||
gint child_exit_status = 0;
|
||||
GError *untar_error = NULL;
|
||||
if (!less_anal_gspawnsync(argv, &stderr_output,
|
||||
&child_exit_status, &untar_error))
|
||||
{
|
||||
llwarns << "Failed to spawn child process: "
|
||||
<< untar_error->message
|
||||
<< llendl;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (child_exit_status)
|
||||
{
|
||||
llwarns << "Untar command failed: "
|
||||
<< (stderr_output ? stderr_output : "(no reason given)")
|
||||
<< llendl;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_free(tar_cmd);
|
||||
g_free(package_file_string_copy);
|
||||
g_free(tmp_dest_dir_string_copy);
|
||||
g_free(stderr_output);
|
||||
if (untar_error) g_error_free(untar_error);
|
||||
|
||||
// move the existing package out of the way if it exists
|
||||
if (gDirUtilp->fileExists(destination))
|
||||
{
|
||||
std::string backup_dir = destination + ".backup";
|
||||
int oldcounter = 1;
|
||||
while (gDirUtilp->fileExists(backup_dir))
|
||||
{
|
||||
// find a foo.backup.N folder name that isn't taken yet
|
||||
backup_dir = destination + ".backup." + llformat("%d", oldcounter);
|
||||
++oldcounter;
|
||||
}
|
||||
|
||||
if (rename_with_sudo_fallback(destination, backup_dir))
|
||||
{
|
||||
llwarns << "Failed to move directory: '"
|
||||
<< destination << "' -> '" << backup_dir
|
||||
<< llendl;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// The package has been unpacked in a staging directory, now we just
|
||||
// need to move it to its destination.
|
||||
if (rename_with_sudo_fallback(tmp_dest_dir, destination))
|
||||
{
|
||||
llwarns << "Failed to move installation to the destination: "
|
||||
<< destination
|
||||
<< llendl;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// \0/ Success!
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean progress_update_timeout(gpointer data)
|
||||
{
|
||||
UpdaterAppState *app_state;
|
||||
|
||||
llassert(data != NULL);
|
||||
|
||||
app_state = (UpdaterAppState *) data;
|
||||
|
||||
gdk_threads_enter();
|
||||
if (app_state->activity_mode)
|
||||
{
|
||||
gtk_progress_bar_pulse
|
||||
(GTK_PROGRESS_BAR(app_state->progress_bar));
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_progress_set_value(GTK_PROGRESS(app_state->progress_bar),
|
||||
app_state->progress_value);
|
||||
}
|
||||
gdk_threads_leave();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean update_progress_text_timeout(gpointer data)
|
||||
{
|
||||
UpdaterAppState *app_state;
|
||||
|
||||
llassert(data != NULL);
|
||||
app_state = (UpdaterAppState *) data;
|
||||
|
||||
if (app_state->activity_mode == TRUE)
|
||||
{
|
||||
// We no longer need this timeout, it will be removed.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!app_state->progress_value)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
std::string progress_text = llformat((LLTrans::getString("UpdaterProgressBarText")+" (%.0f%%)").c_str(), app_state->progress_value);
|
||||
|
||||
gdk_threads_enter();
|
||||
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar),
|
||||
progress_text.c_str());
|
||||
gdk_threads_leave();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int download_progress_cb(gpointer data,
|
||||
double t,
|
||||
double d,
|
||||
double utotal,
|
||||
double ulnow)
|
||||
{
|
||||
UpdaterAppState *app_state;
|
||||
|
||||
llassert(data != NULL);
|
||||
app_state = (UpdaterAppState *) data;
|
||||
|
||||
if (t <= 0.0)
|
||||
{
|
||||
app_state->progress_value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
app_state->progress_value = d * 100.0 / t;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL spawn_viewer(UpdaterAppState *app_state)
|
||||
{
|
||||
llassert(app_state != NULL);
|
||||
|
||||
std::string cmd = app_state->dest_dir + "/secondlife";
|
||||
GError *error = NULL;
|
||||
|
||||
// We want to spawn the Viewer on the same display as the updater app
|
||||
gboolean success = gdk_spawn_command_line_on_screen
|
||||
(gtk_widget_get_screen(app_state->window), cmd.c_str(), &error);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
llwarns << "Failed to launch viewer: " << error->message
|
||||
<< llendl;
|
||||
}
|
||||
|
||||
if (error) g_error_free(error);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void show_usage_and_exit()
|
||||
{
|
||||
std::cout << "Usage: linux-updater --url URL --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE"
|
||||
<< "[--image-dir PATH]"
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if ((!strcmp(argv[i], "--url")) && (++i < argc))
|
||||
{
|
||||
app_state->url = argv[i];
|
||||
}
|
||||
else if ((!strcmp(argv[i], "--name")) && (++i < argc))
|
||||
{
|
||||
app_state->app_name = argv[i];
|
||||
}
|
||||
else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc))
|
||||
{
|
||||
app_state->image_dir = argv[i];
|
||||
}
|
||||
else if ((!strcmp(argv[i], "--dest")) && (++i < argc))
|
||||
{
|
||||
app_state->dest_dir = argv[i];
|
||||
}
|
||||
else if ((!strcmp(argv[i], "--stringsdir")) && (++i < argc))
|
||||
{
|
||||
app_state->strings_dirs = argv[i];
|
||||
}
|
||||
else if ((!strcmp(argv[i], "--stringsfile")) && (++i < argc))
|
||||
{
|
||||
app_state->strings_file = argv[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
// show usage, an invalid option was given.
|
||||
show_usage_and_exit();
|
||||
}
|
||||
}
|
||||
|
||||
if (app_state->app_name.empty()
|
||||
|| app_state->url.empty()
|
||||
|| app_state->dest_dir.empty())
|
||||
{
|
||||
show_usage_and_exit();
|
||||
}
|
||||
|
||||
app_state->progress_value = 0.0;
|
||||
app_state->activity_mode = FALSE;
|
||||
app_state->failure = FALSE;
|
||||
|
||||
translate_init(app_state->strings_dirs, app_state->strings_file);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
UpdaterAppState app_state;
|
||||
GThread *worker_thread;
|
||||
|
||||
parse_args_and_init(argc, argv, &app_state);
|
||||
|
||||
// Initialize logger, and rename old log file
|
||||
gDirUtilp->initAppDirs("SecondLife");
|
||||
LLError::initForApplication
|
||||
(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
|
||||
std::string old_log_file = gDirUtilp->getExpandedFilename
|
||||
(LL_PATH_LOGS, "updater.log.old");
|
||||
std::string log_file =
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log");
|
||||
LLFile::rename(log_file, old_log_file);
|
||||
LLError::logToFile(log_file);
|
||||
|
||||
// initialize gthreads and gtk+
|
||||
if (!g_thread_supported())
|
||||
{
|
||||
g_thread_init(NULL);
|
||||
gdk_threads_init();
|
||||
}
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// create UI
|
||||
updater_app_ui_init(&app_state);
|
||||
|
||||
//llinfos << "SAMPLE TRANSLATION IS: " << LLTrans::getString("LoginInProgress") << llendl;
|
||||
|
||||
// create download thread
|
||||
worker_thread = g_thread_create
|
||||
(GThreadFunc(worker_thread_cb), &app_state, FALSE, NULL);
|
||||
|
||||
gdk_threads_enter();
|
||||
gtk_main();
|
||||
gdk_threads_leave();
|
||||
|
||||
return (app_state.failure == FALSE) ? 0 : 1;
|
||||
}
|
||||
|
|
@ -4,15 +4,16 @@ project(llaudio)
|
|||
|
||||
include(00-Common)
|
||||
include(Audio)
|
||||
include(LLAudio)
|
||||
include(FMOD)
|
||||
include(OPENAL)
|
||||
include(LLCommon)
|
||||
include(LLMath)
|
||||
include(LLMessage)
|
||||
include(LLVFS)
|
||||
include(LLMedia)
|
||||
|
||||
include_directories(
|
||||
${LLAUDIO_INCLUDE_DIRS}
|
||||
${FMOD_INCLUDE_DIR}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
|
|
@ -24,42 +25,43 @@ include_directories(
|
|||
${VORBIS_INCLUDE_DIRS}
|
||||
${OPENAL_LIB_INCLUDE_DIRS}
|
||||
${FREEAULT_LIB_INCLUDE_DIRS}
|
||||
${LLMEDIA_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(llaudio_SOURCE_FILES
|
||||
audioengine.cpp
|
||||
listener.cpp
|
||||
llaudioengine.cpp
|
||||
lllistener.cpp
|
||||
llaudiodecodemgr.cpp
|
||||
vorbisdecode.cpp
|
||||
vorbisencode.cpp
|
||||
llvorbisdecode.cpp
|
||||
llvorbisencode.cpp
|
||||
)
|
||||
|
||||
set(llaudio_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
audioengine.h
|
||||
listener.h
|
||||
llaudioengine.h
|
||||
lllistener.h
|
||||
llaudiodecodemgr.h
|
||||
vorbisdecode.h
|
||||
vorbisencode.h
|
||||
windgen.h
|
||||
llvorbisdecode.h
|
||||
llvorbisencode.h
|
||||
llwindgen.h
|
||||
)
|
||||
|
||||
if (FMOD)
|
||||
list(APPEND llaudio_SOURCE_FILES
|
||||
audioengine_fmod.cpp
|
||||
listener_fmod.cpp
|
||||
llaudioengine_fmod.cpp
|
||||
lllistener_fmod.cpp
|
||||
llstreamingaudio_fmod.cpp
|
||||
)
|
||||
|
||||
list(APPEND llaudio_HEADER_FILES
|
||||
audioengine_fmod.h
|
||||
listener_fmod.h
|
||||
llaudioengine_fmod.h
|
||||
lllistener_fmod.h
|
||||
llstreamingaudio_fmod.h
|
||||
)
|
||||
|
||||
if (LINUX)
|
||||
if (${CXX_VERSION} MATCHES "4.[23]")
|
||||
set_source_files_properties(audioengine_fmod.cpp
|
||||
set_source_files_properties(llaudioengine_fmod.cpp
|
||||
COMPILE_FLAGS -Wno-error=write-strings)
|
||||
endif (${CXX_VERSION} MATCHES "4.[23]")
|
||||
endif (LINUX)
|
||||
|
|
@ -67,13 +69,13 @@ endif (FMOD)
|
|||
|
||||
if (OPENAL)
|
||||
list(APPEND llaudio_SOURCE_FILES
|
||||
audioengine_openal.cpp
|
||||
listener_openal.cpp
|
||||
llaudioengine_openal.cpp
|
||||
lllistener_openal.cpp
|
||||
)
|
||||
|
||||
list(APPEND llaudio_HEADER_FILES
|
||||
audioengine_openal.h
|
||||
listener_openal.h
|
||||
llaudioengine_openal.h
|
||||
lllistener_openal.h
|
||||
)
|
||||
endif (OPENAL)
|
||||
|
||||
|
|
|
|||
|
|
@ -33,15 +33,15 @@
|
|||
|
||||
#include "llaudiodecodemgr.h"
|
||||
|
||||
#include "vorbisdecode.h"
|
||||
#include "audioengine.h"
|
||||
#include "llvorbisdecode.h"
|
||||
#include "llaudioengine.h"
|
||||
#include "lllfsthread.h"
|
||||
#include "llvfile.h"
|
||||
#include "llstring.h"
|
||||
#include "lldir.h"
|
||||
#include "llendianswizzle.h"
|
||||
#include "audioengine.h"
|
||||
#include "llassetstorage.h"
|
||||
#include "llrefcount.h"
|
||||
|
||||
#include "vorbis/codec.h"
|
||||
#include "vorbis/vorbisfile.h"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,452 @@
|
|||
/**
|
||||
* @file audioengine.h
|
||||
* @brief Definition of LLAudioEngine base class abstracting the audio support
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-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_H
|
||||
#define LL_AUDIOENGINE_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "v3math.h"
|
||||
#include "v3dmath.h"
|
||||
#include "lltimer.h"
|
||||
#include "lluuid.h"
|
||||
#include "llframetimer.h"
|
||||
#include "llassettype.h"
|
||||
|
||||
#include "lllistener.h"
|
||||
|
||||
const F32 LL_WIND_UPDATE_INTERVAL = 0.1f;
|
||||
const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water
|
||||
const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f;
|
||||
|
||||
const F32 ATTACHED_OBJECT_TIMEOUT = 5.0f;
|
||||
const F32 DEFAULT_MIN_DISTANCE = 2.0f;
|
||||
|
||||
#define MAX_CHANNELS 30
|
||||
#define MAX_BUFFERS 40 // Some extra for preloading, maybe?
|
||||
|
||||
// This define is intended to allow us to switch from os based wav
|
||||
// file loading to vfs based wav file loading. The problem is that I
|
||||
// am unconvinced that the LLWaveFile works for loading sounds from
|
||||
// memory. So, until that is fixed up, changed, whatever, this remains
|
||||
// undefined.
|
||||
//#define USE_WAV_VFILE
|
||||
|
||||
class LLVFS;
|
||||
|
||||
class LLAudioSource;
|
||||
class LLAudioData;
|
||||
class LLAudioChannel;
|
||||
class LLAudioChannelOpenAL;
|
||||
class LLAudioBuffer;
|
||||
class LLStreamingAudioInterface;
|
||||
|
||||
|
||||
//
|
||||
// LLAudioEngine definition
|
||||
//
|
||||
|
||||
class LLAudioEngine
|
||||
{
|
||||
friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods.
|
||||
|
||||
public:
|
||||
enum LLAudioType
|
||||
{
|
||||
AUDIO_TYPE_NONE = 0,
|
||||
AUDIO_TYPE_SFX = 1,
|
||||
AUDIO_TYPE_UI = 2,
|
||||
AUDIO_TYPE_AMBIENT = 3,
|
||||
AUDIO_TYPE_COUNT = 4 // last
|
||||
};
|
||||
|
||||
LLAudioEngine();
|
||||
virtual ~LLAudioEngine();
|
||||
|
||||
// initialization/startup/shutdown
|
||||
virtual bool init(const S32 num_channels, void *userdata);
|
||||
virtual std::string getDriverName(bool verbose) = 0;
|
||||
virtual void shutdown();
|
||||
|
||||
// Used by the mechanics of the engine
|
||||
//virtual void processQueue(const LLUUID &sound_guid);
|
||||
virtual void setListener(LLVector3 pos,LLVector3 vel,LLVector3 up,LLVector3 at);
|
||||
virtual void updateWind(LLVector3 direction, F32 camera_height_above_water) = 0;
|
||||
virtual void idle(F32 max_decode_time = 0.f);
|
||||
virtual void updateChannels();
|
||||
|
||||
//
|
||||
// "End user" functionality
|
||||
//
|
||||
virtual bool isWindEnabled();
|
||||
virtual void enableWind(bool state_b);
|
||||
|
||||
// Use these for temporarily muting the audio system.
|
||||
// Does not change buffers, initialization, etc. but
|
||||
// stops playing new sounds.
|
||||
virtual void setMuted(bool muted);
|
||||
virtual bool getMuted() const { return mMuted; }
|
||||
#ifdef USE_PLUGIN_MEDIA
|
||||
LLPluginClassMedia* initializeMedia(const std::string& media_type);
|
||||
#endif
|
||||
F32 getMasterGain();
|
||||
void setMasterGain(F32 gain);
|
||||
|
||||
F32 getSecondaryGain(S32 type);
|
||||
void setSecondaryGain(S32 type, F32 gain);
|
||||
|
||||
F32 getInternetStreamGain();
|
||||
|
||||
virtual void setDopplerFactor(F32 factor);
|
||||
virtual F32 getDopplerFactor();
|
||||
virtual void setRolloffFactor(F32 factor);
|
||||
virtual F32 getRolloffFactor();
|
||||
virtual void setMaxWindGain(F32 gain);
|
||||
|
||||
|
||||
// Methods actually related to setting up and removing sounds
|
||||
// Owner ID is the owner of the object making the request
|
||||
void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain,
|
||||
const S32 type = LLAudioEngine::AUDIO_TYPE_NONE,
|
||||
const LLVector3d &pos_global = LLVector3d::zero);
|
||||
bool preloadSound(const LLUUID &id);
|
||||
|
||||
void addAudioSource(LLAudioSource *asp);
|
||||
void cleanupAudioSource(LLAudioSource *asp);
|
||||
|
||||
LLAudioSource *findAudioSource(const LLUUID &source_id);
|
||||
LLAudioData *getAudioData(const LLUUID &audio_uuid);
|
||||
|
||||
// Internet stream implementation manipulation
|
||||
LLStreamingAudioInterface *getStreamingAudioImpl();
|
||||
void setStreamingAudioImpl(LLStreamingAudioInterface *impl);
|
||||
// Internet stream methods - these will call down into the *mStreamingAudioImpl if it exists
|
||||
void startInternetStream(const std::string& url);
|
||||
void stopInternetStream();
|
||||
void pauseInternetStream(int pause);
|
||||
void updateInternetStream(); // expected to be called often
|
||||
int isInternetStreamPlaying();
|
||||
// use a value from 0.0 to 1.0, inclusive
|
||||
void setInternetStreamGain(F32 vol);
|
||||
std::string getInternetStreamURL();
|
||||
|
||||
// For debugging usage
|
||||
virtual LLVector3 getListenerPos();
|
||||
|
||||
LLAudioBuffer *getFreeBuffer(); // Get a free buffer, or flush an existing one if you have to.
|
||||
LLAudioChannel *getFreeChannel(const F32 priority); // Get a free channel or flush an existing one if your priority is higher
|
||||
void cleanupBuffer(LLAudioBuffer *bufferp);
|
||||
|
||||
bool hasDecodedFile(const LLUUID &uuid);
|
||||
bool hasLocalFile(const LLUUID &uuid);
|
||||
|
||||
bool updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid = LLUUID::null);
|
||||
|
||||
|
||||
// Asset callback when we're retrieved a sound from the asset server.
|
||||
void startNextTransfer();
|
||||
static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status);
|
||||
|
||||
friend class LLPipeline; // For debugging
|
||||
public:
|
||||
F32 mMaxWindGain; // Hack. Public to set before fade in?
|
||||
|
||||
protected:
|
||||
virtual LLAudioBuffer *createBuffer() = 0;
|
||||
virtual LLAudioChannel *createChannel() = 0;
|
||||
|
||||
virtual void initWind() = 0;
|
||||
virtual void cleanupWind() = 0;
|
||||
virtual void setInternalGain(F32 gain) = 0;
|
||||
|
||||
void commitDeferredChanges();
|
||||
|
||||
virtual void allocateListener() = 0;
|
||||
|
||||
|
||||
// listener methods
|
||||
virtual void setListenerPos(LLVector3 vec);
|
||||
virtual void setListenerVelocity(LLVector3 vec);
|
||||
virtual void orientListener(LLVector3 up, LLVector3 at);
|
||||
virtual void translateListener(LLVector3 vec);
|
||||
|
||||
|
||||
F64 mapWindVecToGain(LLVector3 wind_vec);
|
||||
F64 mapWindVecToPitch(LLVector3 wind_vec);
|
||||
F64 mapWindVecToPan(LLVector3 wind_vec);
|
||||
|
||||
protected:
|
||||
LLListener *mListenerp;
|
||||
|
||||
bool mMuted;
|
||||
void* mUserData;
|
||||
|
||||
S32 mLastStatus;
|
||||
|
||||
S32 mNumChannels;
|
||||
bool mEnableWind;
|
||||
|
||||
LLUUID mCurrentTransfer; // Audio file currently being transferred by the system
|
||||
LLFrameTimer mCurrentTransferTimer;
|
||||
|
||||
// A list of all audio sources that are known to the viewer at this time.
|
||||
// This is most likely a superset of the ones that we actually have audio
|
||||
// data for, or are playing back.
|
||||
typedef std::map<LLUUID, LLAudioSource *> source_map;
|
||||
typedef std::map<LLUUID, LLAudioData *> data_map;
|
||||
|
||||
source_map mAllSources;
|
||||
data_map mAllData;
|
||||
|
||||
LLAudioChannel *mChannels[MAX_CHANNELS];
|
||||
|
||||
// Buffers needs to change into a different data structure, as the number of buffers
|
||||
// that we have active should be limited by RAM usage, not count.
|
||||
LLAudioBuffer *mBuffers[MAX_BUFFERS];
|
||||
|
||||
F32 mMasterGain;
|
||||
F32 mSecondaryGain[AUDIO_TYPE_COUNT];
|
||||
|
||||
F32 mNextWindUpdate;
|
||||
|
||||
LLFrameTimer mWindUpdateTimer;
|
||||
|
||||
private:
|
||||
void setDefaults();
|
||||
LLStreamingAudioInterface *mStreamingAudioImpl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Standard audio source. Can be derived from for special sources, such as those attached to objects.
|
||||
//
|
||||
|
||||
|
||||
class LLAudioSource
|
||||
{
|
||||
public:
|
||||
// owner_id is the id of the agent responsible for making this sound
|
||||
// play, for example, the owner of the object currently playing it
|
||||
LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE);
|
||||
virtual ~LLAudioSource();
|
||||
|
||||
virtual void update(); // Update this audio source
|
||||
void updatePriority();
|
||||
|
||||
void preload(const LLUUID &audio_id); // Only used for preloading UI sounds, now.
|
||||
|
||||
void addAudioData(LLAudioData *adp, bool set_current = TRUE);
|
||||
|
||||
void setAmbient(const bool ambient) { mAmbient = ambient; }
|
||||
bool isAmbient() const { return mAmbient; }
|
||||
|
||||
void setLoop(const bool loop) { mLoop = loop; }
|
||||
bool isLoop() const { return mLoop; }
|
||||
|
||||
void setSyncMaster(const bool master) { mSyncMaster = master; }
|
||||
bool isSyncMaster() const { return mSyncMaster; }
|
||||
|
||||
void setSyncSlave(const bool slave) { mSyncSlave = slave; }
|
||||
bool isSyncSlave() const { return mSyncSlave; }
|
||||
|
||||
void setQueueSounds(const bool queue) { mQueueSounds = queue; }
|
||||
bool isQueueSounds() const { return mQueueSounds; }
|
||||
|
||||
void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; }
|
||||
|
||||
void setType(S32 type) { mType = type; }
|
||||
S32 getType() { return mType; }
|
||||
|
||||
void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; }
|
||||
LLVector3d getPositionGlobal() const { return mPositionGlobal; }
|
||||
LLVector3 getVelocity() const { return mVelocity; }
|
||||
F32 getPriority() const { return mPriority; }
|
||||
|
||||
// Gain should always be clamped between 0 and 1.
|
||||
F32 getGain() const { return mGain; }
|
||||
virtual void setGain(const F32 gain) { mGain = llclamp(gain, 0.f, 1.f); }
|
||||
|
||||
const LLUUID &getID() const { return mID; }
|
||||
bool isDone();
|
||||
|
||||
LLAudioData *getCurrentData();
|
||||
LLAudioData *getQueuedData();
|
||||
LLAudioBuffer *getCurrentBuffer();
|
||||
|
||||
bool setupChannel();
|
||||
bool play(const LLUUID &audio_id); // Start the audio source playing
|
||||
|
||||
bool hasPendingPreloads() const; // Has preloads that haven't been done yet
|
||||
|
||||
friend class LLAudioEngine;
|
||||
friend class LLAudioChannel;
|
||||
protected:
|
||||
void setChannel(LLAudioChannel *channelp);
|
||||
LLAudioChannel *getChannel() const { return mChannelp; }
|
||||
|
||||
protected:
|
||||
LLUUID mID; // The ID of the source is that of the object if it's attached to an object.
|
||||
LLUUID mOwnerID; // owner of the object playing the sound
|
||||
F32 mPriority;
|
||||
F32 mGain;
|
||||
bool mAmbient;
|
||||
bool mLoop;
|
||||
bool mSyncMaster;
|
||||
bool mSyncSlave;
|
||||
bool mQueueSounds;
|
||||
bool mPlayedOnce;
|
||||
S32 mType;
|
||||
LLVector3d mPositionGlobal;
|
||||
LLVector3 mVelocity;
|
||||
|
||||
//LLAudioSource *mSyncMasterp; // If we're a slave, the source that we're synced to.
|
||||
LLAudioChannel *mChannelp; // If we're currently playing back, this is the channel that we're assigned to.
|
||||
LLAudioData *mCurrentDatap;
|
||||
LLAudioData *mQueuedDatap;
|
||||
|
||||
typedef std::map<LLUUID, LLAudioData *> data_map;
|
||||
data_map mPreloadMap;
|
||||
|
||||
LLFrameTimer mAgeTimer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Generic metadata about a particular piece of audio data.
|
||||
// The actual data is handled by the derived LLAudioBuffer classes which are
|
||||
// derived for each audio engine.
|
||||
//
|
||||
|
||||
|
||||
class LLAudioData
|
||||
{
|
||||
public:
|
||||
LLAudioData(const LLUUID &uuid);
|
||||
bool load();
|
||||
|
||||
LLUUID getID() const { return mID; }
|
||||
LLAudioBuffer *getBuffer() const { return mBufferp; }
|
||||
|
||||
bool hasLocalData() const { return mHasLocalData; }
|
||||
bool hasDecodedData() const { return mHasDecodedData; }
|
||||
bool hasValidData() const { return mHasValidData; }
|
||||
|
||||
void setHasLocalData(const bool hld) { mHasLocalData = hld; }
|
||||
void setHasDecodedData(const bool hdd) { mHasDecodedData = hdd; }
|
||||
void setHasValidData(const bool hvd) { mHasValidData = hvd; }
|
||||
|
||||
friend class LLAudioEngine; // Severe laziness, bad.
|
||||
|
||||
protected:
|
||||
LLUUID mID;
|
||||
LLAudioBuffer *mBufferp; // If this data is being used by the audio system, a pointer to the buffer will be set here.
|
||||
bool mHasLocalData;
|
||||
bool mHasDecodedData;
|
||||
bool mHasValidData;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Base class for an audio channel, i.e. a channel which is capable of playing back a sound.
|
||||
// Management of channels is done generically, methods for actually manipulating the channel
|
||||
// are derived for each audio engine.
|
||||
//
|
||||
|
||||
|
||||
class LLAudioChannel
|
||||
{
|
||||
public:
|
||||
LLAudioChannel();
|
||||
virtual ~LLAudioChannel();
|
||||
|
||||
virtual void setSource(LLAudioSource *sourcep);
|
||||
LLAudioSource *getSource() const { return mCurrentSourcep; }
|
||||
|
||||
void setSecondaryGain(F32 gain) { mSecondaryGain = gain; }
|
||||
F32 getSecondaryGain() { return mSecondaryGain; }
|
||||
|
||||
friend class LLAudioEngine;
|
||||
friend class LLAudioSource;
|
||||
protected:
|
||||
virtual void play() = 0;
|
||||
virtual void playSynced(LLAudioChannel *channelp) = 0;
|
||||
virtual void cleanup() = 0;
|
||||
virtual bool isPlaying() = 0;
|
||||
void setWaiting(const bool waiting) { mWaiting = waiting; }
|
||||
bool isWaiting() const { return mWaiting; }
|
||||
|
||||
virtual bool updateBuffer(); // Check to see if the buffer associated with the source changed, and update if necessary.
|
||||
virtual void update3DPosition() = 0;
|
||||
virtual void updateLoop() = 0; // Update your loop/completion status, for use by queueing/syncing.
|
||||
protected:
|
||||
LLAudioSource *mCurrentSourcep;
|
||||
LLAudioBuffer *mCurrentBufferp;
|
||||
bool mLoopedThisFrame;
|
||||
bool mWaiting; // Waiting for sync.
|
||||
F32 mSecondaryGain;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Basically an interface class to the engine-specific implementation
|
||||
// of audio data that's ready for playback.
|
||||
// Will likely get more complex as we decide to do stuff like real streaming audio.
|
||||
|
||||
|
||||
class LLAudioBuffer
|
||||
{
|
||||
public:
|
||||
virtual ~LLAudioBuffer() {};
|
||||
virtual bool loadWAV(const std::string& filename) = 0;
|
||||
virtual U32 getLength() = 0;
|
||||
|
||||
friend class LLAudioEngine;
|
||||
friend class LLAudioChannel;
|
||||
friend class LLAudioData;
|
||||
protected:
|
||||
bool mInUse;
|
||||
LLAudioData *mAudioDatap;
|
||||
LLFrameTimer mLastUseTimer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
extern LLAudioEngine* gAudiop;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,766 @@
|
|||
/**
|
||||
* @file audioengine_fmod.cpp
|
||||
* @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 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$
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
FSOUND_DSPUNIT *gWindDSP = NULL;
|
||||
|
||||
|
||||
LLAudioEngine_FMOD::LLAudioEngine_FMOD()
|
||||
{
|
||||
mInited = false;
|
||||
mWindGen = 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;
|
||||
#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 (gWindDSP)
|
||||
{
|
||||
FSOUND_DSP_SetActive(gWindDSP,false);
|
||||
FSOUND_DSP_Free(gWindDSP);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
void LLAudioEngine_FMOD::initWind()
|
||||
{
|
||||
mWindGen = new LLWindGen<MIXBUFFERFORMAT>;
|
||||
|
||||
if (!gWindDSP)
|
||||
{
|
||||
gWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen);
|
||||
}
|
||||
if (gWindDSP)
|
||||
{
|
||||
FSOUND_DSP_SetActive(gWindDSP, true);
|
||||
}
|
||||
mNextWindUpdate = 0.0;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioEngine_FMOD::cleanupWind()
|
||||
{
|
||||
if (gWindDSP)
|
||||
{
|
||||
FSOUND_DSP_SetActive(gWindDSP, false);
|
||||
FSOUND_DSP_Free(gWindDSP);
|
||||
gWindDSP = 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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
mCurrentBufferp = NULL;
|
||||
mChannelID = 0;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMOD::play()
|
||||
{
|
||||
if (!mChannelID)
|
||||
{
|
||||
llwarns << "Playing without a channelID, aborting" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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, NULL, 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.
|
||||
// param = user parameter passed through in FSOUND_DSP_Create.
|
||||
//
|
||||
// modify the buffer in some fashion
|
||||
|
||||
LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *windgen =
|
||||
(LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *)userdata;
|
||||
U8 stride;
|
||||
|
||||
#if LL_DARWIN
|
||||
stride = sizeof(LLAudioEngine_FMOD::MIXBUFFERFORMAT);
|
||||
#else
|
||||
int mixertype = FSOUND_GetMixer();
|
||||
if (mixertype == FSOUND_MIXER_BLENDMODE ||
|
||||
mixertype == FSOUND_MIXER_QUALITY_FPU)
|
||||
{
|
||||
stride = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
stride = 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length, stride);
|
||||
|
||||
return newbuffer;
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/**
|
||||
* @file audioengine_fmod.h
|
||||
* @brief Definition of LLAudioEngine class abstracting the audio
|
||||
* support as a FMOD 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_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*/ void 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;
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
|
|
@ -0,0 +1,546 @@
|
|||
/**
|
||||
* @file audioengine_openal.cpp
|
||||
* @brief implementation of audio engine using OpenAL
|
||||
* support as a OpenAL 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$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "lldir.h"
|
||||
|
||||
#include "llaudioengine_openal.h"
|
||||
#include "lllistener_openal.h"
|
||||
|
||||
|
||||
LLAudioEngine_OpenAL::LLAudioEngine_OpenAL()
|
||||
:
|
||||
mWindGen(NULL),
|
||||
mWindBuf(NULL),
|
||||
mWindBufFreq(0),
|
||||
mWindBufSamples(0),
|
||||
mWindBufBytes(0),
|
||||
mWindSource(AL_NONE),
|
||||
mNumEmptyWindALBuffers(MAX_NUM_WIND_BUFFERS)
|
||||
{
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL()
|
||||
{
|
||||
}
|
||||
|
||||
// virtual
|
||||
bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata)
|
||||
{
|
||||
mWindGen = NULL;
|
||||
LLAudioEngine::init(num_channels, userdata);
|
||||
|
||||
if(!alutInit(NULL, NULL))
|
||||
{
|
||||
llwarns << "LLAudioEngine_OpenAL::init() ALUT initialization failed: " << alutGetErrorString (alutGetError ()) << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl;
|
||||
|
||||
llinfos << "OpenAL version: "
|
||||
<< ll_safe_string(alGetString(AL_VERSION)) << llendl;
|
||||
llinfos << "OpenAL vendor: "
|
||||
<< ll_safe_string(alGetString(AL_VENDOR)) << llendl;
|
||||
llinfos << "OpenAL renderer: "
|
||||
<< ll_safe_string(alGetString(AL_RENDERER)) << llendl;
|
||||
|
||||
ALint major = alutGetMajorVersion ();
|
||||
ALint minor = alutGetMinorVersion ();
|
||||
llinfos << "ALUT version: " << major << "." << minor << llendl;
|
||||
|
||||
ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
|
||||
|
||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
|
||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor);
|
||||
llinfos << "ALC version: " << major << "." << minor << llendl;
|
||||
|
||||
llinfos << "ALC default device: "
|
||||
<< ll_safe_string(alcGetString(device,
|
||||
ALC_DEFAULT_DEVICE_SPECIFIER))
|
||||
<< llendl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// virtual
|
||||
std::string LLAudioEngine_OpenAL::getDriverName(bool verbose)
|
||||
{
|
||||
ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
|
||||
std::ostringstream version;
|
||||
|
||||
version <<
|
||||
"OpenAL";
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
version <<
|
||||
", version " <<
|
||||
ll_safe_string(alGetString(AL_VERSION)) <<
|
||||
" / " <<
|
||||
ll_safe_string(alGetString(AL_VENDOR)) <<
|
||||
" / " <<
|
||||
ll_safe_string(alGetString(AL_RENDERER));
|
||||
|
||||
if (device)
|
||||
version <<
|
||||
": " <<
|
||||
ll_safe_string(alcGetString(device,
|
||||
ALC_DEFAULT_DEVICE_SPECIFIER));
|
||||
}
|
||||
|
||||
return version.str();
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLAudioEngine_OpenAL::allocateListener()
|
||||
{
|
||||
mListenerp = (LLListener *) new LLListener_OpenAL();
|
||||
if(!mListenerp)
|
||||
{
|
||||
llwarns << "LLAudioEngine_OpenAL::allocateListener() Listener creation failed" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLAudioEngine_OpenAL::shutdown()
|
||||
{
|
||||
llinfos << "About to LLAudioEngine::shutdown()" << llendl;
|
||||
LLAudioEngine::shutdown();
|
||||
|
||||
llinfos << "About to alutExit()" << llendl;
|
||||
if(!alutExit())
|
||||
{
|
||||
llwarns << "Nuts." << llendl;
|
||||
llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl;
|
||||
}
|
||||
|
||||
llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl;
|
||||
|
||||
delete mListenerp;
|
||||
mListenerp = NULL;
|
||||
}
|
||||
|
||||
LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer()
|
||||
{
|
||||
return new LLAudioBufferOpenAL();
|
||||
}
|
||||
|
||||
LLAudioChannel *LLAudioEngine_OpenAL::createChannel()
|
||||
{
|
||||
return new LLAudioChannelOpenAL();
|
||||
}
|
||||
|
||||
void LLAudioEngine_OpenAL::setInternalGain(F32 gain)
|
||||
{
|
||||
//llinfos << "LLAudioEngine_OpenAL::setInternalGain() Gain: " << gain << llendl;
|
||||
alListenerf(AL_GAIN, gain);
|
||||
}
|
||||
|
||||
LLAudioChannelOpenAL::LLAudioChannelOpenAL()
|
||||
:
|
||||
mALSource(AL_NONE),
|
||||
mLastSamplePos(0)
|
||||
{
|
||||
alGenSources(1, &mALSource);
|
||||
}
|
||||
|
||||
LLAudioChannelOpenAL::~LLAudioChannelOpenAL()
|
||||
{
|
||||
cleanup();
|
||||
alDeleteSources(1, &mALSource);
|
||||
}
|
||||
|
||||
void LLAudioChannelOpenAL::cleanup()
|
||||
{
|
||||
alSourceStop(mALSource);
|
||||
mCurrentBufferp = NULL;
|
||||
}
|
||||
|
||||
void LLAudioChannelOpenAL::play()
|
||||
{
|
||||
if (mALSource == AL_NONE)
|
||||
{
|
||||
llwarns << "Playing without a mALSource, aborting" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isPlaying())
|
||||
{
|
||||
alSourcePlay(mALSource);
|
||||
getSource()->setPlayedOnce(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp)
|
||||
{
|
||||
if (channelp)
|
||||
{
|
||||
LLAudioChannelOpenAL *masterchannelp =
|
||||
(LLAudioChannelOpenAL*)channelp;
|
||||
if (mALSource != AL_NONE &&
|
||||
masterchannelp->mALSource != AL_NONE)
|
||||
{
|
||||
// we have channels allocated to master and slave
|
||||
ALfloat master_offset;
|
||||
alGetSourcef(masterchannelp->mALSource, AL_SEC_OFFSET,
|
||||
&master_offset);
|
||||
|
||||
llinfos << "Syncing with master at " << master_offset
|
||||
<< "sec" << llendl;
|
||||
// *TODO: detect when this fails, maybe use AL_SAMPLE_
|
||||
alSourcef(mALSource, AL_SEC_OFFSET, master_offset);
|
||||
}
|
||||
}
|
||||
play();
|
||||
}
|
||||
|
||||
bool LLAudioChannelOpenAL::isPlaying()
|
||||
{
|
||||
if (mALSource != AL_NONE)
|
||||
{
|
||||
ALint state;
|
||||
alGetSourcei(mALSource, AL_SOURCE_STATE, &state);
|
||||
if(state == AL_PLAYING)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLAudioChannelOpenAL::updateBuffer()
|
||||
{
|
||||
if (LLAudioChannel::updateBuffer())
|
||||
{
|
||||
// Base class update returned true, which means that we need to actually
|
||||
// set up the source for a different buffer.
|
||||
LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer();
|
||||
ALuint buffer = bufferp->getBuffer();
|
||||
alSourcei(mALSource, AL_BUFFER, buffer);
|
||||
mLastSamplePos = 0;
|
||||
}
|
||||
|
||||
if (mCurrentSourcep)
|
||||
{
|
||||
alSourcef(mALSource, AL_GAIN,
|
||||
mCurrentSourcep->getGain() * getSecondaryGain());
|
||||
alSourcei(mALSource, AL_LOOPING,
|
||||
mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE);
|
||||
alSourcef(mALSource, AL_ROLLOFF_FACTOR,
|
||||
gAudiop->mListenerp->getRolloffFactor());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelOpenAL::updateLoop()
|
||||
{
|
||||
if (mALSource == AL_NONE)
|
||||
{
|
||||
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.
|
||||
//
|
||||
ALint cur_pos;
|
||||
alGetSourcei(mALSource, AL_SAMPLE_OFFSET, &cur_pos);
|
||||
if (cur_pos < mLastSamplePos)
|
||||
{
|
||||
mLoopedThisFrame = true;
|
||||
}
|
||||
mLastSamplePos = cur_pos;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelOpenAL::update3DPosition()
|
||||
{
|
||||
if(!mCurrentSourcep)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mCurrentSourcep->isAmbient())
|
||||
{
|
||||
alSource3f(mALSource, AL_POSITION, 0.0, 0.0, 0.0);
|
||||
alSource3f(mALSource, AL_VELOCITY, 0.0, 0.0, 0.0);
|
||||
alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
} else {
|
||||
LLVector3 float_pos;
|
||||
float_pos.setVec(mCurrentSourcep->getPositionGlobal());
|
||||
alSourcefv(mALSource, AL_POSITION, float_pos.mV);
|
||||
alSourcefv(mALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV);
|
||||
alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||
}
|
||||
|
||||
alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain() * getSecondaryGain());
|
||||
}
|
||||
|
||||
LLAudioBufferOpenAL::LLAudioBufferOpenAL()
|
||||
{
|
||||
mALBuffer = AL_NONE;
|
||||
}
|
||||
|
||||
LLAudioBufferOpenAL::~LLAudioBufferOpenAL()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void LLAudioBufferOpenAL::cleanup()
|
||||
{
|
||||
if(mALBuffer != AL_NONE)
|
||||
{
|
||||
alDeleteBuffers(1, &mALBuffer);
|
||||
mALBuffer = AL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLAudioBufferOpenAL::loadWAV(const std::string& filename)
|
||||
{
|
||||
cleanup();
|
||||
mALBuffer = alutCreateBufferFromFile(filename.c_str());
|
||||
if(mALBuffer == AL_NONE)
|
||||
{
|
||||
ALenum error = alutGetError();
|
||||
if (gDirUtilp->fileExists(filename))
|
||||
{
|
||||
llwarns <<
|
||||
"LLAudioBufferOpenAL::loadWAV() Error loading "
|
||||
<< filename
|
||||
<< " " << alutGetErrorString(error) << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's common for the file to not actually exist.
|
||||
lldebugs <<
|
||||
"LLAudioBufferOpenAL::loadWAV() Error loading "
|
||||
<< filename
|
||||
<< " " << alutGetErrorString(error) << llendl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
U32 LLAudioBufferOpenAL::getLength()
|
||||
{
|
||||
if(mALBuffer == AL_NONE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ALint length;
|
||||
alGetBufferi(mALBuffer, AL_SIZE, &length);
|
||||
return length / 2; // convert size in bytes to size in (16-bit) samples
|
||||
}
|
||||
|
||||
// ------------
|
||||
|
||||
void LLAudioEngine_OpenAL::initWind()
|
||||
{
|
||||
ALenum error;
|
||||
llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl;
|
||||
|
||||
mNumEmptyWindALBuffers = MAX_NUM_WIND_BUFFERS;
|
||||
|
||||
alGetError(); /* clear error */
|
||||
|
||||
alGenSources(1,&mWindSource);
|
||||
|
||||
if((error=alGetError()) != AL_NO_ERROR)
|
||||
{
|
||||
llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<<error<<llendl;
|
||||
}
|
||||
|
||||
mWindGen = new LLWindGen<WIND_SAMPLE_T>;
|
||||
|
||||
mWindBufFreq = mWindGen->getInputSamplingRate();
|
||||
mWindBufSamples = llceil(mWindBufFreq * WIND_BUFFER_SIZE_SEC);
|
||||
mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T);
|
||||
|
||||
mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/];
|
||||
|
||||
if(mWindBuf==NULL)
|
||||
{
|
||||
llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl;
|
||||
mEnableWind=false;
|
||||
}
|
||||
|
||||
llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl;
|
||||
}
|
||||
|
||||
void LLAudioEngine_OpenAL::cleanupWind()
|
||||
{
|
||||
llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl;
|
||||
|
||||
if (mWindSource != AL_NONE)
|
||||
{
|
||||
// detach and delete all outstanding buffers on the wind source
|
||||
alSourceStop(mWindSource);
|
||||
ALint processed;
|
||||
alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed);
|
||||
while (processed--)
|
||||
{
|
||||
ALuint buffer = AL_NONE;
|
||||
alSourceUnqueueBuffers(mWindSource, 1, &buffer);
|
||||
alDeleteBuffers(1, &buffer);
|
||||
}
|
||||
|
||||
// delete the wind source itself
|
||||
alDeleteSources(1, &mWindSource);
|
||||
|
||||
mWindSource = AL_NONE;
|
||||
}
|
||||
|
||||
delete[] mWindBuf;
|
||||
mWindBuf = NULL;
|
||||
|
||||
delete mWindGen;
|
||||
mWindGen = NULL;
|
||||
}
|
||||
|
||||
void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
|
||||
{
|
||||
LLVector3 wind_pos;
|
||||
F64 pitch;
|
||||
F64 center_freq;
|
||||
ALenum error;
|
||||
|
||||
if (!mEnableWind)
|
||||
return;
|
||||
|
||||
if(!mWindBuf)
|
||||
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]);
|
||||
|
||||
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);
|
||||
|
||||
alSourcei(mWindSource, AL_LOOPING, AL_FALSE);
|
||||
alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0);
|
||||
alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0);
|
||||
alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0);
|
||||
alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
}
|
||||
|
||||
// ok lets make a wind buffer now
|
||||
|
||||
ALint processed, queued, unprocessed;
|
||||
alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed);
|
||||
alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued);
|
||||
unprocessed = queued - processed;
|
||||
|
||||
// ensure that there are always at least 3x as many filled buffers
|
||||
// queued as we managed to empty since last time.
|
||||
mNumEmptyWindALBuffers = llmin(mNumEmptyWindALBuffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed);
|
||||
mNumEmptyWindALBuffers = llmax(mNumEmptyWindALBuffers, 0);
|
||||
|
||||
//llinfos << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << llendl;
|
||||
|
||||
while(processed--) // unqueue old buffers
|
||||
{
|
||||
ALuint buffer;
|
||||
ALenum error;
|
||||
alGetError(); /* clear error */
|
||||
alSourceUnqueueBuffers(mWindSource, 1, &buffer);
|
||||
error = alGetError();
|
||||
if(error != AL_NO_ERROR)
|
||||
{
|
||||
llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
alDeleteBuffers(1, &buffer);
|
||||
}
|
||||
}
|
||||
|
||||
unprocessed += mNumEmptyWindALBuffers;
|
||||
while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers
|
||||
{
|
||||
ALuint buffer;
|
||||
alGetError(); /* clear error */
|
||||
alGenBuffers(1,&buffer);
|
||||
if((error=alGetError()) != AL_NO_ERROR)
|
||||
{
|
||||
llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << llendl;
|
||||
break;
|
||||
}
|
||||
|
||||
alBufferData(buffer,
|
||||
AL_FORMAT_STEREO16,
|
||||
mWindGen->windGenerate(mWindBuf,
|
||||
mWindBufSamples, 2),
|
||||
mWindBufBytes,
|
||||
mWindBufFreq);
|
||||
error = alGetError();
|
||||
if(error != AL_NO_ERROR)
|
||||
{
|
||||
llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << llendl;
|
||||
}
|
||||
|
||||
alSourceQueueBuffers(mWindSource, 1, &buffer);
|
||||
error = alGetError();
|
||||
if(error != AL_NO_ERROR)
|
||||
{
|
||||
llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << llendl;
|
||||
}
|
||||
|
||||
--mNumEmptyWindALBuffers;
|
||||
}
|
||||
|
||||
ALint playing;
|
||||
alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing);
|
||||
if(playing != AL_PLAYING)
|
||||
{
|
||||
alSourcePlay(mWindSource);
|
||||
|
||||
lldebugs << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* @file audioengine_openal.cpp
|
||||
* @brief implementation of audio engine using OpenAL
|
||||
* support as a OpenAL 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_OPENAL_H
|
||||
#define LL_AUDIOENGINE_OPENAL_H
|
||||
|
||||
#include "llaudioengine.h"
|
||||
#include "lllistener_openal.h"
|
||||
#include "llwindgen.h"
|
||||
|
||||
class LLAudioEngine_OpenAL : public LLAudioEngine
|
||||
{
|
||||
public:
|
||||
LLAudioEngine_OpenAL();
|
||||
virtual ~LLAudioEngine_OpenAL();
|
||||
|
||||
virtual bool init(const S32 num_channels, void *user_data);
|
||||
virtual std::string getDriverName(bool verbose);
|
||||
virtual void allocateListener();
|
||||
|
||||
virtual void shutdown();
|
||||
|
||||
void setInternalGain(F32 gain);
|
||||
|
||||
LLAudioBuffer* createBuffer();
|
||||
LLAudioChannel* createChannel();
|
||||
|
||||
/*virtual*/ void initWind();
|
||||
/*virtual*/ void cleanupWind();
|
||||
/*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude);
|
||||
|
||||
private:
|
||||
void * windDSP(void *newbuffer, int length);
|
||||
typedef S16 WIND_SAMPLE_T;
|
||||
LLWindGen<WIND_SAMPLE_T> *mWindGen;
|
||||
S16 *mWindBuf;
|
||||
U32 mWindBufFreq;
|
||||
U32 mWindBufSamples;
|
||||
U32 mWindBufBytes;
|
||||
ALuint mWindSource;
|
||||
int mNumEmptyWindALBuffers;
|
||||
|
||||
static const int MAX_NUM_WIND_BUFFERS = 80;
|
||||
static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec
|
||||
};
|
||||
|
||||
class LLAudioChannelOpenAL : public LLAudioChannel
|
||||
{
|
||||
public:
|
||||
LLAudioChannelOpenAL();
|
||||
virtual ~LLAudioChannelOpenAL();
|
||||
protected:
|
||||
/*virtual*/ void play();
|
||||
/*virtual*/ void playSynced(LLAudioChannel *channelp);
|
||||
/*virtual*/ void cleanup();
|
||||
/*virtual*/ bool isPlaying();
|
||||
|
||||
/*virtual*/ bool updateBuffer();
|
||||
/*virtual*/ void update3DPosition();
|
||||
/*virtual*/ void updateLoop();
|
||||
|
||||
ALuint mALSource;
|
||||
ALint mLastSamplePos;
|
||||
};
|
||||
|
||||
class LLAudioBufferOpenAL : public LLAudioBuffer{
|
||||
public:
|
||||
LLAudioBufferOpenAL();
|
||||
virtual ~LLAudioBufferOpenAL();
|
||||
|
||||
bool loadWAV(const std::string& filename);
|
||||
U32 getLength();
|
||||
|
||||
friend class LLAudioChannelOpenAL;
|
||||
protected:
|
||||
void cleanup();
|
||||
ALuint getBuffer() {return mALBuffer;}
|
||||
|
||||
ALuint mALBuffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
/**
|
||||
* @file listener.cpp
|
||||
* @brief Implementation of LISTENER class abstracting the audio support
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-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 "lllistener.h"
|
||||
|
||||
#define DEFAULT_AT 0.0f,0.0f,-1.0f
|
||||
#define DEFAULT_UP 0.0f,1.0f,0.0f
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener::LLListener()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener::~LLListener()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::init(void)
|
||||
{
|
||||
mPosition.zeroVec();
|
||||
mListenAt.setVec(DEFAULT_AT);
|
||||
mListenUp.setVec(DEFAULT_UP);
|
||||
mVelocity.zeroVec();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::translate(LLVector3 offset)
|
||||
{
|
||||
mPosition += offset;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::setPosition(LLVector3 pos)
|
||||
{
|
||||
mPosition = pos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
LLVector3 LLListener::getPosition(void)
|
||||
{
|
||||
return(mPosition);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
LLVector3 LLListener::getAt(void)
|
||||
{
|
||||
return(mListenAt);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
LLVector3 LLListener::getUp(void)
|
||||
{
|
||||
return(mListenUp);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::setVelocity(LLVector3 vel)
|
||||
{
|
||||
mVelocity = vel;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::orient(LLVector3 up, LLVector3 at)
|
||||
{
|
||||
mListenUp = up;
|
||||
mListenAt = at;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at)
|
||||
{
|
||||
mPosition = pos;
|
||||
mVelocity = vel;
|
||||
|
||||
setPosition(pos);
|
||||
setVelocity(vel);
|
||||
orient(up,at);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::setDopplerFactor(F32 factor)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
F32 LLListener::getDopplerFactor()
|
||||
{
|
||||
return (1.f);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::setRolloffFactor(F32 factor)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
F32 LLListener::getRolloffFactor()
|
||||
{
|
||||
return (1.f);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::commitDeferredChanges()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* @file listener.h
|
||||
* @brief Description of LISTENER base class abstracting the audio support.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-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_H
|
||||
#define LL_LISTENER_H
|
||||
|
||||
#include "v3math.h"
|
||||
|
||||
class LLListener
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
LLVector3 mPosition;
|
||||
LLVector3 mVelocity;
|
||||
LLVector3 mListenAt;
|
||||
LLVector3 mListenUp;
|
||||
|
||||
public:
|
||||
|
||||
private:
|
||||
protected:
|
||||
public:
|
||||
LLListener();
|
||||
virtual ~LLListener();
|
||||
virtual void init();
|
||||
|
||||
virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at);
|
||||
|
||||
virtual void setPosition(LLVector3 pos);
|
||||
virtual void setVelocity(LLVector3 vel);
|
||||
|
||||
virtual void orient(LLVector3 up, LLVector3 at);
|
||||
virtual void translate(LLVector3 offset);
|
||||
|
||||
virtual void setDopplerFactor(F32 factor);
|
||||
virtual void setRolloffFactor(F32 factor);
|
||||
|
||||
virtual LLVector3 getPosition();
|
||||
virtual LLVector3 getAt();
|
||||
virtual LLVector3 getUp();
|
||||
|
||||
virtual F32 getDopplerFactor();
|
||||
virtual F32 getRolloffFactor();
|
||||
|
||||
virtual void commitDeferredChanges();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file listener_ds3d.h
|
||||
* @brief Description of LISTENER class abstracting the audio support
|
||||
* as a DirectSound 3D implementation (windows only)
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-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_DS3D_H
|
||||
#define LL_LISTENER_DS3D_H
|
||||
|
||||
#include "lllistener.h"
|
||||
|
||||
#include <dmusici.h>
|
||||
#include <dsound.h>
|
||||
#include <ks.h>
|
||||
|
||||
class LLListener_DS3D : public LLListener
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
IDirectSound3DListener8 *m3DListener;
|
||||
public:
|
||||
|
||||
private:
|
||||
protected:
|
||||
public:
|
||||
LLListener_DS3D();
|
||||
virtual ~LLListener_DS3D();
|
||||
virtual void init();
|
||||
|
||||
virtual void setDS3DLPtr (IDirectSound3DListener8 *listener_p);
|
||||
|
||||
virtual void translate(LLVector3 offset);
|
||||
virtual void setPosition(LLVector3 pos);
|
||||
virtual void setVelocity(LLVector3 vel);
|
||||
virtual void orient(LLVector3 up, LLVector3 at);
|
||||
|
||||
virtual void setDopplerFactor(F32 factor);
|
||||
virtual F32 getDopplerFactor();
|
||||
virtual void setRolloffFactor(F32 factor);
|
||||
virtual F32 getRolloffFactor();
|
||||
|
||||
virtual void commitDeferredChanges();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
/**
|
||||
* @file listener_fmod.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_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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @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=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_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
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* @file audioengine_openal.cpp
|
||||
* @brief implementation of audio engine using OpenAL
|
||||
* support as a OpenAL 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$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llaudioengine.h"
|
||||
|
||||
#include "lllistener_openal.h"
|
||||
|
||||
LLListener_OpenAL::LLListener_OpenAL()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
LLListener_OpenAL::~LLListener_OpenAL()
|
||||
{
|
||||
}
|
||||
|
||||
void LLListener_OpenAL::translate(LLVector3 offset)
|
||||
{
|
||||
//llinfos << "LLListener_OpenAL::translate() : " << offset << llendl;
|
||||
LLListener::translate(offset);
|
||||
}
|
||||
|
||||
void LLListener_OpenAL::setPosition(LLVector3 pos)
|
||||
{
|
||||
//llinfos << "LLListener_OpenAL::setPosition() : " << pos << llendl;
|
||||
LLListener::setPosition(pos);
|
||||
}
|
||||
|
||||
void LLListener_OpenAL::setVelocity(LLVector3 vel)
|
||||
{
|
||||
LLListener::setVelocity(vel);
|
||||
}
|
||||
|
||||
void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at)
|
||||
{
|
||||
//llinfos << "LLListener_OpenAL::orient() up: " << up << " at: " << at << llendl;
|
||||
LLListener::orient(up, at);
|
||||
}
|
||||
|
||||
void LLListener_OpenAL::commitDeferredChanges()
|
||||
{
|
||||
ALfloat orientation[6];
|
||||
orientation[0] = mListenAt.mV[0];
|
||||
orientation[1] = mListenAt.mV[1];
|
||||
orientation[2] = mListenAt.mV[2];
|
||||
orientation[3] = mListenUp.mV[0];
|
||||
orientation[4] = mListenUp.mV[1];
|
||||
orientation[5] = mListenUp.mV[2];
|
||||
|
||||
ALfloat velocity[3];
|
||||
velocity[0] = mVelocity.mV[0];
|
||||
velocity[1] = mVelocity.mV[1];
|
||||
velocity[2] = mVelocity.mV[2];
|
||||
|
||||
alListenerfv(AL_ORIENTATION, orientation);
|
||||
alListenerfv(AL_POSITION, mPosition.mV);
|
||||
alListenerfv(AL_VELOCITY, velocity);
|
||||
}
|
||||
|
||||
void LLListener_OpenAL::setDopplerFactor(F32 factor)
|
||||
{
|
||||
//llinfos << "LLListener_OpenAL::setDopplerFactor() : " << factor << llendl;
|
||||
alDopplerFactor(factor);
|
||||
}
|
||||
|
||||
F32 LLListener_OpenAL::getDopplerFactor()
|
||||
{
|
||||
ALfloat factor;
|
||||
factor = alGetFloat(AL_DOPPLER_FACTOR);
|
||||
//llinfos << "LLListener_OpenAL::getDopplerFactor() : " << factor << llendl;
|
||||
return factor;
|
||||
}
|
||||
|
||||
|
||||
void LLListener_OpenAL::setRolloffFactor(F32 factor)
|
||||
{
|
||||
mRolloffFactor = factor;
|
||||
}
|
||||
|
||||
F32 LLListener_OpenAL::getRolloffFactor()
|
||||
{
|
||||
return mRolloffFactor;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @file listener_openal.h
|
||||
* @brief Description of LISTENER class abstracting the audio support
|
||||
* as an OpenAL implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-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_OPENAL_H
|
||||
#define LL_LISTENER_OPENAL_H
|
||||
|
||||
#include "lllistener.h"
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alut.h"
|
||||
|
||||
class LLListener_OpenAL : public LLListener
|
||||
{
|
||||
public:
|
||||
LLListener_OpenAL();
|
||||
virtual ~LLListener_OpenAL();
|
||||
|
||||
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 mRolloffFactor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* @file streamingaudio.h
|
||||
* @author Tofu Linden
|
||||
* @brief Definition of LLStreamingAudioInterface base class abstracting the streaming audio interface
|
||||
*
|
||||
* $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_H
|
||||
#define LL_STREAMINGAUDIO_H
|
||||
|
||||
#include "stdtypes.h" // from llcommon
|
||||
|
||||
// Entirely abstract. Based exactly on the historic API.
|
||||
class LLStreamingAudioInterface
|
||||
{
|
||||
public:
|
||||
virtual ~LLStreamingAudioInterface() {}
|
||||
|
||||
virtual void start(const std::string& url) = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void pause(int pause) = 0;
|
||||
virtual void update() = 0;
|
||||
virtual int isPlaying() = 0;
|
||||
// use a value from 0.0 to 1.0, inclusive
|
||||
virtual void setGain(F32 vol) = 0;
|
||||
virtual F32 getGain() = 0;
|
||||
virtual std::string getURL() = 0;
|
||||
};
|
||||
|
||||
#endif // LL_STREAMINGAUDIO_H
|
||||
|
|
@ -0,0 +1,362 @@
|
|||
/**
|
||||
* @file streamingaudio_fmod.cpp
|
||||
* @brief LLStreamingAudio_FMOD 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 "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();
|
||||
protected:
|
||||
FSOUND_STREAM* mInternetStream;
|
||||
bool mReady;
|
||||
|
||||
std::string mInternetStreamURL;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Internet Streaming
|
||||
//---------------------------------------------------------------------------
|
||||
LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() :
|
||||
mCurrentInternetStreamp(NULL),
|
||||
mFMODInternetStreamChannel(-1),
|
||||
mGain(1.0f)
|
||||
{
|
||||
// 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.
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 << "InternetSteam - failed to open" << llendl;
|
||||
stop();
|
||||
return;
|
||||
case -4:
|
||||
// connecting
|
||||
break;
|
||||
case -5:
|
||||
// buffering
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMOD::stop()
|
||||
{
|
||||
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, 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* @file streamingaudio_fmod.h
|
||||
* @author Tofu Linden
|
||||
* @brief Definition of LLStreamingAudio_FMOD 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_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();
|
||||
|
||||
private:
|
||||
LLAudioStreamManagerFMOD *mCurrentInternetStreamp;
|
||||
int mFMODInternetStreamChannel;
|
||||
std::list<LLAudioStreamManagerFMOD *> mDeadStreams;
|
||||
|
||||
std::string mURL;
|
||||
F32 mGain;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_STREAMINGAUDIO_FMOD_H
|
||||
|
|
@ -0,0 +1,505 @@
|
|||
/**
|
||||
* @file vorbisencode.cpp
|
||||
* @brief Vorbis encoding routine routine for Indra.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-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 "vorbis/vorbisenc.h"
|
||||
|
||||
#include "llvorbisencode.h"
|
||||
#include "llerror.h"
|
||||
#include "llrand.h"
|
||||
#include "llmath.h"
|
||||
#include "llapr.h"
|
||||
|
||||
//#if LL_DARWIN
|
||||
// MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions.
|
||||
#if 0
|
||||
#include "VorbisFramework.h"
|
||||
|
||||
#define vorbis_analysis mac_vorbis_analysis
|
||||
#define vorbis_analysis_headerout mac_vorbis_analysis_headerout
|
||||
#define vorbis_analysis_init mac_vorbis_analysis_init
|
||||
#define vorbis_encode_ctl mac_vorbis_encode_ctl
|
||||
#define vorbis_encode_setup_init mac_vorbis_encode_setup_init
|
||||
#define vorbis_encode_setup_managed mac_vorbis_encode_setup_managed
|
||||
|
||||
#define vorbis_info_init mac_vorbis_info_init
|
||||
#define vorbis_info_clear mac_vorbis_info_clear
|
||||
#define vorbis_comment_init mac_vorbis_comment_init
|
||||
#define vorbis_comment_clear mac_vorbis_comment_clear
|
||||
#define vorbis_block_init mac_vorbis_block_init
|
||||
#define vorbis_block_clear mac_vorbis_block_clear
|
||||
#define vorbis_dsp_clear mac_vorbis_dsp_clear
|
||||
#define vorbis_analysis_buffer mac_vorbis_analysis_buffer
|
||||
#define vorbis_analysis_wrote mac_vorbis_analysis_wrote
|
||||
#define vorbis_analysis_blockout mac_vorbis_analysis_blockout
|
||||
|
||||
#define ogg_stream_packetin mac_ogg_stream_packetin
|
||||
#define ogg_stream_init mac_ogg_stream_init
|
||||
#define ogg_stream_flush mac_ogg_stream_flush
|
||||
#define ogg_stream_pageout mac_ogg_stream_pageout
|
||||
#define ogg_page_eos mac_ogg_page_eos
|
||||
#define ogg_stream_clear mac_ogg_stream_clear
|
||||
|
||||
#endif
|
||||
|
||||
S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg)
|
||||
{
|
||||
U16 num_channels = 0;
|
||||
U32 sample_rate = 0;
|
||||
U32 bits_per_sample = 0;
|
||||
U32 physical_file_size = 0;
|
||||
U32 chunk_length = 0;
|
||||
U32 raw_data_length = 0;
|
||||
U32 bytes_per_sec = 0;
|
||||
BOOL uncompressed_pcm = FALSE;
|
||||
|
||||
unsigned char wav_header[44]; /*Flawfinder: ignore*/
|
||||
|
||||
error_msg.clear();
|
||||
|
||||
//********************************
|
||||
LLAPRFile infile ;
|
||||
infile.open(in_fname,LL_APR_RB);
|
||||
//********************************
|
||||
if (!infile.getFileHandle())
|
||||
{
|
||||
error_msg = "CannotUploadSoundFile";
|
||||
return(LLVORBISENC_SOURCE_OPEN_ERR);
|
||||
}
|
||||
|
||||
infile.read(wav_header, 44);
|
||||
physical_file_size = infile.seek(APR_END,0);
|
||||
|
||||
if (strncmp((char *)&(wav_header[0]),"RIFF",4))
|
||||
{
|
||||
error_msg = "SoundFileNotRIFF";
|
||||
return(LLVORBISENC_WAV_FORMAT_ERR);
|
||||
}
|
||||
|
||||
if (strncmp((char *)&(wav_header[8]),"WAVE",4))
|
||||
{
|
||||
error_msg = "SoundFileNotRIFF";
|
||||
return(LLVORBISENC_WAV_FORMAT_ERR);
|
||||
}
|
||||
|
||||
// parse the chunks
|
||||
|
||||
U32 file_pos = 12; // start at the first chunk (usually fmt but not always)
|
||||
|
||||
while ((file_pos + 8)< physical_file_size)
|
||||
{
|
||||
infile.seek(APR_SET,file_pos);
|
||||
infile.read(wav_header, 44);
|
||||
|
||||
chunk_length = ((U32) wav_header[7] << 24)
|
||||
+ ((U32) wav_header[6] << 16)
|
||||
+ ((U32) wav_header[5] << 8)
|
||||
+ wav_header[4];
|
||||
|
||||
// llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl;
|
||||
|
||||
if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
|
||||
{
|
||||
if ((wav_header[8] == 0x01) && (wav_header[9] == 0x00))
|
||||
{
|
||||
uncompressed_pcm = TRUE;
|
||||
}
|
||||
num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
|
||||
sample_rate = ((U32) wav_header[15] << 24)
|
||||
+ ((U32) wav_header[14] << 16)
|
||||
+ ((U32) wav_header[13] << 8)
|
||||
+ wav_header[12];
|
||||
bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
|
||||
bytes_per_sec = ((U32) wav_header[19] << 24)
|
||||
+ ((U32) wav_header[18] << 16)
|
||||
+ ((U32) wav_header[17] << 8)
|
||||
+ wav_header[16];
|
||||
}
|
||||
else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
|
||||
{
|
||||
raw_data_length = chunk_length;
|
||||
}
|
||||
file_pos += (chunk_length + 8);
|
||||
chunk_length = 0;
|
||||
}
|
||||
//****************
|
||||
infile.close();
|
||||
//****************
|
||||
|
||||
if (!uncompressed_pcm)
|
||||
{
|
||||
error_msg = "SoundFileNotPCM";
|
||||
return(LLVORBISENC_PCM_FORMAT_ERR);
|
||||
}
|
||||
|
||||
if ((num_channels < 1) || (num_channels > 2))
|
||||
{
|
||||
error_msg = "SoundFileInvalidChannelCount";
|
||||
return(LLVORBISENC_MULTICHANNEL_ERR);
|
||||
}
|
||||
|
||||
if (sample_rate != 44100)
|
||||
{
|
||||
error_msg = "SoundFileInvalidSampleRate";
|
||||
return(LLVORBISENC_UNSUPPORTED_SAMPLE_RATE);
|
||||
}
|
||||
|
||||
if ((bits_per_sample != 16) && (bits_per_sample != 8))
|
||||
{
|
||||
error_msg = "SoundFileInvalidWordSize";
|
||||
return(LLVORBISENC_UNSUPPORTED_WORD_SIZE);
|
||||
}
|
||||
|
||||
if (!raw_data_length)
|
||||
{
|
||||
error_msg = "SoundFileInvalidHeader";
|
||||
return(LLVORBISENC_CLIP_TOO_LONG);
|
||||
}
|
||||
|
||||
F32 clip_length = (F32)raw_data_length/(F32)bytes_per_sec;
|
||||
|
||||
if (clip_length > 10.0f)
|
||||
{
|
||||
error_msg = "SoundFileInvalidTooLong";
|
||||
return(LLVORBISENC_CLIP_TOO_LONG);
|
||||
}
|
||||
|
||||
return(LLVORBISENC_NOERR);
|
||||
}
|
||||
|
||||
S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname)
|
||||
{
|
||||
#define READ_BUFFER 1024
|
||||
unsigned char readbuffer[READ_BUFFER*4+44]; /* out of the data segment, not the stack */ /*Flawfinder: ignore*/
|
||||
|
||||
ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */
|
||||
ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
|
||||
ogg_packet op; /* one raw packet of data for decode */
|
||||
|
||||
vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */
|
||||
vorbis_comment vc; /* struct that stores all the user comments */
|
||||
|
||||
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
|
||||
vorbis_block vb; /* local working space for packet->PCM decode */
|
||||
|
||||
int eos=0;
|
||||
int result;
|
||||
|
||||
U16 num_channels = 0;
|
||||
U32 sample_rate = 0;
|
||||
U32 bits_per_sample = 0;
|
||||
|
||||
S32 format_error = 0;
|
||||
std::string error_msg;
|
||||
if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg)))
|
||||
{
|
||||
llwarns << error_msg << ": " << in_fname << llendl;
|
||||
return(format_error);
|
||||
}
|
||||
|
||||
#if 1
|
||||
unsigned char wav_header[44]; /*Flawfinder: ignore*/
|
||||
|
||||
S32 data_left = 0;
|
||||
|
||||
LLAPRFile infile ;
|
||||
infile.open(in_fname,LL_APR_RB);
|
||||
if (!infile.getFileHandle())
|
||||
{
|
||||
llwarns << "Couldn't open temporary ogg file for writing: " << in_fname
|
||||
<< llendl;
|
||||
return(LLVORBISENC_SOURCE_OPEN_ERR);
|
||||
}
|
||||
|
||||
LLAPRFile outfile ;
|
||||
outfile.open(out_fname,LL_APR_WPB);
|
||||
if (!outfile.getFileHandle())
|
||||
{
|
||||
llwarns << "Couldn't open upload sound file for reading: " << in_fname
|
||||
<< llendl;
|
||||
return(LLVORBISENC_DEST_OPEN_ERR);
|
||||
}
|
||||
|
||||
// parse the chunks
|
||||
U32 chunk_length = 0;
|
||||
U32 file_pos = 12; // start at the first chunk (usually fmt but not always)
|
||||
|
||||
while (infile.eof() != APR_EOF)
|
||||
{
|
||||
infile.seek(APR_SET,file_pos);
|
||||
infile.read(wav_header, 44);
|
||||
|
||||
chunk_length = ((U32) wav_header[7] << 24)
|
||||
+ ((U32) wav_header[6] << 16)
|
||||
+ ((U32) wav_header[5] << 8)
|
||||
+ wav_header[4];
|
||||
|
||||
// llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl;
|
||||
|
||||
if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
|
||||
{
|
||||
num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
|
||||
sample_rate = ((U32) wav_header[15] << 24)
|
||||
+ ((U32) wav_header[14] << 16)
|
||||
+ ((U32) wav_header[13] << 8)
|
||||
+ wav_header[12];
|
||||
bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
|
||||
}
|
||||
else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
|
||||
{
|
||||
infile.seek(APR_SET,file_pos+8);
|
||||
// leave the file pointer at the beginning of the data chunk data
|
||||
data_left = chunk_length;
|
||||
break;
|
||||
}
|
||||
file_pos += (chunk_length + 8);
|
||||
chunk_length = 0;
|
||||
}
|
||||
|
||||
|
||||
/********** Encode setup ************/
|
||||
|
||||
/* choose an encoding mode */
|
||||
/* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
|
||||
vorbis_info_init(&vi);
|
||||
|
||||
// always encode to mono
|
||||
|
||||
// SL-52913 & SL-53779 determined this quality level to be our 'good
|
||||
// enough' general-purpose quality level with a nice low bitrate.
|
||||
// Equivalent to oggenc -q0.5
|
||||
F32 quality = 0.05f;
|
||||
// quality = (bitrate==128000 ? 0.4f : 0.1);
|
||||
|
||||
// if (vorbis_encode_init(&vi, /* num_channels */ 1 ,sample_rate, -1, bitrate, -1))
|
||||
if (vorbis_encode_init_vbr(&vi, /* num_channels */ 1 ,sample_rate, quality))
|
||||
// if (vorbis_encode_setup_managed(&vi,1,sample_rate,-1,bitrate,-1) ||
|
||||
// vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE_AVG,NULL) ||
|
||||
// vorbis_encode_setup_init(&vi))
|
||||
{
|
||||
llwarns << "unable to initialize vorbis codec at quality " << quality << llendl;
|
||||
// llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl;
|
||||
return(LLVORBISENC_DEST_OPEN_ERR);
|
||||
}
|
||||
|
||||
/* add a comment */
|
||||
vorbis_comment_init(&vc);
|
||||
// vorbis_comment_add(&vc,"Linden");
|
||||
|
||||
/* set up the analysis state and auxiliary encoding storage */
|
||||
vorbis_analysis_init(&vd,&vi);
|
||||
vorbis_block_init(&vd,&vb);
|
||||
|
||||
/* set up our packet->stream encoder */
|
||||
/* pick a random serial number; that way we can more likely build
|
||||
chained streams just by concatenation */
|
||||
ogg_stream_init(&os, ll_rand());
|
||||
|
||||
/* Vorbis streams begin with three headers; the initial header (with
|
||||
most of the codec setup parameters) which is mandated by the Ogg
|
||||
bitstream spec. The second header holds any comment fields. The
|
||||
third header holds the bitstream codebook. We merely need to
|
||||
make the headers, then pass them to libvorbis one at a time;
|
||||
libvorbis handles the additional Ogg bitstream constraints */
|
||||
|
||||
{
|
||||
ogg_packet header;
|
||||
ogg_packet header_comm;
|
||||
ogg_packet header_code;
|
||||
|
||||
vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
|
||||
ogg_stream_packetin(&os,&header); /* automatically placed in its own
|
||||
page */
|
||||
ogg_stream_packetin(&os,&header_comm);
|
||||
ogg_stream_packetin(&os,&header_code);
|
||||
|
||||
/* We don't have to write out here, but doing so makes streaming
|
||||
* much easier, so we do, flushing ALL pages. This ensures the actual
|
||||
* audio data will start on a new page
|
||||
*/
|
||||
while(!eos){
|
||||
int result=ogg_stream_flush(&os,&og);
|
||||
if(result==0)break;
|
||||
outfile.write(og.header, og.header_len);
|
||||
outfile.write(og.body, og.body_len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
while(!eos)
|
||||
{
|
||||
long bytes_per_sample = bits_per_sample/8;
|
||||
|
||||
long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */
|
||||
|
||||
if (bytes==0)
|
||||
{
|
||||
/* end of file. this can be done implicitly in the mainline,
|
||||
but it's easier to see here in non-clever fashion.
|
||||
Tell the library we're at end of stream so that it can handle
|
||||
the last frame and mark end of stream in the output properly */
|
||||
|
||||
vorbis_analysis_wrote(&vd,0);
|
||||
// eos = 1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
long i;
|
||||
long samples;
|
||||
int temp;
|
||||
|
||||
data_left -= bytes;
|
||||
/* data to encode */
|
||||
|
||||
/* expose the buffer to submit data */
|
||||
float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER);
|
||||
|
||||
i = 0;
|
||||
samples = bytes / (num_channels * bytes_per_sample);
|
||||
|
||||
if (num_channels == 2)
|
||||
{
|
||||
if (bytes_per_sample == 2)
|
||||
{
|
||||
/* uninterleave samples */
|
||||
for(i=0; i<samples ;i++)
|
||||
{
|
||||
temp = ((signed char *)readbuffer)[i*4+1]; /*Flawfinder: ignore*/
|
||||
temp += ((signed char *)readbuffer)[i*4+3]; /*Flawfinder: ignore*/
|
||||
temp <<= 8;
|
||||
temp += readbuffer[i*4];
|
||||
temp += readbuffer[i*4+2];
|
||||
|
||||
buffer[0][i] = ((float)temp) / 65536.f;
|
||||
}
|
||||
}
|
||||
else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
|
||||
{
|
||||
/* uninterleave samples */
|
||||
for(i=0; i<samples ;i++)
|
||||
{
|
||||
temp = readbuffer[i*2+0];
|
||||
temp += readbuffer[i*2+1];
|
||||
temp -= 256;
|
||||
buffer[0][i] = ((float)temp) / 256.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (num_channels == 1)
|
||||
{
|
||||
if (bytes_per_sample == 2)
|
||||
{
|
||||
for(i=0; i < samples ;i++)
|
||||
{
|
||||
temp = ((signed char*)readbuffer)[i*2+1];
|
||||
temp <<= 8;
|
||||
temp += readbuffer[i*2];
|
||||
buffer[0][i] = ((float)temp) / 32768.f;
|
||||
}
|
||||
}
|
||||
else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
|
||||
{
|
||||
for(i=0; i < samples ;i++)
|
||||
{
|
||||
temp = readbuffer[i];
|
||||
temp -= 128;
|
||||
buffer[0][i] = ((float)temp) / 128.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* tell the library how much we actually submitted */
|
||||
vorbis_analysis_wrote(&vd,i);
|
||||
}
|
||||
|
||||
/* vorbis does some data preanalysis, then divvies up blocks for
|
||||
more involved (potentially parallel) processing. Get a single
|
||||
block for encoding now */
|
||||
while(vorbis_analysis_blockout(&vd,&vb)==1)
|
||||
{
|
||||
|
||||
/* analysis */
|
||||
/* Do the main analysis, creating a packet */
|
||||
vorbis_analysis(&vb, NULL);
|
||||
vorbis_bitrate_addblock(&vb);
|
||||
|
||||
while(vorbis_bitrate_flushpacket(&vd, &op))
|
||||
{
|
||||
|
||||
/* weld the packet into the bitstream */
|
||||
ogg_stream_packetin(&os,&op);
|
||||
|
||||
/* write out pages (if any) */
|
||||
while(!eos)
|
||||
{
|
||||
result = ogg_stream_pageout(&os,&og);
|
||||
|
||||
if(result==0)
|
||||
break;
|
||||
|
||||
outfile.write(og.header, og.header_len);
|
||||
outfile.write(og.body, og.body_len);
|
||||
|
||||
/* this could be set above, but for illustrative purposes, I do
|
||||
it here (to show that vorbis does know where the stream ends) */
|
||||
|
||||
if(ogg_page_eos(&og))
|
||||
eos=1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* clean up and exit. vorbis_info_clear() must be called last */
|
||||
|
||||
ogg_stream_clear(&os);
|
||||
vorbis_block_clear(&vb);
|
||||
vorbis_dsp_clear(&vd);
|
||||
vorbis_comment_clear(&vc);
|
||||
vorbis_info_clear(&vi);
|
||||
|
||||
/* ogg_page and ogg_packet structs always point to storage in
|
||||
libvorbis. They're never freed or manipulated directly */
|
||||
|
||||
// fprintf(stderr,"Vorbis encoding: Done.\n");
|
||||
llinfos << "Vorbis encoding: Done." << llendl;
|
||||
|
||||
#endif
|
||||
return(LLVORBISENC_NOERR);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* @file vorbisencode.h
|
||||
* @brief Vorbis encoding routine routine for Indra.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-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_VORBISENCODE_H
|
||||
#define LL_VORBISENCODE_H
|
||||
|
||||
const S32 LLVORBISENC_NOERR = 0; // no error
|
||||
const S32 LLVORBISENC_SOURCE_OPEN_ERR = 1; // error opening source
|
||||
const S32 LLVORBISENC_DEST_OPEN_ERR = 2; // error opening destination
|
||||
const S32 LLVORBISENC_WAV_FORMAT_ERR = 3; // not a WAV
|
||||
const S32 LLVORBISENC_PCM_FORMAT_ERR = 4; // not a PCM
|
||||
const S32 LLVORBISENC_MONO_ERR = 5; // can't do mono
|
||||
const S32 LLVORBISENC_STEREO_ERR = 6; // can't do stereo
|
||||
const S32 LLVORBISENC_MULTICHANNEL_ERR = 7; // can't do stereo
|
||||
const S32 LLVORBISENC_UNSUPPORTED_SAMPLE_RATE = 8; // unsupported sample rate
|
||||
const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size
|
||||
const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long
|
||||
|
||||
|
||||
S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg);
|
||||
S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* @file windgen.h
|
||||
* @brief Templated wind noise generation
|
||||
*
|
||||
* $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 WINDGEN_H
|
||||
#define WINDGEN_H
|
||||
|
||||
#include "llcommon.h"
|
||||
#include "llrand.h"
|
||||
|
||||
template <class MIXBUFFERFORMAT_T>
|
||||
class LLWindGen
|
||||
{
|
||||
public:
|
||||
LLWindGen() :
|
||||
mTargetGain(0.f),
|
||||
mTargetFreq(100.f),
|
||||
mTargetPanGainR(0.5f),
|
||||
mbuf0(0.0),
|
||||
mbuf1(0.0),
|
||||
mbuf2(0.0),
|
||||
mbuf3(0.0),
|
||||
mbuf4(0.0),
|
||||
mbuf5(0.0),
|
||||
mY0(0.0),
|
||||
mY1(0.0),
|
||||
mCurrentGain(0.f),
|
||||
mCurrentFreq(100.f),
|
||||
mCurrentPanGainR(0.5f) {};
|
||||
|
||||
static const U32 getInputSamplingRate() {return mInputSamplingRate;}
|
||||
|
||||
// newbuffer = the buffer passed from the previous DSP unit.
|
||||
// numsamples = length in samples-per-channel at this mix time.
|
||||
// stride = number of bytes between start of each sample.
|
||||
// NOTE: generates L/R interleaved stereo
|
||||
MIXBUFFERFORMAT_T* windGenerate(MIXBUFFERFORMAT_T *newbuffer, int numsamples, int stride)
|
||||
{
|
||||
U8 *cursamplep = (U8*)newbuffer;
|
||||
|
||||
double bandwidth = 50.0F;
|
||||
double a0,b1,b2;
|
||||
|
||||
// calculate resonant filter coeffs
|
||||
b2 = exp(-(F_TWO_PI) * (bandwidth / mInputSamplingRate));
|
||||
|
||||
while (numsamples--)
|
||||
{
|
||||
mCurrentFreq = (float)((0.999 * mCurrentFreq) + (0.001 * mTargetFreq));
|
||||
mCurrentGain = (float)((0.999 * mCurrentGain) + (0.001 * mTargetGain));
|
||||
mCurrentPanGainR = (float)((0.999 * mCurrentPanGainR) + (0.001 * mTargetPanGainR));
|
||||
b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (mCurrentFreq / mInputSamplingRate));
|
||||
a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2));
|
||||
double nextSample;
|
||||
|
||||
// start with white noise
|
||||
nextSample = ll_frand(2.0f) - 1.0f;
|
||||
|
||||
// apply pinking filter
|
||||
mbuf0 = 0.997f * mbuf0 + 0.0126502f * nextSample;
|
||||
mbuf1 = 0.985f * mbuf1 + 0.0139083f * nextSample;
|
||||
mbuf2 = 0.950f * mbuf2 + 0.0205439f * nextSample;
|
||||
mbuf3 = 0.850f * mbuf3 + 0.0387225f * nextSample;
|
||||
mbuf4 = 0.620f * mbuf4 + 0.0465932f * nextSample;
|
||||
mbuf5 = 0.250f * mbuf5 + 0.1093477f * nextSample;
|
||||
|
||||
nextSample = mbuf0 + mbuf1 + mbuf2 + mbuf3 + mbuf4 + mbuf5;
|
||||
|
||||
// do a resonant filter on the noise
|
||||
nextSample = (double)( a0 * nextSample - b1 * mY0 - b2 * mY1 );
|
||||
mY1 = mY0;
|
||||
mY0 = nextSample;
|
||||
|
||||
nextSample *= mCurrentGain;
|
||||
|
||||
MIXBUFFERFORMAT_T sample;
|
||||
|
||||
sample = llfloor(((F32)nextSample*32768.f*(1.0f - mCurrentPanGainR))+0.5f);
|
||||
*(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767);
|
||||
cursamplep += stride;
|
||||
|
||||
sample = llfloor(((F32)nextSample*32768.f*mCurrentPanGainR)+0.5f);
|
||||
*(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767);
|
||||
cursamplep += stride;
|
||||
}
|
||||
|
||||
return newbuffer;
|
||||
}
|
||||
|
||||
F32 mTargetGain;
|
||||
F32 mTargetFreq;
|
||||
F32 mTargetPanGainR;
|
||||
|
||||
private:
|
||||
static const U32 mInputSamplingRate = 44100;
|
||||
F64 mbuf0;
|
||||
F64 mbuf1;
|
||||
F64 mbuf2;
|
||||
F64 mbuf3;
|
||||
F64 mbuf4;
|
||||
F64 mbuf5;
|
||||
F64 mY0;
|
||||
F64 mY1;
|
||||
F32 mCurrentGain;
|
||||
F32 mCurrentFreq;
|
||||
F32 mCurrentPanGainR;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -56,7 +56,7 @@ const F32 ROTATION_MOTION_THRESHOLD = 0.001f;
|
|||
|
||||
char gInFile[1024]; /* Flawfinder: ignore */
|
||||
char gOutFile[1024]; /* Flawfinder: ignore */
|
||||
|
||||
/*
|
||||
//------------------------------------------------------------------------
|
||||
// Status Codes
|
||||
//------------------------------------------------------------------------
|
||||
|
|
@ -91,7 +91,7 @@ const char *LLBVHLoader::ST_NO_XLT_EASEIN = "Can't get easeIn values.";
|
|||
const char *LLBVHLoader::ST_NO_XLT_EASEOUT = "Can't get easeOut values.";
|
||||
const char *LLBVHLoader::ST_NO_XLT_HAND = "Can't get hand morph value.";
|
||||
const char *LLBVHLoader::ST_NO_XLT_EMOTE = "Can't read emote name.";
|
||||
|
||||
*/
|
||||
//------------------------------------------------------------------------
|
||||
// find_next_whitespace()
|
||||
//------------------------------------------------------------------------
|
||||
|
|
@ -124,7 +124,9 @@ LLQuaternion::Order bvhStringToOrder( char *str )
|
|||
//-----------------------------------------------------------------------------
|
||||
// LLBVHLoader()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLBVHLoader::LLBVHLoader(const char* buffer)
|
||||
|
||||
/*
|
||||
LLBVHLoader::LLBVHLoader(const char* buffer)
|
||||
{
|
||||
reset();
|
||||
|
||||
|
|
@ -144,7 +146,7 @@ LLBVHLoader::LLBVHLoader(const char* buffer)
|
|||
}
|
||||
}
|
||||
|
||||
char error_text[128]; /* Flawfinder: ignore */
|
||||
char error_text[128]; // Flawfinder: ignore
|
||||
S32 error_line;
|
||||
mStatus = loadBVHFile(buffer, error_text, error_line);
|
||||
if (mStatus != LLBVHLoader::ST_OK)
|
||||
|
|
@ -158,6 +160,49 @@ LLBVHLoader::LLBVHLoader(const char* buffer)
|
|||
|
||||
mInitialized = TRUE;
|
||||
}
|
||||
*/
|
||||
LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine)
|
||||
{
|
||||
reset();
|
||||
errorLine = 0;
|
||||
mStatus = loadTranslationTable("anim.ini");
|
||||
loadStatus = mStatus;
|
||||
llinfos<<"Load Status 00 : "<< loadStatus << llendl;
|
||||
if (mStatus == E_ST_NO_XLT_FILE)
|
||||
{
|
||||
//llwarns << "NOTE: No translation table found." << llendl;
|
||||
loadStatus = mStatus;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mStatus != E_ST_OK)
|
||||
{
|
||||
//llwarns << "ERROR: [line: " << getLineNumber() << "] " << mStatus << llendl;
|
||||
errorLine = getLineNumber();
|
||||
loadStatus = mStatus;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char error_text[128]; /* Flawfinder: ignore */
|
||||
S32 error_line;
|
||||
mStatus = loadBVHFile(buffer, error_text, error_line);
|
||||
|
||||
if (mStatus != E_ST_OK)
|
||||
{
|
||||
//llwarns << "ERROR: [line: " << getLineNumber() << "] " << mStatus << llendl;
|
||||
loadStatus = mStatus;
|
||||
errorLine = getLineNumber();
|
||||
return;
|
||||
}
|
||||
|
||||
applyTranslations();
|
||||
optimize();
|
||||
|
||||
mInitialized = TRUE;
|
||||
}
|
||||
|
||||
|
||||
LLBVHLoader::~LLBVHLoader()
|
||||
{
|
||||
|
|
@ -167,7 +212,7 @@ LLBVHLoader::~LLBVHLoader()
|
|||
//------------------------------------------------------------------------
|
||||
// LLBVHLoader::loadTranslationTable()
|
||||
//------------------------------------------------------------------------
|
||||
LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
||||
ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
|
||||
{
|
||||
mLineNumber = 0;
|
||||
mTranslations.clear();
|
||||
|
|
@ -182,7 +227,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
infile.open(path, LL_APR_R);
|
||||
apr_file_t *fp = infile.getFileHandle();
|
||||
if (!fp)
|
||||
return ST_NO_XLT_FILE;
|
||||
return E_ST_NO_XLT_FILE;
|
||||
|
||||
llinfos << "NOTE: Loading translation table: " << fileName << llendl;
|
||||
|
||||
|
|
@ -194,9 +239,9 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
// load header
|
||||
//--------------------------------------------------------------------
|
||||
if ( ! getLine(fp) )
|
||||
return ST_EOF;
|
||||
return E_ST_EOF;
|
||||
if ( strncmp(mLine, "Translations 1.0", 16) )
|
||||
return ST_NO_XLT_HEADER;
|
||||
return E_ST_NO_XLT_HEADER;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// load data one line at a time
|
||||
|
|
@ -222,7 +267,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
{
|
||||
char name[128]; /* Flawfinder: ignore */
|
||||
if ( sscanf(mLine, " [%127[^]]", name) != 1 )
|
||||
return ST_NO_XLT_NAME;
|
||||
return E_ST_NO_XLT_NAME;
|
||||
|
||||
if (strcmp(name, "GLOBALS")==0)
|
||||
{
|
||||
|
|
@ -245,7 +290,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
{
|
||||
char emote_str[1024]; /* Flawfinder: ignore */
|
||||
if ( sscanf(mLine, " %*s = %1023s", emote_str) != 1 ) /* Flawfinder: ignore */
|
||||
return ST_NO_XLT_EMOTE;
|
||||
return E_ST_NO_XLT_EMOTE;
|
||||
|
||||
mEmoteName.assign( emote_str );
|
||||
// llinfos << "NOTE: Emote: " << mEmoteName.c_str() << llendl;
|
||||
|
|
@ -260,7 +305,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
{
|
||||
S32 priority;
|
||||
if ( sscanf(mLine, " %*s = %d", &priority) != 1 )
|
||||
return ST_NO_XLT_PRIORITY;
|
||||
return E_ST_NO_XLT_PRIORITY;
|
||||
|
||||
mPriority = priority;
|
||||
// llinfos << "NOTE: Priority: " << mPriority << llendl;
|
||||
|
|
@ -288,7 +333,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
}
|
||||
else
|
||||
{
|
||||
return ST_NO_XLT_LOOP;
|
||||
return E_ST_NO_XLT_LOOP;
|
||||
}
|
||||
|
||||
mLoopInPoint = loop_in * mDuration;
|
||||
|
|
@ -305,7 +350,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
F32 duration;
|
||||
char type[128]; /* Flawfinder: ignore */
|
||||
if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */
|
||||
return ST_NO_XLT_EASEIN;
|
||||
return E_ST_NO_XLT_EASEIN;
|
||||
|
||||
mEaseIn = duration;
|
||||
continue;
|
||||
|
|
@ -319,7 +364,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
F32 duration;
|
||||
char type[128]; /* Flawfinder: ignore */
|
||||
if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */
|
||||
return ST_NO_XLT_EASEOUT;
|
||||
return E_ST_NO_XLT_EASEOUT;
|
||||
|
||||
mEaseOut = duration;
|
||||
continue;
|
||||
|
|
@ -332,7 +377,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
{
|
||||
S32 handMorph;
|
||||
if (sscanf(mLine, " %*s = %d", &handMorph) != 1)
|
||||
return ST_NO_XLT_HAND;
|
||||
return E_ST_NO_XLT_HAND;
|
||||
|
||||
mHand = handMorph;
|
||||
continue;
|
||||
|
|
@ -380,7 +425,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
&constraint.mTargetOffset.mV[VY],
|
||||
&constraint.mTargetOffset.mV[VZ]) != 13)
|
||||
{
|
||||
return ST_NO_CONSTRAINT;
|
||||
return E_ST_NO_CONSTRAINT;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -440,7 +485,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
&constraint.mTargetOffset.mV[VY],
|
||||
&constraint.mTargetOffset.mV[VZ]) != 13)
|
||||
{
|
||||
return ST_NO_CONSTRAINT;
|
||||
return E_ST_NO_CONSTRAINT;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -463,7 +508,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
// at this point there must be a valid trans pointer
|
||||
//----------------------------------------------------------------
|
||||
if ( ! trans )
|
||||
return ST_NO_XLT_NAME;
|
||||
return E_ST_NO_XLT_NAME;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// check for ignore flag
|
||||
|
|
@ -472,7 +517,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
{
|
||||
char trueFalse[128]; /* Flawfinder: ignore */
|
||||
if ( sscanf(mLine, " %*s = %127s", trueFalse) != 1 ) /* Flawfinder: ignore */
|
||||
return ST_NO_XLT_IGNORE;
|
||||
return E_ST_NO_XLT_IGNORE;
|
||||
|
||||
trans->mIgnore = (LLStringUtil::compareInsensitive(trueFalse, "true")==0);
|
||||
continue;
|
||||
|
|
@ -497,12 +542,12 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
}
|
||||
else
|
||||
{
|
||||
return ST_NO_XLT_RELATIVE;
|
||||
return E_ST_NO_XLT_RELATIVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ST_NO_XLT_RELATIVE;
|
||||
return E_ST_NO_XLT_RELATIVE;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
|
@ -523,12 +568,12 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
}
|
||||
else
|
||||
{
|
||||
return ST_NO_XLT_RELATIVE;
|
||||
return E_ST_NO_XLT_RELATIVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ST_NO_XLT_RELATIVE;
|
||||
return E_ST_NO_XLT_RELATIVE;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
|
@ -541,7 +586,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
{
|
||||
char outName[128]; /* Flawfinder: ignore */
|
||||
if ( sscanf(mLine, " %*s = %127s", outName) != 1 ) /* Flawfinder: ignore */
|
||||
return ST_NO_XLT_OUTNAME;
|
||||
return E_ST_NO_XLT_OUTNAME;
|
||||
|
||||
trans->mOutName = outName;
|
||||
continue;
|
||||
|
|
@ -557,7 +602,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
&fm.mMatrix[0][0], &fm.mMatrix[0][1], &fm.mMatrix[0][2],
|
||||
&fm.mMatrix[1][0], &fm.mMatrix[1][1], &fm.mMatrix[1][2],
|
||||
&fm.mMatrix[2][0], &fm.mMatrix[2][1], &fm.mMatrix[2][2] ) != 9 )
|
||||
return ST_NO_XLT_MATRIX;
|
||||
return E_ST_NO_XLT_MATRIX;
|
||||
|
||||
trans->mFrameMatrix = fm;
|
||||
continue;
|
||||
|
|
@ -573,7 +618,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
&om.mMatrix[0][0], &om.mMatrix[0][1], &om.mMatrix[0][2],
|
||||
&om.mMatrix[1][0], &om.mMatrix[1][1], &om.mMatrix[1][2],
|
||||
&om.mMatrix[2][0], &om.mMatrix[2][1], &om.mMatrix[2][2] ) != 9 )
|
||||
return ST_NO_XLT_MATRIX;
|
||||
return E_ST_NO_XLT_MATRIX;
|
||||
|
||||
trans->mOffsetMatrix = om;
|
||||
continue;
|
||||
|
|
@ -586,7 +631,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
{
|
||||
char mergeParentName[128]; /* Flawfinder: ignore */
|
||||
if ( sscanf(mLine, " %*s = %127s", mergeParentName) != 1 ) /* Flawfinder: ignore */
|
||||
return ST_NO_XLT_MERGEPARENT;
|
||||
return E_ST_NO_XLT_MERGEPARENT;
|
||||
|
||||
trans->mMergeParentName = mergeParentName;
|
||||
continue;
|
||||
|
|
@ -599,7 +644,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
{
|
||||
char mergeChildName[128]; /* Flawfinder: ignore */
|
||||
if ( sscanf(mLine, " %*s = %127s", mergeChildName) != 1 ) /* Flawfinder: ignore */
|
||||
return ST_NO_XLT_MERGECHILD;
|
||||
return E_ST_NO_XLT_MERGECHILD;
|
||||
|
||||
trans->mMergeChildName = mergeChildName;
|
||||
continue;
|
||||
|
|
@ -612,7 +657,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
{
|
||||
S32 priority;
|
||||
if ( sscanf(mLine, " %*s = %d", &priority) != 1 )
|
||||
return ST_NO_XLT_PRIORITY;
|
||||
return E_ST_NO_XLT_PRIORITY;
|
||||
|
||||
trans->mPriorityModifier = priority;
|
||||
continue;
|
||||
|
|
@ -621,14 +666,14 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
|
|||
}
|
||||
|
||||
infile.close() ;
|
||||
return ST_OK;
|
||||
return E_ST_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// LLBVHLoader::loadBVHFile()
|
||||
//------------------------------------------------------------------------
|
||||
LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &err_line)
|
||||
ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &err_line)
|
||||
{
|
||||
std::string line;
|
||||
|
||||
|
|
@ -650,14 +695,14 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
// consume hierarchy
|
||||
//--------------------------------------------------------------------
|
||||
if (iter == tokens.end())
|
||||
return ST_EOF;
|
||||
return E_ST_EOF;
|
||||
line = (*(iter++));
|
||||
err_line++;
|
||||
|
||||
if ( !strstr(line.c_str(), "HIERARCHY") )
|
||||
{
|
||||
// llinfos << line << llendl;
|
||||
return ST_NO_HIER;
|
||||
return E_ST_NO_HIER;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -669,7 +714,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
// get next line
|
||||
//----------------------------------------------------------------
|
||||
if (iter == tokens.end())
|
||||
return ST_EOF;
|
||||
return E_ST_EOF;
|
||||
line = (*(iter++));
|
||||
err_line++;
|
||||
|
||||
|
|
@ -719,7 +764,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
else
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */
|
||||
return ST_NO_JOINT;
|
||||
return E_ST_NO_JOINT;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
|
@ -729,7 +774,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if ( sscanf(line.c_str(), "%*s %79s", jointName) != 1 ) /* Flawfinder: ignore */
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */
|
||||
return ST_NO_NAME;
|
||||
return E_ST_NO_NAME;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
|
@ -754,7 +799,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
//----------------------------------------------------------------
|
||||
if (iter == tokens.end())
|
||||
{
|
||||
return ST_EOF;
|
||||
return E_ST_EOF;
|
||||
}
|
||||
line = (*(iter++));
|
||||
err_line++;
|
||||
|
|
@ -765,7 +810,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if ( !strstr(line.c_str(), "{") )
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_OFFSET;
|
||||
return E_ST_NO_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -777,7 +822,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
//----------------------------------------------------------------
|
||||
if (iter == tokens.end())
|
||||
{
|
||||
return ST_EOF;
|
||||
return E_ST_EOF;
|
||||
}
|
||||
line = (*(iter++));
|
||||
err_line++;
|
||||
|
|
@ -788,7 +833,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if ( !strstr(line.c_str(), "OFFSET") )
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_OFFSET;
|
||||
return E_ST_NO_OFFSET;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
|
@ -796,7 +841,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
//----------------------------------------------------------------
|
||||
if (iter == tokens.end())
|
||||
{
|
||||
return ST_EOF;
|
||||
return E_ST_EOF;
|
||||
}
|
||||
line = (*(iter++));
|
||||
err_line++;
|
||||
|
|
@ -807,7 +852,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if ( !strstr(line.c_str(), "CHANNELS") )
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_CHANNELS;
|
||||
return E_ST_NO_CHANNELS;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
|
@ -820,14 +865,14 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if (!p)
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_ROTATION;
|
||||
return E_ST_NO_ROTATION;
|
||||
}
|
||||
|
||||
const char axis = *(p - 1);
|
||||
if ((axis != 'X') && (axis != 'Y') && (axis != 'Z'))
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_AXIS;
|
||||
return E_ST_NO_AXIS;
|
||||
}
|
||||
|
||||
joint->mOrder[i] = axis;
|
||||
|
|
@ -842,7 +887,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if ( !strstr(line.c_str(), "MOTION") )
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_MOTION;
|
||||
return E_ST_NO_MOTION;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -850,7 +895,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
//--------------------------------------------------------------------
|
||||
if (iter == tokens.end())
|
||||
{
|
||||
return ST_EOF;
|
||||
return E_ST_EOF;
|
||||
}
|
||||
line = (*(iter++));
|
||||
err_line++;
|
||||
|
|
@ -858,13 +903,13 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if ( !strstr(line.c_str(), "Frames:") )
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_FRAMES;
|
||||
return E_ST_NO_FRAMES;
|
||||
}
|
||||
|
||||
if ( sscanf(line.c_str(), "Frames: %d", &mNumFrames) != 1 )
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_FRAMES;
|
||||
return E_ST_NO_FRAMES;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -872,7 +917,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
//--------------------------------------------------------------------
|
||||
if (iter == tokens.end())
|
||||
{
|
||||
return ST_EOF;
|
||||
return E_ST_EOF;
|
||||
}
|
||||
line = (*(iter++));
|
||||
err_line++;
|
||||
|
|
@ -880,13 +925,13 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if ( !strstr(line.c_str(), "Frame Time:") )
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_FRAME_TIME;
|
||||
return E_ST_NO_FRAME_TIME;
|
||||
}
|
||||
|
||||
if ( sscanf(line.c_str(), "Frame Time: %f", &mFrameTime) != 1 )
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_FRAME_TIME;
|
||||
return E_ST_NO_FRAME_TIME;
|
||||
}
|
||||
|
||||
mDuration = (F32)mNumFrames * mFrameTime;
|
||||
|
|
@ -903,7 +948,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
// get next line
|
||||
if (iter == tokens.end())
|
||||
{
|
||||
return ST_EOF;
|
||||
return E_ST_EOF;
|
||||
}
|
||||
line = (*(iter++));
|
||||
err_line++;
|
||||
|
|
@ -922,7 +967,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if ( sscanf(p, "%f %f %f", key.mPos, key.mPos+1, key.mPos+2) != 3 )
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_POS;
|
||||
return E_ST_NO_POS;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -931,19 +976,19 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if (!p)
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_ROT;
|
||||
return E_ST_NO_ROT;
|
||||
}
|
||||
p = find_next_whitespace(++p);
|
||||
if (!p)
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_ROT;
|
||||
return E_ST_NO_ROT;
|
||||
}
|
||||
p = find_next_whitespace(++p);
|
||||
if (!p)
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_ROT;
|
||||
return E_ST_NO_ROT;
|
||||
}
|
||||
|
||||
// get 3 rot values for joint
|
||||
|
|
@ -951,7 +996,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
if ( sscanf(p, " %f %f %f", rot, rot+1, rot+2) != 3 )
|
||||
{
|
||||
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
|
||||
return ST_NO_ROT;
|
||||
return E_ST_NO_ROT;
|
||||
}
|
||||
|
||||
p++;
|
||||
|
|
@ -962,7 +1007,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
|
|||
}
|
||||
}
|
||||
|
||||
return ST_OK;
|
||||
return E_ST_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -184,6 +184,41 @@ public:
|
|||
S32 mPriorityModifier;
|
||||
};
|
||||
|
||||
typedef enum e_load_status
|
||||
{
|
||||
E_ST_OK,
|
||||
E_ST_EOF,
|
||||
E_ST_NO_CONSTRAINT,
|
||||
E_ST_NO_FILE,
|
||||
E_ST_NO_HIER,
|
||||
E_ST_NO_JOINT,
|
||||
E_ST_NO_NAME,
|
||||
E_ST_NO_OFFSET,
|
||||
E_ST_NO_CHANNELS,
|
||||
E_ST_NO_ROTATION,
|
||||
E_ST_NO_AXIS,
|
||||
E_ST_NO_MOTION,
|
||||
E_ST_NO_FRAMES,
|
||||
E_ST_NO_FRAME_TIME,
|
||||
E_ST_NO_POS,
|
||||
E_ST_NO_ROT,
|
||||
E_ST_NO_XLT_FILE,
|
||||
E_ST_NO_XLT_HEADER,
|
||||
E_ST_NO_XLT_NAME,
|
||||
E_ST_NO_XLT_IGNORE,
|
||||
E_ST_NO_XLT_RELATIVE,
|
||||
E_ST_NO_XLT_OUTNAME,
|
||||
E_ST_NO_XLT_MATRIX,
|
||||
E_ST_NO_XLT_MERGECHILD,
|
||||
E_ST_NO_XLT_MERGEPARENT,
|
||||
E_ST_NO_XLT_PRIORITY,
|
||||
E_ST_NO_XLT_LOOP,
|
||||
E_ST_NO_XLT_EASEIN,
|
||||
E_ST_NO_XLT_EASEOUT,
|
||||
E_ST_NO_XLT_HAND,
|
||||
E_ST_NO_XLT_EMOTE
|
||||
} ELoadStatus;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// TranslationMap
|
||||
//------------------------------------------------------------------------
|
||||
|
|
@ -194,9 +229,11 @@ class LLBVHLoader
|
|||
friend class LLKeyframeMotion;
|
||||
public:
|
||||
// Constructor
|
||||
LLBVHLoader(const char* buffer);
|
||||
// LLBVHLoader(const char* buffer);
|
||||
LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine);
|
||||
~LLBVHLoader();
|
||||
|
||||
|
||||
/*
|
||||
// Status Codes
|
||||
typedef const char *Status;
|
||||
static const char *ST_OK;
|
||||
|
|
@ -230,13 +267,13 @@ public:
|
|||
static const char *ST_NO_XLT_EASEOUT;
|
||||
static const char *ST_NO_XLT_HAND;
|
||||
static const char *ST_NO_XLT_EMOTE;
|
||||
|
||||
*/
|
||||
// Loads the specified translation table.
|
||||
Status loadTranslationTable(const char *fileName);
|
||||
ELoadStatus loadTranslationTable(const char *fileName);
|
||||
|
||||
// Load the specified BVH file.
|
||||
// Returns status code.
|
||||
Status loadBVHFile(const char *buffer, char *error_text, S32 &error_line);
|
||||
ELoadStatus loadBVHFile(const char *buffer, char *error_text, S32 &error_line);
|
||||
|
||||
// Applies translations to BVH data loaded.
|
||||
void applyTranslations();
|
||||
|
|
@ -260,7 +297,7 @@ public:
|
|||
|
||||
BOOL isInitialized() { return mInitialized; }
|
||||
|
||||
Status getStatus() { return mStatus; }
|
||||
ELoadStatus getStatus() { return mStatus; }
|
||||
|
||||
protected:
|
||||
// Consumes one line of input from file.
|
||||
|
|
@ -287,7 +324,7 @@ protected:
|
|||
std::string mEmoteName;
|
||||
|
||||
BOOL mInitialized;
|
||||
Status mStatus;
|
||||
ELoadStatus mStatus;
|
||||
// computed values
|
||||
F32 mDuration;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -180,9 +180,11 @@ void LLCharacter::requestStopMotion( LLMotion* motion)
|
|||
//-----------------------------------------------------------------------------
|
||||
// updateMotions()
|
||||
//-----------------------------------------------------------------------------
|
||||
static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation");
|
||||
|
||||
void LLCharacter::updateMotions(e_update_t update_type)
|
||||
{
|
||||
LLFastTimer t(LLFastTimer::FTM_UPDATE_ANIMATION);
|
||||
LLFastTimer t(FTM_UPDATE_ANIMATION);
|
||||
if (update_type == HIDDEN_UPDATE)
|
||||
{
|
||||
mMotionController.updateMotionsMinimal();
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
#include "llmotioncontroller.h"
|
||||
#include "llvisualparam.h"
|
||||
#include "string_table.h"
|
||||
#include "llmemory.h"
|
||||
#include "llpointer.h"
|
||||
#include "llthread.h"
|
||||
|
||||
class LLPolyMesh;
|
||||
|
|
@ -169,7 +169,7 @@ public:
|
|||
void updateMotions(e_update_t update_type);
|
||||
|
||||
LLAnimPauseRequest requestPause();
|
||||
BOOL areAnimationsPaused() { return mMotionController.isPaused(); }
|
||||
BOOL areAnimationsPaused() const { return mMotionController.isPaused(); }
|
||||
void setAnimTimeFactor(F32 factor) { mMotionController.setTimeFactor(factor); }
|
||||
void setTimeStep(F32 time_step) { mMotionController.setTimeStep(time_step); }
|
||||
|
||||
|
|
@ -231,9 +231,9 @@ public:
|
|||
return (mCurIterator++)->second;
|
||||
}
|
||||
|
||||
LLVisualParam* getVisualParam(S32 id)
|
||||
LLVisualParam* getVisualParam(S32 id) const
|
||||
{
|
||||
VisualParamIndexMap_t::iterator iter = mVisualParamIndexMap.find(id);
|
||||
VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.find(id);
|
||||
return (iter == mVisualParamIndexMap.end()) ? 0 : iter->second;
|
||||
}
|
||||
S32 getVisualParamID(LLVisualParam *id)
|
||||
|
|
@ -246,11 +246,11 @@ public:
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
S32 getVisualParamCount() { return (S32)mVisualParamIndexMap.size(); }
|
||||
S32 getVisualParamCount() const { return (S32)mVisualParamIndexMap.size(); }
|
||||
LLVisualParam* getVisualParam(const char *name);
|
||||
|
||||
|
||||
ESex getSex() { return mSex; }
|
||||
ESex getSex() const { return mSex; }
|
||||
void setSex( ESex sex ) { mSex = sex; }
|
||||
|
||||
U32 getAppearanceSerialNum() const { return mAppearanceSerialNum; }
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ public:
|
|||
|
||||
void clampRotation(LLQuaternion old_rot, LLQuaternion new_rot);
|
||||
|
||||
virtual BOOL isAnimatable() { return TRUE; }
|
||||
virtual BOOL isAnimatable() const { return TRUE; }
|
||||
|
||||
S32 getJointNum() const { return mJointNum; }
|
||||
void setJointNum(S32 joint_num) { mJointNum = joint_num; }
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
// Header Files
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "lljoint.h"
|
||||
#include "llmemory.h"
|
||||
#include "llrefcount.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class LLJointState
|
||||
|
|
|
|||
|
|
@ -347,8 +347,11 @@ BOOL LLKeyframeMotionParam::loadMotions()
|
|||
// Load named file by concatenating the character prefix with the motion name.
|
||||
// Load data into a buffer to be parsed.
|
||||
//-------------------------------------------------------------------------
|
||||
std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix())
|
||||
+ "_" + getName() + ".llp";
|
||||
//std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix())
|
||||
// + "_" + getName() + ".llp";
|
||||
//RN: deprecated unused reference to "motion" directory
|
||||
std::string path;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// open the file
|
||||
|
|
|
|||
|
|
@ -1019,9 +1019,9 @@ bool LLMotionController::isMotionLoading(LLMotion* motion)
|
|||
//-----------------------------------------------------------------------------
|
||||
// findMotion()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLMotion* LLMotionController::findMotion(const LLUUID& id)
|
||||
LLMotion* LLMotionController::findMotion(const LLUUID& id) const
|
||||
{
|
||||
motion_map_t::iterator iter = mAllMotions.find(id);
|
||||
motion_map_t::const_iterator iter = mAllMotions.find(id);
|
||||
if(iter == mAllMotions.end())
|
||||
{
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -153,12 +153,12 @@ public:
|
|||
// pause and continue all motions
|
||||
void pauseAllMotions();
|
||||
void unpauseAllMotions();
|
||||
BOOL isPaused() { return mPaused; }
|
||||
BOOL isPaused() const { return mPaused; }
|
||||
|
||||
void setTimeStep(F32 step);
|
||||
|
||||
void setTimeFactor(F32 time_factor);
|
||||
F32 getTimeFactor() { return mTimeFactor; }
|
||||
F32 getTimeFactor() const { return mTimeFactor; }
|
||||
|
||||
motion_list_t& getActiveMotions() { return mActiveMotions; }
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ public:
|
|||
//protected:
|
||||
bool isMotionActive( LLMotion *motion );
|
||||
bool isMotionLoading( LLMotion *motion );
|
||||
LLMotion *findMotion( const LLUUID& id );
|
||||
LLMotion *findMotion( const LLUUID& id ) const;
|
||||
|
||||
protected:
|
||||
// internal operations act on motion instances directly
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ const S32 GESTURE_VERSION = 2;
|
|||
LLMultiGesture::LLMultiGesture()
|
||||
: mKey(),
|
||||
mMask(),
|
||||
mName(),
|
||||
mTrigger(),
|
||||
mReplaceText(),
|
||||
mSteps(),
|
||||
|
|
@ -243,7 +244,7 @@ void LLMultiGesture::dump()
|
|||
//---------------------------------------------------------------------------
|
||||
LLGestureStepAnimation::LLGestureStepAnimation()
|
||||
: LLGestureStep(),
|
||||
mAnimName("None"),
|
||||
mAnimName("None"),
|
||||
mAnimAssetID(),
|
||||
mFlags(0x0)
|
||||
{ }
|
||||
|
|
@ -292,20 +293,27 @@ BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp)
|
|||
dp.unpackU32(mFlags, "flags");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
std::string LLGestureStepAnimation::getLabel() const
|
||||
// *TODO: Translate
|
||||
std::vector<std::string> LLGestureStepAnimation::getLabel() const
|
||||
{
|
||||
std::string label;
|
||||
std::vector<std::string> strings;
|
||||
|
||||
// std::string label;
|
||||
if (mFlags & ANIM_FLAG_STOP)
|
||||
{
|
||||
label = "Stop Animation: ";
|
||||
strings.push_back( "AnimFlagStop");
|
||||
|
||||
// label = "Stop Animation: ";
|
||||
}
|
||||
else
|
||||
{
|
||||
label = "Start Animation: ";
|
||||
strings.push_back( "AnimFlagStart");
|
||||
|
||||
// label = "Start Animation: ";
|
||||
}
|
||||
label += mAnimName;
|
||||
return label;
|
||||
strings.push_back( mAnimName);
|
||||
// label += mAnimName;
|
||||
return strings;
|
||||
}
|
||||
|
||||
void LLGestureStepAnimation::dump()
|
||||
|
|
@ -359,12 +367,15 @@ BOOL LLGestureStepSound::deserialize(LLDataPacker& dp)
|
|||
dp.unpackU32(mFlags, "flags");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
std::string LLGestureStepSound::getLabel() const
|
||||
// *TODO: Translate
|
||||
std::vector<std::string> LLGestureStepSound::getLabel() const
|
||||
{
|
||||
std::string label("Sound: ");
|
||||
label += mSoundName;
|
||||
return label;
|
||||
std::vector<std::string> strings;
|
||||
strings.push_back( "Sound");
|
||||
strings.push_back( mSoundName);
|
||||
// std::string label("Sound: ");
|
||||
// label += mSoundName;
|
||||
return strings;
|
||||
}
|
||||
|
||||
void LLGestureStepSound::dump()
|
||||
|
|
@ -414,12 +425,13 @@ BOOL LLGestureStepChat::deserialize(LLDataPacker& dp)
|
|||
dp.unpackU32(mFlags, "flags");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
std::string LLGestureStepChat::getLabel() const
|
||||
// *TODO: Translate
|
||||
std::vector<std::string> LLGestureStepChat::getLabel() const
|
||||
{
|
||||
std::string label("Chat: ");
|
||||
label += mChatText;
|
||||
return label;
|
||||
std::vector<std::string> strings;
|
||||
strings.push_back("Chat");
|
||||
strings.push_back(mChatText);
|
||||
return strings;
|
||||
}
|
||||
|
||||
void LLGestureStepChat::dump()
|
||||
|
|
@ -467,22 +479,27 @@ BOOL LLGestureStepWait::deserialize(LLDataPacker& dp)
|
|||
dp.unpackU32(mFlags, "flags");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
std::string LLGestureStepWait::getLabel() const
|
||||
// *TODO: Translate
|
||||
std::vector<std::string> LLGestureStepWait::getLabel() const
|
||||
{
|
||||
std::string label("--- Wait: ");
|
||||
std::vector<std::string> strings;
|
||||
strings.push_back( "Wait" );
|
||||
|
||||
// std::string label("--- Wait: ");
|
||||
if (mFlags & WAIT_FLAG_TIME)
|
||||
{
|
||||
char buffer[64]; /* Flawfinder: ignore */
|
||||
snprintf(buffer, sizeof(buffer), "%.1f seconds", (double)mWaitSeconds); /* Flawfinder: ignore */
|
||||
label += buffer;
|
||||
strings.push_back(buffer);
|
||||
// label += buffer;
|
||||
}
|
||||
else if (mFlags & WAIT_FLAG_ALL_ANIM)
|
||||
{
|
||||
label += "until animations are done";
|
||||
strings.push_back("until animations are done");
|
||||
// label += "until animations are done";
|
||||
}
|
||||
|
||||
return label;
|
||||
return strings;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -65,11 +65,13 @@ protected:
|
|||
const LLMultiGesture& operator=(const LLMultiGesture& rhs);
|
||||
|
||||
public:
|
||||
// name is stored at asset level
|
||||
// desc is stored at asset level
|
||||
KEY mKey;
|
||||
MASK mMask;
|
||||
|
||||
// This name can be empty if the inventory item is not around and
|
||||
// the gesture manager has not yet set the name
|
||||
std::string mName;
|
||||
|
||||
// String, like "/foo" or "hello" that makes it play
|
||||
std::string mTrigger;
|
||||
|
||||
|
|
@ -130,7 +132,7 @@ public:
|
|||
virtual EStepType getType() = 0;
|
||||
|
||||
// Return a user-readable label for this step
|
||||
virtual std::string getLabel() const = 0;
|
||||
virtual std::vector<std::string> getLabel() const = 0;
|
||||
|
||||
virtual S32 getMaxSerialSize() const = 0;
|
||||
virtual BOOL serialize(LLDataPacker& dp) const = 0;
|
||||
|
|
@ -152,7 +154,7 @@ public:
|
|||
|
||||
virtual EStepType getType() { return STEP_ANIMATION; }
|
||||
|
||||
virtual std::string getLabel() const;
|
||||
virtual std::vector<std::string> getLabel() const;
|
||||
|
||||
virtual S32 getMaxSerialSize() const;
|
||||
virtual BOOL serialize(LLDataPacker& dp) const;
|
||||
|
|
@ -175,7 +177,7 @@ public:
|
|||
|
||||
virtual EStepType getType() { return STEP_SOUND; }
|
||||
|
||||
virtual std::string getLabel() const;
|
||||
virtual std::vector<std::string> getLabel() const;
|
||||
|
||||
virtual S32 getMaxSerialSize() const;
|
||||
virtual BOOL serialize(LLDataPacker& dp) const;
|
||||
|
|
@ -198,7 +200,7 @@ public:
|
|||
|
||||
virtual EStepType getType() { return STEP_CHAT; }
|
||||
|
||||
virtual std::string getLabel() const;
|
||||
virtual std::vector<std::string> getLabel() const;
|
||||
|
||||
virtual S32 getMaxSerialSize() const;
|
||||
virtual BOOL serialize(LLDataPacker& dp) const;
|
||||
|
|
@ -223,7 +225,7 @@ public:
|
|||
|
||||
virtual EStepType getType() { return STEP_WAIT; }
|
||||
|
||||
virtual std::string getLabel() const;
|
||||
virtual std::vector<std::string> getLabel() const;
|
||||
|
||||
virtual S32 getMaxSerialSize() const;
|
||||
virtual BOOL serialize(LLDataPacker& dp) const;
|
||||
|
|
|
|||
|
|
@ -516,9 +516,9 @@ BOOL LLPoseBlender::addMotion(LLMotion* motion)
|
|||
void LLPoseBlender::blendAndApply()
|
||||
{
|
||||
for (blender_list_t::iterator iter = mActiveBlenders.begin();
|
||||
iter != mActiveBlenders.end(); ++iter)
|
||||
iter != mActiveBlenders.end(); )
|
||||
{
|
||||
LLJointStateBlender* jsbp = *iter;
|
||||
LLJointStateBlender* jsbp = *iter++;
|
||||
jsbp->blendJointStates();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,12 +36,14 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Header Files
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <string>
|
||||
|
||||
#include "llmap.h"
|
||||
#include "lljointstate.h"
|
||||
#include "lljoint.h"
|
||||
#include "llmap.h"
|
||||
#include "llpointer.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
virtual void stopAnimating(BOOL set_by_user);
|
||||
|
||||
// Interface methods
|
||||
S32 getID() { return mID; }
|
||||
S32 getID() const { return mID; }
|
||||
void setID(S32 id) { llassert(!mInfo); mID = id; }
|
||||
|
||||
const std::string& getName() const { return mInfo->mName; }
|
||||
|
|
@ -124,22 +124,22 @@ public:
|
|||
void setMaxDisplayName(const std::string& s) { mInfo->mMaxName = s; }
|
||||
void setMinDisplayName(const std::string& s) { mInfo->mMinName = s; }
|
||||
|
||||
EVisualParamGroup getGroup() { return mInfo->mGroup; }
|
||||
F32 getMinWeight() { return mInfo->mMinWeight; }
|
||||
F32 getMaxWeight() { return mInfo->mMaxWeight; }
|
||||
F32 getDefaultWeight() { return mInfo->mDefaultWeight; }
|
||||
ESex getSex() { return mInfo->mSex; }
|
||||
EVisualParamGroup getGroup() const { return mInfo->mGroup; }
|
||||
F32 getMinWeight() const { return mInfo->mMinWeight; }
|
||||
F32 getMaxWeight() const { return mInfo->mMaxWeight; }
|
||||
F32 getDefaultWeight() const { return mInfo->mDefaultWeight; }
|
||||
ESex getSex() const { return mInfo->mSex; }
|
||||
|
||||
F32 getWeight() { return mIsAnimating ? mTargetWeight : mCurWeight; }
|
||||
F32 getCurrentWeight() { return mCurWeight; }
|
||||
F32 getLastWeight() { return mLastWeight; }
|
||||
BOOL isAnimating() { return mIsAnimating; }
|
||||
F32 getWeight() const { return mIsAnimating ? mTargetWeight : mCurWeight; }
|
||||
F32 getCurrentWeight() const { return mCurWeight; }
|
||||
F32 getLastWeight() const { return mLastWeight; }
|
||||
BOOL isAnimating() const { return mIsAnimating; }
|
||||
|
||||
LLVisualParam* getNextParam() { return mNext; }
|
||||
void setNextParam( LLVisualParam *next );
|
||||
|
||||
virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating; }
|
||||
BOOL getAnimating() { return mIsAnimating; }
|
||||
BOOL getAnimating() const { return mIsAnimating; }
|
||||
|
||||
protected:
|
||||
F32 mCurWeight; // current weight
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
project(llcommon)
|
||||
|
||||
include(00-Common)
|
||||
include(LLAddBuildTest)
|
||||
include(LLCommon)
|
||||
include(Boost)
|
||||
|
||||
include_directories(
|
||||
${EXPAT_INCLUDE_DIRS}
|
||||
|
|
@ -11,7 +13,14 @@ include_directories(
|
|||
${ZLIB_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# add_executable(lltreeiterators lltreeiterators.cpp)
|
||||
#
|
||||
# target_link_libraries(lltreeiterators
|
||||
# ${LLCOMMON_LIBRARIES})
|
||||
|
||||
set(llcommon_SOURCE_FILES
|
||||
llallocator.cpp
|
||||
llallocator_heap_profile.cpp
|
||||
llapp.cpp
|
||||
llapr.cpp
|
||||
llassettype.cpp
|
||||
|
|
@ -40,11 +49,16 @@ set(llcommon_SOURCE_FILES
|
|||
llmd5.cpp
|
||||
llmemory.cpp
|
||||
llmemorystream.cpp
|
||||
llmemtype.cpp
|
||||
llmetrics.cpp
|
||||
llmortician.cpp
|
||||
lloptioninterface.cpp
|
||||
llptrto.cpp
|
||||
llprocesslauncher.cpp
|
||||
llprocessor.cpp
|
||||
llqueuedthread.cpp
|
||||
llrand.cpp
|
||||
llrefcount.cpp
|
||||
llrun.cpp
|
||||
llsd.cpp
|
||||
llsdserialize.cpp
|
||||
|
|
@ -52,6 +66,7 @@ set(llcommon_SOURCE_FILES
|
|||
llsdutil.cpp
|
||||
llsecondlifeurls.cpp
|
||||
llstat.cpp
|
||||
llstacktrace.cpp
|
||||
llstreamtools.cpp
|
||||
llstring.cpp
|
||||
llstringtable.cpp
|
||||
|
|
@ -78,6 +93,8 @@ set(llcommon_HEADER_FILES
|
|||
indra_constants.h
|
||||
linden_common.h
|
||||
linked_lists.h
|
||||
llallocator.h
|
||||
llallocator_heap_profile.h
|
||||
llagentconstants.h
|
||||
llapp.h
|
||||
llapr.h
|
||||
|
|
@ -98,9 +115,11 @@ set(llcommon_HEADER_FILES
|
|||
lldate.h
|
||||
lldefs.h
|
||||
lldependencies.h
|
||||
lldeleteutils.h
|
||||
lldepthstack.h
|
||||
lldictionary.h
|
||||
lldlinked.h
|
||||
lldoubledispatch.h
|
||||
lldqueueptr.h
|
||||
llendianswizzle.h
|
||||
llenum.h
|
||||
|
|
@ -122,6 +141,7 @@ set(llcommon_HEADER_FILES
|
|||
llheartbeat.h
|
||||
llhttpstatuscodes.h
|
||||
llindexedqueue.h
|
||||
llinstancetracker.h
|
||||
llkeythrottle.h
|
||||
lllazy.h
|
||||
lllinkedqueue.h
|
||||
|
|
@ -138,23 +158,32 @@ set(llcommon_HEADER_FILES
|
|||
llmetrics.h
|
||||
llmortician.h
|
||||
llnametable.h
|
||||
lloptioninterface.h
|
||||
llpointer.h
|
||||
llpreprocessor.h
|
||||
llpriqueuemap.h
|
||||
llprocesslauncher.h
|
||||
llprocessor.h
|
||||
llptrskiplist.h
|
||||
llptrskipmap.h
|
||||
llptrto.h
|
||||
llqueuedthread.h
|
||||
llrand.h
|
||||
llrefcount.h
|
||||
llrun.h
|
||||
llrefcount.h
|
||||
llsafehandle.h
|
||||
llsd.h
|
||||
llsdserialize.h
|
||||
llsdserialize_xml.h
|
||||
llsdutil.h
|
||||
llsecondlifeurls.h
|
||||
llsimplehash.h
|
||||
llsingleton.h
|
||||
llskiplist.h
|
||||
llskipmap.h
|
||||
llstack.h
|
||||
llstacktrace.h
|
||||
llstat.h
|
||||
llstatenums.h
|
||||
llstl.h
|
||||
|
|
@ -165,6 +194,7 @@ set(llcommon_HEADER_FILES
|
|||
llsys.h
|
||||
llthread.h
|
||||
lltimer.h
|
||||
lltreeiterators.h
|
||||
lluri.h
|
||||
lluuid.h
|
||||
lluuidhashmap.h
|
||||
|
|
@ -200,6 +230,8 @@ target_link_libraries(
|
|||
${APR_LIBRARIES}
|
||||
${EXPAT_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${BOOST_PROGRAM_OPTIONS_LIBRARY}
|
||||
${BOOST_REGEX_LIBRARY}
|
||||
)
|
||||
|
||||
include(LLAddBuildTest)
|
||||
|
|
@ -209,3 +241,11 @@ SET(llcommon_TEST_SOURCE_FILES
|
|||
)
|
||||
LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")
|
||||
|
||||
#set(TEST_DEBUG on)
|
||||
set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
|
||||
LL_ADD_INTEGRATION_TEST(lllazy lllazy.cpp "${test_libs}")
|
||||
|
||||
# *TODO - reenable these once tcmalloc libs no longer break the build.
|
||||
#ADD_BUILD_TEST(llallocator llcommon)
|
||||
#ADD_BUILD_TEST(llallocator_heap_profile llcommon)
|
||||
#ADD_BUILD_TEST(llmemtype llcommon)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,30 @@
|
|||
* making llcommon depend on llmath.
|
||||
*
|
||||
* $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$
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@
|
|||
#ifndef LL_LINDEN_COMMON_H
|
||||
#define LL_LINDEN_COMMON_H
|
||||
|
||||
// *NOTE: Please keep includes here to a minimum!
|
||||
//
|
||||
// Files included here are included in every library .cpp file and
|
||||
// are not precompiled.
|
||||
|
||||
#if defined(LL_WINDOWS) && defined(_DEBUG)
|
||||
# if _MSC_VER >= 1400 // Visual C++ 2005 or later
|
||||
# define _CRTDBG_MAP_ALLOC
|
||||
|
|
@ -51,23 +56,22 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iosfwd>
|
||||
|
||||
// Work Microsoft compiler warnings
|
||||
// Work around Microsoft compiler warnings in STL headers
|
||||
#ifdef LL_WINDOWS
|
||||
#pragma warning (disable : 4702) // unreachable code
|
||||
#pragma warning (disable : 4244) // conversion from time_t to S32
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#pragma warning (3 : 4702) // we like level 3, not 4
|
||||
// Reenable warnings we disabled above
|
||||
#pragma warning (3 : 4702) // unreachable code, we like level 3, not 4
|
||||
// level 4 warnings that we need to disable:
|
||||
#pragma warning (disable : 4100) // unreferenced formal parameter
|
||||
#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) )
|
||||
|
|
@ -78,6 +82,7 @@
|
|||
#endif // LL_WINDOWS
|
||||
|
||||
// Linden only libs in alpha-order other than stdtypes.h
|
||||
// *NOTE: Please keep includes here to a minimum, see above.
|
||||
#include "stdtypes.h"
|
||||
#include "lldefs.h"
|
||||
#include "llerror.h"
|
||||
|
|
@ -85,8 +90,5 @@
|
|||
#include "llfasttimer.h"
|
||||
#include "llfile.h"
|
||||
#include "llformat.h"
|
||||
#include "llstring.h"
|
||||
#include "llsys.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* @file llallocator.cpp
|
||||
* @brief Implementation of the LLAllocator class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-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 "llallocator.h"
|
||||
|
||||
#if LL_USE_TCMALLOC
|
||||
|
||||
#include "google/heap-profiler.h"
|
||||
#include "google/commandlineflags_public.h"
|
||||
|
||||
DECLARE_bool(heap_profile_use_stack_trace);
|
||||
//DECLARE_double(tcmalloc_release_rate);
|
||||
|
||||
// static
|
||||
void LLAllocator::pushMemType(S32 type)
|
||||
{
|
||||
if(isProfiling())
|
||||
{
|
||||
PushMemType(type);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
S32 LLAllocator::popMemType()
|
||||
{
|
||||
if (isProfiling())
|
||||
{
|
||||
return PopMemType();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void LLAllocator::setProfilingEnabled(bool should_enable)
|
||||
{
|
||||
// NULL disables dumping to disk
|
||||
static char const * const PREFIX = NULL;
|
||||
if(should_enable)
|
||||
{
|
||||
HeapProfilerSetUseStackTrace(false);
|
||||
HeapProfilerStart(PREFIX);
|
||||
}
|
||||
else
|
||||
{
|
||||
HeapProfilerStop();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLAllocator::isProfiling()
|
||||
{
|
||||
return IsHeapProfilerRunning();
|
||||
}
|
||||
|
||||
std::string LLAllocator::getRawProfile()
|
||||
{
|
||||
// *TODO - fix google-perftools to accept an buffer to avoid this
|
||||
// malloc-copy-free cycle.
|
||||
char * buffer = GetHeapProfile();
|
||||
std::string ret = buffer;
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else // LL_USE_TCMALLOC
|
||||
|
||||
//
|
||||
// stub implementations for when tcmalloc is disabled
|
||||
//
|
||||
|
||||
// static
|
||||
void LLAllocator::pushMemType(S32 type)
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
S32 LLAllocator::popMemType()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void LLAllocator::setProfilingEnabled(bool should_enable)
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLAllocator::isProfiling()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string LLAllocator::getRawProfile()
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
#endif // LL_USE_TCMALLOC
|
||||
|
||||
LLAllocatorHeapProfile const & LLAllocator::getProfile()
|
||||
{
|
||||
mProf.mLines.clear();
|
||||
|
||||
// *TODO - avoid making all these extra copies of things...
|
||||
std::string prof_text = getRawProfile();
|
||||
//std::cout << prof_text << std::endl;
|
||||
mProf.parse(prof_text);
|
||||
return mProf;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @file llallocator.h
|
||||
* @brief Declaration of the LLAllocator class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-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_LLALLOCATOR_H
|
||||
#define LL_LLALLOCATOR_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "llmemtype.h"
|
||||
#include "llallocator_heap_profile.h"
|
||||
|
||||
class LLAllocator {
|
||||
friend class LLMemoryView;
|
||||
friend class LLMemType;
|
||||
|
||||
private:
|
||||
static void pushMemType(S32 type);
|
||||
static S32 popMemType();
|
||||
|
||||
public:
|
||||
void setProfilingEnabled(bool should_enable);
|
||||
|
||||
static bool isProfiling();
|
||||
|
||||
LLAllocatorHeapProfile const & getProfile();
|
||||
|
||||
private:
|
||||
std::string getRawProfile();
|
||||
|
||||
private:
|
||||
LLAllocatorHeapProfile mProf;
|
||||
};
|
||||
|
||||
#endif // LL_LLALLOCATOR_H
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* @file llallocator_heap_profile.cpp
|
||||
* @brief Implementation of the parser for tcmalloc heap profile data.
|
||||
* @author Brad Kittenbrink
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-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 "llallocator_heap_profile.h"
|
||||
|
||||
#if LL_MSVC
|
||||
// disable warning about boost::lexical_cast returning uninitialized data
|
||||
// when it fails to parse the string
|
||||
#pragma warning (disable:4701)
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
static const std::string HEAP_PROFILE_MAGIC_STR = "heap profile:";
|
||||
|
||||
static bool is_separator(char c)
|
||||
{
|
||||
return isspace(c) || c == '[' || c == ']' || c == ':';
|
||||
}
|
||||
|
||||
void LLAllocatorHeapProfile::parse(std::string const & prof_text)
|
||||
{
|
||||
// a typedef for handling a token in the string buffer
|
||||
// it's a begin/end pair of string::const_iterators
|
||||
typedef boost::iterator_range<std::string::const_iterator> range_t;
|
||||
|
||||
mLines.clear();
|
||||
|
||||
if(prof_text.compare(0, HEAP_PROFILE_MAGIC_STR.length(), HEAP_PROFILE_MAGIC_STR) != 0)
|
||||
{
|
||||
// *TODO - determine if there should be some better error state than
|
||||
// mLines being empty. -brad
|
||||
llwarns << "invalid heap profile data passed into parser." << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector< range_t > prof_lines;
|
||||
|
||||
std::string::const_iterator prof_begin = prof_text.begin() + HEAP_PROFILE_MAGIC_STR.length();
|
||||
|
||||
range_t prof_range(prof_begin, prof_text.end());
|
||||
boost::algorithm::split(prof_lines,
|
||||
prof_range,
|
||||
boost::bind(std::equal_to<llwchar>(), '\n', _1));
|
||||
|
||||
std::vector< range_t >::const_iterator i;
|
||||
for(i = prof_lines.begin(); i != prof_lines.end() && !i->empty(); ++i)
|
||||
{
|
||||
range_t const & line_text = *i;
|
||||
|
||||
std::vector<range_t> line_elems;
|
||||
|
||||
boost::algorithm::split(line_elems,
|
||||
line_text,
|
||||
is_separator);
|
||||
|
||||
std::vector< range_t >::iterator j;
|
||||
j = line_elems.begin();
|
||||
|
||||
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
|
||||
llassert_always(j != line_elems.end());
|
||||
U32 live_count = boost::lexical_cast<U32>(*j);
|
||||
++j;
|
||||
|
||||
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
|
||||
llassert_always(j != line_elems.end());
|
||||
U64 live_size = boost::lexical_cast<U64>(*j);
|
||||
++j;
|
||||
|
||||
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
|
||||
llassert_always(j != line_elems.end());
|
||||
U32 tot_count = boost::lexical_cast<U32>(*j);
|
||||
++j;
|
||||
|
||||
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
|
||||
llassert_always(j != line_elems.end());
|
||||
U64 tot_size = boost::lexical_cast<U64>(*j);
|
||||
++j;
|
||||
|
||||
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
|
||||
llassert_always(j != line_elems.end());
|
||||
++j; // skip the '@'
|
||||
|
||||
mLines.push_back(line(live_count, live_size, tot_count, tot_size));
|
||||
line & current_line = mLines.back();
|
||||
|
||||
for(; j != line_elems.end(); ++j)
|
||||
{
|
||||
if(!j->empty()) {
|
||||
U32 marker = boost::lexical_cast<U32>(*j);
|
||||
current_line.mTrace.push_back(marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *TODO - parse MAPPED_LIBRARIES section here if we're ever interested in it
|
||||
}
|
||||
|
||||
void LLAllocatorHeapProfile::dump(std::ostream & out) const
|
||||
{
|
||||
lines_t::const_iterator i;
|
||||
for(i = mLines.begin(); i != mLines.end(); ++i)
|
||||
{
|
||||
out << i->mLiveCount << ": " << i->mLiveSize << '[' << i->mTotalCount << ": " << i->mTotalSize << "] @";
|
||||
|
||||
stack_trace::const_iterator j;
|
||||
for(j = i->mTrace.begin(); j != i->mTrace.end(); ++j)
|
||||
{
|
||||
out << ' ' << *j;
|
||||
}
|
||||
out << '\n';
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* @file llallocator_heap_profile.h
|
||||
* @brief Declaration of the parser for tcmalloc heap profile data.
|
||||
* @author Brad Kittenbrink
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-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_LLALLOCATOR_HEAP_PROFILE_H
|
||||
#define LL_LLALLOCATOR_HEAP_PROFILE_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class LLAllocatorHeapProfile
|
||||
{
|
||||
public:
|
||||
typedef int stack_marker;
|
||||
|
||||
typedef std::vector<stack_marker> stack_trace;
|
||||
|
||||
struct line {
|
||||
line(U32 live_count, U64 live_size, U32 tot_count, U64 tot_size) :
|
||||
mLiveSize(live_size),
|
||||
mTotalSize(tot_size),
|
||||
mLiveCount(live_count),
|
||||
mTotalCount(tot_count)
|
||||
{
|
||||
}
|
||||
U64 mLiveSize, mTotalSize;
|
||||
U32 mLiveCount, mTotalCount;
|
||||
stack_trace mTrace;
|
||||
};
|
||||
|
||||
typedef std::vector<line> lines_t;
|
||||
|
||||
LLAllocatorHeapProfile()
|
||||
{
|
||||
}
|
||||
|
||||
void parse(std::string const & prof_text);
|
||||
|
||||
void dump(std::ostream & out) const;
|
||||
|
||||
public:
|
||||
lines_t mLines;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_LLALLOCATOR_HEAP_PROFILE_H
|
||||
|
|
@ -37,6 +37,7 @@
|
|||
#include "llapr.h"
|
||||
#include "llrun.h"
|
||||
#include "llsd.h"
|
||||
#include "lloptioninterface.h"
|
||||
|
||||
// Forward declarations
|
||||
class LLErrorThread;
|
||||
|
|
@ -61,7 +62,7 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
class LLApp
|
||||
class LLApp : public LLOptionInterface
|
||||
{
|
||||
friend class LLErrorThread;
|
||||
public:
|
||||
|
|
@ -110,7 +111,7 @@ public:
|
|||
* @param name The name of the option.
|
||||
* @return Returns the option data.
|
||||
*/
|
||||
LLSD getOption(const std::string& name) const;
|
||||
virtual LLSD getOption(const std::string& name) const;
|
||||
|
||||
/**
|
||||
* @brief Parse command line options and insert them into
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "llassettype.h"
|
||||
#include "lldictionary.h"
|
||||
#include "llmemory.h"
|
||||
#include "llsingleton.h"
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class LLAssetType
|
||||
|
|
@ -100,7 +101,7 @@ LLAssetDictionary::LLAssetDictionary()
|
|||
addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE, FALSE, TRUE));
|
||||
|
||||
|
|
@ -115,7 +116,7 @@ LLAssetDictionary::LLAssetDictionary()
|
|||
}
|
||||
|
||||
addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("CURRENT", "current", "current outfit", "Current Outfit", DAD_CATEGORY, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", "Outfit", DAD_CATEGORY, TRUE, FALSE));
|
||||
addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", "New Outfit", DAD_CATEGORY, TRUE, FALSE));
|
||||
addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", "My Outfits", DAD_CATEGORY, FALSE, TRUE));
|
||||
|
||||
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE, FALSE, FALSE));
|
||||
|
|
@ -281,6 +282,15 @@ bool LLAssetType::lookupIsProtectedCategoryType(EType asset_type)
|
|||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLAssetType::lookupIsEnsembleCategoryType(EType asset_type)
|
||||
{
|
||||
return (asset_type >= AT_FOLDER_ENSEMBLE_START &&
|
||||
asset_type <= AT_FOLDER_ENSEMBLE_END);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// static. Generate a good default description
|
||||
void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type,
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ public:
|
|||
|
||||
static const char* lookupCategoryName(EType asset_type);
|
||||
static bool lookupIsProtectedCategoryType(EType asset_type);
|
||||
static bool lookupIsEnsembleCategoryType(EType asset_type);
|
||||
|
||||
/* TODO: Change return types from "const char *" to "const std::string &".
|
||||
This is fairly straightforward, but requires changing some calls to use .c_str().
|
||||
|
|
|
|||
|
|
@ -46,4 +46,19 @@
|
|||
*/
|
||||
typedef boost::tokenizer<boost::char_separator<char> > boost_tokenizer;
|
||||
|
||||
// Useful combiner for boost signals that return a bool (e.g. validation)
|
||||
// returns false if any of the callbacks return false
|
||||
struct boost_boolean_combiner
|
||||
{
|
||||
typedef bool result_type;
|
||||
template<typename InputIterator>
|
||||
bool operator()(InputIterator first, InputIterator last) const
|
||||
{
|
||||
bool res = true;
|
||||
while (first != last)
|
||||
res &= *first++;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // LL_LLBOOST_H
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include "linden_common.h"
|
||||
|
||||
#include "llcommon.h"
|
||||
|
||||
#include "llmemory.h"
|
||||
#include "llthread.h"
|
||||
|
||||
//static
|
||||
|
|
|
|||
|
|
@ -32,9 +32,8 @@
|
|||
#ifndef LL_COMMON_H
|
||||
#define LL_COMMON_H
|
||||
|
||||
#include "llmemory.h"
|
||||
// *TODO: remove these?
|
||||
#include "llapr.h"
|
||||
// #include "llframecallbackmanager.h"
|
||||
#include "lltimer.h"
|
||||
#include "llfile.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,13 @@
|
|||
#include "apr_time.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include "lltimer.h"
|
||||
#include "llstring.h"
|
||||
|
||||
static const F64 DATE_EPOCH = 0.0;
|
||||
|
||||
|
|
@ -88,45 +91,36 @@ std::string LLDate::asString() const
|
|||
// is one of the standards used and the prefered format
|
||||
std::string LLDate::asRFC1123() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
toHTTPDateStream(stream);
|
||||
return stream.str();
|
||||
return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
|
||||
}
|
||||
|
||||
void LLDate::toHTTPDateStream(std::ostream& s) const
|
||||
std::string LLDate::toHTTPDateString (std::string fmt) const
|
||||
{
|
||||
// http://apr.apache.org/docs/apr/0.9/group__apr__time.html
|
||||
apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
|
||||
std::ostringstream stream;
|
||||
time_t locSeconds = (time_t) mSecondsSinceEpoch;
|
||||
struct tm * gmt = gmtime (&locSeconds);
|
||||
|
||||
apr_time_exp_t exp_time ; //Apache time module
|
||||
stream.imbue (std::locale(LLStringUtil::getLocale().c_str()));
|
||||
toHTTPDateStream (stream, gmt, fmt);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
|
||||
{
|
||||
// Return Epoch UTC date
|
||||
s << "Thursday, 01 Jan 1970 00:00:00 GMT" ;
|
||||
return;
|
||||
}
|
||||
std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream.imbue (std::locale(LLStringUtil::getLocale().c_str()));
|
||||
toHTTPDateStream (stream, gmt, fmt);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
s << std::dec << std::setfill('0');
|
||||
#if( LL_WINDOWS || __GNUC__ > 2)
|
||||
s << std::right ;
|
||||
#else
|
||||
s.setf(ios::right);
|
||||
#endif
|
||||
std::string day = weekdays[exp_time.tm_wday];
|
||||
std::string month = months[exp_time.tm_mon];
|
||||
void LLDate::toHTTPDateStream(std::ostream& s, tm * gmt, std::string fmt)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
s << std::setw(day.length()) << (day)
|
||||
<< ", " << std::setw(2) << (exp_time.tm_mday)
|
||||
<< ' ' << std::setw(month.length()) << (month)
|
||||
<< ' ' << std::setw(4) << (exp_time.tm_year + 1900)
|
||||
<< ' ' << std::setw(2) << (exp_time.tm_hour)
|
||||
<< ':' << std::setw(2) << (exp_time.tm_min)
|
||||
<< ':' << std::setw(2) << (exp_time.tm_sec)
|
||||
<< " GMT";
|
||||
|
||||
// RFC 1123 date does not use microseconds
|
||||
//llinfos << "Date in RFC 1123 format is " << s << llendl;
|
||||
const char * pBeg = fmt.c_str();
|
||||
const char * pEnd = pBeg + fmt.length();
|
||||
const time_put<char>& tp = use_facet<time_put<char> >(s.getloc());
|
||||
tp.put (s, s, s.fill(), gmt, pBeg, pEnd);
|
||||
}
|
||||
|
||||
void LLDate::toStream(std::ostream& s) const
|
||||
|
|
|
|||
|
|
@ -84,7 +84,9 @@ public:
|
|||
std::string asString() const;
|
||||
std::string asRFC1123() const;
|
||||
void toStream(std::ostream&) const;
|
||||
void toHTTPDateStream(std::ostream&) const;
|
||||
std::string toHTTPDateString (std::string fmt) const;
|
||||
static std::string toHTTPDateString (tm * gmt, std::string fmt);
|
||||
static void toHTTPDateStream(std::ostream&, tm *, std::string);
|
||||
/**
|
||||
* @brief Set the date from an ISO-8601 string.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* @file lldeleteutils.h
|
||||
* @brief Utility functions to simplify some common pointer-munging idioms.
|
||||
*
|
||||
* $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_DELETE_UTILS_H
|
||||
#define LL_DELETE_UTILS_H
|
||||
|
||||
// Simple utility functions to eventually replace the common 2-line
|
||||
// idiom scattered throughout the viewer codebase. Note that where
|
||||
// possible we would rather be using smart pointers of some sort.
|
||||
|
||||
template <class T>
|
||||
inline void deleteAndClear(T*& ptr)
|
||||
{
|
||||
delete ptr;
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void deleteAndClearArray(T*& array_ptr)
|
||||
{
|
||||
delete[] array_ptr;
|
||||
array_ptr = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -581,6 +581,8 @@ public:
|
|||
return sorted_range(begin, end);
|
||||
}
|
||||
|
||||
using LLDependenciesBase::describe; // unhide virtual std::string describe(bool full=true) const;
|
||||
|
||||
/// Override base-class describe() with actual implementation
|
||||
virtual std::ostream& describe(std::ostream& out, bool full=true) const
|
||||
{
|
||||
|
|
@ -597,6 +599,7 @@ public:
|
|||
return out;
|
||||
}
|
||||
|
||||
|
||||
/// describe() helper: report a DepNodeEntry
|
||||
static std::ostream& describe(std::ostream& out, std::string& sep,
|
||||
const DepNodeMapEntry& entry, bool full)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,332 @@
|
|||
/**
|
||||
* @file lldoubledispatch.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2008-11-11
|
||||
* @brief function calls virtual on more than one parameter
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2008-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$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_LLDOUBLEDISPATCH_H)
|
||||
#define LL_LLDOUBLEDISPATCH_H
|
||||
|
||||
#include <list>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
/**
|
||||
* This class supports function calls which are virtual on the dynamic type of
|
||||
* more than one parameter. Specifically, we address a limited but useful
|
||||
* subset of that problem: function calls which accept two parameters, and
|
||||
* select which particular function to call depending on the dynamic type of
|
||||
* both.
|
||||
*
|
||||
* Scott Meyers, in More Effective C++ (Item 31), talks about some of the perils
|
||||
* and pitfalls lurking down this pathway. He discusses and dismisses the
|
||||
* straightforward approaches of using single-dispatch virtual functions twice,
|
||||
* and of using a family of single-dispatch virtual functions which each examine
|
||||
* RTTI for their other parameter. He advocates using a registry in which you
|
||||
* look up the actual types of both parameters (he uses the classes' string names,
|
||||
* via typeid(param).name()) to obtain a pointer to a free (non-member) function
|
||||
* that will accept this pair of parameters.
|
||||
*
|
||||
* He does point out that his approach doesn't handle inheritance. If you have a
|
||||
* registry entry for SpaceShip, and you have in hand a MilitaryShip (subclass of
|
||||
* SpaceShip) and an Asteroid, you'd like to call the function appropriate for
|
||||
* SpaceShips and Asteroids -- but alas, his lookup fails because the class name
|
||||
* for your MilitaryShip subclass isn't in the registry.
|
||||
*
|
||||
* This class extends his idea to build a registry whose entries can examine the
|
||||
* dynamic type of the parameter in a more flexible way -- using dynamic_cast<>
|
||||
* -- thereby supporting inheritance relationships.
|
||||
*
|
||||
* Of course we must allow for the ambiguity this permits. We choose to use a
|
||||
* sequence container rather than a map, and require that the client code
|
||||
* specify the order in which dispatch-table entries should be searched. The
|
||||
* result resembles the semantics of the catch clauses for a try/catch block:
|
||||
* you must code catch clauses in decreasing order of specificity, because if
|
||||
* you catch ErrorBaseClass before you catch ErrorSubclass, then any
|
||||
* ErrorSubclass exceptions thrown by the protected code will always match
|
||||
* ErrorBaseClass, and you will never reach your catch(ErrorSubclass) clause.
|
||||
*
|
||||
* So, in a similar way, if you have a specific routine to process
|
||||
* MilitaryShip and Asteroid, you'd better place that in the table @em before
|
||||
* your more general routine that processes SpaceShip and Asteroid, or else
|
||||
* the MilitaryShip variant will never be called.
|
||||
*
|
||||
* @todo This implementation doesn't attempt to deal with
|
||||
* <tt>const</tt>-correctness of arguments. Our container stores templated
|
||||
* objects into which the specific parameter types have been "frozen." But to
|
||||
* store all these in the same container, they are all instances of a base
|
||||
* class with a virtual invocation method. Naturally the base-class virtual
|
||||
* method definition cannot know the <tt>const</tt>-ness of the particular
|
||||
* types with which its template subclass is instantiated.
|
||||
*
|
||||
* One is tempted to suggest four different virtual methods, one for each
|
||||
* combination of @c const and non-<tt>const</tt> arguments. Then the client
|
||||
* will select the particular virtual method that best fits the
|
||||
* <tt>const</tt>-ness of the arguments in hand. The trouble with that idea is
|
||||
* that in order to instantiate the subclass instance, we must compile all
|
||||
* four of its virtual method overrides, which means we must be prepared to
|
||||
* pass all four combinations of @c const and non-<tt>const</tt> arguments to
|
||||
* the registered callable. That only works when the registered callable
|
||||
* accepts both parameters as @c const.
|
||||
*
|
||||
* Of course the virtual method overrides could use @c const_cast to force
|
||||
* them to compile correctly regardless of the <tt>const</tt>-ness of the
|
||||
* registered callable's parameter declarations. But if we're going to force
|
||||
* the issue with @c const_cast anyway, why bother with the four different
|
||||
* virtual methods? Why not just require canonical parameter
|
||||
* <tt>const</tt>-ness for any callables used with this mechanism?
|
||||
*
|
||||
* We therefore require that your callable accept both params as
|
||||
* non-<tt>const</tt>. (This is more general than @c const: you can perform @c
|
||||
* const operations on a non-<tt>const</tt> parameter, but you can't perform
|
||||
* non-<tt>const</tt> operations on a @c const parameter.)
|
||||
*
|
||||
* For ease of use, though, our invocation method accepts both params as @c
|
||||
* const. Again, you can pass a non-<tt>const</tt> object to a @c const param,
|
||||
* but not the other way around. We take care of the @c const_cast for you.
|
||||
*/
|
||||
// LLDoubleDispatch is a template because we have to assume that all parameter
|
||||
// types are subclasses of some common base class -- but we don't have to
|
||||
// impose that base class on client code. Instead, we let IT tell US the
|
||||
// common parameter base class.
|
||||
template<class ReturnType, class ParamBaseType>
|
||||
class LLDoubleDispatch
|
||||
{
|
||||
typedef LLDoubleDispatch<ReturnType, ParamBaseType> self_type;
|
||||
|
||||
public:
|
||||
LLDoubleDispatch() {}
|
||||
|
||||
/**
|
||||
* Call the first matching entry. If there's no registered Functor
|
||||
* appropriate for this pair of parameter types, this call will do
|
||||
* @em nothing! (If you want notification in this case, simply add a new
|
||||
* Functor for (ParamBaseType&, ParamBaseType&) at the end of the table.
|
||||
* The two base-class entries should match anything that isn't matched by
|
||||
* any more specific entry.)
|
||||
*
|
||||
* See note in class documentation about <tt>const</tt>-correctness.
|
||||
*/
|
||||
inline
|
||||
ReturnType operator()(const ParamBaseType& param1, const ParamBaseType& param2) const;
|
||||
|
||||
// Borrow a trick from Alexandrescu: use a Type class to "wrap" a type
|
||||
// for purposes of passing the type itself into a template method.
|
||||
template<typename T>
|
||||
struct Type {};
|
||||
|
||||
/**
|
||||
* Add a new Entry for a given @a Functor. As mentioned above, the order
|
||||
* in which you add these entries is very important.
|
||||
*
|
||||
* If you want symmetrical entries -- that is, if a B and an A can call
|
||||
* the same Functor as an A and a B -- then pass @c true for the last
|
||||
* parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But
|
||||
* your @a Functor can still be written to expect exactly the pair of types
|
||||
* you've explicitly specified, because the Entry with the reversed params
|
||||
* will call a special thunk that swaps params before calling your @a
|
||||
* Functor.
|
||||
*/
|
||||
template<typename Type1, typename Type2, class Functor>
|
||||
void add(const Type<Type1>& t1, const Type<Type2>& t2, Functor func, bool symmetrical=false)
|
||||
{
|
||||
insert(t1, t2, func);
|
||||
if (symmetrical)
|
||||
{
|
||||
// Use boost::bind() to construct a param-swapping thunk. Don't
|
||||
// forget to reverse the parameters too.
|
||||
insert(t2, t1, boost::bind(func, _2, _1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Entry for a given @a Functor, explicitly passing instances of
|
||||
* the Functor's leaf param types to help us figure out where to insert.
|
||||
* Because it can use RTTI, this add() method isn't order-sensitive like
|
||||
* the other one.
|
||||
*
|
||||
* If you want symmetrical entries -- that is, if a B and an A can call
|
||||
* the same Functor as an A and a B -- then pass @c true for the last
|
||||
* parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But
|
||||
* your @a Functor can still be written to expect exactly the pair of types
|
||||
* you've explicitly specified, because the Entry with the reversed params
|
||||
* will call a special thunk that swaps params before calling your @a
|
||||
* Functor.
|
||||
*/
|
||||
template <typename Type1, typename Type2, class Functor>
|
||||
void add(const Type1& prototype1, const Type2& prototype2, Functor func, bool symmetrical=false)
|
||||
{
|
||||
// Because we expect our caller to pass leaf param types, we can just
|
||||
// perform an ordinary search to find the first matching iterator. If
|
||||
// we find an existing Entry that matches both params, either the
|
||||
// param types are the same, or the existing Entry uses the base class
|
||||
// for one or both params, and the new Entry must precede that. Assume
|
||||
// our client won't register two callables with exactly the SAME set
|
||||
// of types; in that case we'll insert the new one before any earlier
|
||||
// ones, meaning the last one registered will "win." Note that if
|
||||
// find() doesn't find any matching Entry, it will return end(),
|
||||
// meaning the new Entry will be last, which is fine.
|
||||
typename DispatchTable::iterator insertion = find(prototype1, prototype2);
|
||||
insert(Type<Type1>(), Type<Type2>(), func, insertion);
|
||||
if (symmetrical)
|
||||
{
|
||||
insert(Type<Type2>(), Type<Type1>(), boost::bind(func, _2, _1), insertion);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Entry for a given @a Functor, specifying the Functor's leaf
|
||||
* param types as explicit template arguments. This will instantiate
|
||||
* temporary objects of each of these types, which requires that they have
|
||||
* a lightweight default constructor.
|
||||
*
|
||||
* If you want symmetrical entries -- that is, if a B and an A can call
|
||||
* the same Functor as an A and a B -- then pass @c true for the last
|
||||
* parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But
|
||||
* your @a Functor can still be written to expect exactly the pair of types
|
||||
* you've explicitly specified, because the Entry with the reversed params
|
||||
* will call a special thunk that swaps params before calling your @a
|
||||
* Functor.
|
||||
*/
|
||||
template <typename Type1, typename Type2, class Functor>
|
||||
void add(Functor func, bool symmetrical=false)
|
||||
{
|
||||
// This is a convenience wrapper for the add() variant taking explicit
|
||||
// instances.
|
||||
add(Type1(), Type2(), func, symmetrical);
|
||||
}
|
||||
|
||||
private:
|
||||
/// This is the base class for each entry in our dispatch table.
|
||||
struct EntryBase
|
||||
{
|
||||
virtual ~EntryBase() {}
|
||||
virtual bool matches(const ParamBaseType& param1, const ParamBaseType& param2) const = 0;
|
||||
virtual ReturnType operator()(ParamBaseType& param1, ParamBaseType& param2) const = 0;
|
||||
};
|
||||
|
||||
/// Here's the template subclass that actually creates each entry.
|
||||
template<typename Type1, typename Type2, class Functor>
|
||||
class Entry: public EntryBase
|
||||
{
|
||||
public:
|
||||
Entry(Functor func): mFunc(func) {}
|
||||
/// Is this entry appropriate for these arguments?
|
||||
virtual bool matches(const ParamBaseType& param1, const ParamBaseType& param2) const
|
||||
{
|
||||
return (dynamic_cast<const Type1*>(¶m1) &&
|
||||
dynamic_cast<const Type2*>(¶m2));
|
||||
}
|
||||
/// invocation
|
||||
virtual ReturnType operator()(ParamBaseType& param1, ParamBaseType& param2) const
|
||||
{
|
||||
// We perform the downcast so callable can accept leaf param
|
||||
// types, instead of accepting ParamBaseType and downcasting
|
||||
// explicitly.
|
||||
return mFunc(dynamic_cast<Type1&>(param1), dynamic_cast<Type2&>(param2));
|
||||
}
|
||||
private:
|
||||
/// Bind whatever function or function object the instantiator passed.
|
||||
Functor mFunc;
|
||||
};
|
||||
|
||||
/// shared_ptr manages Entry lifespan for us
|
||||
typedef boost::shared_ptr<EntryBase> EntryPtr;
|
||||
/// use a @c list to make it easy to insert
|
||||
typedef std::list<EntryPtr> DispatchTable;
|
||||
DispatchTable mDispatch;
|
||||
|
||||
/// Look up the location of the first matching entry.
|
||||
typename DispatchTable::const_iterator find(const ParamBaseType& param1, const ParamBaseType& param2) const
|
||||
{
|
||||
// We assert that it's safe to call the non-const find() method on a
|
||||
// const LLDoubleDispatch instance. Cast away the const-ness of 'this'.
|
||||
return const_cast<self_type*>(this)->find(param1, param2);
|
||||
}
|
||||
|
||||
/// Look up the location of the first matching entry.
|
||||
typename DispatchTable::iterator find(const ParamBaseType& param1, const ParamBaseType& param2)
|
||||
{
|
||||
return std::find_if(mDispatch.begin(), mDispatch.end(),
|
||||
boost::bind(&EntryBase::matches, _1,
|
||||
boost::ref(param1), boost::ref(param2)));
|
||||
}
|
||||
|
||||
/// Look up the first matching entry.
|
||||
EntryPtr lookup(const ParamBaseType& param1, const ParamBaseType& param2) const
|
||||
{
|
||||
typename DispatchTable::const_iterator found = find(param1, param2);
|
||||
if (found != mDispatch.end())
|
||||
{
|
||||
// Dereferencing the list iterator gets us an EntryPtr
|
||||
return *found;
|
||||
}
|
||||
// not found
|
||||
return EntryPtr();
|
||||
}
|
||||
|
||||
// Break out the actual insert operation so the public add() template
|
||||
// function can avoid calling itself recursively. See add() comments.
|
||||
template<typename Type1, typename Type2, class Functor>
|
||||
void insert(const Type<Type1>& param1, const Type<Type2>& param2, Functor func)
|
||||
{
|
||||
insert(param1, param2, func, mDispatch.end());
|
||||
}
|
||||
|
||||
// Break out the actual insert operation so the public add() template
|
||||
// function can avoid calling itself recursively. See add() comments.
|
||||
template<typename Type1, typename Type2, class Functor>
|
||||
void insert(const Type<Type1>&, const Type<Type2>&, Functor func,
|
||||
typename DispatchTable::iterator where)
|
||||
{
|
||||
mDispatch.insert(where, EntryPtr(new Entry<Type1, Type2, Functor>(func)));
|
||||
}
|
||||
|
||||
/// Don't implement the copy ctor. Everyone will be happier if the
|
||||
/// LLDoubleDispatch object isn't copied.
|
||||
LLDoubleDispatch(const LLDoubleDispatch& src);
|
||||
};
|
||||
|
||||
template <class ReturnType, class ParamBaseType>
|
||||
ReturnType LLDoubleDispatch<ReturnType, ParamBaseType>::operator()(const ParamBaseType& param1,
|
||||
const ParamBaseType& param2) const
|
||||
{
|
||||
EntryPtr found = lookup(param1, param2);
|
||||
if (found.get() == 0)
|
||||
return ReturnType(); // bogus return value
|
||||
|
||||
// otherwise, call the Functor we found
|
||||
return (*found)(const_cast<ParamBaseType&>(param1), const_cast<ParamBaseType&>(param2));
|
||||
}
|
||||
|
||||
#endif /* ! defined(LL_LLDOUBLEDISPATCH_H) */
|
||||
|
|
@ -53,12 +53,11 @@
|
|||
#include "llapp.h"
|
||||
#include "llapr.h"
|
||||
#include "llfile.h"
|
||||
#include "llfixedbuffer.h"
|
||||
#include "lllivefile.h"
|
||||
#include "llsd.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llstl.h"
|
||||
|
||||
#include "lltimer.h"
|
||||
|
||||
namespace {
|
||||
#if !LL_WINDOWS
|
||||
|
|
@ -192,16 +191,16 @@ namespace {
|
|||
class RecordToFixedBuffer : public LLError::Recorder
|
||||
{
|
||||
public:
|
||||
RecordToFixedBuffer(LLFixedBuffer& buffer) : mBuffer(buffer) { }
|
||||
RecordToFixedBuffer(LLLineBuffer* buffer) : mBuffer(buffer) { }
|
||||
|
||||
virtual void recordMessage(LLError::ELevel level,
|
||||
const std::string& message)
|
||||
const std::string& message)
|
||||
{
|
||||
mBuffer.addLine(message);
|
||||
mBuffer->addLine(message);
|
||||
}
|
||||
|
||||
private:
|
||||
LLFixedBuffer& mBuffer;
|
||||
LLLineBuffer* mBuffer;
|
||||
};
|
||||
|
||||
#if LL_WINDOWS
|
||||
|
|
@ -209,7 +208,7 @@ namespace {
|
|||
{
|
||||
public:
|
||||
virtual void recordMessage(LLError::ELevel level,
|
||||
const std::string& message)
|
||||
const std::string& message)
|
||||
{
|
||||
llutf16string utf16str =
|
||||
wstring_to_utf16str(utf8str_to_wstring(message));
|
||||
|
|
@ -792,7 +791,7 @@ namespace LLError
|
|||
addRecorder(f);
|
||||
}
|
||||
|
||||
void logToFixedBuffer(LLFixedBuffer* fixedBuffer)
|
||||
void logToFixedBuffer(LLLineBuffer* fixedBuffer)
|
||||
{
|
||||
LLError::Settings& s = LLError::Settings::get();
|
||||
|
||||
|
|
@ -805,7 +804,7 @@ namespace LLError
|
|||
return;
|
||||
}
|
||||
|
||||
s.fixedBufferRecorder = new RecordToFixedBuffer(*fixedBuffer);
|
||||
s.fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
|
||||
addRecorder(s.fixedBufferRecorder);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
#include "boost/function.hpp"
|
||||
#include <string>
|
||||
|
||||
class LLFixedBuffer;
|
||||
class LLSD;
|
||||
|
||||
/*
|
||||
|
|
@ -49,6 +48,18 @@ class LLSD;
|
|||
These implementations are in llerror.cpp.
|
||||
*/
|
||||
|
||||
// Line buffer interface
|
||||
class LLLineBuffer
|
||||
{
|
||||
public:
|
||||
LLLineBuffer() {};
|
||||
virtual ~LLLineBuffer() {};
|
||||
|
||||
virtual void clear() = 0; // Clear the buffer, and reset it.
|
||||
|
||||
virtual void addLine(const std::string& utf8line) = 0;
|
||||
};
|
||||
|
||||
|
||||
namespace LLError
|
||||
{
|
||||
|
|
@ -73,6 +84,7 @@ namespace LLError
|
|||
void setFunctionLevel(const std::string& function_name, LLError::ELevel);
|
||||
void setClassLevel(const std::string& class_name, LLError::ELevel);
|
||||
void setFileLevel(const std::string& file_name, LLError::ELevel);
|
||||
void setTagLevel(const std::string& file_name, LLError::ELevel);
|
||||
|
||||
void configure(const LLSD&);
|
||||
// the LLSD can configure all of the settings
|
||||
|
|
@ -143,7 +155,7 @@ namespace LLError
|
|||
// each error message is passed to each recorder via recordMessage()
|
||||
|
||||
void logToFile(const std::string& filename);
|
||||
void logToFixedBuffer(LLFixedBuffer*);
|
||||
void logToFixedBuffer(LLLineBuffer*);
|
||||
// Utilities to add recorders for logging to a file or a fixed buffer
|
||||
// A second call to the same function will remove the logger added
|
||||
// with the first.
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
#include "llerrorthread.h"
|
||||
|
||||
#include "llapp.h"
|
||||
#include "lltimer.h" // ms_sleep()
|
||||
|
||||
LLErrorThread::LLErrorThread()
|
||||
: LLThread("Error"),
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
#define LL_EVENT_H
|
||||
|
||||
#include "llsd.h"
|
||||
#include "llmemory.h"
|
||||
#include "llpointer.h"
|
||||
#include "llthread.h"
|
||||
|
||||
namespace LLOldEvents
|
||||
|
|
|
|||
|
|
@ -22,7 +22,16 @@
|
|||
#include <list>
|
||||
#include <deque>
|
||||
#include <stdexcept>
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
|
||||
#pragma warning (disable : 4264)
|
||||
#endif
|
||||
#include <boost/signals2.hpp>
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
|
@ -38,7 +47,7 @@
|
|||
#include <boost/function.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include "llsd.h"
|
||||
#include "llmemory.h"
|
||||
#include "llsingleton.h"
|
||||
#include "lldependencies.h"
|
||||
|
||||
// override this to allow binding free functions with more parameters
|
||||
|
|
|
|||
|
|
@ -30,229 +30,215 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLFASTTIMER_H
|
||||
#define LL_LLFASTTIMER_H
|
||||
#ifndef LL_FASTTIMER_H
|
||||
#define LL_FASTTIMER_H
|
||||
|
||||
#include "llinstancetracker.h"
|
||||
|
||||
#define FAST_TIMER_ON 1
|
||||
|
||||
U64 get_cpu_clock_count();
|
||||
|
||||
class LLMutex;
|
||||
|
||||
#include <queue>
|
||||
#include "llsd.h"
|
||||
|
||||
|
||||
class LLFastTimer
|
||||
{
|
||||
public:
|
||||
enum EFastTimerType
|
||||
// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
|
||||
class NamedTimer
|
||||
: public LLInstanceTracker<NamedTimer>
|
||||
{
|
||||
// high level
|
||||
FTM_FRAME,
|
||||
FTM_UPDATE,
|
||||
FTM_RENDER,
|
||||
FTM_SWAP,
|
||||
FTM_CLIENT_COPY,
|
||||
FTM_IDLE,
|
||||
FTM_SLEEP,
|
||||
public:
|
||||
~NamedTimer();
|
||||
|
||||
// common messaging components
|
||||
FTM_PUMP,
|
||||
FTM_CURL,
|
||||
enum { HISTORY_NUM = 60 };
|
||||
|
||||
const std::string& getName() { return mName; }
|
||||
NamedTimer* getParent() { return mParent; }
|
||||
void setParent(NamedTimer* parent);
|
||||
S32 getDepth();
|
||||
std::string getToolTip(S32 history_index = -1);
|
||||
|
||||
typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
|
||||
child_const_iter beginChildren();
|
||||
child_const_iter endChildren();
|
||||
std::vector<NamedTimer*>& getChildren();
|
||||
|
||||
void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
|
||||
bool getCollapsed() const { return mCollapsed; }
|
||||
|
||||
U64 getCountAverage() const { return mCountAverage; }
|
||||
U64 getCallAverage() const { return mCallAverage; }
|
||||
|
||||
U64 getHistoricalCount(S32 history_index = 0) const;
|
||||
U64 getHistoricalCalls(S32 history_index = 0) const;
|
||||
|
||||
static NamedTimer& getRootNamedTimer();
|
||||
|
||||
struct FrameState
|
||||
{
|
||||
FrameState(NamedTimer* timerp);
|
||||
|
||||
U64 mSelfTimeCounter;
|
||||
U64 mLastStartTime; // most recent time when this timer was started
|
||||
U32 mCalls;
|
||||
FrameState* mParent; // info for caller timer
|
||||
FrameState* mLastCaller; // used to bootstrap tree construction
|
||||
NamedTimer* mTimer;
|
||||
U16 mActiveCount; // number of timers with this ID active on stack
|
||||
bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
|
||||
};
|
||||
|
||||
FrameState& getFrameStateFast() const
|
||||
{
|
||||
return (*sTimerInfos)[mFrameStateIndex];
|
||||
}
|
||||
|
||||
S32 getFrameStateIndex() const { return mFrameStateIndex; }
|
||||
|
||||
FrameState& getFrameState() const;
|
||||
|
||||
|
||||
private:
|
||||
friend class LLFastTimer;
|
||||
friend class NamedTimerFactory;
|
||||
|
||||
//
|
||||
// methods
|
||||
//
|
||||
NamedTimer(const std::string& name);
|
||||
// recursive call to gather total time from children
|
||||
static void accumulateTimings();
|
||||
|
||||
// called once per frame by LLFastTimer
|
||||
static void processFrame();
|
||||
|
||||
static void buildHierarchy();
|
||||
static void resetFrame();
|
||||
static void reset();
|
||||
|
||||
typedef std::vector<FrameState> info_list_t;
|
||||
static info_list_t& getFrameStateList();
|
||||
static void createFrameStateList(); // must call before any call to getFrameStateList()
|
||||
|
||||
// common simulation components
|
||||
FTM_UPDATE_ANIMATION,
|
||||
FTM_UPDATE_TERRAIN,
|
||||
FTM_UPDATE_PRIMITIVES,
|
||||
FTM_UPDATE_PARTICLES,
|
||||
FTM_SIMULATE_PARTICLES,
|
||||
FTM_UPDATE_SKY,
|
||||
FTM_UPDATE_TEXTURES,
|
||||
FTM_UPDATE_WLPARAM,
|
||||
FTM_UPDATE_WATER,
|
||||
FTM_UPDATE_CLOUDS,
|
||||
FTM_UPDATE_GRASS,
|
||||
FTM_UPDATE_TREE,
|
||||
FTM_UPDATE_AVATAR,
|
||||
|
||||
// common render components
|
||||
FTM_SHADOW_GEOMETRY,
|
||||
FTM_SHADOW_RENDER,
|
||||
FTM_SHADOW_TERRAIN,
|
||||
FTM_SHADOW_AVATAR,
|
||||
FTM_SHADOW_SIMPLE,
|
||||
FTM_SHADOW_ALPHA,
|
||||
FTM_SHADOW_TREE,
|
||||
|
||||
FTM_RENDER_GEOMETRY,
|
||||
FTM_RENDER_TERRAIN,
|
||||
FTM_RENDER_SIMPLE,
|
||||
FTM_RENDER_FULLBRIGHT,
|
||||
FTM_RENDER_GLOW,
|
||||
FTM_RENDER_GRASS,
|
||||
FTM_RENDER_INVISIBLE,
|
||||
FTM_RENDER_SHINY,
|
||||
FTM_RENDER_BUMP,
|
||||
FTM_RENDER_TREES,
|
||||
FTM_RENDER_CHARACTERS,
|
||||
FTM_RENDER_OCCLUSION,
|
||||
FTM_RENDER_ALPHA,
|
||||
FTM_RENDER_CLOUDS,
|
||||
FTM_RENDER_HUD,
|
||||
FTM_RENDER_PARTICLES,
|
||||
FTM_RENDER_WATER,
|
||||
FTM_RENDER_WL_SKY,
|
||||
FTM_RENDER_FAKE_VBO_UPDATE,
|
||||
FTM_RENDER_TIMER,
|
||||
FTM_RENDER_UI,
|
||||
FTM_RENDER_BLOOM,
|
||||
FTM_RENDER_BLOOM_FBO,
|
||||
FTM_RENDER_FONTS,
|
||||
|
||||
// newview specific
|
||||
FTM_MESSAGES,
|
||||
FTM_MOUSEHANDLER,
|
||||
FTM_KEYHANDLER,
|
||||
FTM_REBUILD,
|
||||
FTM_STATESORT,
|
||||
FTM_STATESORT_DRAWABLE,
|
||||
FTM_STATESORT_POSTSORT,
|
||||
FTM_REBUILD_VBO,
|
||||
FTM_REBUILD_VOLUME_VB,
|
||||
FTM_REBUILD_BRIDGE_VB,
|
||||
FTM_REBUILD_HUD_VB,
|
||||
FTM_REBUILD_TERRAIN_VB,
|
||||
FTM_REBUILD_WATER_VB,
|
||||
FTM_REBUILD_TREE_VB,
|
||||
FTM_REBUILD_PARTICLE_VB,
|
||||
FTM_REBUILD_CLOUD_VB,
|
||||
FTM_REBUILD_GRASS_VB,
|
||||
FTM_REBUILD_NONE_VB,
|
||||
FTM_REBUILD_OCCLUSION_VB,
|
||||
FTM_POOLS,
|
||||
FTM_POOLRENDER,
|
||||
FTM_IDLE_CB,
|
||||
FTM_WORLD_UPDATE,
|
||||
FTM_UPDATE_MOVE,
|
||||
FTM_OCTREE_BALANCE,
|
||||
FTM_UPDATE_LIGHTS,
|
||||
FTM_CULL,
|
||||
FTM_CULL_REBOUND,
|
||||
FTM_FRUSTUM_CULL,
|
||||
FTM_GEO_UPDATE,
|
||||
FTM_GEO_RESERVE,
|
||||
FTM_GEO_LIGHT,
|
||||
FTM_GEO_SHADOW,
|
||||
FTM_GEO_SKY,
|
||||
FTM_GEN_VOLUME,
|
||||
FTM_GEN_TRIANGLES,
|
||||
FTM_GEN_FLEX,
|
||||
FTM_AUDIO_UPDATE,
|
||||
FTM_RESET_DRAWORDER,
|
||||
FTM_OBJECTLIST_UPDATE,
|
||||
FTM_AVATAR_UPDATE,
|
||||
FTM_JOINT_UPDATE,
|
||||
FTM_ATTACHMENT_UPDATE,
|
||||
FTM_LOD_UPDATE,
|
||||
FTM_REGION_UPDATE,
|
||||
FTM_CLEANUP,
|
||||
FTM_NETWORK,
|
||||
FTM_IDLE_NETWORK,
|
||||
FTM_CREATE_OBJECT,
|
||||
FTM_LOAD_AVATAR,
|
||||
FTM_PROCESS_MESSAGES,
|
||||
FTM_PROCESS_OBJECTS,
|
||||
FTM_PROCESS_IMAGES,
|
||||
FTM_IMAGE_UPDATE,
|
||||
FTM_IMAGE_CREATE,
|
||||
FTM_IMAGE_DECODE,
|
||||
FTM_IMAGE_MARK_DIRTY,
|
||||
FTM_PIPELINE,
|
||||
FTM_VFILE_WAIT,
|
||||
FTM_FLEXIBLE_UPDATE,
|
||||
FTM_OCCLUSION_READBACK,
|
||||
FTM_HUD_EFFECTS,
|
||||
FTM_HUD_UPDATE,
|
||||
FTM_INVENTORY,
|
||||
FTM_AUTO_SELECT,
|
||||
FTM_ARRANGE,
|
||||
FTM_FILTER,
|
||||
FTM_REFRESH,
|
||||
FTM_SORT,
|
||||
FTM_PICK,
|
||||
|
||||
// Temp
|
||||
FTM_TEMP1,
|
||||
FTM_TEMP2,
|
||||
FTM_TEMP3,
|
||||
FTM_TEMP4,
|
||||
FTM_TEMP5,
|
||||
FTM_TEMP6,
|
||||
FTM_TEMP7,
|
||||
FTM_TEMP8,
|
||||
|
||||
FTM_OTHER, // Special, used by display code
|
||||
|
||||
FTM_NUM_TYPES
|
||||
//
|
||||
// members
|
||||
//
|
||||
S32 mFrameStateIndex;
|
||||
|
||||
std::string mName;
|
||||
|
||||
U64 mTotalTimeCounter;
|
||||
|
||||
U64 mCountAverage;
|
||||
U64 mCallAverage;
|
||||
|
||||
U64* mCountHistory;
|
||||
U64* mCallHistory;
|
||||
|
||||
// tree structure
|
||||
NamedTimer* mParent; // NamedTimer of caller(parent)
|
||||
std::vector<NamedTimer*> mChildren;
|
||||
bool mCollapsed; // don't show children
|
||||
bool mNeedsSorting; // sort children whenever child added
|
||||
|
||||
static info_list_t* sTimerInfos;
|
||||
};
|
||||
enum { FTM_HISTORY_NUM = 60 };
|
||||
enum { FTM_MAX_DEPTH = 64 };
|
||||
|
||||
|
||||
// used to statically declare a new named timer
|
||||
class DeclareTimer
|
||||
{
|
||||
public:
|
||||
DeclareTimer(const std::string& name, bool open);
|
||||
DeclareTimer(const std::string& name);
|
||||
|
||||
// convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer)
|
||||
operator NamedTimer::FrameState&() { return mNamedTimer.getFrameStateFast(); }
|
||||
private:
|
||||
NamedTimer& mNamedTimer;
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
static LLFastTimer::EFastTimerType sCurType;
|
||||
enum RootTimerMarker { ROOT };
|
||||
|
||||
static LLMutex* sLogLock;
|
||||
static std::queue<LLSD> sLogQueue;
|
||||
static BOOL sLog;
|
||||
static BOOL sMetricLog;
|
||||
|
||||
LLFastTimer(EFastTimerType type)
|
||||
LLFastTimer(RootTimerMarker);
|
||||
|
||||
LLFastTimer(NamedTimer::FrameState& timer)
|
||||
: mFrameState(&timer)
|
||||
{
|
||||
#if FAST_TIMER_ON
|
||||
mType = type;
|
||||
sCurType = type;
|
||||
// These don't get counted, because they use CPU clockticks
|
||||
//gTimerBins[gCurTimerBin]++;
|
||||
//LLTimer::sNumTimerCalls++;
|
||||
NamedTimer::FrameState* frame_state = mFrameState;
|
||||
frame_state->mLastStartTime = get_cpu_clock_count();
|
||||
mStartSelfTime = frame_state->mLastStartTime;
|
||||
|
||||
U64 cpu_clocks = get_cpu_clock_count();
|
||||
|
||||
sStart[sCurDepth] = cpu_clocks;
|
||||
sCurDepth++;
|
||||
#endif
|
||||
};
|
||||
~LLFastTimer()
|
||||
{
|
||||
#if FAST_TIMER_ON
|
||||
U64 end,delta;
|
||||
int i;
|
||||
|
||||
// These don't get counted, because they use CPU clockticks
|
||||
//gTimerBins[gCurTimerBin]++;
|
||||
//LLTimer::sNumTimerCalls++;
|
||||
end = get_cpu_clock_count();
|
||||
|
||||
sCurDepth--;
|
||||
delta = end - sStart[sCurDepth];
|
||||
sCounter[mType] += delta;
|
||||
sCalls[mType]++;
|
||||
// Subtract delta from parents
|
||||
for (i=0; i<sCurDepth; i++)
|
||||
sStart[i] += delta;
|
||||
frame_state->mActiveCount++;
|
||||
frame_state->mCalls++;
|
||||
// keep current parent as long as it is active when we are
|
||||
frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
|
||||
|
||||
mLastTimer = sCurTimer;
|
||||
sCurTimer = this;
|
||||
#endif
|
||||
}
|
||||
|
||||
~LLFastTimer()
|
||||
{
|
||||
#if FAST_TIMER_ON
|
||||
NamedTimer::FrameState* frame_state = mFrameState;
|
||||
U64 cur_time = get_cpu_clock_count();
|
||||
frame_state->mSelfTimeCounter += cur_time - mStartSelfTime;
|
||||
|
||||
frame_state->mActiveCount--;
|
||||
LLFastTimer* last_timer = mLastTimer;
|
||||
sCurTimer = last_timer;
|
||||
|
||||
// store last caller to bootstrap tree creation
|
||||
frame_state->mLastCaller = last_timer->mFrameState;
|
||||
|
||||
// we are only tracking self time, so subtract our total time delta from parents
|
||||
U64 total_time = cur_time - frame_state->mLastStartTime;
|
||||
last_timer->mStartSelfTime += total_time;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// call this once a frame to reset timers
|
||||
static void nextFrame();
|
||||
|
||||
// call this to reset timer hierarchy, averages, etc.
|
||||
static void reset();
|
||||
|
||||
static U64 countsPerSecond();
|
||||
static S32 getLastFrameIndex() { return sLastFrameIndex; }
|
||||
static S32 getCurFrameIndex() { return sCurFrameIndex; }
|
||||
|
||||
static void writeLog(std::ostream& os);
|
||||
static const NamedTimer* getTimerByName(const std::string& name);
|
||||
|
||||
public:
|
||||
static int sCurDepth;
|
||||
static U64 sStart[FTM_MAX_DEPTH];
|
||||
static U64 sCounter[FTM_NUM_TYPES];
|
||||
static U64 sCalls[FTM_NUM_TYPES];
|
||||
static U64 sCountAverage[FTM_NUM_TYPES];
|
||||
static U64 sCallAverage[FTM_NUM_TYPES];
|
||||
static U64 sCountHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES];
|
||||
static U64 sCallHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES];
|
||||
static S32 sCurFrameIndex;
|
||||
static S32 sLastFrameIndex;
|
||||
static int sPauseHistory;
|
||||
static int sResetHistory;
|
||||
static F64 sCPUClockFrequency;
|
||||
static bool sPauseHistory;
|
||||
static bool sResetHistory;
|
||||
|
||||
private:
|
||||
EFastTimerType mType;
|
||||
typedef std::vector<LLFastTimer*> timer_stack_t;
|
||||
static LLFastTimer* sCurTimer;
|
||||
static S32 sCurFrameIndex;
|
||||
static S32 sLastFrameIndex;
|
||||
|
||||
static F64 sCPUClockFrequency;
|
||||
U64 mStartSelfTime; // start time + time of all child timers
|
||||
NamedTimer::FrameState* mFrameState;
|
||||
LLFastTimer* mLastTimer;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_LLFASTTIMER_H
|
||||
|
|
|
|||
|
|
@ -32,20 +32,21 @@
|
|||
|
||||
#include "llfixedbuffer.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
|
||||
: mMutex(NULL)
|
||||
: LLLineBuffer(),
|
||||
mMaxLines(max_lines),
|
||||
mMutex(NULL)
|
||||
{
|
||||
mMaxLines = max_lines;
|
||||
mTimer.reset();
|
||||
}
|
||||
|
||||
|
||||
LLFixedBuffer::~LLFixedBuffer()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
void LLFixedBuffer::clear()
|
||||
{
|
||||
mMutex.lock() ;
|
||||
|
|
@ -61,10 +62,10 @@ void LLFixedBuffer::clear()
|
|||
void LLFixedBuffer::addLine(const std::string& utf8line)
|
||||
{
|
||||
LLWString wstring = utf8str_to_wstring(utf8line);
|
||||
LLFixedBuffer::addLine(wstring);
|
||||
addWLine(wstring);
|
||||
}
|
||||
|
||||
void LLFixedBuffer::addLine(const LLWString& line)
|
||||
void LLFixedBuffer::addWLine(const LLWString& line)
|
||||
{
|
||||
if (line.empty())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,14 +38,14 @@
|
|||
#include <string>
|
||||
#include "llstring.h"
|
||||
#include "llthread.h"
|
||||
#include "llerrorcontrol.h"
|
||||
|
||||
// Fixed size buffer for console output and other things.
|
||||
|
||||
class LLFixedBuffer
|
||||
// fixed buffer implementation
|
||||
class LLFixedBuffer : public LLLineBuffer
|
||||
{
|
||||
public:
|
||||
LLFixedBuffer(const U32 max_lines = 20);
|
||||
virtual ~LLFixedBuffer();
|
||||
~LLFixedBuffer();
|
||||
|
||||
LLTimer mTimer;
|
||||
U32 mMaxLines;
|
||||
|
|
@ -53,22 +53,18 @@ public:
|
|||
std::deque<F32> mAddTimes;
|
||||
std::deque<S32> mLineLengths;
|
||||
|
||||
void clear(); // Clear the buffer, and reset it.
|
||||
/*virtual*/ void clear(); // Clear the buffer, and reset it.
|
||||
|
||||
//do not make these two "virtual"
|
||||
void addLine(const std::string& utf8line);
|
||||
void addLine(const LLWString& line);
|
||||
/*virtual*/ void addLine(const std::string& utf8line);
|
||||
|
||||
// Get lines currently in the buffer, up to max_size chars, max_length lines
|
||||
char *getLines(U32 max_size = 0, U32 max_length = 0);
|
||||
void setMaxLines(S32 max_lines);
|
||||
|
||||
protected:
|
||||
virtual void removeExtraLines();
|
||||
void removeExtraLines();
|
||||
void addWLine(const LLWString& line);
|
||||
|
||||
protected:
|
||||
LLMutex mMutex ;
|
||||
};
|
||||
|
||||
const U32 FIXED_BUF_MAX_LINE_LEN = 255; // Not including termnating 0
|
||||
|
||||
#endif //LL_FIXED_BUFFER_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
* @file llinstancetracker.h
|
||||
* @brief LLInstanceTracker is a mixin class that automatically tracks object
|
||||
* instances with or without an associated key
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-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_LLINSTANCETRACKER_H
|
||||
#define LL_LLINSTANCETRACKER_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "string_table.h"
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
// This mix-in class adds support for tracking all instances of the specified class parameter T
|
||||
// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
|
||||
// If KEY is not provided, then instances are stored in a simple set
|
||||
// *NOTE: see explicit specialization below for default KEY==T* case
|
||||
template<typename T, typename KEY = T*>
|
||||
class LLInstanceTracker : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
typedef typename std::map<KEY, T*>::iterator instance_iter;
|
||||
typedef typename std::map<KEY, T*>::const_iterator instance_const_iter;
|
||||
|
||||
static T* getInstance(const KEY& k) { instance_iter found = getMap().find(k); return (found == getMap().end()) ? NULL : found->second; }
|
||||
|
||||
static instance_iter beginInstances() { return getMap().begin(); }
|
||||
static instance_iter endInstances() { return getMap().end(); }
|
||||
static S32 instanceCount() { return getMap().size(); }
|
||||
protected:
|
||||
LLInstanceTracker(KEY key) { add(key); }
|
||||
virtual ~LLInstanceTracker() { remove(); }
|
||||
virtual void setKey(KEY key) { remove(); add(key); }
|
||||
virtual const KEY& getKey() const { return mKey; }
|
||||
|
||||
private:
|
||||
void add(KEY key)
|
||||
{
|
||||
mKey = key;
|
||||
getMap()[key] = static_cast<T*>(this);
|
||||
}
|
||||
void remove() { getMap().erase(mKey); }
|
||||
|
||||
static std::map<KEY, T*>& getMap()
|
||||
{
|
||||
if (! sInstances)
|
||||
{
|
||||
sInstances = new std::map<KEY, T*>;
|
||||
}
|
||||
return *sInstances;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
KEY mKey;
|
||||
static std::map<KEY, T*>* sInstances;
|
||||
};
|
||||
|
||||
// explicit specialization for default case where KEY is T*
|
||||
// use a simple std::set<T*>
|
||||
template<typename T>
|
||||
class LLInstanceTracker<T, T*>
|
||||
{
|
||||
public:
|
||||
typedef typename std::set<T*>::iterator instance_iter;
|
||||
typedef typename std::set<T*>::const_iterator instance_const_iter;
|
||||
|
||||
static instance_iter beginInstances() { return getSet().begin(); }
|
||||
static instance_iter endInstances() { return getSet().end(); }
|
||||
static S32 instanceCount() { return getSet().size(); }
|
||||
|
||||
protected:
|
||||
LLInstanceTracker() { getSet().insert(static_cast<T*>(this)); }
|
||||
virtual ~LLInstanceTracker() { getSet().erase(static_cast<T*>(this)); }
|
||||
|
||||
LLInstanceTracker(const LLInstanceTracker& other) { getSet().insert(static_cast<T*>(this)); }
|
||||
|
||||
static std::set<T*>& getSet() // called after getReady() but before go()
|
||||
{
|
||||
if (! sInstances)
|
||||
{
|
||||
sInstances = new std::set<T*>;
|
||||
}
|
||||
return *sInstances;
|
||||
}
|
||||
|
||||
static std::set<T*>* sInstances;
|
||||
};
|
||||
|
||||
template <typename T, typename KEY> std::map<KEY, T*>* LLInstanceTracker<T, KEY>::sInstances = NULL;
|
||||
template <typename T> std::set<T*>* LLInstanceTracker<T, T*>::sInstances = NULL;
|
||||
|
||||
#endif
|
||||
|
|
@ -83,6 +83,7 @@ documentation and/or software.
|
|||
#include "llmd5.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream> // cerr
|
||||
|
||||
// how many bytes to grab at a time when checking files
|
||||
const int LLMD5::BLOCK_LEN = 4096;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
#endif
|
||||
|
||||
#include "llmemory.h"
|
||||
#include "llmemtype.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -74,162 +73,6 @@ void LLMemory::freeReserve()
|
|||
reserveMem = NULL;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//static
|
||||
#if MEM_TRACK_TYPE
|
||||
S32 LLMemType::sCurDepth = 0;
|
||||
S32 LLMemType::sCurType = LLMemType::MTYPE_INIT;
|
||||
S32 LLMemType::sType[LLMemType::MTYPE_MAX_DEPTH];
|
||||
S32 LLMemType::sMemCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
|
||||
S32 LLMemType::sMaxMemCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
|
||||
S32 LLMemType::sNewCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
|
||||
S32 LLMemType::sOverheadMem = 0;
|
||||
|
||||
const char* LLMemType::sTypeDesc[LLMemType::MTYPE_NUM_TYPES] =
|
||||
{
|
||||
"INIT",
|
||||
"STARTUP",
|
||||
"MAIN",
|
||||
|
||||
"IMAGEBASE",
|
||||
"IMAGERAW",
|
||||
"IMAGEFORMATTED",
|
||||
|
||||
"APPFMTIMAGE",
|
||||
"APPRAWIMAGE",
|
||||
"APPAUXRAWIMAGE",
|
||||
|
||||
"DRAWABLE",
|
||||
"OBJECT",
|
||||
"PIPELINE",
|
||||
"AVATAR",
|
||||
"PARTICLES",
|
||||
"REGIONS",
|
||||
"INVENTORY",
|
||||
"ANIMATION",
|
||||
"NETWORK",
|
||||
"PHYSICS",
|
||||
"INTERESTLIST",
|
||||
|
||||
"SCRIPT",
|
||||
"SCRIPT_RUN",
|
||||
"SCRIPT_BYTECODE",
|
||||
|
||||
"IO_PUMP",
|
||||
"IO_TCP",
|
||||
"IO_BUFFER",
|
||||
"IO_HTTP_SERVER"
|
||||
"IO_SD_SERVER",
|
||||
"IO_SD_CLIENT",
|
||||
"IO_URL_REQUEST",
|
||||
|
||||
"TEMP1",
|
||||
"TEMP2",
|
||||
"TEMP3",
|
||||
"TEMP4",
|
||||
"TEMP5",
|
||||
"TEMP6",
|
||||
"TEMP7",
|
||||
"TEMP8",
|
||||
"TEMP9"
|
||||
};
|
||||
|
||||
#endif
|
||||
S32 LLMemType::sTotalMem = 0;
|
||||
S32 LLMemType::sMaxTotalMem = 0;
|
||||
|
||||
//static
|
||||
void LLMemType::printMem()
|
||||
{
|
||||
S32 misc_mem = sTotalMem;
|
||||
#if MEM_TRACK_TYPE
|
||||
for (S32 i=0; i<MTYPE_NUM_TYPES; i++)
|
||||
{
|
||||
if (sMemCount[i])
|
||||
{
|
||||
llinfos << llformat("MEM: % 20s %03d MB (%03d MB) in %06d News",sTypeDesc[i],sMemCount[i]>>20,sMaxMemCount[i]>>20, sNewCount[i]) << llendl;
|
||||
}
|
||||
misc_mem -= sMemCount[i];
|
||||
}
|
||||
#endif
|
||||
llinfos << llformat("MEM: % 20s %03d MB","MISC",misc_mem>>20) << llendl;
|
||||
llinfos << llformat("MEM: % 20s %03d MB (Max=%d MB)","TOTAL",sTotalMem>>20,sMaxTotalMem>>20) << llendl;
|
||||
}
|
||||
|
||||
#if MEM_TRACK_MEM
|
||||
|
||||
void* ll_allocate (size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
llwarns << "Null allocation" << llendl;
|
||||
}
|
||||
|
||||
size = (size+3)&~3;
|
||||
S32 alloc_size = size + 4;
|
||||
#if MEM_TRACK_TYPE
|
||||
alloc_size += 4;
|
||||
#endif
|
||||
char* p = (char*)malloc(alloc_size);
|
||||
if (p == NULL)
|
||||
{
|
||||
LLMemory::freeReserve();
|
||||
llerrs << "Out of memory Error" << llendl;
|
||||
}
|
||||
LLMemType::sTotalMem += size;
|
||||
LLMemType::sMaxTotalMem = llmax(LLMemType::sTotalMem, LLMemType::sMaxTotalMem);
|
||||
LLMemType::sOverheadMem += 4;
|
||||
*(size_t*)p = size;
|
||||
p += 4;
|
||||
#if MEM_TRACK_TYPE
|
||||
if (LLMemType::sCurType < 0 || LLMemType::sCurType >= LLMemType::MTYPE_NUM_TYPES)
|
||||
{
|
||||
llerrs << "Memory Type Error: new" << llendl;
|
||||
}
|
||||
LLMemType::sOverheadMem += 4;
|
||||
*(S32*)p = LLMemType::sCurType;
|
||||
p += 4;
|
||||
LLMemType::sMemCount[LLMemType::sCurType] += size;
|
||||
if (LLMemType::sMemCount[LLMemType::sCurType] > LLMemType::sMaxMemCount[LLMemType::sCurType])
|
||||
{
|
||||
LLMemType::sMaxMemCount[LLMemType::sCurType] = LLMemType::sMemCount[LLMemType::sCurType];
|
||||
}
|
||||
LLMemType::sNewCount[LLMemType::sCurType]++;
|
||||
#endif
|
||||
return (void*)p;
|
||||
}
|
||||
|
||||
void ll_release (void *pin)
|
||||
{
|
||||
if (!pin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
char* p = (char*)pin;
|
||||
#if MEM_TRACK_TYPE
|
||||
p -= 4;
|
||||
S32 type = *(S32*)p;
|
||||
if (type < 0 || type >= LLMemType::MTYPE_NUM_TYPES)
|
||||
{
|
||||
llerrs << "Memory Type Error: delete" << llendl;
|
||||
}
|
||||
#endif
|
||||
p -= 4;
|
||||
S32 size = *(size_t*)p;
|
||||
LLMemType::sOverheadMem -= 4;
|
||||
#if MEM_TRACK_TYPE
|
||||
LLMemType::sMemCount[type] -= size;
|
||||
LLMemType::sOverheadMem -= 4;
|
||||
LLMemType::sNewCount[type]--;
|
||||
#endif
|
||||
LLMemType::sTotalMem -= size;
|
||||
free(p);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void* ll_allocate (size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
|
|
@ -250,52 +93,11 @@ void ll_release (void *p)
|
|||
free(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if MEM_TRACK_MEM
|
||||
|
||||
void* operator new (size_t size)
|
||||
{
|
||||
return ll_allocate(size);
|
||||
}
|
||||
|
||||
void* operator new[] (size_t size)
|
||||
{
|
||||
return ll_allocate(size);
|
||||
}
|
||||
|
||||
void operator delete (void *p)
|
||||
{
|
||||
ll_release(p);
|
||||
}
|
||||
|
||||
void operator delete[] (void *p)
|
||||
{
|
||||
ll_release(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
LLRefCount::LLRefCount() :
|
||||
mRef(0)
|
||||
{
|
||||
}
|
||||
|
||||
LLRefCount::~LLRefCount()
|
||||
{
|
||||
if (mRef != 0)
|
||||
{
|
||||
llerrs << "deleting non-zero reference" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
|
||||
U64 getCurrentRSS()
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
HANDLE self = GetCurrentProcess();
|
||||
PROCESS_MEMORY_COUNTERS counters;
|
||||
|
|
@ -333,7 +135,7 @@ U64 getCurrentRSS()
|
|||
// }
|
||||
// }
|
||||
|
||||
U64 getCurrentRSS()
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
U64 residentSize = 0;
|
||||
task_basic_info_data_t basicInfo;
|
||||
|
|
@ -357,7 +159,7 @@ U64 getCurrentRSS()
|
|||
|
||||
#elif defined(LL_LINUX)
|
||||
|
||||
U64 getCurrentRSS()
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
static const char statPath[] = "/proc/self/stat";
|
||||
LLFILE *fp = LLFile::fopen(statPath, "r");
|
||||
|
|
@ -396,7 +198,7 @@ bail:
|
|||
#define _STRUCTURED_PROC 1
|
||||
#include <sys/procfs.h>
|
||||
|
||||
U64 getCurrentRSS()
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
char path [LL_MAX_PATH]; /* Flawfinder: ignore */
|
||||
|
||||
|
|
@ -419,7 +221,7 @@ U64 getCurrentRSS()
|
|||
}
|
||||
#else
|
||||
|
||||
U64 getCurrentRSS()
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,21 +29,17 @@
|
|||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LL_MEMORY_H
|
||||
#define LL_MEMORY_H
|
||||
#ifndef LLMEMORY_H
|
||||
#define LLMEMORY_H
|
||||
|
||||
#include <new>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "llerror.h"
|
||||
|
||||
extern S32 gTotalDAlloc;
|
||||
extern S32 gTotalDAUse;
|
||||
extern S32 gDACount;
|
||||
|
||||
const U32 LLREFCOUNT_SENTINEL_VALUE = 0xAAAAAAAA;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
extern void* ll_allocate (size_t size);
|
||||
extern void ll_release (void *p);
|
||||
|
||||
class LLMemory
|
||||
{
|
||||
|
|
@ -51,422 +47,19 @@ public:
|
|||
static void initClass();
|
||||
static void cleanupClass();
|
||||
static void freeReserve();
|
||||
// Return the resident set size of the current process, in bytes.
|
||||
// Return value is zero if not known.
|
||||
static U64 getCurrentRSS();
|
||||
private:
|
||||
static char* reserveMem;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// RefCount objects should generally only be accessed by way of LLPointer<>'s
|
||||
// NOTE: LLPointer<LLFoo> x = new LLFoo(); MAY NOT BE THREAD SAFE
|
||||
// if LLFoo::LLFoo() does anything like put itself in an update queue.
|
||||
// The queue may get accessed before it gets assigned to x.
|
||||
// The correct implementation is:
|
||||
// LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting
|
||||
// x->instantiate(); // does stuff like place x into an update queue
|
||||
// LLRefCount moved to llrefcount.h
|
||||
|
||||
// see llthread.h for LLThreadSafeRefCount
|
||||
// LLPointer moved to llpointer.h
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// LLSafeHandle moved to llsafehandle.h
|
||||
|
||||
class LLRefCount
|
||||
{
|
||||
protected:
|
||||
LLRefCount(const LLRefCount&); // not implemented
|
||||
private:
|
||||
LLRefCount&operator=(const LLRefCount&); // not implemented
|
||||
|
||||
protected:
|
||||
virtual ~LLRefCount(); // use unref()
|
||||
|
||||
public:
|
||||
LLRefCount();
|
||||
|
||||
void ref()
|
||||
{
|
||||
mRef++;
|
||||
}
|
||||
|
||||
S32 unref()
|
||||
{
|
||||
llassert(mRef >= 1);
|
||||
if (0 == --mRef)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return mRef;
|
||||
}
|
||||
|
||||
S32 getNumRefs() const
|
||||
{
|
||||
return mRef;
|
||||
}
|
||||
|
||||
private:
|
||||
S32 mRef;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Note: relies on Type having ref() and unref() methods
|
||||
template <class Type> class LLPointer
|
||||
{
|
||||
public:
|
||||
|
||||
LLPointer() :
|
||||
mPointer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLPointer(Type* ptr) :
|
||||
mPointer(ptr)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
LLPointer(const LLPointer<Type>& ptr) :
|
||||
mPointer(ptr.mPointer)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLPointer(const LLPointer<Subclass>& ptr) :
|
||||
mPointer(ptr.get())
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
~LLPointer()
|
||||
{
|
||||
unref();
|
||||
}
|
||||
|
||||
Type* get() const { return mPointer; }
|
||||
const Type* operator->() const { return mPointer; }
|
||||
Type* operator->() { return mPointer; }
|
||||
const Type& operator*() const { return *mPointer; }
|
||||
Type& operator*() { return *mPointer; }
|
||||
|
||||
operator BOOL() const { return (mPointer != NULL); }
|
||||
operator bool() const { return (mPointer != NULL); }
|
||||
bool operator!() const { return (mPointer == NULL); }
|
||||
bool isNull() const { return (mPointer == NULL); }
|
||||
bool notNull() const { return (mPointer != NULL); }
|
||||
|
||||
operator Type*() const { return mPointer; }
|
||||
operator const Type*() const { return mPointer; }
|
||||
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
||||
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
||||
bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
||||
bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
||||
bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
||||
|
||||
LLPointer<Type>& operator =(Type* ptr)
|
||||
{
|
||||
if( mPointer != ptr )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr;
|
||||
ref();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
|
||||
{
|
||||
if( mPointer != ptr.mPointer )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr.mPointer;
|
||||
ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
|
||||
{
|
||||
if( mPointer != ptr.get() )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr.get();
|
||||
ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Just exchange the pointers, which will not change the reference counts.
|
||||
static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
|
||||
{
|
||||
Type* temp = a.mPointer;
|
||||
a.mPointer = b.mPointer;
|
||||
b.mPointer = temp;
|
||||
}
|
||||
|
||||
protected:
|
||||
void ref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
mPointer->ref();
|
||||
}
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
Type *tempp = mPointer;
|
||||
mPointer = NULL;
|
||||
tempp->unref();
|
||||
if (mPointer != NULL)
|
||||
{
|
||||
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
||||
unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Type* mPointer;
|
||||
};
|
||||
|
||||
//template <class Type>
|
||||
//class LLPointerTraits
|
||||
//{
|
||||
// static Type* null();
|
||||
//};
|
||||
//
|
||||
// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL.
|
||||
// This is useful in instances where operations on NULL pointers are semantically safe and/or
|
||||
// when error checking occurs at a different granularity or in a different part of the code
|
||||
// than when referencing an object via a LLSafeHandle.
|
||||
//
|
||||
|
||||
template <class Type>
|
||||
class LLSafeHandle
|
||||
{
|
||||
public:
|
||||
LLSafeHandle() :
|
||||
mPointer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLSafeHandle(Type* ptr) :
|
||||
mPointer(NULL)
|
||||
{
|
||||
assign(ptr);
|
||||
}
|
||||
|
||||
LLSafeHandle(const LLSafeHandle<Type>& ptr) :
|
||||
mPointer(NULL)
|
||||
{
|
||||
assign(ptr.mPointer);
|
||||
}
|
||||
|
||||
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLSafeHandle(const LLSafeHandle<Subclass>& ptr) :
|
||||
mPointer(NULL)
|
||||
{
|
||||
assign(ptr.get());
|
||||
}
|
||||
|
||||
~LLSafeHandle()
|
||||
{
|
||||
unref();
|
||||
}
|
||||
|
||||
const Type* operator->() const { return nonNull(mPointer); }
|
||||
Type* operator->() { return nonNull(mPointer); }
|
||||
|
||||
Type* get() const { return mPointer; }
|
||||
// we disallow these operations as they expose our null objects to direct manipulation
|
||||
// and bypass the reference counting semantics
|
||||
//const Type& operator*() const { return *nonNull(mPointer); }
|
||||
//Type& operator*() { return *nonNull(mPointer); }
|
||||
|
||||
operator BOOL() const { return mPointer != NULL; }
|
||||
operator bool() const { return mPointer != NULL; }
|
||||
bool operator!() const { return mPointer == NULL; }
|
||||
bool isNull() const { return mPointer == NULL; }
|
||||
bool notNull() const { return mPointer != NULL; }
|
||||
|
||||
|
||||
operator Type*() const { return mPointer; }
|
||||
operator const Type*() const { return mPointer; }
|
||||
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
||||
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
||||
bool operator ==(const LLSafeHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
||||
bool operator < (const LLSafeHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
||||
bool operator > (const LLSafeHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
||||
|
||||
LLSafeHandle<Type>& operator =(Type* ptr)
|
||||
{
|
||||
assign(ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLSafeHandle<Type>& operator =(const LLSafeHandle<Type>& ptr)
|
||||
{
|
||||
assign(ptr.mPointer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLSafeHandle<Type>& operator =(const LLSafeHandle<Subclass>& ptr)
|
||||
{
|
||||
assign(ptr.get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Type* (*NullFunc)();
|
||||
static const NullFunc sNullFunc;
|
||||
|
||||
protected:
|
||||
void ref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
mPointer->ref();
|
||||
}
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
Type *tempp = mPointer;
|
||||
mPointer = NULL;
|
||||
tempp->unref();
|
||||
if (mPointer != NULL)
|
||||
{
|
||||
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
||||
unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assign(Type* ptr)
|
||||
{
|
||||
if( mPointer != ptr )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr;
|
||||
ref();
|
||||
}
|
||||
}
|
||||
|
||||
static Type* nonNull(Type* ptr)
|
||||
{
|
||||
return ptr == NULL ? sNullFunc() : ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
Type* mPointer;
|
||||
};
|
||||
|
||||
// LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL
|
||||
// NOT a smart pointer like LLPointer<>
|
||||
// Useful for example in std::map<int,LLInitializedPointer<LLFoo> >
|
||||
// (std::map uses the default constructor for creating new entries)
|
||||
template <typename T> class LLInitializedPointer
|
||||
{
|
||||
public:
|
||||
LLInitializedPointer() : mPointer(NULL) {}
|
||||
~LLInitializedPointer() { delete mPointer; }
|
||||
|
||||
const T* operator->() const { return mPointer; }
|
||||
T* operator->() { return mPointer; }
|
||||
const T& operator*() const { return *mPointer; }
|
||||
T& operator*() { return *mPointer; }
|
||||
operator const T*() const { return mPointer; }
|
||||
operator T*() { return mPointer; }
|
||||
T* operator=(T* x) { return (mPointer = x); }
|
||||
operator bool() const { return mPointer != NULL; }
|
||||
bool operator!() const { return mPointer == NULL; }
|
||||
bool operator==(T* rhs) { return mPointer == rhs; }
|
||||
bool operator==(const LLInitializedPointer<T>* rhs) { return mPointer == rhs.mPointer; }
|
||||
|
||||
protected:
|
||||
T* mPointer;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// LLSingleton implements the getInstance() method part of the Singleton
|
||||
// pattern. It can't make the derived class constructors protected, though, so
|
||||
// you have to do that yourself.
|
||||
//
|
||||
// There are two ways to use LLSingleton. The first way is to inherit from it
|
||||
// while using the typename that you'd like to be static as the template
|
||||
// parameter, like so:
|
||||
//
|
||||
// class Foo: public LLSingleton<Foo>{};
|
||||
//
|
||||
// Foo& instance = Foo::instance();
|
||||
//
|
||||
// The second way is to use the singleton class directly, without inheritance:
|
||||
//
|
||||
// typedef LLSingleton<Foo> FooSingleton;
|
||||
//
|
||||
// Foo& instance = FooSingleton::instance();
|
||||
//
|
||||
// In this case, the class being managed as a singleton needs to provide an
|
||||
// initSingleton() method since the LLSingleton virtual method won't be
|
||||
// available
|
||||
//
|
||||
// As currently written, it is not thread-safe.
|
||||
template <typename T>
|
||||
class LLSingleton
|
||||
{
|
||||
public:
|
||||
virtual ~LLSingleton() {}
|
||||
#ifdef LL_MSVC7
|
||||
// workaround for VC7 compiler bug
|
||||
// adapted from http://www.codeproject.com/KB/tips/VC2003MeyersSingletonBug.aspx
|
||||
// our version doesn't introduce a nested struct so that you can still declare LLSingleton<MyClass>
|
||||
// a friend and hide your constructor
|
||||
static T* getInstance()
|
||||
{
|
||||
LLSingleton<T> singleton;
|
||||
return singleton.vsHack();
|
||||
}
|
||||
|
||||
T* vsHack()
|
||||
#else
|
||||
static T* getInstance()
|
||||
#endif
|
||||
{
|
||||
static T instance;
|
||||
static bool needs_init = true;
|
||||
if (needs_init)
|
||||
{
|
||||
needs_init = false;
|
||||
instance.initSingleton();
|
||||
}
|
||||
return &instance;
|
||||
}
|
||||
|
||||
static T& instance()
|
||||
{
|
||||
return *getInstance();
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void initSingleton() {}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Return the resident set size of the current process, in bytes.
|
||||
// Return value is zero if not known.
|
||||
U64 getCurrentRSS();
|
||||
// LLSingleton moved to llsingleton.h
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,237 @@
|
|||
/**
|
||||
* @file llmemtype.cpp
|
||||
* @brief Simple memory allocation/deallocation tracking stuff here
|
||||
*
|
||||
* $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 "llmemtype.h"
|
||||
#include "llallocator.h"
|
||||
|
||||
std::vector<char const *> LLMemType::DeclareMemType::mNameList;
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INIT("Init");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_STARTUP("Startup");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_MAIN("Main");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_FRAME("Frame");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_GATHER_INPUT("GatherInput");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_JOY_KEY("JoyKey");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE("Idle");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_PUMP("IdlePump");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_NETWORK("IdleNetwork");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_REGIONS("IdleUpdateRegions");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION("IdleUpdateViewerRegion");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_SURFACE("IdleUpdateSurface");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_PARCEL_OVERLAY("IdleUpdateParcelOverlay");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_AUDIO("IdleAudio");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING("CacheProcessPending");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS("CacheProcessPendingAsks");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING_REPLIES("CacheProcessPendingReplies");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_MESSAGE_CHECK_ALL("MessageCheckAll");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_MESSAGE_PROCESS_ACKS("MessageProcessAcks");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_RENDER("Render");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_SLEEP("Sleep");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_NETWORK("Network");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PHYSICS("Physics");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INTERESTLIST("InterestList");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IMAGEBASE("ImageBase");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IMAGERAW("ImageRaw");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IMAGEFORMATTED("ImageFormatted");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_APPFMTIMAGE("AppFmtImage");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_APPRAWIMAGE("AppRawImage");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_APPAUXRAWIMAGE("AppAuxRawImage");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DRAWABLE("Drawable");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT("Object");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT_PROCESS_UPDATE("ObjectProcessUpdate");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT_PROCESS_UPDATE_CORE("ObjectProcessUpdateCore");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY("Display");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE("DisplayUpdate");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA("DisplayUpdateCam");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_GEOM("DisplayUpdateGeom");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_SWAP("DisplaySwap");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_HUD("DisplayUpdateHud");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_GEN_REFLECTION("DisplayGenRefl");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE("DisplayImageUpdate");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_STATE_SORT("DisplayStateSort");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_SKY("DisplaySky");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_GEOM("DisplayRenderGeom");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_FLUSH("DisplayRenderFlush");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_UI("DisplayRenderUI");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS("DisplayRenderAttach");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DATA("VertexData");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CONSTRUCTOR("VertexConstr");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTRUCTOR("VertexDestr");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CREATE_VERTICES("VertexCreateVerts");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CREATE_INDICES("VertexCreateIndices");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTROY_BUFFER("VertexDestroyBuff");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTROY_INDICES("VertexDestroyIndices");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UPDATE_VERTS("VertexUpdateVerts");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UPDATE_INDICES("VertexUpdateIndices");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER("VertexAllocateBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_RESIZE_BUFFER("VertexResizeBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER("VertexMapBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES("VertexMapBufferVerts");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES("VertexMapBufferIndices");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UNMAP_BUFFER("VertexUnmapBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SET_STRIDE("VertexSetStride");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SET_BUFFER("VertexSetBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER("VertexSetupVertBuff");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CLEANUP_CLASS("VertexCleanupClass");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_SPACE_PARTITION("SpacePartition");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE("Pipeline");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_INIT("PipelineInit");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS("PipelineCreateBuffs");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RESTORE_GL("PipelineRestroGL");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS("PipelineUnloadShaders");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL("PipelineLightingDetail");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE("PipelineGetPoolType");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ADD_POOL("PipelineAddPool");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE("PipelineAllocDrawable");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ADD_OBJECT("PipelineAddObj");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS("PipelineCreateObjs");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_MOVE("PipelineUpdateMove");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_GEOM("PipelineUpdateGeom");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_VISIBLE("PipelineMarkVisible");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_MOVED("PipelineMarkMoved");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_SHIFT("PipelineMarkShift");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS("PipelineShiftObjs");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_TEXTURED("PipelineMarkTextured");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_REBUILD("PipelineMarkRebuild");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_CULL("PipelineUpdateCull");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_STATE_SORT("PipelineStateSort");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_POST_SORT("PipelinePostSort");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS("PipelineHudEls");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_HL("PipelineRenderHL");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM("PipelineRenderGeom");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED("PipelineRenderGeomDef");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF("PipelineRenderGeomPostDef");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW("PipelineRenderGeomShadow");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_SELECT("PipelineRenderSelect");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_REBUILD_POOLS("PipelineRebuildPools");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP("PipelineQuickLookup");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS("PipelineRenderObjs");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR("PipelineGenImpostors");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_BLOOM("PipelineRenderBloom");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_UPKEEP_POOLS("UpkeepPools");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_AVATAR("Avatar");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_AVATAR_MESH("AvatarMesh");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PARTICLES("Particles");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_REGIONS("Regions");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY("Inventory");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_DRAW("InventoryDraw");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS("InventoryBuildNewViews");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_DO_FOLDER("InventoryDoFolder");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_POST_BUILD("InventoryPostBuild");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_FROM_XML("InventoryFromXML");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_CREATE_NEW_ITEM("InventoryCreateNewItem");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_INIT("InventoryViewInit");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_SHOW("InventoryViewShow");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE("InventoryViewToggle");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_ANIMATION("Animation");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VOLUME("Volume");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PRIMITIVE("Primitive");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT("Script");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT_RUN("ScriptRun");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT_BYTECODE("ScriptByteCode");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_PUMP("IoPump");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_TCP("IoTCP");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_BUFFER("IoBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_HTTP_SERVER("IoHttpServer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_SD_SERVER("IoSDServer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_SD_CLIENT("IoSDClient");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_URL_REQUEST("IOUrlRequest");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DIRECTX_INIT("DirectXInit");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP1("Temp1");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP2("Temp2");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP3("Temp3");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP4("Temp4");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP5("Temp5");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP6("Temp6");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP7("Temp7");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP8("Temp8");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP9("Temp9");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_OTHER("Other");
|
||||
|
||||
|
||||
LLMemType::DeclareMemType::DeclareMemType(char const * st)
|
||||
{
|
||||
mID = (S32)mNameList.size();
|
||||
mName = st;
|
||||
|
||||
mNameList.push_back(mName);
|
||||
}
|
||||
|
||||
LLMemType::DeclareMemType::~DeclareMemType()
|
||||
{
|
||||
}
|
||||
|
||||
LLMemType::LLMemType(LLMemType::DeclareMemType& dt)
|
||||
{
|
||||
mTypeIndex = dt.mID;
|
||||
LLAllocator::pushMemType(dt.mID);
|
||||
}
|
||||
|
||||
LLMemType::~LLMemType()
|
||||
{
|
||||
LLAllocator::popMemType();
|
||||
}
|
||||
|
||||
char const * LLMemType::getNameFromID(S32 id)
|
||||
{
|
||||
if (id < 0 || id >= (S32)DeclareMemType::mNameList.size())
|
||||
{
|
||||
return "INVALID";
|
||||
}
|
||||
|
||||
return DeclareMemType::mNameList[id];
|
||||
}
|
||||
|
||||
|
|
@ -36,128 +36,210 @@
|
|||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class LLMemType;
|
||||
|
||||
extern void* ll_allocate (size_t size);
|
||||
extern void ll_release (void *p);
|
||||
|
||||
#define MEM_TRACK_MEM 0
|
||||
#define MEM_TRACK_TYPE (1 && MEM_TRACK_MEM)
|
||||
|
||||
#if MEM_TRACK_TYPE
|
||||
#define MEM_DUMP_DATA 1
|
||||
#define MEM_TYPE_NEW(T) \
|
||||
static void* operator new(size_t s) { LLMemType mt(T); return ll_allocate(s); } \
|
||||
static void operator delete(void* p) { ll_release(p); }
|
||||
|
||||
#else
|
||||
#define MEM_TYPE_NEW(T)
|
||||
#endif // MEM_TRACK_TYPE
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "linden_common.h"
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// WARNING: Never commit with MEM_TRACK_MEM == 1
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
#define MEM_TRACK_MEM (0 && LL_WINDOWS)
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define MEM_TYPE_NEW(T)
|
||||
|
||||
class LLMemType
|
||||
{
|
||||
public:
|
||||
// Also update sTypeDesc in llmemory.cpp
|
||||
enum EMemType
|
||||
|
||||
// class we'll initialize all instances of as
|
||||
// static members of MemType. Then use
|
||||
// to construct any new mem type.
|
||||
class DeclareMemType
|
||||
{
|
||||
MTYPE_INIT,
|
||||
MTYPE_STARTUP,
|
||||
MTYPE_MAIN,
|
||||
|
||||
MTYPE_IMAGEBASE,
|
||||
MTYPE_IMAGERAW,
|
||||
MTYPE_IMAGEFORMATTED,
|
||||
public:
|
||||
DeclareMemType(char const * st);
|
||||
~DeclareMemType();
|
||||
|
||||
S32 mID;
|
||||
char const * mName;
|
||||
|
||||
MTYPE_APPFMTIMAGE,
|
||||
MTYPE_APPRAWIMAGE,
|
||||
MTYPE_APPAUXRAWIMAGE,
|
||||
|
||||
MTYPE_DRAWABLE,
|
||||
MTYPE_OBJECT,
|
||||
MTYPE_VERTEX_DATA,
|
||||
MTYPE_SPACE_PARTITION,
|
||||
MTYPE_PIPELINE,
|
||||
MTYPE_AVATAR,
|
||||
MTYPE_AVATAR_MESH,
|
||||
MTYPE_PARTICLES,
|
||||
MTYPE_REGIONS,
|
||||
MTYPE_INVENTORY,
|
||||
MTYPE_ANIMATION,
|
||||
MTYPE_VOLUME,
|
||||
MTYPE_PRIMITIVE,
|
||||
|
||||
MTYPE_NETWORK,
|
||||
MTYPE_PHYSICS,
|
||||
MTYPE_INTERESTLIST,
|
||||
|
||||
MTYPE_SCRIPT,
|
||||
MTYPE_SCRIPT_RUN,
|
||||
MTYPE_SCRIPT_BYTECODE,
|
||||
|
||||
MTYPE_IO_PUMP,
|
||||
MTYPE_IO_TCP,
|
||||
MTYPE_IO_BUFFER,
|
||||
MTYPE_IO_HTTP_SERVER,
|
||||
MTYPE_IO_SD_SERVER,
|
||||
MTYPE_IO_SD_CLIENT,
|
||||
MTYPE_IO_URL_REQUEST,
|
||||
|
||||
MTYPE_TEMP1,
|
||||
MTYPE_TEMP2,
|
||||
MTYPE_TEMP3,
|
||||
MTYPE_TEMP4,
|
||||
MTYPE_TEMP5,
|
||||
MTYPE_TEMP6,
|
||||
MTYPE_TEMP7,
|
||||
MTYPE_TEMP8,
|
||||
MTYPE_TEMP9,
|
||||
|
||||
MTYPE_OTHER, // Special, used by display code
|
||||
|
||||
MTYPE_NUM_TYPES
|
||||
// array so we can map an index ID to Name
|
||||
static std::vector<char const *> mNameList;
|
||||
};
|
||||
enum { MTYPE_MAX_DEPTH = 64 };
|
||||
|
||||
public:
|
||||
LLMemType(EMemType type)
|
||||
{
|
||||
#if MEM_TRACK_TYPE
|
||||
if (type < 0 || type >= MTYPE_NUM_TYPES)
|
||||
llerrs << "LLMemType error" << llendl;
|
||||
if (sCurDepth < 0 || sCurDepth >= MTYPE_MAX_DEPTH)
|
||||
llerrs << "LLMemType error" << llendl;
|
||||
sType[sCurDepth] = sCurType;
|
||||
sCurDepth++;
|
||||
sCurType = type;
|
||||
#endif
|
||||
}
|
||||
~LLMemType()
|
||||
{
|
||||
#if MEM_TRACK_TYPE
|
||||
sCurDepth--;
|
||||
sCurType = sType[sCurDepth];
|
||||
#endif
|
||||
}
|
||||
|
||||
static void reset();
|
||||
static void printMem();
|
||||
LLMemType(DeclareMemType& dt);
|
||||
~LLMemType();
|
||||
|
||||
static char const * getNameFromID(S32 id);
|
||||
|
||||
static DeclareMemType MTYPE_INIT;
|
||||
static DeclareMemType MTYPE_STARTUP;
|
||||
static DeclareMemType MTYPE_MAIN;
|
||||
static DeclareMemType MTYPE_FRAME;
|
||||
|
||||
static DeclareMemType MTYPE_GATHER_INPUT;
|
||||
static DeclareMemType MTYPE_JOY_KEY;
|
||||
|
||||
static DeclareMemType MTYPE_IDLE;
|
||||
static DeclareMemType MTYPE_IDLE_PUMP;
|
||||
static DeclareMemType MTYPE_IDLE_NETWORK;
|
||||
static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS;
|
||||
static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION;
|
||||
static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE;
|
||||
static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY;
|
||||
static DeclareMemType MTYPE_IDLE_AUDIO;
|
||||
|
||||
static DeclareMemType MTYPE_CACHE_PROCESS_PENDING;
|
||||
static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS;
|
||||
static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES;
|
||||
|
||||
static DeclareMemType MTYPE_MESSAGE_CHECK_ALL;
|
||||
static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS;
|
||||
|
||||
static DeclareMemType MTYPE_RENDER;
|
||||
static DeclareMemType MTYPE_SLEEP;
|
||||
|
||||
static DeclareMemType MTYPE_NETWORK;
|
||||
static DeclareMemType MTYPE_PHYSICS;
|
||||
static DeclareMemType MTYPE_INTERESTLIST;
|
||||
|
||||
static DeclareMemType MTYPE_IMAGEBASE;
|
||||
static DeclareMemType MTYPE_IMAGERAW;
|
||||
static DeclareMemType MTYPE_IMAGEFORMATTED;
|
||||
|
||||
public:
|
||||
#if MEM_TRACK_TYPE
|
||||
static S32 sCurDepth;
|
||||
static S32 sCurType;
|
||||
static S32 sType[MTYPE_MAX_DEPTH];
|
||||
static S32 sMemCount[MTYPE_NUM_TYPES];
|
||||
static S32 sMaxMemCount[MTYPE_NUM_TYPES];
|
||||
static S32 sNewCount[MTYPE_NUM_TYPES];
|
||||
static S32 sOverheadMem;
|
||||
static const char* sTypeDesc[MTYPE_NUM_TYPES];
|
||||
#endif
|
||||
static S32 sTotalMem;
|
||||
static S32 sMaxTotalMem;
|
||||
static DeclareMemType MTYPE_APPFMTIMAGE;
|
||||
static DeclareMemType MTYPE_APPRAWIMAGE;
|
||||
static DeclareMemType MTYPE_APPAUXRAWIMAGE;
|
||||
|
||||
static DeclareMemType MTYPE_DRAWABLE;
|
||||
|
||||
static DeclareMemType MTYPE_OBJECT;
|
||||
static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE;
|
||||
static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE;
|
||||
|
||||
static DeclareMemType MTYPE_DISPLAY;
|
||||
static DeclareMemType MTYPE_DISPLAY_UPDATE;
|
||||
static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA;
|
||||
static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM;
|
||||
static DeclareMemType MTYPE_DISPLAY_SWAP;
|
||||
static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD;
|
||||
static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION;
|
||||
static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE;
|
||||
static DeclareMemType MTYPE_DISPLAY_STATE_SORT;
|
||||
static DeclareMemType MTYPE_DISPLAY_SKY;
|
||||
static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM;
|
||||
static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH;
|
||||
static DeclareMemType MTYPE_DISPLAY_RENDER_UI;
|
||||
static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS;
|
||||
|
||||
static DeclareMemType MTYPE_VERTEX_DATA;
|
||||
static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR;
|
||||
static DeclareMemType MTYPE_VERTEX_DESTRUCTOR;
|
||||
static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES;
|
||||
static DeclareMemType MTYPE_VERTEX_CREATE_INDICES;
|
||||
static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES;
|
||||
static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS;
|
||||
static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES;
|
||||
static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_MAP_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES;
|
||||
static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES;
|
||||
static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_SET_STRIDE;
|
||||
static DeclareMemType MTYPE_VERTEX_SET_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS;
|
||||
|
||||
static DeclareMemType MTYPE_SPACE_PARTITION;
|
||||
|
||||
static DeclareMemType MTYPE_PIPELINE;
|
||||
static DeclareMemType MTYPE_PIPELINE_INIT;
|
||||
static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS;
|
||||
static DeclareMemType MTYPE_PIPELINE_RESTORE_GL;
|
||||
static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS;
|
||||
static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL;
|
||||
static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE;
|
||||
static DeclareMemType MTYPE_PIPELINE_ADD_POOL;
|
||||
static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE;
|
||||
static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT;
|
||||
static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS;
|
||||
static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE;
|
||||
static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM;
|
||||
static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE;
|
||||
static DeclareMemType MTYPE_PIPELINE_MARK_MOVED;
|
||||
static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT;
|
||||
static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS;
|
||||
static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED;
|
||||
static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD;
|
||||
static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL;
|
||||
static DeclareMemType MTYPE_PIPELINE_STATE_SORT;
|
||||
static DeclareMemType MTYPE_PIPELINE_POST_SORT;
|
||||
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_HL;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT;
|
||||
static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS;
|
||||
static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS;
|
||||
static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM;
|
||||
|
||||
static DeclareMemType MTYPE_UPKEEP_POOLS;
|
||||
|
||||
static DeclareMemType MTYPE_AVATAR;
|
||||
static DeclareMemType MTYPE_AVATAR_MESH;
|
||||
static DeclareMemType MTYPE_PARTICLES;
|
||||
static DeclareMemType MTYPE_REGIONS;
|
||||
|
||||
static DeclareMemType MTYPE_INVENTORY;
|
||||
static DeclareMemType MTYPE_INVENTORY_DRAW;
|
||||
static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS;
|
||||
static DeclareMemType MTYPE_INVENTORY_DO_FOLDER;
|
||||
static DeclareMemType MTYPE_INVENTORY_POST_BUILD;
|
||||
static DeclareMemType MTYPE_INVENTORY_FROM_XML;
|
||||
static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM;
|
||||
static DeclareMemType MTYPE_INVENTORY_VIEW_INIT;
|
||||
static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW;
|
||||
static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE;
|
||||
|
||||
static DeclareMemType MTYPE_ANIMATION;
|
||||
static DeclareMemType MTYPE_VOLUME;
|
||||
static DeclareMemType MTYPE_PRIMITIVE;
|
||||
|
||||
static DeclareMemType MTYPE_SCRIPT;
|
||||
static DeclareMemType MTYPE_SCRIPT_RUN;
|
||||
static DeclareMemType MTYPE_SCRIPT_BYTECODE;
|
||||
|
||||
static DeclareMemType MTYPE_IO_PUMP;
|
||||
static DeclareMemType MTYPE_IO_TCP;
|
||||
static DeclareMemType MTYPE_IO_BUFFER;
|
||||
static DeclareMemType MTYPE_IO_HTTP_SERVER;
|
||||
static DeclareMemType MTYPE_IO_SD_SERVER;
|
||||
static DeclareMemType MTYPE_IO_SD_CLIENT;
|
||||
static DeclareMemType MTYPE_IO_URL_REQUEST;
|
||||
|
||||
static DeclareMemType MTYPE_DIRECTX_INIT;
|
||||
|
||||
static DeclareMemType MTYPE_TEMP1;
|
||||
static DeclareMemType MTYPE_TEMP2;
|
||||
static DeclareMemType MTYPE_TEMP3;
|
||||
static DeclareMemType MTYPE_TEMP4;
|
||||
static DeclareMemType MTYPE_TEMP5;
|
||||
static DeclareMemType MTYPE_TEMP6;
|
||||
static DeclareMemType MTYPE_TEMP7;
|
||||
static DeclareMemType MTYPE_TEMP8;
|
||||
static DeclareMemType MTYPE_TEMP9;
|
||||
|
||||
static DeclareMemType MTYPE_OTHER; // Special; used by display code
|
||||
|
||||
S32 mTypeIndex;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ void LLMetricsImpl::recordEventDetails(const std::string& location,
|
|||
metrics["location"] = location;
|
||||
metrics["stats"] = stats;
|
||||
|
||||
llinfos << "LLMETRICS: " << LLSDNotationStreamer(metrics) << llendl;
|
||||
llinfos << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << llendl;
|
||||
}
|
||||
|
||||
// Store this:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* @file lloptioninterface.cpp
|
||||
* @brief
|
||||
*
|
||||
* $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 "lloptioninterface.h"
|
||||
|
||||
|
||||
LLOptionInterface::~LLOptionInterface()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* @file lloptioninterface.h
|
||||
* @brief
|
||||
*
|
||||
* $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_LLOPTIONINTERFACE_H
|
||||
#define LL_LLOPTIONINTERFACE_H
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
class LLSD;
|
||||
class LLOptionInterface
|
||||
{
|
||||
public:
|
||||
virtual ~LLOptionInterface() = 0;
|
||||
virtual LLSD getOption(const std::string& name) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* @file llpointer.h
|
||||
* @brief A reference-counted pointer for objects derived from LLRefCount
|
||||
*
|
||||
* $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 LLPOINTER_H
|
||||
#define LLPOINTER_H
|
||||
|
||||
#include "llerror.h" // *TODO: consider eliminating this
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// RefCount objects should generally only be accessed by way of LLPointer<>'s
|
||||
// NOTE: LLPointer<LLFoo> x = new LLFoo(); MAY NOT BE THREAD SAFE
|
||||
// if LLFoo::LLFoo() does anything like put itself in an update queue.
|
||||
// The queue may get accessed before it gets assigned to x.
|
||||
// The correct implementation is:
|
||||
// LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting
|
||||
// x->instantiate(); // does stuff like place x into an update queue
|
||||
|
||||
// see llthread.h for LLThreadSafeRefCount
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Note: relies on Type having ref() and unref() methods
|
||||
template <class Type> class LLPointer
|
||||
{
|
||||
public:
|
||||
|
||||
LLPointer() :
|
||||
mPointer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLPointer(Type* ptr) :
|
||||
mPointer(ptr)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
LLPointer(const LLPointer<Type>& ptr) :
|
||||
mPointer(ptr.mPointer)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLPointer(const LLPointer<Subclass>& ptr) :
|
||||
mPointer(ptr.get())
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
~LLPointer()
|
||||
{
|
||||
unref();
|
||||
}
|
||||
|
||||
Type* get() const { return mPointer; }
|
||||
const Type* operator->() const { return mPointer; }
|
||||
Type* operator->() { return mPointer; }
|
||||
const Type& operator*() const { return *mPointer; }
|
||||
Type& operator*() { return *mPointer; }
|
||||
|
||||
operator BOOL() const { return (mPointer != NULL); }
|
||||
operator bool() const { return (mPointer != NULL); }
|
||||
bool operator!() const { return (mPointer == NULL); }
|
||||
bool isNull() const { return (mPointer == NULL); }
|
||||
bool notNull() const { return (mPointer != NULL); }
|
||||
|
||||
operator Type*() const { return mPointer; }
|
||||
operator const Type*() const { return mPointer; }
|
||||
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
||||
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
||||
bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
||||
bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
||||
bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
||||
|
||||
LLPointer<Type>& operator =(Type* ptr)
|
||||
{
|
||||
if( mPointer != ptr )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr;
|
||||
ref();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
|
||||
{
|
||||
if( mPointer != ptr.mPointer )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr.mPointer;
|
||||
ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
|
||||
{
|
||||
if( mPointer != ptr.get() )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr.get();
|
||||
ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Just exchange the pointers, which will not change the reference counts.
|
||||
static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
|
||||
{
|
||||
Type* temp = a.mPointer;
|
||||
a.mPointer = b.mPointer;
|
||||
b.mPointer = temp;
|
||||
}
|
||||
|
||||
protected:
|
||||
void ref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
mPointer->ref();
|
||||
}
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
Type *tempp = mPointer;
|
||||
mPointer = NULL;
|
||||
tempp->unref();
|
||||
if (mPointer != NULL)
|
||||
{
|
||||
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
||||
unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Type* mPointer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -127,8 +127,10 @@ using snprintf_hack::snprintf;
|
|||
#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4.
|
||||
#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4.
|
||||
//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4.
|
||||
#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function
|
||||
#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden"
|
||||
#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual"
|
||||
#pragma warning( disable : 4786 ) // silly MS warning deep inside their <map> include file
|
||||
#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden
|
||||
#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file
|
||||
#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
|
||||
#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue