Merge branch 'master' of https://vcs.firestormviewer.org/viewer-merges/phoenix-firestorm-501
commit
6a05670f6f
|
|
@ -3,9 +3,11 @@
|
|||
*.bak
|
||||
*.diff
|
||||
*.orig
|
||||
*.patch
|
||||
*.pyc
|
||||
*.rej
|
||||
*.swp
|
||||
*.tar.bz2
|
||||
*~
|
||||
|
||||
# Specific paths and/or names
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>68f6096e055e7a0e46913e1c2613b9db</string>
|
||||
<string>7725e9abe4bf84d11bc7286c74467026</string>
|
||||
<key>url</key>
|
||||
<string>http://downloads.phoenixviewer.com/dullahan_gcc5-1.1.1320_3.3626.1895.g7001d56-linux64-191221945.tar.bz2</string>
|
||||
<string>http://downloads.phoenixviewer.com/dullahan_gcc5-1.7.0.202005301906_81.3.10_gb223419_chromium-81.0.4044.138-linux64-201511706.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -838,9 +838,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>9fad2e6e1fb3c698afa2b9094deb8422</string>
|
||||
<string>05bdafd8e9f32fc6763862ada4b5c4bc</string>
|
||||
<key>url</key>
|
||||
<string>http://downloads.phoenixviewer.com/dullahan-1.6.4.202005232231_81.3.3_g072a5f5_chromium-81.0.4044.147-linux64-201442030.tar.bz2</string>
|
||||
<string>http://downloads.phoenixviewer.com/dullahan-1.7.0.202005300110_81.3.10_gb223419_chromium-81.0.4044.138-linux64-201502309.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -850,9 +850,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>71fa66203326aca918796e874976c080</string>
|
||||
<string>43c03679c3847754b407532efe5d4392</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/34070/283477/dullahan-1.1.1320_3.3626.1895.g7001d56-windows-525361.tar.bz2</string>
|
||||
<string>http://downloads.phoenixviewer.com/dullahan-1.7.0.202005292352_81.3.10_gb223419_chromium-81.0.4044.138-windows-201512310.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -862,9 +862,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c7162e4805f50a3609f5dc63d0cf2bc0</string>
|
||||
<string>13574736220c05de847980f851f42827</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/34071/283480/dullahan-1.1.1320_3.3626.1895.g7001d56-windows64-525361.tar.bz2</string>
|
||||
<string>http://downloads.phoenixviewer.com/dullahan-1.7.0.202005292352_81.3.10_gb223419_chromium-81.0.4044.138-windows64-201512301.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
@ -990,11 +990,11 @@
|
|||
<key>fmodstudio</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>FMOD Studio, copyright (c) Firelight Technologies Pty, Ltd., 2012-2017.</string>
|
||||
<string>FMOD Studio by Firelight Technologies Pty Ltd.</string>
|
||||
<key>description</key>
|
||||
<string>FMOD Studio audio system library</string>
|
||||
<string>FMOD Studio API</string>
|
||||
<key>license</key>
|
||||
<string>fmodstudio</string>
|
||||
<string>fmod</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/fmodstudio.txt</string>
|
||||
<key>name</key>
|
||||
|
|
@ -1061,58 +1061,6 @@
|
|||
<key>version</key>
|
||||
<string>2.01.01</string>
|
||||
</map>
|
||||
<key>fmodex</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>COPYRIGHT 2014 FIRELIGHT TECHNOLOGIES PTY LTD. ALL RIGHTS RESERVED</string>
|
||||
<key>license</key>
|
||||
<string>fmodex</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/fmodex.txt</string>
|
||||
<key>name</key>
|
||||
<string>fmodex</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>darwin</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>cba1feed7f6bb671d791a517fddf205a</string>
|
||||
<key>url</key>
|
||||
<string>file:///opt/firestorm/fmodex-44461-darwin-201601300040-r23.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin</string>
|
||||
</map>
|
||||
<key>linux</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>9b090869508fabee82dc53cae977fb99</string>
|
||||
<key>url</key>
|
||||
<string>file:///opt/firestorm/fmodex-44461-linux-201601282301-r23.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
<key>windows</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>5b1b5ce866afd2a74e445af1fffe6a8b</string>
|
||||
<key>url</key>
|
||||
<string>file:///c:/cygwin/opt/firestorm/fmodex-44461-windows-201601282252-r23.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>4.44.61</string>
|
||||
</map>
|
||||
<key>fontconfig</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ set(cmake_SOURCE_FILES
|
|||
FindAutobuild.cmake
|
||||
FindBerkeleyDB.cmake
|
||||
FindFMODSTUDIO.cmake
|
||||
FindFMODEX.cmake
|
||||
FindGLH.cmake
|
||||
FindGoogleBreakpad.cmake
|
||||
FindHUNSPELL.cmake
|
||||
|
|
@ -42,7 +41,6 @@ set(cmake_SOURCE_FILES
|
|||
FindXmlRpcEpi.cmake
|
||||
FindZLIB.cmake
|
||||
FMODSTUDIO.cmake
|
||||
FMODEX.cmake
|
||||
FreeType.cmake
|
||||
GLEXT.cmake
|
||||
GLH.cmake
|
||||
|
|
|
|||
|
|
@ -68,14 +68,6 @@ if(WINDOWS)
|
|||
set(release_files ${release_files} fmod.dll)
|
||||
endif (FMODSTUDIO)
|
||||
|
||||
if (FMODEX)
|
||||
if(ADDRESS_SIZE EQUAL 32)
|
||||
set(release_files ${release_files} fmodex.dll)
|
||||
else(ADDRESS_SIZE EQUAL 32)
|
||||
set(release_files ${release_files} fmodex64.dll)
|
||||
endif(ADDRESS_SIZE EQUAL 32)
|
||||
endif (FMODEX)
|
||||
|
||||
if (OPENAL)
|
||||
list(APPEND release_files openal32.dll alut.dll)
|
||||
endif (OPENAL)
|
||||
|
|
@ -208,11 +200,6 @@ elseif(DARWIN)
|
|||
set(release_files ${release_files} libfmod.dylib)
|
||||
endif (FMODSTUDIO)
|
||||
|
||||
if (FMODEX)
|
||||
set(debug_files ${debug_files} libfmodexL.dylib)
|
||||
set(release_files ${release_files} libfmodex.dylib)
|
||||
endif (FMODEX)
|
||||
|
||||
elseif(LINUX)
|
||||
# linux is weird, multiple side by side configurations aren't supported
|
||||
# and we don't seem to have any debug shared libs built yet anyways...
|
||||
|
|
@ -271,16 +258,6 @@ elseif(LINUX)
|
|||
set(release_files ${release_files} "libfmod.so")
|
||||
endif (FMODSTUDIO)
|
||||
|
||||
if (FMODEX)
|
||||
if(ADDRESS_SIZE EQUAL 32)
|
||||
set(debug_files ${debug_files} "libfmodexL.so")
|
||||
set(release_files ${release_files} "libfmodex.so")
|
||||
else(ADDRESS_SIZE EQUAL 32)
|
||||
set(debug_files ${debug_files} "libfmodexL64.so")
|
||||
set(release_files ${release_files} "libfmodex64.so")
|
||||
endif(ADDRESS_SIZE EQUAL 32)
|
||||
endif (FMODEX)
|
||||
|
||||
else(WINDOWS)
|
||||
message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...")
|
||||
set(vivox_lib_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-linux")
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
# FMOD can be set when launching the make using the argument -DFMODEX:BOOL=ON
|
||||
# When building using proprietary binaries though (i.e. having access to LL private servers),
|
||||
# we always build with FMODEX.
|
||||
# Open source devs should use the -DFMODEX:BOOL=ON then if they want to build with FMOD, whether
|
||||
# they are using USESYSTEMLIBS or not.
|
||||
if (INSTALL_PROPRIETARY)
|
||||
set(FMODEX ON CACHE BOOL "Using FMOD Ex sound library.")
|
||||
endif (INSTALL_PROPRIETARY)
|
||||
|
||||
if (FMODEX)
|
||||
if (FMODSTUDIO)
|
||||
MESSAGE(FATAL_ERROR "You cannot use FMOD Ex if you are already using FMOD Studio.")
|
||||
endif (FMODSTUDIO)
|
||||
|
||||
if (USESYSTEMLIBS)
|
||||
# In that case, we use the version of the library installed on the system
|
||||
set(FMODEX_FIND_REQUIRED ON)
|
||||
include(FindFMODEX)
|
||||
else (USESYSTEMLIBS)
|
||||
if (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
|
||||
# If the path have been specified in the arguments, use that
|
||||
set(FMODEX_LIBRARIES ${FMODEX_LIBRARY})
|
||||
MESSAGE(STATUS "Using FMODEX path: ${FMODEX_LIBRARIES}, ${FMODEX_INCLUDE_DIR}")
|
||||
else (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
|
||||
# If not, we're going to try to get the package listed in autobuild.xml
|
||||
# Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL)
|
||||
# as accessing the private LL location will fail if you don't have the credential
|
||||
include(Prebuilt)
|
||||
use_prebuilt_binary(fmodex)
|
||||
if (WINDOWS)
|
||||
if( ADDRESS_SIZE EQUAL 32 )
|
||||
set(FMODEX_LIBRARY
|
||||
debug fmodexL_vc
|
||||
optimized fmodex_vc)
|
||||
else( )
|
||||
set(FMODEX_LIBRARY
|
||||
debug fmodexL64_vc
|
||||
optimized fmodex64_vc)
|
||||
endif( )
|
||||
elseif (DARWIN)
|
||||
set(FMODEX_LIBRARY
|
||||
debug fmodexL
|
||||
optimized fmodex)
|
||||
elseif (LINUX)
|
||||
if( ADDRESS_SIZE EQUAL 64 )
|
||||
set(FMODEX_LIBRARY
|
||||
debug fmodexL64
|
||||
optimized fmodex64)
|
||||
else( )
|
||||
set(FMODEX_LIBRARY
|
||||
debug fmodexL
|
||||
optimized fmodex)
|
||||
endif( )
|
||||
endif (WINDOWS)
|
||||
set(FMODEX_LIBRARIES ${FMODEX_LIBRARY})
|
||||
set(FMODEX_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodex)
|
||||
endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
|
||||
endif (USESYSTEMLIBS)
|
||||
endif (FMODEX)
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
# - Find FMODEX
|
||||
# Find the FMODEX includes and library
|
||||
# This module defines
|
||||
# FMODEX_INCLUDE_DIR, where to find fmod.h and fmod_errors.h
|
||||
# FMODEX_LIBRARIES, the libraries needed to use FMODEX.
|
||||
# FMODEX, If false, do not try to use FMODEX.
|
||||
# also defined, but not for general use are
|
||||
# FMODEX_LIBRARY, where to find the FMODEX library.
|
||||
|
||||
FIND_PATH(FMODEX_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod)
|
||||
|
||||
SET(FMODEX_NAMES ${FMODEX_NAMES} fmodex fmodvc fmodexL_vc)
|
||||
FIND_LIBRARY(FMODEX_LIBRARY
|
||||
NAMES ${FMODEX_NAMES}
|
||||
PATH_SUFFIXES fmodex
|
||||
)
|
||||
|
||||
IF (FMODEX_SDK_DIR OR WINDOWS)
|
||||
if(WINDOWS)
|
||||
set(FMODEX_SDK_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows" CACHE PATH "Path to FMODEX")
|
||||
STRING(REGEX REPLACE "\\\\" "/" FMODEX_SDK_DIR ${FMODEX_SDK_DIR})
|
||||
endif(WINDOWS)
|
||||
find_library(FMODEX_LIBRARY
|
||||
fmodex_vc fmodexL_vc
|
||||
PATHS
|
||||
${FMODEX_SDK_DIR}/api/lib
|
||||
${FMODEX_SDK_DIR}/api
|
||||
${FMODEX_SDK_DIR}
|
||||
)
|
||||
find_path(FMODEX_INCLUDE_DIR fmod.h
|
||||
${FMODEX_SDK_DIR}/api/inc
|
||||
${FMODEX_SDK_DIR}/api
|
||||
${FMODEX_SDK_DIR}
|
||||
)
|
||||
find_path(FMODEX_INCLUDE_DIR fmod.h
|
||||
${FMODEX_SDK_DIR}/api/inc
|
||||
${FMODEX_SDK_DIR}/api
|
||||
${FMODEX_SDK_DIR}
|
||||
)
|
||||
IF (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
|
||||
SET(FMODEX_LIBRARIES ${FMODEX_LIBRARY})
|
||||
SET(FMODEX_FOUND "YES")
|
||||
endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
|
||||
ENDIF (FMODEX_SDK_DIR OR WINDOWS)
|
||||
|
||||
IF (FMODEX_FOUND)
|
||||
IF (NOT FMODEX_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found FMODEX: ${FMODEX_LIBRARIES}")
|
||||
ENDIF (NOT FMODEX_FIND_QUIETLY)
|
||||
ELSE (FMODEX_FOUND)
|
||||
IF (FMODEX_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find FMODEX library")
|
||||
ENDIF (FMODEX_FIND_REQUIRED)
|
||||
ENDIF (FMODEX_FOUND)
|
||||
|
||||
# Deprecated declarations.
|
||||
SET (NATIVE_FMODEX_INCLUDE_PATH ${FMODEX_INCLUDE_DIR} )
|
||||
GET_FILENAME_COMPONENT (NATIVE_FMODEX_LIB_PATH ${FMODEX_LIBRARY} PATH)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
FMODEX_LIBRARY
|
||||
FMODEX_INCLUDE_DIR
|
||||
)
|
||||
|
|
@ -160,8 +160,6 @@ BASE_ARGUMENTS=[
|
|||
description="""The name of a file containing the full version number."""),
|
||||
dict(name='viewer_flavor',
|
||||
description='Type of viewer build. Can be oss or hvk.', default="oss"),
|
||||
dict(name='fmodversion',
|
||||
description='Version of FMOD used. Can be fmodstudio or fmodex.', default=None)
|
||||
]
|
||||
|
||||
def usage(arguments, srctree=""):
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ project(llaudio)
|
|||
include(00-Common)
|
||||
include(LLAudio)
|
||||
include(FMODSTUDIO)
|
||||
include(FMODEX)
|
||||
include(OPENAL)
|
||||
include(LLCommon)
|
||||
include(LLMath)
|
||||
|
|
@ -60,23 +59,6 @@ if (FMODSTUDIO)
|
|||
)
|
||||
endif (FMODSTUDIO)
|
||||
|
||||
if (FMODEX)
|
||||
include_directories(
|
||||
${FMODEX_INCLUDE_DIR}
|
||||
)
|
||||
list(APPEND llaudio_SOURCE_FILES
|
||||
llaudioengine_fmodex.cpp
|
||||
lllistener_fmodex.cpp
|
||||
llstreamingaudio_fmodex.cpp
|
||||
)
|
||||
|
||||
list(APPEND llaudio_HEADER_FILES
|
||||
llaudioengine_fmodex.h
|
||||
lllistener_fmodex.h
|
||||
llstreamingaudio_fmodex.h
|
||||
)
|
||||
endif (FMODEX)
|
||||
|
||||
if (OPENAL)
|
||||
include_directories(
|
||||
${OPENAL_LIBRARIES}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ void LLAudioEngine::setDefaults()
|
|||
}
|
||||
|
||||
|
||||
bool LLAudioEngine::init(const S32 num_channels, void* userdata)
|
||||
bool LLAudioEngine::init(const S32 num_channels, void* userdata, const std::string &app_title)
|
||||
{
|
||||
setDefaults();
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ public:
|
|||
virtual ~LLAudioEngine();
|
||||
|
||||
// initialization/startup/shutdown
|
||||
virtual bool init(const S32 num_channels, void *userdata);
|
||||
virtual bool init(const S32 num_channels, void *userdata, const std::string &app_title);
|
||||
virtual std::string getDriverName(bool verbose) = 0;
|
||||
virtual void shutdown();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,975 +0,0 @@
|
|||
/**
|
||||
* @file audioengine_fmodex.cpp
|
||||
* @brief Implementation of LLAudioEngine class abstracting the audio
|
||||
* support as a FMODEX implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llstreamingaudio.h"
|
||||
#include "llstreamingaudio_fmodex.h"
|
||||
|
||||
#include "llaudioengine_fmodex.h"
|
||||
#include "lllistener_fmodex.h"
|
||||
|
||||
#include "llerror.h"
|
||||
#include "llmath.h"
|
||||
#include "llrand.h"
|
||||
|
||||
#include "fmod.hpp"
|
||||
#include "fmod_errors.h"
|
||||
#include "lldir.h"
|
||||
#include "llapr.h"
|
||||
|
||||
#include "sound_ids.h"
|
||||
|
||||
#include "indra_constants.h"
|
||||
|
||||
FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
|
||||
|
||||
// <FS:Ansariel> Output device selection
|
||||
static inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string);
|
||||
|
||||
LLUUID FMOD_GUID_to_LLUUID(FMOD_GUID guid)
|
||||
{
|
||||
return LLUUID(llformat("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", guid.Data1, guid.Data2, guid.Data3,
|
||||
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]));
|
||||
}
|
||||
|
||||
void set_device(FMOD::System* system, const LLUUID& device_uuid)
|
||||
{
|
||||
LL_INFOS() << "LLAudioEngine_FMODEX::setDevice with device_uuid=" << device_uuid << LL_ENDL;
|
||||
|
||||
int drivercount;
|
||||
if (!Check_FMOD_Error(system->getNumDrivers(&drivercount), "FMOD::System::getNumDrivers") && drivercount > 0)
|
||||
{
|
||||
if (device_uuid.isNull())
|
||||
{
|
||||
LL_INFOS() << "Setting driver \"Default\"" << LL_ENDL;
|
||||
Check_FMOD_Error(system->setDriver(0), "FMOD::System::setDriver");
|
||||
}
|
||||
else
|
||||
{
|
||||
FMOD_GUID guid;
|
||||
|
||||
for (int i = 0; i < drivercount; ++i)
|
||||
{
|
||||
if (!Check_FMOD_Error(system->getDriverInfo(i, NULL, 0, &guid), "FMOD::System::getDriverInfo"))
|
||||
{
|
||||
LLUUID driver_guid = FMOD_GUID_to_LLUUID(guid);
|
||||
|
||||
if (driver_guid == device_uuid)
|
||||
{
|
||||
LL_INFOS() << "Setting driver " << i << ": " << driver_guid << LL_ENDL;
|
||||
Check_FMOD_Error(system->setDriver(i), "FMOD::System::setDriver");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LL_INFOS() << "Device not available (anymore) - falling back to default" << LL_ENDL;
|
||||
Check_FMOD_Error(system->setDriver(0), "FMOD::System::setDriver");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALLBACK systemCallback(FMOD_SYSTEM *system, FMOD_SYSTEM_CALLBACKTYPE type, void *commanddata1, void *commanddata2)
|
||||
{
|
||||
FMOD::System* sys = (FMOD::System*)system;
|
||||
LLAudioEngine_FMODEX* audio_engine = NULL;
|
||||
if (sys)
|
||||
{
|
||||
void* userdata = NULL;
|
||||
Check_FMOD_Error(sys->getUserData(&userdata), "FMOD::System::getUserData");
|
||||
audio_engine = (LLAudioEngine_FMODEX*)userdata;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FMOD_SYSTEM_CALLBACKTYPE_DEVICELISTCHANGED:
|
||||
LL_DEBUGS() << "FMOD system callback FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED" << LL_ENDL;
|
||||
if (sys && audio_engine)
|
||||
{
|
||||
set_device(sys, audio_engine->getSelectedDeviceUUID());
|
||||
audio_engine->OnOutputDeviceListChanged(audio_engine->getDevices());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FMOD_OK;
|
||||
}
|
||||
// </FS:Ansariel>>
|
||||
|
||||
FMOD::ChannelGroup *LLAudioEngine_FMODEX::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0};
|
||||
|
||||
LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler)
|
||||
{
|
||||
mInited = false;
|
||||
mWindGen = NULL;
|
||||
mWindDSP = NULL;
|
||||
mSystem = NULL;
|
||||
mEnableProfiler = enable_profiler;
|
||||
mWindDSPDesc = new FMOD_DSP_DESCRIPTION();
|
||||
mSelectedDeviceUUID = LLUUID::null; // <FS:Ansariel> Output device selection
|
||||
}
|
||||
|
||||
|
||||
LLAudioEngine_FMODEX::~LLAudioEngine_FMODEX()
|
||||
{
|
||||
delete mWindDSPDesc;
|
||||
}
|
||||
|
||||
|
||||
static // <FS:Ansariel> Make this file scope so it doesn't collide with the same function in llstreamingaudio_fmodex.cpp
|
||||
inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
|
||||
{
|
||||
if(result == FMOD_OK)
|
||||
return false;
|
||||
// </FS:Ansariel> Always print out error
|
||||
//LL_DEBUGS() << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
if (result != FMOD_ERR_INVALID_HANDLE)
|
||||
{
|
||||
LL_WARNS() << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS() << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
return true;
|
||||
}
|
||||
|
||||
void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
|
||||
{
|
||||
if(type & FMOD_MEMORY_STREAM_DECODE)
|
||||
{
|
||||
LL_INFOS() << "Decode buffer size: " << size << LL_ENDL;
|
||||
}
|
||||
else if(type & FMOD_MEMORY_STREAM_FILE)
|
||||
{
|
||||
LL_INFOS() << "Stream buffer size: " << size << LL_ENDL;
|
||||
}
|
||||
return new char[size];
|
||||
}
|
||||
void* F_STDCALL decode_realloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
|
||||
{
|
||||
memset(ptr,0,size);
|
||||
return ptr;
|
||||
}
|
||||
void F_STDCALL decode_dealloc(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr)
|
||||
{
|
||||
delete[] (char*)ptr;
|
||||
}
|
||||
|
||||
bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
{
|
||||
U32 version;
|
||||
FMOD_RESULT result;
|
||||
|
||||
LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL;
|
||||
|
||||
//result = FMOD::Memory_Initialize(NULL, 0, &decode_alloc, &decode_realloc, &decode_dealloc, FMOD_MEMORY_STREAM_DECODE | FMOD_MEMORY_STREAM_FILE);
|
||||
//if(Check_FMOD_Error(result, "FMOD::Memory_Initialize"))
|
||||
// return false;
|
||||
|
||||
// turn off non-error log spam to fmod.log (TODO: why do we even have an fmod.log if we don't link against log lib?)
|
||||
FMOD::Debug_SetLevel(FMOD_DEBUG_LEVEL_ERROR);
|
||||
|
||||
result = FMOD::System_Create(&mSystem);
|
||||
if(Check_FMOD_Error(result, "FMOD::System_Create"))
|
||||
return false;
|
||||
|
||||
//will call LLAudioEngine_FMODEX::allocateListener, which needs a valid mSystem pointer.
|
||||
LLAudioEngine::init(num_channels, userdata);
|
||||
|
||||
result = mSystem->getVersion(&version);
|
||||
Check_FMOD_Error(result, "FMOD::System::getVersion");
|
||||
|
||||
if (version < FMOD_VERSION)
|
||||
{
|
||||
LL_WARNS("AppInit") << "Error : You are using the wrong FMOD Ex version (" << version
|
||||
<< ")! You should be using FMOD Ex" << FMOD_VERSION << LL_ENDL;
|
||||
}
|
||||
|
||||
result = mSystem->setSoftwareFormat(44100, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
|
||||
Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat");
|
||||
|
||||
// In this case, all sounds, PLUS wind and stream will be software.
|
||||
result = mSystem->setSoftwareChannels(num_channels + 2);
|
||||
Check_FMOD_Error(result,"FMOD::System::setSoftwareChannels");
|
||||
|
||||
// <FS:Ansariel> Output device selection
|
||||
Check_FMOD_Error(mSystem->setCallback(systemCallback), "FMOD::System::setCallback");
|
||||
Check_FMOD_Error(mSystem->setUserData(this), "FMOD::System::setUserData");
|
||||
// </FS:Ansariel>
|
||||
|
||||
U32 fmod_flags = FMOD_INIT_NORMAL;
|
||||
if(mEnableProfiler)
|
||||
{
|
||||
fmod_flags |= FMOD_INIT_ENABLE_PROFILE;
|
||||
// <FS> FMOD fixes
|
||||
//mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]);
|
||||
//mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]);
|
||||
//mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]);
|
||||
//mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]);
|
||||
// </FS>
|
||||
}
|
||||
|
||||
#if LL_LINUX
|
||||
bool audio_ok = false;
|
||||
|
||||
if (!audio_ok)
|
||||
{
|
||||
if (NULL == getenv("LL_BAD_FMOD_PULSEAUDIO")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL;
|
||||
// <FS> FMOD fixes
|
||||
//if(mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK &&
|
||||
// (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
|
||||
if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO)) == FMOD_OK &&
|
||||
// </FS>
|
||||
(result = mSystem->init(num_channels + 2, fmod_flags, const_cast<char*>(APP_NAME.c_str()))) == FMOD_OK)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL;
|
||||
audio_ok = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "PulseAudio 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;
|
||||
// <FS> FMOD fixes
|
||||
//if(mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK &&
|
||||
if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA)) == FMOD_OK &&
|
||||
// </FS>
|
||||
(result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL;
|
||||
audio_ok = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Check_FMOD_Error(result, "ALSA audio output FAILED to initialize");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "ALSA 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;
|
||||
// <FS> FMOD fixes
|
||||
//if(mSystem->setOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK &&
|
||||
if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_OSS)) == FMOD_OK &&
|
||||
// </FS>
|
||||
(result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL;
|
||||
audio_ok = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Check_FMOD_Error(result, "OSS audio output FAILED to initialize");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
if (!audio_ok)
|
||||
{
|
||||
LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We're interested in logging which output method we
|
||||
// ended up with, for QA purposes.
|
||||
FMOD_OUTPUTTYPE output_type;
|
||||
// <FS> FMOD fixes
|
||||
//mSystem->getOutput(&output_type);
|
||||
if(!Check_FMOD_Error(mSystem->getOutput(&output_type), "FMOD::System::getOutput"))
|
||||
{
|
||||
// </FS>
|
||||
switch (output_type)
|
||||
{
|
||||
case FMOD_OUTPUTTYPE_NOSOUND:
|
||||
LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_PULSEAUDIO:
|
||||
LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_ALSA:
|
||||
LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_OSS:
|
||||
LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
|
||||
default:
|
||||
LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
|
||||
};
|
||||
// <FS> FMOD fixes
|
||||
}
|
||||
// </FS>
|
||||
#else // LL_LINUX
|
||||
|
||||
// initialize the FMOD engine
|
||||
result = mSystem->init( num_channels + 2, fmod_flags, 0);
|
||||
if (result == FMOD_ERR_OUTPUT_CREATEBUFFER)
|
||||
{
|
||||
/*
|
||||
Ok, the speaker mode selected isn't supported by this soundcard. Switch it
|
||||
back to stereo...
|
||||
*/
|
||||
result = mSystem->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
|
||||
Check_FMOD_Error(result,"Error falling back to stereo mode");
|
||||
/*
|
||||
... and re-init.
|
||||
*/
|
||||
result = mSystem->init( num_channels + 2, fmod_flags, 0);
|
||||
}
|
||||
if(Check_FMOD_Error(result, "Error initializing FMOD Ex"))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// <FS> FMOD fixes
|
||||
if (mEnableProfiler)
|
||||
{
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]), "FMOD::System::createChannelGroup");
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]), "FMOD::System::createChannelGroup");
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]), "FMOD::System::createChannelGroup");
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]), "FMOD::System::createChannelGroup");
|
||||
}
|
||||
// </FS>
|
||||
|
||||
// set up our favourite FMOD-native streaming audio implementation if none has already been added
|
||||
if (!getStreamingAudioImpl()) // no existing implementation added
|
||||
setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem));
|
||||
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD Ex initialized correctly" << LL_ENDL;
|
||||
|
||||
int r_numbuffers, r_samplerate, r_channels, r_bits;
|
||||
unsigned int r_bufferlength;
|
||||
mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers);
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_bufferlength=" << r_bufferlength << " bytes" << LL_ENDL;
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_numbuffers=" << r_numbuffers << LL_ENDL;
|
||||
|
||||
mSystem->getSoftwareFormat(&r_samplerate, NULL, &r_channels, NULL, NULL, &r_bits);
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_samplerate=" << r_samplerate << "Hz" << LL_ENDL;
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_channels=" << r_channels << LL_ENDL;
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_bits =" << r_bits << LL_ENDL;
|
||||
|
||||
char r_name[512];
|
||||
mSystem->getDriverInfo(0, r_name, 511, 0);
|
||||
r_name[511] = '\0';
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_name=\"" << r_name << "\"" << LL_ENDL;
|
||||
|
||||
int latency = 100; // optimistic default - i suspect if sample rate is 0, everything breaks.
|
||||
if ( r_samplerate != 0 )
|
||||
latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate);
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): latency=" << latency << "ms" << LL_ENDL;
|
||||
|
||||
mInited = true;
|
||||
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): initialization complete." << LL_ENDL;
|
||||
|
||||
// <FS:Ansariel> Output device selection
|
||||
getDevices(); // Purely to print out available devices for debugging reasons
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Output device selection
|
||||
//virtual
|
||||
LLAudioEngine_FMODEX::output_device_map_t LLAudioEngine_FMODEX::getDevices()
|
||||
{
|
||||
output_device_map_t driver_map;
|
||||
|
||||
int drivercount;
|
||||
char r_name[512];
|
||||
FMOD_GUID guid;
|
||||
|
||||
if (!Check_FMOD_Error(mSystem->getNumDrivers(&drivercount), "FMOD::System::getNumDrivers"))
|
||||
{
|
||||
for (int i = 0; i < drivercount; ++i)
|
||||
{
|
||||
memset(r_name, 0, sizeof(r_name));
|
||||
if (!Check_FMOD_Error(mSystem->getDriverInfo(i, r_name, 511, &guid), "FMOD::System::getDriverInfo"))
|
||||
{
|
||||
LLUUID driver_guid = FMOD_GUID_to_LLUUID(guid);
|
||||
driver_map.insert(std::make_pair(driver_guid, r_name));
|
||||
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::getDevices(): r_name=\"" << r_name << "\" - guid: " << driver_guid << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return driver_map;
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLAudioEngine_FMODEX::setDevice(const LLUUID& device_uuid)
|
||||
{
|
||||
mSelectedDeviceUUID = device_uuid;
|
||||
set_device(mSystem, device_uuid);
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
std::string LLAudioEngine_FMODEX::getDriverName(bool verbose)
|
||||
{
|
||||
llassert_always(mSystem);
|
||||
if (verbose)
|
||||
{
|
||||
U32 version;
|
||||
if(!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion"))
|
||||
{
|
||||
return llformat("FMOD Ex %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF);
|
||||
}
|
||||
}
|
||||
return "FMODEx";
|
||||
}
|
||||
|
||||
|
||||
void LLAudioEngine_FMODEX::allocateListener(void)
|
||||
{
|
||||
mListenerp = (LLListener *) new LLListener_FMODEX(mSystem);
|
||||
if (!mListenerp)
|
||||
{
|
||||
LL_WARNS() << "Listener creation failed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLAudioEngine_FMODEX::shutdown()
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//stopInternetStream();
|
||||
|
||||
LL_INFOS() << "About to LLAudioEngine::shutdown()" << LL_ENDL;
|
||||
LLAudioEngine::shutdown();
|
||||
|
||||
LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << LL_ENDL;
|
||||
if ( mSystem ) // speculative fix for MAINT-2657
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//mSystem->close();
|
||||
//mSystem->release();
|
||||
Check_FMOD_Error(mSystem->close(), "FMOD::System::close");
|
||||
LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() FMOD Ex system closed. Now releasing..." << LL_ENDL;
|
||||
Check_FMOD_Error(mSystem->release(), "FMOD::System::release");
|
||||
// </FS>
|
||||
}
|
||||
LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << LL_ENDL;
|
||||
|
||||
delete mListenerp;
|
||||
mListenerp = NULL;
|
||||
}
|
||||
|
||||
|
||||
LLAudioBuffer * LLAudioEngine_FMODEX::createBuffer()
|
||||
{
|
||||
return new LLAudioBufferFMODEX(mSystem);
|
||||
}
|
||||
|
||||
|
||||
LLAudioChannel * LLAudioEngine_FMODEX::createChannel()
|
||||
{
|
||||
return new LLAudioChannelFMODEX(mSystem);
|
||||
}
|
||||
|
||||
bool LLAudioEngine_FMODEX::initWind()
|
||||
{
|
||||
mNextWindUpdate = 0.0;
|
||||
|
||||
if (!mWindDSP)
|
||||
{
|
||||
memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc)); //Set everything to zero
|
||||
strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name));
|
||||
mWindDSPDesc->channels = 2;
|
||||
mWindDSPDesc->read = &windCallback; // Assign callback - may be called from arbitrary threads
|
||||
if (Check_FMOD_Error(mSystem->createDSP(mWindDSPDesc, &mWindDSP), "FMOD::createDSP"))
|
||||
return false;
|
||||
|
||||
if (mWindGen)
|
||||
delete mWindGen;
|
||||
|
||||
float frequency = 44100;
|
||||
mWindDSP->getDefaults(&frequency,0,0,0);
|
||||
mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency);
|
||||
mWindDSP->setUserData((void*)mWindGen);
|
||||
}
|
||||
|
||||
// *TODO: Should this guard against multiple plays?
|
||||
if (mWindDSP)
|
||||
{
|
||||
mSystem->playDSP(FMOD_CHANNEL_FREE, mWindDSP, false, 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioEngine_FMODEX::cleanupWind()
|
||||
{
|
||||
if (mWindDSP)
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//mWindDSP->remove();
|
||||
//mWindDSP->release();
|
||||
Check_FMOD_Error(mWindDSP->remove(), "FMOD::DSP::remove");
|
||||
Check_FMOD_Error(mWindDSP->release(), "FMOD::DSP::release");
|
||||
// </FS>
|
||||
mWindDSP = NULL;
|
||||
}
|
||||
|
||||
delete mWindGen;
|
||||
mWindGen = NULL;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLAudioEngine_FMODEX::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_FMODEX::setInternalGain(F32 gain)
|
||||
{
|
||||
if (!mInited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gain = llclamp( gain, 0.0f, 1.0f );
|
||||
|
||||
FMOD::ChannelGroup *master_group;
|
||||
// <FS> FMOD fixes
|
||||
//mSystem->getMasterChannelGroup(&master_group);
|
||||
if(Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup"))
|
||||
return;
|
||||
// </FS>
|
||||
master_group->setVolume(gain);
|
||||
|
||||
LLStreamingAudioInterface *saimpl = getStreamingAudioImpl();
|
||||
if ( saimpl )
|
||||
{
|
||||
// fmod likes its streaming audio channel gain re-asserted after
|
||||
// master volume change.
|
||||
saimpl->setGain(saimpl->getGain());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LLAudioChannelFMODEX implementation
|
||||
//
|
||||
|
||||
LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LLAudioChannelFMODEX::~LLAudioChannelFMODEX()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
bool LLAudioChannelFMODEX::updateBuffer()
|
||||
{
|
||||
if (LLAudioChannel::updateBuffer())
|
||||
{
|
||||
// Base class update returned true, which means that we need to actually
|
||||
// set up the channel for a different buffer.
|
||||
|
||||
LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentSourcep->getCurrentBuffer();
|
||||
|
||||
// Grab the FMOD sample associated with the buffer
|
||||
FMOD::Sound *soundp = bufferp->getSound();
|
||||
if (!soundp)
|
||||
{
|
||||
// This is bad, there should ALWAYS be a sound associated with a legit
|
||||
// buffer.
|
||||
LL_ERRS() << "No FMOD sound!" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Actually play the sound. Start it off paused so we can do all the necessary
|
||||
// setup.
|
||||
if(!mChannelp)
|
||||
{
|
||||
FMOD_RESULT result = getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp);
|
||||
Check_FMOD_Error(result, "FMOD::System::playSound");
|
||||
}
|
||||
|
||||
//LL_INFOS() << "Setting up channel " << std::hex << mChannelID << std::dec << LL_ENDL;
|
||||
}
|
||||
|
||||
// If we have a source for the channel, we need to update its gain.
|
||||
if (mCurrentSourcep)
|
||||
{
|
||||
// SJB: warnings can spam and hurt framerate, disabling
|
||||
//FMOD_RESULT result;
|
||||
|
||||
mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain());
|
||||
//Check_FMOD_Error(result, "FMOD::Channel::setVolume");
|
||||
|
||||
mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
|
||||
/*if(Check_FMOD_Error(result, "FMOD::Channel::setMode"))
|
||||
{
|
||||
S32 index;
|
||||
mChannelp->getIndex(&index);
|
||||
LL_WARNS() << "Channel " << index << "Source ID: " << mCurrentSourcep->getID()
|
||||
<< " at " << mCurrentSourcep->getPositionGlobal() << LL_ENDL;
|
||||
}*/
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMODEX::update3DPosition()
|
||||
{
|
||||
if (!mChannelp)
|
||||
{
|
||||
// We're not actually a live channel (i.e., we're not playing back anything)
|
||||
return;
|
||||
}
|
||||
|
||||
LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)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.
|
||||
set3DMode(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Localized sound. Update the position and velocity of the sound.
|
||||
set3DMode(true);
|
||||
|
||||
LLVector3 float_pos;
|
||||
float_pos.setVec(mCurrentSourcep->getPositionGlobal());
|
||||
FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV);
|
||||
Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMODEX::updateLoop()
|
||||
{
|
||||
if (!mChannelp)
|
||||
{
|
||||
// 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;
|
||||
// <FS> FMOD fixes
|
||||
//mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES);
|
||||
Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES),"FMOD::Channel::getPosition");
|
||||
// </FS>
|
||||
|
||||
if (cur_pos < (U32)mLastSamplePos)
|
||||
{
|
||||
mLoopedThisFrame = true;
|
||||
}
|
||||
mLastSamplePos = cur_pos;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMODEX::cleanup()
|
||||
{
|
||||
if (!mChannelp)
|
||||
{
|
||||
//LL_INFOS() << "Aborting cleanup with no channel handle." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
//LL_INFOS() << "Cleaning up channel: " << mChannelID << LL_ENDL;
|
||||
Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop");
|
||||
|
||||
mCurrentBufferp = NULL;
|
||||
mChannelp = NULL;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMODEX::play()
|
||||
{
|
||||
if (!mChannelp)
|
||||
{
|
||||
LL_WARNS() << "Playing without a channel handle, aborting" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// <FS> FMOD fixes
|
||||
//Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause");
|
||||
Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
// </FS>
|
||||
|
||||
getSource()->setPlayedOnce(true);
|
||||
|
||||
if(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()])
|
||||
// <FS> FMOD fixes
|
||||
//mChannelp->setChannelGroup(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]);
|
||||
Check_FMOD_Error(mChannelp->setChannelGroup(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]),"FMOD::Channel::setChannelGroup");
|
||||
// </FS>
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMODEX::playSynced(LLAudioChannel *channelp)
|
||||
{
|
||||
LLAudioChannelFMODEX *fmod_channelp = (LLAudioChannelFMODEX*)channelp;
|
||||
if (!(fmod_channelp->mChannelp && mChannelp))
|
||||
{
|
||||
// Don't have channels allocated to both the master and the slave
|
||||
return;
|
||||
}
|
||||
|
||||
U32 cur_pos;
|
||||
if(Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position"))
|
||||
return;
|
||||
|
||||
cur_pos %= mCurrentBufferp->getLength();
|
||||
|
||||
// Try to match the position of our sync master
|
||||
Check_FMOD_Error(mChannelp->setPosition(cur_pos,FMOD_TIMEUNIT_PCMBYTES),"Unable to set current position");
|
||||
|
||||
// Start us playing
|
||||
play();
|
||||
}
|
||||
|
||||
|
||||
bool LLAudioChannelFMODEX::isPlaying()
|
||||
{
|
||||
if (!mChannelp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool paused, playing;
|
||||
// <FS> FMOD fixes
|
||||
//mChannelp->getPaused(&paused);
|
||||
//mChannelp->isPlaying(&playing);
|
||||
Check_FMOD_Error(mChannelp->getPaused(&paused),"FMOD::Channel::getPaused");
|
||||
Check_FMOD_Error(mChannelp->isPlaying(&playing),"FMOD::Channel::isPlaying");
|
||||
// </FS>
|
||||
return !paused && playing;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LLAudioChannelFMODEX implementation
|
||||
//
|
||||
|
||||
|
||||
LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : mSystemp(system), mSoundp(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LLAudioBufferFMODEX::~LLAudioBufferFMODEX()
|
||||
{
|
||||
if(mSoundp)
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//mSoundp->release();
|
||||
Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::Release");
|
||||
// </FS>
|
||||
mSoundp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLAudioBufferFMODEX::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;
|
||||
}
|
||||
|
||||
// <FS> FMOD fixes
|
||||
//if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB))
|
||||
if (!gDirUtilp->fileExists(filename))
|
||||
// </FS>
|
||||
{
|
||||
// File not found, abort.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mSoundp)
|
||||
{
|
||||
// If there's already something loaded in this buffer, clean it up.
|
||||
// <FS> FMOD fixes
|
||||
//mSoundp->release();
|
||||
Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::release");
|
||||
// </FS>
|
||||
mSoundp = NULL;
|
||||
}
|
||||
|
||||
FMOD_MODE base_mode = FMOD_LOOP_NORMAL | FMOD_SOFTWARE;
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
memset(&exinfo,0,sizeof(exinfo));
|
||||
exinfo.cbsize = sizeof(exinfo);
|
||||
exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading.
|
||||
// Load up the wav file into an fmod sample
|
||||
#if LL_WINDOWS
|
||||
FMOD_RESULT result = getSystem()->createSound((const char*)utf8str_to_utf16str(filename).c_str(), base_mode | FMOD_UNICODE, &exinfo, &mSoundp);
|
||||
#else
|
||||
FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp);
|
||||
#endif
|
||||
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
// We failed to load the file for some reason.
|
||||
LL_WARNS() << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
|
||||
//
|
||||
// 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 LLAudioBufferFMODEX::getLength()
|
||||
{
|
||||
if (!mSoundp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
U32 length;
|
||||
// <FS> FMOD fixes
|
||||
//mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES);
|
||||
Check_FMOD_Error(mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES),"FMOD::Sound::getLength");
|
||||
// </FS>
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
void LLAudioChannelFMODEX::set3DMode(bool use3d)
|
||||
{
|
||||
FMOD_MODE current_mode;
|
||||
// <FS> FMOD fixes
|
||||
//if(mChannelp->getMode(¤t_mode) != FMOD_OK)
|
||||
if(Check_FMOD_Error(mChannelp->getMode(¤t_mode),"FMOD::Channel::getMode"))
|
||||
// </FS>
|
||||
return;
|
||||
FMOD_MODE new_mode = current_mode;
|
||||
new_mode &= ~(use3d ? FMOD_2D : FMOD_3D);
|
||||
new_mode |= use3d ? FMOD_3D : FMOD_2D;
|
||||
|
||||
if(current_mode != new_mode)
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//mChannelp->setMode(new_mode);
|
||||
Check_FMOD_Error(mChannelp->setMode(new_mode),"FMOD::Channel::setMode");
|
||||
// </FS>
|
||||
}
|
||||
}
|
||||
|
||||
// *NOTE: This is almost certainly being called on the mixer thread,
|
||||
// not the main thread. May have implications for callees or audio
|
||||
// engine shutdown.
|
||||
|
||||
FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *originalbuffer, float *newbuffer, unsigned int length, int inchannels, int outchannels)
|
||||
{
|
||||
// originalbuffer = fmod's original mixbuffer.
|
||||
// newbuffer = the buffer passed from the previous DSP unit.
|
||||
// length = length in samples at this mix time.
|
||||
// userdata = user parameter passed through in FSOUND_DSP_Create.
|
||||
|
||||
LLWindGen<LLAudioEngine_FMODEX::MIXBUFFERFORMAT> *windgen;
|
||||
FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance;
|
||||
|
||||
thisdsp->getUserData((void **)&windgen);
|
||||
// <FS> FMOD fixes
|
||||
//S32 channels, configwidth, configheight;
|
||||
//thisdsp->getInfo(0, 0, &channels, &configwidth, &configheight);
|
||||
//
|
||||
//windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length);
|
||||
if (windgen)
|
||||
windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length);
|
||||
// </FS>
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
/**
|
||||
* @file audioengine_fmodex.h
|
||||
* @brief Definition of LLAudioEngine class abstracting the audio
|
||||
* support as a FMODEX implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_AUDIOENGINE_FMODEX_H
|
||||
#define LL_AUDIOENGINE_FMODEX_H
|
||||
|
||||
#include "llaudioengine.h"
|
||||
#include "llwindgen.h"
|
||||
|
||||
//Stubs
|
||||
class LLAudioStreamManagerFMODEX;
|
||||
namespace FMOD
|
||||
{
|
||||
class System;
|
||||
class Channel;
|
||||
class ChannelGroup;
|
||||
class Sound;
|
||||
class DSP;
|
||||
}
|
||||
typedef struct FMOD_DSP_DESCRIPTION FMOD_DSP_DESCRIPTION;
|
||||
|
||||
//Interfaces
|
||||
class LLAudioEngine_FMODEX : public LLAudioEngine
|
||||
{
|
||||
public:
|
||||
LLAudioEngine_FMODEX(bool enable_profiler);
|
||||
virtual ~LLAudioEngine_FMODEX();
|
||||
|
||||
// initialization/startup/shutdown
|
||||
virtual bool init(const S32 num_channels, void *user_data);
|
||||
virtual std::string getDriverName(bool verbose);
|
||||
virtual void allocateListener();
|
||||
|
||||
virtual void shutdown();
|
||||
|
||||
/*virtual*/ bool initWind();
|
||||
/*virtual*/ void cleanupWind();
|
||||
|
||||
/*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water);
|
||||
|
||||
typedef F32 MIXBUFFERFORMAT;
|
||||
|
||||
FMOD::System *getSystem() const {return mSystem;}
|
||||
|
||||
// <FS:Ansariel> Output device selection
|
||||
/*virtual*/ std::map<LLUUID, std::string> getDevices();
|
||||
/*virtual*/ void setDevice(const LLUUID& device_uuid);
|
||||
|
||||
LLUUID getSelectedDeviceUUID() const { return mSelectedDeviceUUID; }
|
||||
// </FS:Ansariel>
|
||||
|
||||
protected:
|
||||
/*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to.
|
||||
/*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel.
|
||||
|
||||
/*virtual*/ void setInternalGain(F32 gain);
|
||||
|
||||
bool mInited;
|
||||
|
||||
LLWindGen<MIXBUFFERFORMAT> *mWindGen;
|
||||
|
||||
FMOD_DSP_DESCRIPTION *mWindDSPDesc;
|
||||
FMOD::DSP *mWindDSP;
|
||||
FMOD::System *mSystem;
|
||||
bool mEnableProfiler;
|
||||
|
||||
// <FS:Ansariel> Output device selection
|
||||
LLUUID mSelectedDeviceUUID;
|
||||
|
||||
public:
|
||||
static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT];
|
||||
};
|
||||
|
||||
|
||||
class LLAudioChannelFMODEX : public LLAudioChannel
|
||||
{
|
||||
public:
|
||||
LLAudioChannelFMODEX(FMOD::System *audioengine);
|
||||
virtual ~LLAudioChannelFMODEX();
|
||||
|
||||
protected:
|
||||
/*virtual*/ void play();
|
||||
/*virtual*/ void playSynced(LLAudioChannel *channelp);
|
||||
/*virtual*/ void cleanup();
|
||||
/*virtual*/ bool isPlaying();
|
||||
|
||||
/*virtual*/ bool updateBuffer();
|
||||
/*virtual*/ void update3DPosition();
|
||||
/*virtual*/ void updateLoop();
|
||||
|
||||
void set3DMode(bool use3d);
|
||||
protected:
|
||||
FMOD::System *getSystem() const {return mSystemp;}
|
||||
FMOD::System *mSystemp;
|
||||
FMOD::Channel *mChannelp;
|
||||
S32 mLastSamplePos;
|
||||
};
|
||||
|
||||
|
||||
class LLAudioBufferFMODEX : public LLAudioBuffer
|
||||
{
|
||||
public:
|
||||
LLAudioBufferFMODEX(FMOD::System *audioengine);
|
||||
virtual ~LLAudioBufferFMODEX();
|
||||
|
||||
/*virtual*/ bool loadWAV(const std::string& filename);
|
||||
/*virtual*/ U32 getLength();
|
||||
friend class LLAudioChannelFMODEX;
|
||||
protected:
|
||||
FMOD::System *getSystem() const {return mSystemp;}
|
||||
FMOD::System *mSystemp;
|
||||
FMOD::Sound *getSound() const{ return mSoundp; }
|
||||
FMOD::Sound *mSoundp;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_AUDIOENGINE_FMODEX_H
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,11 +1,11 @@
|
|||
/**
|
||||
* @file audioengine_fmodstudio.h
|
||||
* @brief Definition of LLAudioEngine class abstracting the audio
|
||||
* support as a FMOD Studio implementation
|
||||
* support as a FMODSTUDIO implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
* Copyright (C) 2020, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -57,7 +57,7 @@ public:
|
|||
virtual ~LLAudioEngine_FMODSTUDIO();
|
||||
|
||||
// initialization/startup/shutdown
|
||||
virtual bool init(const S32 num_channels, void *user_data);
|
||||
virtual bool init(const S32 num_channels, void *user_data, const std::string &app_title);
|
||||
virtual std::string getDriverName(bool verbose);
|
||||
virtual void allocateListener();
|
||||
|
||||
|
|
@ -103,8 +103,8 @@ public:
|
|||
class LLAudioChannelFMODSTUDIO : public LLAudioChannel
|
||||
{
|
||||
public:
|
||||
LLAudioChannelFMODSTUDIO(FMOD::System *audioengine);
|
||||
virtual ~LLAudioChannelFMODSTUDIO();
|
||||
LLAudioChannelFMODSTUDIO(FMOD::System *audioengine);
|
||||
virtual ~LLAudioChannelFMODSTUDIO();
|
||||
|
||||
protected:
|
||||
/*virtual*/ void play();
|
||||
|
|
@ -128,8 +128,8 @@ protected:
|
|||
class LLAudioBufferFMODSTUDIO : public LLAudioBuffer
|
||||
{
|
||||
public:
|
||||
LLAudioBufferFMODSTUDIO(FMOD::System *audioengine);
|
||||
virtual ~LLAudioBufferFMODSTUDIO();
|
||||
LLAudioBufferFMODSTUDIO(FMOD::System *audioengine);
|
||||
virtual ~LLAudioBufferFMODSTUDIO();
|
||||
|
||||
/*virtual*/ bool loadWAV(const std::string& filename);
|
||||
/*virtual*/ U32 getLength();
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@ LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL()
|
|||
}
|
||||
|
||||
// virtual
|
||||
bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata)
|
||||
bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata, const std::string &app_title)
|
||||
{
|
||||
mWindGen = NULL;
|
||||
LLAudioEngine::init(num_channels, userdata);
|
||||
LLAudioEngine::init(num_channels, userdata, app_title);
|
||||
|
||||
if(!alutInit(NULL, NULL))
|
||||
{
|
||||
|
|
@ -241,6 +241,13 @@ bool LLAudioChannelOpenAL::isPlaying()
|
|||
|
||||
bool LLAudioChannelOpenAL::updateBuffer()
|
||||
{
|
||||
if (!mCurrentSourcep)
|
||||
{
|
||||
// This channel isn't associated with any source, nothing
|
||||
// to be updated
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LLAudioChannel::updateBuffer())
|
||||
{
|
||||
// Base class update returned true, which means that we need to actually
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ class LLAudioEngine_OpenAL : public LLAudioEngine
|
|||
LLAudioEngine_OpenAL();
|
||||
virtual ~LLAudioEngine_OpenAL();
|
||||
|
||||
virtual bool init(const S32 num_channels, void *user_data);
|
||||
virtual std::string getDriverName(bool verbose);
|
||||
virtual bool init(const S32 num_channels, void *user_data, const std::string &app_title);
|
||||
virtual std::string getDriverName(bool verbose);
|
||||
virtual void allocateListener();
|
||||
|
||||
virtual void shutdown();
|
||||
|
|
|
|||
|
|
@ -1,140 +0,0 @@
|
|||
/**
|
||||
* @file listener_fmodex.cpp
|
||||
* @brief Implementation of LISTENER class abstracting the audio
|
||||
* support as a FMODEX implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llaudioengine.h"
|
||||
#include "lllistener_fmodex.h"
|
||||
#include "fmod.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener_FMODEX::LLListener_FMODEX(FMOD::System *system)
|
||||
{
|
||||
mSystem = system;
|
||||
init();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener_FMODEX::~LLListener_FMODEX()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODEX::init(void)
|
||||
{
|
||||
// do inherited
|
||||
LLListener::init();
|
||||
mDopplerFactor = 1.0f;
|
||||
mRolloffFactor = 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODEX::translate(LLVector3 offset)
|
||||
{
|
||||
LLListener::translate(offset);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODEX::setPosition(LLVector3 pos)
|
||||
{
|
||||
LLListener::setPosition(pos);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODEX::setVelocity(LLVector3 vel)
|
||||
{
|
||||
LLListener::setVelocity(vel);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODEX::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;
|
||||
|
||||
mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODEX::commitDeferredChanges()
|
||||
{
|
||||
if(!mSystem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mSystem->update();
|
||||
}
|
||||
|
||||
|
||||
void LLListener_FMODEX::setRolloffFactor(F32 factor)
|
||||
{
|
||||
//An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment.
|
||||
//Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well.
|
||||
//In short: Changing the position ticks a dirtyflag inside fmodex, which makes it not skip 3D processing next update call.
|
||||
if(mRolloffFactor != factor)
|
||||
{
|
||||
LLVector3 pos = mVelocity - LLVector3(0.f,0.f,.1f);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL, NULL);
|
||||
}
|
||||
mRolloffFactor = factor;
|
||||
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
|
||||
}
|
||||
|
||||
|
||||
F32 LLListener_FMODEX::getRolloffFactor()
|
||||
{
|
||||
return mRolloffFactor;
|
||||
}
|
||||
|
||||
|
||||
void LLListener_FMODEX::setDopplerFactor(F32 factor)
|
||||
{
|
||||
mDopplerFactor = factor;
|
||||
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
|
||||
}
|
||||
|
||||
|
||||
F32 LLListener_FMODEX::getDopplerFactor()
|
||||
{
|
||||
return mDopplerFactor;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/**
|
||||
* @file listener_fmodex.h
|
||||
* @brief Description of LISTENER class abstracting the audio support
|
||||
* as an FMOD 3D implementation (windows and Linux)
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LISTENER_FMODEX_H
|
||||
#define LL_LISTENER_FMODEX_H
|
||||
|
||||
#include "lllistener.h"
|
||||
|
||||
//Stubs
|
||||
namespace FMOD
|
||||
{
|
||||
class System;
|
||||
}
|
||||
|
||||
//Interfaces
|
||||
class LLListener_FMODEX : public LLListener
|
||||
{
|
||||
public:
|
||||
LLListener_FMODEX(FMOD::System *system);
|
||||
virtual ~LLListener_FMODEX();
|
||||
virtual void init();
|
||||
|
||||
virtual void translate(LLVector3 offset);
|
||||
virtual void setPosition(LLVector3 pos);
|
||||
virtual void setVelocity(LLVector3 vel);
|
||||
virtual void orient(LLVector3 up, LLVector3 at);
|
||||
virtual void commitDeferredChanges();
|
||||
|
||||
virtual void setDopplerFactor(F32 factor);
|
||||
virtual F32 getDopplerFactor();
|
||||
virtual void setRolloffFactor(F32 factor);
|
||||
virtual F32 getRolloffFactor();
|
||||
protected:
|
||||
FMOD::System *mSystem;
|
||||
F32 mDopplerFactor;
|
||||
F32 mRolloffFactor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
/**
|
||||
* @file listener_fmodstudio.cpp
|
||||
* @brief Implementation of LISTENER class abstracting the audio
|
||||
* support as a FMOD Studio implementation
|
||||
* support as a FMODSTUDIO implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
* Copyright (C) 2020, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -28,17 +28,15 @@
|
|||
#include "linden_common.h"
|
||||
#include "llaudioengine.h"
|
||||
#include "lllistener_fmodstudio.h"
|
||||
#include "fmod.hpp"
|
||||
#include "fmodstudio/fmod.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system)
|
||||
: LLListener(),
|
||||
mDopplerFactor(1.0f),
|
||||
mRolloffFactor(1.0f)
|
||||
LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system)
|
||||
{
|
||||
mSystem = system;
|
||||
mSystem = system;
|
||||
init();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
|
@ -46,82 +44,93 @@ LLListener_FMODSTUDIO::~LLListener_FMODSTUDIO()
|
|||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::init(void)
|
||||
{
|
||||
// do inherited
|
||||
LLListener::init();
|
||||
mDopplerFactor = 1.0f;
|
||||
mRolloffFactor = 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::translate(LLVector3 offset)
|
||||
{
|
||||
LLListener::translate(offset);
|
||||
LLListener::translate(offset);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::setPosition(LLVector3 pos)
|
||||
{
|
||||
LLListener::setPosition(pos);
|
||||
LLListener::setPosition(pos);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::setVelocity(LLVector3 vel)
|
||||
{
|
||||
LLListener::setVelocity(vel);
|
||||
LLListener::setVelocity(vel);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL);
|
||||
mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::orient(LLVector3 up, LLVector3 at)
|
||||
{
|
||||
LLListener::orient(up, at);
|
||||
LLListener::orient(up, at);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
|
||||
// at = -at; by default Fmod studio is 'left-handed' but we are providing
|
||||
// flag FMOD_INIT_3D_RIGHTHANDED so no correction are needed
|
||||
|
||||
mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::commitDeferredChanges()
|
||||
{
|
||||
if(!mSystem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!mSystem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mSystem->update();
|
||||
mSystem->update();
|
||||
}
|
||||
|
||||
|
||||
void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor)
|
||||
{
|
||||
//An internal FMOD Studio optimization skips 3D updates if there have not been changes to the 3D sound environment.
|
||||
//Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well.
|
||||
//In short: Changing the position ticks a dirtyflag inside fmod studio, which makes it not skip 3D processing next update call.
|
||||
if(mRolloffFactor != factor)
|
||||
{
|
||||
LLVector3 tmp_pos = mPosition - LLVector3(0.f,0.f,.1f);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*) tmp_pos.mV, NULL, NULL, NULL);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*) mPosition.mV, NULL, NULL, NULL);
|
||||
}
|
||||
mRolloffFactor = factor;
|
||||
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
|
||||
//An internal FMOD optimization skips 3D updates if there have not been changes to the 3D sound environment.
|
||||
// (this was true for FMODex, looks to be still true for FMOD STUDIO, but needs a recheck)
|
||||
//Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well.
|
||||
//In short: Changing the position ticks a dirtyflag inside fmod, which makes it not skip 3D processing next update call.
|
||||
if (mRolloffFactor != factor)
|
||||
{
|
||||
LLVector3 pos = mPosition - LLVector3(0.f, 0.f, .1f);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL);
|
||||
}
|
||||
mRolloffFactor = factor;
|
||||
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
|
||||
}
|
||||
|
||||
|
||||
F32 LLListener_FMODSTUDIO::getRolloffFactor()
|
||||
{
|
||||
return mRolloffFactor;
|
||||
return mRolloffFactor;
|
||||
}
|
||||
|
||||
|
||||
void LLListener_FMODSTUDIO::setDopplerFactor(F32 factor)
|
||||
{
|
||||
mDopplerFactor = factor;
|
||||
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
|
||||
mDopplerFactor = factor;
|
||||
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
|
||||
}
|
||||
|
||||
|
||||
F32 LLListener_FMODSTUDIO::getDopplerFactor()
|
||||
{
|
||||
return mDopplerFactor;
|
||||
return mDopplerFactor;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
/**
|
||||
* @file listener_fmodstudio.h
|
||||
* @brief Description of LISTENER class abstracting the audio support
|
||||
* as an FMOD Studio implementation (windows and Linux)
|
||||
* as an FMOD 3D implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
* Copyright (C) 2020, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -39,24 +39,25 @@ namespace FMOD
|
|||
//Interfaces
|
||||
class LLListener_FMODSTUDIO : public LLListener
|
||||
{
|
||||
public:
|
||||
LLListener_FMODSTUDIO(FMOD::System *system);
|
||||
virtual ~LLListener_FMODSTUDIO();
|
||||
public:
|
||||
LLListener_FMODSTUDIO(FMOD::System *system);
|
||||
virtual ~LLListener_FMODSTUDIO();
|
||||
virtual void init();
|
||||
|
||||
virtual void translate(LLVector3 offset);
|
||||
virtual void setPosition(LLVector3 pos);
|
||||
virtual void setVelocity(LLVector3 vel);
|
||||
virtual void orient(LLVector3 up, LLVector3 at);
|
||||
virtual void commitDeferredChanges();
|
||||
virtual void translate(LLVector3 offset);
|
||||
virtual void setPosition(LLVector3 pos);
|
||||
virtual void setVelocity(LLVector3 vel);
|
||||
virtual void orient(LLVector3 up, LLVector3 at);
|
||||
virtual void commitDeferredChanges();
|
||||
|
||||
virtual void setDopplerFactor(F32 factor);
|
||||
virtual F32 getDopplerFactor();
|
||||
virtual void setRolloffFactor(F32 factor);
|
||||
virtual F32 getRolloffFactor();
|
||||
protected:
|
||||
FMOD::System *mSystem;
|
||||
F32 mDopplerFactor;
|
||||
F32 mRolloffFactor;
|
||||
virtual void setDopplerFactor(F32 factor);
|
||||
virtual F32 getDopplerFactor();
|
||||
virtual void setRolloffFactor(F32 factor);
|
||||
virtual F32 getRolloffFactor();
|
||||
protected:
|
||||
FMOD::System *mSystem;
|
||||
F32 mDopplerFactor;
|
||||
F32 mRolloffFactor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,667 +0,0 @@
|
|||
/**
|
||||
* @file streamingaudio_fmodex.cpp
|
||||
* @brief LLStreamingAudio_FMODEX implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llmath.h"
|
||||
|
||||
#include "fmod.hpp"
|
||||
#include "fmod_errors.h"
|
||||
|
||||
#include "llstreamingaudio_fmodex.h"
|
||||
|
||||
// <FS> FMOD fixes
|
||||
static inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
|
||||
{
|
||||
if (result == FMOD_OK)
|
||||
return false;
|
||||
LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
// </FS>
|
||||
|
||||
class LLAudioStreamManagerFMODEX
|
||||
{
|
||||
public:
|
||||
LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url);
|
||||
FMOD::Channel* startStream();
|
||||
bool stopStream(); // Returns true if the stream was successfully stopped.
|
||||
bool ready();
|
||||
|
||||
const std::string& getURL() { return mInternetStreamURL; }
|
||||
|
||||
// <FS> FMOD fixes
|
||||
//FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL);
|
||||
FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL);
|
||||
// </FS>
|
||||
protected:
|
||||
FMOD::System* mSystem;
|
||||
FMOD::Channel* mStreamChannel;
|
||||
FMOD::Sound* mInternetStream;
|
||||
bool mReady;
|
||||
|
||||
std::string mInternetStreamURL;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Internet Streaming
|
||||
//---------------------------------------------------------------------------
|
||||
LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) :
|
||||
mSystem(system),
|
||||
mCurrentInternetStreamp(NULL),
|
||||
mFMODInternetStreamChannelp(NULL),
|
||||
mGain(1.0f)
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
FMOD_RESULT result;
|
||||
|
||||
// Number of milliseconds of audio to buffer for the audio card.
|
||||
// Must be larger than the usual Second Life frame stutter time.
|
||||
const U32 buffer_seconds = 10; //sec
|
||||
const U32 estimated_bitrate = 128; //kbit/sec
|
||||
// <FS> FMOD fixes
|
||||
//mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
|
||||
result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
|
||||
Check_FMOD_Error(result, "FMOD::System::setStreamBufferSize");
|
||||
// </FS>
|
||||
|
||||
// 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_FMODEX::~LLStreamingAudio_FMODEX()
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//// nothing interesting/safe to do.
|
||||
LL_INFOS() << "LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX() destructing FMOD Ex Streaming" << LL_ENDL;
|
||||
stop();
|
||||
for (U32 i = 0; i < 100; ++i)
|
||||
{
|
||||
if (releaseDeadStreams())
|
||||
break;
|
||||
ms_sleep(10);
|
||||
}
|
||||
LL_INFOS() << "LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX() finished" << LL_ENDL;
|
||||
// </FS>
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODEX::start(const std::string& url)
|
||||
{
|
||||
//if (!mInited)
|
||||
//{
|
||||
// LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL;
|
||||
// return;
|
||||
//}
|
||||
|
||||
// "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
|
||||
stop();
|
||||
|
||||
if (!url.empty())
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
|
||||
//mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url);
|
||||
//mURL = url;
|
||||
if(mDeadStreams.empty())
|
||||
{
|
||||
LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url);
|
||||
mURL = url;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Deferring stream load until buffer release: " << url << LL_ENDL;
|
||||
mPendingURL = url;
|
||||
}
|
||||
// <FS>
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Set internet stream to null" << LL_ENDL;
|
||||
mURL.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLStreamingAudio_FMODEX::update()
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//// Kill dead internet streams, if possible
|
||||
//std::list<LLAudioStreamManagerFMODEX *>::iterator iter;
|
||||
//for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
|
||||
//{
|
||||
// LLAudioStreamManagerFMODEX *streamp = *iter;
|
||||
// if (streamp->stopStream())
|
||||
// {
|
||||
// LL_INFOS() << "Closed dead stream" << LL_ENDL;
|
||||
// delete streamp;
|
||||
// mDeadStreams.erase(iter++);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// iter++;
|
||||
// }
|
||||
//}
|
||||
if (!releaseDeadStreams())
|
||||
{
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!mPendingURL.empty())
|
||||
{
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,mPendingURL);
|
||||
mURL = mPendingURL;
|
||||
mPendingURL.clear();
|
||||
}
|
||||
// </FS>
|
||||
|
||||
// Don't do anything if there are no streams playing
|
||||
if (!mCurrentInternetStreamp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int progress;
|
||||
bool starving;
|
||||
bool diskbusy;
|
||||
// <FS> FMOD fixes
|
||||
//FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy);
|
||||
|
||||
//if (open_state == FMOD_OPENSTATE_READY)
|
||||
|
||||
FMOD_OPENSTATE open_state;
|
||||
FMOD_RESULT result = mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy);
|
||||
|
||||
if (result != FMOD_OK || open_state == FMOD_OPENSTATE_ERROR)
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
else if (open_state == FMOD_OPENSTATE_READY)
|
||||
// </FS>
|
||||
{
|
||||
// Stream is live
|
||||
|
||||
// start the stream if it's ready
|
||||
if (!mFMODInternetStreamChannelp &&
|
||||
(mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))
|
||||
{
|
||||
// Reset volume to previously set volume
|
||||
setGain(getGain());
|
||||
// <FS> FMOD fixes
|
||||
//mFMODInternetStreamChannelp->setPaused(false);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
// </FS>
|
||||
}
|
||||
}
|
||||
// <FS> FMOD fixes
|
||||
//else if(open_state == FMOD_OPENSTATE_ERROR)
|
||||
//{
|
||||
// stop();
|
||||
// return;
|
||||
//}
|
||||
// </FS>
|
||||
|
||||
if(mFMODInternetStreamChannelp)
|
||||
{
|
||||
FMOD::Sound *sound = NULL;
|
||||
|
||||
// <FS:CR> FmodEX Error checking
|
||||
//if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound)
|
||||
if (!Check_FMOD_Error(mFMODInternetStreamChannelp->getCurrentSound(&sound), "FMOD::Channel::getCurrentSound") && sound)
|
||||
// </FS:CR>
|
||||
{
|
||||
FMOD_TAG tag;
|
||||
S32 tagcount, dirtytagcount;
|
||||
|
||||
// <FS:CR> FmodEX Error checking
|
||||
//if(sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount)
|
||||
if (!Check_FMOD_Error(sound->getNumTags(&tagcount, &dirtytagcount), "FMOD::Sound::getNumTags") && dirtytagcount)
|
||||
// </FS:CR>
|
||||
{
|
||||
// <FS:CR> Stream metadata - originally by Shyotl Khur
|
||||
LL_DEBUGS("StreamMetadata") << "Tag count: " << tagcount << " Dirty tag count: " << dirtytagcount << LL_ENDL;
|
||||
|
||||
mMetadata.clear();
|
||||
mNewMetadata = true;
|
||||
// </FS:CR>
|
||||
for(S32 i = 0; i < tagcount; ++i)
|
||||
{
|
||||
// <FS:Ansariel> FmodEX Error checking
|
||||
//if(sound->getTag(NULL, i, &tag) != FMOD_OK)
|
||||
if(Check_FMOD_Error(sound->getTag(NULL, i, &tag), "FMOD::Sound::getTag"))
|
||||
// </FS:Ansariel>
|
||||
continue;
|
||||
|
||||
// <FS:CR> Stream metadata - originally by Shyotl Khur
|
||||
//if (tag.type == FMOD_TAGTYPE_FMOD)
|
||||
//{
|
||||
// if (!strcmp(tag.name, "Sample Rate Change"))
|
||||
// {
|
||||
// LL_INFOS("FmodEX") << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL;
|
||||
// mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data));
|
||||
// }
|
||||
// continue;
|
||||
//}
|
||||
LL_DEBUGS("StreamMetadata") << "Tag name: " << tag.name << " - Tag type: " << tag.type << " - Tag data type: " << tag.datatype << LL_ENDL;
|
||||
std::string name = tag.name;
|
||||
switch(tag.type)
|
||||
{
|
||||
case(FMOD_TAGTYPE_ID3V2):
|
||||
{
|
||||
if(name == "TIT2") name = "TITLE";
|
||||
else if(name == "TPE1") name = "ARTIST";
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGTYPE_ASF):
|
||||
{
|
||||
if(name == "Title") name = "TITLE";
|
||||
else if(name == "WM/AlbumArtist") name = "ARTIST";
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGTYPE_VORBISCOMMENT):
|
||||
{
|
||||
if(name == "title") name = "TITLE";
|
||||
else if(name == "artist") name = "ARTIST";
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGTYPE_FMOD):
|
||||
{
|
||||
if (!strcmp(tag.name, "Sample Rate Change"))
|
||||
{
|
||||
LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL;
|
||||
mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(tag.datatype)
|
||||
{
|
||||
case(FMOD_TAGDATATYPE_INT):
|
||||
{
|
||||
(mMetadata)[name]=*(LLSD::Integer*)(tag.data);
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << *(int*)(tag.data) << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGDATATYPE_FLOAT):
|
||||
{
|
||||
(mMetadata)[name]=*(LLSD::Real*)(tag.data);
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << *(float*)(tag.data) << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGDATATYPE_STRING):
|
||||
{
|
||||
std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen));
|
||||
(mMetadata)[name]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF8):
|
||||
{
|
||||
std::string out((char*)tag.data);
|
||||
(mMetadata)[name]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF16):
|
||||
{
|
||||
std::string out((char*)tag.data,tag.datalen);
|
||||
(mMetadata)[std::string(tag.name)]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF16BE):
|
||||
{
|
||||
std::string out((char*)tag.data,tag.datalen);
|
||||
//U16* buf = (U16*)out.c_str();
|
||||
//for(U32 j = 0; j < out.size()/2; ++j)
|
||||
//(((buf[j] & 0xff)<<8) | ((buf[j] & 0xff00)>>8));
|
||||
(mMetadata)[std::string(tag.name)]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// </FS:CR> Stream metadata - originally by Shyotl Khur
|
||||
}
|
||||
}
|
||||
|
||||
if(starving)
|
||||
{
|
||||
bool paused = false;
|
||||
// <FS> FMOD fixes
|
||||
//mFMODInternetStreamChannelp->getPaused(&paused);
|
||||
//if(!paused)
|
||||
if (mFMODInternetStreamChannelp->getPaused(&paused) == FMOD_OK && !paused)
|
||||
// </FS>
|
||||
{
|
||||
LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL;
|
||||
LL_INFOS() << " (diskbusy="<<diskbusy<<")" << LL_ENDL;
|
||||
LL_INFOS() << " (progress="<<progress<<")" << LL_ENDL;
|
||||
// <FS> FMOD fixes
|
||||
//mFMODInternetStreamChannelp->setPaused(true);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
// </FS>
|
||||
}
|
||||
}
|
||||
else if(progress > 80)
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//mFMODInternetStreamChannelp->setPaused(false);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
// </FS>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODEX::stop()
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
mPendingURL.clear();
|
||||
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//mFMODInternetStreamChannelp->setPaused(true);
|
||||
//mFMODInternetStreamChannelp->setPriority(0);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority");
|
||||
// </FS>
|
||||
mFMODInternetStreamChannelp = NULL;
|
||||
}
|
||||
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
|
||||
if (mCurrentInternetStreamp->stopStream())
|
||||
{
|
||||
delete mCurrentInternetStreamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
|
||||
mDeadStreams.push_back(mCurrentInternetStreamp);
|
||||
}
|
||||
mCurrentInternetStreamp = NULL;
|
||||
//mURL.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODEX::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_FMODEX::isPlaying()
|
||||
{
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
return 1; // Active and playing
|
||||
}
|
||||
// <FS> FMOD fixes
|
||||
//else if (!mURL.empty())
|
||||
else if (!mURL.empty() || !mPendingURL.empty())
|
||||
// </FS>
|
||||
{
|
||||
return 2; // "Paused"
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
F32 LLStreamingAudio_FMODEX::getGain()
|
||||
{
|
||||
return mGain;
|
||||
}
|
||||
|
||||
|
||||
std::string LLStreamingAudio_FMODEX::getURL()
|
||||
{
|
||||
return mURL;
|
||||
}
|
||||
|
||||
|
||||
void LLStreamingAudio_FMODEX::setGain(F32 vol)
|
||||
{
|
||||
mGain = vol;
|
||||
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here?
|
||||
|
||||
// <FS> FMOD fixes
|
||||
//mFMODInternetStreamChannelp->setVolume(vol);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume");
|
||||
// </FS>
|
||||
}
|
||||
}
|
||||
|
||||
// <FS:CR> Streamtitle display
|
||||
// virtual
|
||||
bool LLStreamingAudio_FMODEX::getNewMetadata(LLSD& metadata)
|
||||
{
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
if (mNewMetadata)
|
||||
{
|
||||
metadata = mMetadata;
|
||||
mNewMetadata = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return mNewMetadata;
|
||||
}
|
||||
|
||||
metadata = LLSD();
|
||||
return false;
|
||||
}
|
||||
// </FS:CR>
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// manager of possibly-multiple internet audio streams
|
||||
|
||||
LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url) :
|
||||
mSystem(system),
|
||||
mStreamChannel(NULL),
|
||||
mInternetStream(NULL),
|
||||
mReady(false)
|
||||
{
|
||||
mInternetStreamURL = url;
|
||||
|
||||
FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream);
|
||||
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
LL_WARNS() << "Couldn't open fmod stream, error "
|
||||
<< FMOD_ErrorString(result)
|
||||
<< LL_ENDL;
|
||||
mReady = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mReady = true;
|
||||
}
|
||||
|
||||
FMOD::Channel *LLAudioStreamManagerFMODEX::startStream()
|
||||
{
|
||||
// We need a live and opened stream before we try and play it.
|
||||
// <FS> FMOD fixes
|
||||
//if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY)
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (getOpenState(open_state) != FMOD_OK || open_state != FMOD_OPENSTATE_READY)
|
||||
// </FS>
|
||||
{
|
||||
LL_WARNS() << "No internet stream to start playing!" << LL_ENDL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mStreamChannel)
|
||||
return mStreamChannel; //Already have a channel for this stream.
|
||||
|
||||
// <FS> FMOD fixes
|
||||
//mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel);
|
||||
Check_FMOD_Error(mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel), "FMOD::System::playSound");
|
||||
// </FS>
|
||||
return mStreamChannel;
|
||||
}
|
||||
|
||||
bool LLAudioStreamManagerFMODEX::stopStream()
|
||||
{
|
||||
if (mInternetStream)
|
||||
{
|
||||
bool close = true;
|
||||
// <FS> FMOD fixes
|
||||
//switch (getOpenState())
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (getOpenState(open_state) == FMOD_OK)
|
||||
{
|
||||
switch (open_state)
|
||||
// </FS>
|
||||
{
|
||||
case FMOD_OPENSTATE_CONNECTING:
|
||||
close = false;
|
||||
break;
|
||||
default:
|
||||
close = true;
|
||||
}
|
||||
// <FS> FMOD fixes
|
||||
}
|
||||
// </FS>
|
||||
|
||||
// <FS> FMOD fixes
|
||||
//if (close)
|
||||
//{
|
||||
// mInternetStream->release();
|
||||
if (close && mInternetStream->release() == FMOD_OK)
|
||||
{
|
||||
// </FS>
|
||||
mStreamChannel = NULL;
|
||||
mInternetStream = NULL;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// <FS> FMOD fixes
|
||||
//FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy)
|
||||
//{
|
||||
// FMOD_OPENSTATE state;
|
||||
// mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
|
||||
// return state;
|
||||
//}
|
||||
FMOD_RESULT LLAudioStreamManagerFMODEX::getOpenState(FMOD_OPENSTATE& state, unsigned int* percentbuffered, bool* starving, bool* diskbusy)
|
||||
{
|
||||
if (!mInternetStream)
|
||||
return FMOD_ERR_INVALID_HANDLE;
|
||||
FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
|
||||
Check_FMOD_Error(result, "FMOD::Sound::getOpenState");
|
||||
return result;
|
||||
}
|
||||
// </FS>
|
||||
|
||||
void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)
|
||||
{
|
||||
// <FS> FMOD fixes
|
||||
//mSystem->setStreamBufferSize(streambuffertime/1000*128*128, FMOD_TIMEUNIT_RAWBYTES);
|
||||
Check_FMOD_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
|
||||
// </FS>
|
||||
FMOD_ADVANCEDSETTINGS settings;
|
||||
memset(&settings,0,sizeof(settings));
|
||||
settings.cbsize=sizeof(settings);
|
||||
settings.defaultDecodeBufferSize = decodebuffertime;//ms
|
||||
// <FS> FMOD fixes
|
||||
//mSystem->setAdvancedSettings(&settings);
|
||||
Check_FMOD_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings");
|
||||
// </FS>
|
||||
}
|
||||
|
||||
// <FS> FMOD fixes
|
||||
bool LLStreamingAudio_FMODEX::releaseDeadStreams()
|
||||
{
|
||||
// Kill dead internet streams, if possible
|
||||
std::list<LLAudioStreamManagerFMODEX *>::iterator iter;
|
||||
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
|
||||
{
|
||||
LLAudioStreamManagerFMODEX *streamp = *iter;
|
||||
if (streamp->stopStream())
|
||||
{
|
||||
LL_INFOS() << "Closed dead stream" << LL_ENDL;
|
||||
delete streamp;
|
||||
mDeadStreams.erase(iter++);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
return mDeadStreams.empty();
|
||||
}
|
||||
// </FS>
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
/**
|
||||
* @file streamingaudio_fmodex.h
|
||||
* @brief Definition of LLStreamingAudio_FMODEX implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_STREAMINGAUDIO_FMODEX_H
|
||||
#define LL_STREAMINGAUDIO_FMODEX_H
|
||||
|
||||
#include "stdtypes.h" // from llcommon
|
||||
|
||||
#include "llstreamingaudio.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
//Stubs
|
||||
class LLAudioStreamManagerFMODEX;
|
||||
namespace FMOD
|
||||
{
|
||||
class System;
|
||||
class Channel;
|
||||
}
|
||||
|
||||
//Interfaces
|
||||
class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface
|
||||
{
|
||||
public:
|
||||
LLStreamingAudio_FMODEX(FMOD::System *system);
|
||||
/*virtual*/ ~LLStreamingAudio_FMODEX();
|
||||
|
||||
/*virtual*/ void start(const std::string& url);
|
||||
/*virtual*/ void stop();
|
||||
/*virtual*/ void pause(S32 pause);
|
||||
/*virtual*/ void update();
|
||||
/*virtual*/ S32 isPlaying();
|
||||
/*virtual*/ void setGain(F32 vol);
|
||||
/*virtual*/ F32 getGain();
|
||||
/*virtual*/ std::string getURL();
|
||||
|
||||
/*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
|
||||
/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
|
||||
|
||||
// <FS:CR> Streamtitle display
|
||||
virtual bool getNewMetadata(LLSD& metadata);
|
||||
// </FS:CR>
|
||||
|
||||
private:
|
||||
// <FS> FMOD fixes
|
||||
bool releaseDeadStreams();
|
||||
|
||||
FMOD::System *mSystem;
|
||||
|
||||
LLAudioStreamManagerFMODEX *mCurrentInternetStreamp;
|
||||
FMOD::Channel *mFMODInternetStreamChannelp;
|
||||
std::list<LLAudioStreamManagerFMODEX *> mDeadStreams;
|
||||
|
||||
std::string mURL;
|
||||
std::string mPendingURL; // <FS> FMOD fixes
|
||||
F32 mGain;
|
||||
|
||||
// <FS:CR> Streamtitle display
|
||||
bool mNewMetadata;
|
||||
LLSD mMetadata;
|
||||
// </FS:CR> Streamtitle display
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_STREAMINGAUDIO_FMODEX_H
|
||||
|
|
@ -2,9 +2,9 @@
|
|||
* @file streamingaudio_fmodstudio.cpp
|
||||
* @brief LLStreamingAudio_FMODSTUDIO implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
* Copyright (C) 2020, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -28,38 +28,38 @@
|
|||
|
||||
#include "llmath.h"
|
||||
|
||||
#include "fmod.hpp"
|
||||
#include "fmod_errors.h"
|
||||
#include "fmodstudio/fmod.hpp"
|
||||
#include "fmodstudio/fmod_errors.h"
|
||||
|
||||
#include "llstreamingaudio_fmodstudio.h"
|
||||
|
||||
inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
|
||||
{
|
||||
if (result == FMOD_OK)
|
||||
return false;
|
||||
LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
return true;
|
||||
if (result == FMOD_OK)
|
||||
return false;
|
||||
LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
class LLAudioStreamManagerFMODSTUDIO
|
||||
{
|
||||
public:
|
||||
LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url);
|
||||
FMOD::Channel* startStream();
|
||||
bool stopStream(); // Returns true if the stream was successfully stopped.
|
||||
bool ready();
|
||||
LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url);
|
||||
FMOD::Channel* startStream();
|
||||
bool stopStream(); // Returns true if the stream was successfully stopped.
|
||||
bool ready();
|
||||
|
||||
const std::string& getURL() { return mInternetStreamURL; }
|
||||
const std::string& getURL() { return mInternetStreamURL; }
|
||||
|
||||
FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL);
|
||||
FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL);
|
||||
protected:
|
||||
FMOD::System* mSystem;
|
||||
FMOD::ChannelGroup* mChannelGroup;
|
||||
FMOD::Channel* mStreamChannel;
|
||||
FMOD::Sound* mInternetStream;
|
||||
bool mReady;
|
||||
FMOD::System* mSystem;
|
||||
FMOD::ChannelGroup* mChannelGroup;
|
||||
FMOD::Channel* mStreamChannel;
|
||||
FMOD::Sound* mInternetStream;
|
||||
bool mReady;
|
||||
|
||||
std::string mInternetStreamURL;
|
||||
std::string mInternetStreamURL;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -68,290 +68,285 @@ protected:
|
|||
// Internet Streaming
|
||||
//---------------------------------------------------------------------------
|
||||
LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) :
|
||||
mSystem(system),
|
||||
mCurrentInternetStreamp(NULL),
|
||||
mStreamGroup(NULL),
|
||||
mFMODInternetStreamChannelp(NULL),
|
||||
mGain(1.0f)
|
||||
mSystem(system),
|
||||
mCurrentInternetStreamp(NULL),
|
||||
mStreamGroup(NULL),
|
||||
mFMODInternetStreamChannelp(NULL),
|
||||
mGain(1.0f)
|
||||
{
|
||||
FMOD_RESULT result;
|
||||
// Number of milliseconds of audio to buffer for the audio card.
|
||||
// Must be larger than the usual Second Life frame stutter time.
|
||||
const U32 buffer_seconds = 10; //sec
|
||||
const U32 estimated_bitrate = 128; //kbit/sec
|
||||
Check_FMOD_Error(mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
|
||||
|
||||
// Number of milliseconds of audio to buffer for the audio card.
|
||||
// Must be larger than the usual Second Life frame stutter time.
|
||||
const U32 buffer_seconds = 10; //sec
|
||||
const U32 estimated_bitrate = 128; //kbit/sec
|
||||
result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
|
||||
Check_FMOD_Error(result, "FMOD::System::setStreamBufferSize");
|
||||
|
||||
Check_FMOD_Error(system->createChannelGroup("stream", &mStreamGroup), "FMOD::System::createChannelGroup");
|
||||
Check_FMOD_Error(system->createChannelGroup("stream", &mStreamGroup), "FMOD::System::createChannelGroup");
|
||||
}
|
||||
|
||||
LLStreamingAudio_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO()
|
||||
{
|
||||
stop();
|
||||
for (U32 i = 0; i < 100; ++i)
|
||||
{
|
||||
if (releaseDeadStreams())
|
||||
break;
|
||||
ms_sleep(10);
|
||||
}
|
||||
|
||||
stop();
|
||||
for (U32 i = 0; i < 100; ++i)
|
||||
{
|
||||
if (releaseDeadStreams())
|
||||
break;
|
||||
ms_sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::start(const std::string& url)
|
||||
{
|
||||
//if (!mInited)
|
||||
//{
|
||||
// LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL;
|
||||
// return;
|
||||
//}
|
||||
//if (!mInited)
|
||||
//{
|
||||
// LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL;
|
||||
// return;
|
||||
//}
|
||||
|
||||
// "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
|
||||
stop();
|
||||
// "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
|
||||
stop();
|
||||
|
||||
if (!url.empty())
|
||||
{
|
||||
if(mDeadStreams.empty())
|
||||
{
|
||||
LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, url);
|
||||
mURL = url;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Deferring stream load until buffer release: " << url << LL_ENDL;
|
||||
mPendingURL = url;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Set internet stream to null" << LL_ENDL;
|
||||
mURL.clear();
|
||||
}
|
||||
if (!url.empty())
|
||||
{
|
||||
if (mDeadStreams.empty())
|
||||
{
|
||||
LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, url);
|
||||
mURL = url;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Deferring stream load until buffer release: " << url << LL_ENDL;
|
||||
mPendingURL = url;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Set internet stream to null" << LL_ENDL;
|
||||
mURL.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::update()
|
||||
{
|
||||
if (!releaseDeadStreams())
|
||||
{
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
return;
|
||||
}
|
||||
if (!releaseDeadStreams())
|
||||
{
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!mPendingURL.empty())
|
||||
{
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, mPendingURL);
|
||||
mURL = mPendingURL;
|
||||
mPendingURL.clear();
|
||||
}
|
||||
if (!mPendingURL.empty())
|
||||
{
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, mPendingURL);
|
||||
mURL = mPendingURL;
|
||||
mPendingURL.clear();
|
||||
}
|
||||
|
||||
// Don't do anything if there are no streams playing
|
||||
if (!mCurrentInternetStreamp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Don't do anything if there are no streams playing
|
||||
if (!mCurrentInternetStreamp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int progress;
|
||||
bool starving;
|
||||
bool diskbusy;
|
||||
FMOD_OPENSTATE open_state;
|
||||
FMOD_RESULT result = mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy);
|
||||
unsigned int progress;
|
||||
bool starving;
|
||||
bool diskbusy;
|
||||
FMOD_OPENSTATE open_state;
|
||||
|
||||
if (result != FMOD_OK || open_state == FMOD_OPENSTATE_ERROR)
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
else if (open_state == FMOD_OPENSTATE_READY)
|
||||
{
|
||||
// Stream is live
|
||||
if (Check_FMOD_Error(mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy), "FMOD::Sound::getOpenState") || open_state == FMOD_OPENSTATE_ERROR)
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
else if (open_state == FMOD_OPENSTATE_READY)
|
||||
{
|
||||
// Stream is live
|
||||
|
||||
// start the stream if it's ready
|
||||
if (!mFMODInternetStreamChannelp &&
|
||||
(mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))
|
||||
{
|
||||
// Reset volume to previously set volume
|
||||
setGain(getGain());
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
// start the stream if it's ready
|
||||
if (!mFMODInternetStreamChannelp &&
|
||||
(mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))
|
||||
{
|
||||
// Reset volume to previously set volume
|
||||
setGain(getGain());
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(mFMODInternetStreamChannelp)
|
||||
{
|
||||
FMOD::Sound *sound = NULL;
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
FMOD::Sound *sound = NULL;
|
||||
|
||||
if (!Check_FMOD_Error(mFMODInternetStreamChannelp->getCurrentSound(&sound), "FMOD::Channel::getCurrentSound") && sound)
|
||||
{
|
||||
FMOD_TAG tag;
|
||||
S32 tagcount, dirtytagcount;
|
||||
if (!Check_FMOD_Error(mFMODInternetStreamChannelp->getCurrentSound(&sound), "FMOD::Channel::getCurrentSound") && sound)
|
||||
{
|
||||
FMOD_TAG tag;
|
||||
S32 tagcount, dirtytagcount;
|
||||
|
||||
if (!Check_FMOD_Error(sound->getNumTags(&tagcount, &dirtytagcount), "FMOD::Sound::getNumTags") && dirtytagcount)
|
||||
{
|
||||
LL_DEBUGS("StreamMetadata") << "Tag count: " << tagcount << " Dirty tag count: " << dirtytagcount << LL_ENDL;
|
||||
if (!Check_FMOD_Error(sound->getNumTags(&tagcount, &dirtytagcount), "FMOD::Sound::getNumTags") && dirtytagcount)
|
||||
{
|
||||
LL_DEBUGS("StreamMetadata") << "Tag count: " << tagcount << " Dirty tag count: " << dirtytagcount << LL_ENDL;
|
||||
|
||||
// <DKO> Stream metadata - originally by Shyotl Khur
|
||||
mMetadata.clear();
|
||||
mNewMetadata = true;
|
||||
// </DKO>
|
||||
for(S32 i = 0; i < tagcount; ++i)
|
||||
{
|
||||
if(Check_FMOD_Error(sound->getTag(NULL, i, &tag), "FMOD::Sound::getTag"))
|
||||
continue;
|
||||
// <DKO> Stream metadata - originally by Shyotl Khur
|
||||
mMetadata.clear();
|
||||
mNewMetadata = true;
|
||||
// </DKO>
|
||||
for (S32 i = 0; i < tagcount; ++i)
|
||||
{
|
||||
if (Check_FMOD_Error(sound->getTag(NULL, i, &tag), "FMOD::Sound::getTag"))
|
||||
continue;
|
||||
|
||||
LL_DEBUGS("StreamMetadata") << "Tag name: " << tag.name << " - Tag type: " << tag.type << " - Tag data type: " << tag.datatype << LL_ENDL;
|
||||
LL_DEBUGS("StreamMetadata") << "Tag name: " << tag.name << " - Tag type: " << tag.type << " - Tag data type: " << tag.datatype << LL_ENDL;
|
||||
|
||||
std::string name = tag.name;
|
||||
switch(tag.type)
|
||||
{
|
||||
case(FMOD_TAGTYPE_ID3V2):
|
||||
{
|
||||
if(name == "TIT2") name = "TITLE";
|
||||
else if(name == "TPE1") name = "ARTIST";
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGTYPE_ASF):
|
||||
{
|
||||
if(name == "Title") name = "TITLE";
|
||||
else if(name == "WM/AlbumArtist") name = "ARTIST";
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGTYPE_VORBISCOMMENT):
|
||||
{
|
||||
if(name == "title") name = "TITLE";
|
||||
else if(name == "artist") name = "ARTIST";
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGTYPE_FMOD):
|
||||
{
|
||||
if (!strcmp(tag.name, "Sample Rate Change"))
|
||||
{
|
||||
LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL;
|
||||
mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(tag.datatype)
|
||||
{
|
||||
case(FMOD_TAGDATATYPE_INT):
|
||||
{
|
||||
(mMetadata)[name]=*(LLSD::Integer*)(tag.data);
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << *(int*)(tag.data) << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGDATATYPE_FLOAT):
|
||||
{
|
||||
(mMetadata)[name]=*(LLSD::Real*)(tag.data);
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << *(float*)(tag.data) << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGDATATYPE_STRING):
|
||||
{
|
||||
std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen));
|
||||
(mMetadata)[name]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF8):
|
||||
{
|
||||
std::string out((char*)tag.data);
|
||||
(mMetadata)[name]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF16):
|
||||
{
|
||||
std::string out((char*)tag.data,tag.datalen);
|
||||
(mMetadata)[std::string(tag.name)]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case(FMOD_TAGDATATYPE_STRING_UTF16BE):
|
||||
{
|
||||
std::string out((char*)tag.data,tag.datalen);
|
||||
//U16* buf = (U16*)out.c_str();
|
||||
//for(U32 j = 0; j < out.size()/2; ++j)
|
||||
//(((buf[j] & 0xff)<<8) | ((buf[j] & 0xff00)>>8));
|
||||
(mMetadata)[std::string(tag.name)]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string name = tag.name;
|
||||
switch (tag.type)
|
||||
{
|
||||
case FMOD_TAGTYPE_ID3V2:
|
||||
{
|
||||
if (name == "TIT2") name = "TITLE";
|
||||
else if (name == "TPE1") name = "ARTIST";
|
||||
break;
|
||||
}
|
||||
case FMOD_TAGTYPE_ASF:
|
||||
{
|
||||
if (name == "Title") name = "TITLE";
|
||||
else if (name == "WM/AlbumArtist") name = "ARTIST";
|
||||
break;
|
||||
}
|
||||
case FMOD_TAGTYPE_VORBISCOMMENT:
|
||||
{
|
||||
if (name == "title") name = "TITLE";
|
||||
else if (name == "artist") name = "ARTIST";
|
||||
break;
|
||||
}
|
||||
case FMOD_TAGTYPE_FMOD:
|
||||
{
|
||||
if (!strcmp(tag.name, "Sample Rate Change"))
|
||||
{
|
||||
LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL;
|
||||
mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (tag.datatype)
|
||||
{
|
||||
case FMOD_TAGDATATYPE_INT:
|
||||
{
|
||||
(mMetadata)[name]=*(LLSD::Integer*)(tag.data);
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << *(int*)(tag.data) << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case FMOD_TAGDATATYPE_FLOAT:
|
||||
{
|
||||
(mMetadata)[name]=*(LLSD::Real*)(tag.data);
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << *(float*)(tag.data) << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case FMOD_TAGDATATYPE_STRING:
|
||||
{
|
||||
std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen));
|
||||
(mMetadata)[name]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case FMOD_TAGDATATYPE_STRING_UTF8:
|
||||
{
|
||||
std::string out((char*)tag.data);
|
||||
(mMetadata)[name]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case FMOD_TAGDATATYPE_STRING_UTF16:
|
||||
{
|
||||
std::string out((char*)tag.data,tag.datalen);
|
||||
(mMetadata)[std::string(tag.name)]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case FMOD_TAGDATATYPE_STRING_UTF16BE:
|
||||
{
|
||||
std::string out((char*)tag.data,tag.datalen);
|
||||
//U16* buf = (U16*)out.c_str();
|
||||
//for(U32 j = 0; j < out.size()/2; ++j)
|
||||
//(((buf[j] & 0xff)<<8) | ((buf[j] & 0xff00)>>8));
|
||||
(mMetadata)[std::string(tag.name)]=out;
|
||||
LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(starving)
|
||||
{
|
||||
bool paused = false;
|
||||
if (mFMODInternetStreamChannelp->getPaused(&paused) == FMOD_OK && !paused)
|
||||
{
|
||||
LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL;
|
||||
LL_INFOS() << " (diskbusy="<<diskbusy<<")" << LL_ENDL;
|
||||
LL_INFOS() << " (progress="<<progress<<")" << LL_ENDL;
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
else if(progress > 80)
|
||||
{
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (starving)
|
||||
{
|
||||
bool paused = false;
|
||||
if (!Check_FMOD_Error(mFMODInternetStreamChannelp->getPaused(&paused), "FMOD:Channel::getPaused") && !paused)
|
||||
{
|
||||
LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL;
|
||||
LL_INFOS() << " (diskbusy=" << diskbusy << ")" << LL_ENDL;
|
||||
LL_INFOS() << " (progress=" << progress << ")" << LL_ENDL;
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
else if (progress > 80)
|
||||
{
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::stop()
|
||||
{
|
||||
mPendingURL.clear();
|
||||
mPendingURL.clear();
|
||||
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority");
|
||||
mFMODInternetStreamChannelp = NULL;
|
||||
}
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority");
|
||||
mFMODInternetStreamChannelp = NULL;
|
||||
}
|
||||
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
|
||||
if (mCurrentInternetStreamp->stopStream())
|
||||
{
|
||||
delete mCurrentInternetStreamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
|
||||
mDeadStreams.push_back(mCurrentInternetStreamp);
|
||||
}
|
||||
mCurrentInternetStreamp = NULL;
|
||||
}
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
|
||||
if (mCurrentInternetStreamp->stopStream())
|
||||
{
|
||||
delete mCurrentInternetStreamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
|
||||
mDeadStreams.push_back(mCurrentInternetStreamp);
|
||||
}
|
||||
mCurrentInternetStreamp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::pause(int pauseopt)
|
||||
{
|
||||
if (pauseopt < 0)
|
||||
{
|
||||
pauseopt = mCurrentInternetStreamp ? 1 : 0;
|
||||
}
|
||||
if (pauseopt < 0)
|
||||
{
|
||||
pauseopt = mCurrentInternetStreamp ? 1 : 0;
|
||||
}
|
||||
|
||||
if (pauseopt)
|
||||
{
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
start(getURL());
|
||||
}
|
||||
if (pauseopt)
|
||||
{
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
start(getURL());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -359,179 +354,179 @@ void LLStreamingAudio_FMODSTUDIO::pause(int pauseopt)
|
|||
// doesn't necessarily mean audio is coming out of the speakers.
|
||||
int LLStreamingAudio_FMODSTUDIO::isPlaying()
|
||||
{
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
return 1; // Active and playing
|
||||
}
|
||||
else if (!mURL.empty() || !mPendingURL.empty())
|
||||
{
|
||||
return 2; // "Paused"
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
return 1; // Active and playing
|
||||
}
|
||||
else if (!mURL.empty() || !mPendingURL.empty())
|
||||
{
|
||||
return 2; // "Paused"
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
F32 LLStreamingAudio_FMODSTUDIO::getGain()
|
||||
{
|
||||
return mGain;
|
||||
return mGain;
|
||||
}
|
||||
|
||||
|
||||
std::string LLStreamingAudio_FMODSTUDIO::getURL()
|
||||
{
|
||||
return mURL;
|
||||
return mURL;
|
||||
}
|
||||
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol)
|
||||
{
|
||||
mGain = vol;
|
||||
mGain = vol;
|
||||
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here?
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here?
|
||||
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume");
|
||||
}
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume");
|
||||
}
|
||||
}
|
||||
// <DKO> Streamtitle display
|
||||
// virtual
|
||||
bool LLStreamingAudio_FMODSTUDIO::getNewMetadata(LLSD& metadata)
|
||||
{
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
if (mNewMetadata)
|
||||
{
|
||||
metadata = mMetadata;
|
||||
mNewMetadata = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return mNewMetadata;
|
||||
}
|
||||
if (mCurrentInternetStreamp)
|
||||
{
|
||||
if (mNewMetadata)
|
||||
{
|
||||
metadata = mMetadata;
|
||||
mNewMetadata = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return mNewMetadata;
|
||||
}
|
||||
|
||||
metadata = LLSD();
|
||||
return false;
|
||||
metadata = LLSD();
|
||||
return false;
|
||||
}
|
||||
// </DKO>
|
||||
///////////////////////////////////////////////////////
|
||||
// manager of possibly-multiple internet audio streams
|
||||
|
||||
LLAudioStreamManagerFMODSTUDIO::LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url) :
|
||||
mSystem(system),
|
||||
mChannelGroup(group),
|
||||
mStreamChannel(NULL),
|
||||
mInternetStream(NULL),
|
||||
mReady(false)
|
||||
mSystem(system),
|
||||
mChannelGroup(group),
|
||||
mStreamChannel(NULL),
|
||||
mInternetStream(NULL),
|
||||
mReady(false)
|
||||
{
|
||||
mInternetStreamURL = url;
|
||||
mInternetStreamURL = url;
|
||||
|
||||
FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream);
|
||||
FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream);
|
||||
|
||||
if (result!= FMOD_OK)
|
||||
{
|
||||
LL_WARNS() << "Couldn't open fmod stream, error "
|
||||
<< FMOD_ErrorString(result)
|
||||
<< LL_ENDL;
|
||||
mReady = false;
|
||||
return;
|
||||
}
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
LL_WARNS() << "Couldn't open fmod stream, error "
|
||||
<< FMOD_ErrorString(result)
|
||||
<< LL_ENDL;
|
||||
mReady = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mReady = true;
|
||||
mReady = true;
|
||||
}
|
||||
|
||||
FMOD::Channel *LLAudioStreamManagerFMODSTUDIO::startStream()
|
||||
{
|
||||
// We need a live and opened stream before we try and play it.
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (getOpenState(open_state) != FMOD_OK || open_state != FMOD_OPENSTATE_READY)
|
||||
{
|
||||
LL_WARNS() << "No internet stream to start playing!" << LL_ENDL;
|
||||
return NULL;
|
||||
}
|
||||
// We need a live and opened stream before we try and play it.
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (!mInternetStream || Check_FMOD_Error(getOpenState(open_state), "FMOD::Sound::getOpenState") || open_state != FMOD_OPENSTATE_READY)
|
||||
{
|
||||
LL_WARNS() << "No internet stream to start playing!" << LL_ENDL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mStreamChannel)
|
||||
return mStreamChannel; //Already have a channel for this stream.
|
||||
if (mStreamChannel)
|
||||
return mStreamChannel; //Already have a channel for this stream.
|
||||
|
||||
Check_FMOD_Error(mSystem->playSound(mInternetStream, mChannelGroup, true, &mStreamChannel), "FMOD::System::playSound");
|
||||
return mStreamChannel;
|
||||
Check_FMOD_Error(mSystem->playSound(mInternetStream, mChannelGroup, true, &mStreamChannel), "FMOD::System::playSound");
|
||||
return mStreamChannel;
|
||||
}
|
||||
|
||||
bool LLAudioStreamManagerFMODSTUDIO::stopStream()
|
||||
{
|
||||
if (mInternetStream)
|
||||
{
|
||||
bool close = true;
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (getOpenState(open_state) == FMOD_OK)
|
||||
{
|
||||
switch (open_state)
|
||||
{
|
||||
case FMOD_OPENSTATE_CONNECTING:
|
||||
close = false;
|
||||
break;
|
||||
default:
|
||||
close = true;
|
||||
}
|
||||
}
|
||||
if (mInternetStream)
|
||||
{
|
||||
bool close = true;
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (!Check_FMOD_Error(getOpenState(open_state), "FMOD::Sound::getOpenState"))
|
||||
{
|
||||
switch (open_state)
|
||||
{
|
||||
case FMOD_OPENSTATE_CONNECTING:
|
||||
close = false;
|
||||
break;
|
||||
default:
|
||||
close = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (close && mInternetStream->release() == FMOD_OK)
|
||||
{
|
||||
mStreamChannel = NULL;
|
||||
mInternetStream = NULL;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (close && !Check_FMOD_Error(mInternetStream->release(), "FMOD::Sound::release"))
|
||||
{
|
||||
mStreamChannel = NULL;
|
||||
mInternetStream = NULL;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
FMOD_RESULT LLAudioStreamManagerFMODSTUDIO::getOpenState(FMOD_OPENSTATE& state, unsigned int* percentbuffered, bool* starving, bool* diskbusy)
|
||||
{
|
||||
if (!mInternetStream)
|
||||
return FMOD_ERR_INVALID_HANDLE;
|
||||
FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
|
||||
Check_FMOD_Error(result, "FMOD::Sound::getOpenState");
|
||||
return result;
|
||||
if (!mInternetStream)
|
||||
return FMOD_ERR_INVALID_HANDLE;
|
||||
FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
|
||||
Check_FMOD_Error(result, "FMOD::Sound::getOpenState");
|
||||
return result;
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODSTUDIO::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)
|
||||
{
|
||||
Check_FMOD_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
|
||||
FMOD_ADVANCEDSETTINGS settings;
|
||||
memset(&settings,0,sizeof(settings));
|
||||
settings.cbSize=sizeof(settings);
|
||||
settings.defaultDecodeBufferSize = decodebuffertime;//ms
|
||||
Check_FMOD_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings");
|
||||
Check_FMOD_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
|
||||
FMOD_ADVANCEDSETTINGS settings;
|
||||
memset(&settings, 0, sizeof(settings));
|
||||
settings.cbSize = sizeof(settings);
|
||||
settings.defaultDecodeBufferSize = decodebuffertime;//ms
|
||||
Check_FMOD_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings");
|
||||
}
|
||||
|
||||
bool LLStreamingAudio_FMODSTUDIO::releaseDeadStreams()
|
||||
{
|
||||
// Kill dead internet streams, if possible
|
||||
std::list<LLAudioStreamManagerFMODSTUDIO *>::iterator iter;
|
||||
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
|
||||
{
|
||||
LLAudioStreamManagerFMODSTUDIO *streamp = *iter;
|
||||
if (streamp->stopStream())
|
||||
{
|
||||
LL_INFOS() << "Closed dead stream" << LL_ENDL;
|
||||
delete streamp;
|
||||
mDeadStreams.erase(iter++);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
// Kill dead internet streams, if possible
|
||||
std::list<LLAudioStreamManagerFMODSTUDIO *>::iterator iter;
|
||||
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
|
||||
{
|
||||
LLAudioStreamManagerFMODSTUDIO *streamp = *iter;
|
||||
if (streamp->stopStream())
|
||||
{
|
||||
LL_INFOS() << "Closed dead stream" << LL_ENDL;
|
||||
delete streamp;
|
||||
mDeadStreams.erase(iter++);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
return mDeadStreams.empty();
|
||||
return mDeadStreams.empty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
* @file streamingaudio_fmodstudio.h
|
||||
* @brief Definition of LLStreamingAudio_FMODSTUDIO implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
* Copyright (C) 2020, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -45,41 +45,41 @@ namespace FMOD
|
|||
//Interfaces
|
||||
class LLStreamingAudio_FMODSTUDIO : public LLStreamingAudioInterface
|
||||
{
|
||||
public:
|
||||
LLStreamingAudio_FMODSTUDIO(FMOD::System *system);
|
||||
/*virtual*/ ~LLStreamingAudio_FMODSTUDIO();
|
||||
public:
|
||||
LLStreamingAudio_FMODSTUDIO(FMOD::System *system);
|
||||
/*virtual*/ ~LLStreamingAudio_FMODSTUDIO();
|
||||
|
||||
/*virtual*/ void start(const std::string& url);
|
||||
/*virtual*/ void stop();
|
||||
/*virtual*/ void pause(S32 pause);
|
||||
/*virtual*/ void update();
|
||||
/*virtual*/ S32 isPlaying();
|
||||
/*virtual*/ void setGain(F32 vol);
|
||||
/*virtual*/ F32 getGain();
|
||||
/*virtual*/ std::string getURL();
|
||||
/*virtual*/ void start(const std::string& url);
|
||||
/*virtual*/ void stop();
|
||||
/*virtual*/ void pause(S32 pause);
|
||||
/*virtual*/ void update();
|
||||
/*virtual*/ S32 isPlaying();
|
||||
/*virtual*/ void setGain(F32 vol);
|
||||
/*virtual*/ F32 getGain();
|
||||
/*virtual*/ std::string getURL();
|
||||
|
||||
/*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
|
||||
/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
|
||||
//Streamtitle display DKO
|
||||
virtual bool getNewMetadata(LLSD& metadata);
|
||||
// DKO
|
||||
/*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
|
||||
/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
|
||||
//Streamtitle display DKO
|
||||
virtual bool getNewMetadata(LLSD& metadata);
|
||||
// DKO
|
||||
private:
|
||||
bool releaseDeadStreams();
|
||||
bool releaseDeadStreams();
|
||||
|
||||
FMOD::System *mSystem;
|
||||
FMOD::System *mSystem;
|
||||
|
||||
LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp;
|
||||
FMOD::ChannelGroup* mStreamGroup;
|
||||
FMOD::Channel *mFMODInternetStreamChannelp;
|
||||
std::list<LLAudioStreamManagerFMODSTUDIO *> mDeadStreams;
|
||||
LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp;
|
||||
FMOD::ChannelGroup* mStreamGroup;
|
||||
FMOD::Channel *mFMODInternetStreamChannelp;
|
||||
std::list<LLAudioStreamManagerFMODSTUDIO *> mDeadStreams;
|
||||
|
||||
std::string mURL;
|
||||
std::string mPendingURL;
|
||||
F32 mGain;
|
||||
// <DKO> Streamtitle display
|
||||
bool mNewMetadata;
|
||||
LLSD mMetadata;
|
||||
// </DKO> Streamtitle display
|
||||
std::string mURL;
|
||||
std::string mPendingURL;
|
||||
F32 mGain;
|
||||
// <DKO> Streamtitle display
|
||||
bool mNewMetadata;
|
||||
LLSD mMetadata;
|
||||
// </DKO> Streamtitle display
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -659,7 +659,8 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, const LLFontGL* font, L
|
|||
// <FS> FIRE-8257: Sometimes text is cut off on left side of console
|
||||
else
|
||||
{
|
||||
break;
|
||||
mLines.push_back(Line());
|
||||
skip_chars = 1;
|
||||
}
|
||||
// </FS>
|
||||
paragraph_offset += (drawable + skip_chars);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ LLSpellChecker::LLSpellChecker()
|
|||
: mHunspell(NULL)
|
||||
{
|
||||
// Load initial dictionary information
|
||||
refreshDictionaryMap();
|
||||
//refreshDictionaryMap(); // <FS:Ansariel> FIRE-29649: Crash when opening spellcheck settings
|
||||
}
|
||||
|
||||
LLSpellChecker::~LLSpellChecker()
|
||||
|
|
@ -58,6 +58,14 @@ LLSpellChecker::~LLSpellChecker()
|
|||
delete mHunspell;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> FIRE-29649: Crash when opening spellcheck settings
|
||||
void LLSpellChecker::initSingleton()
|
||||
{
|
||||
// Load initial dictionary information
|
||||
refreshDictionaryMap();
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
bool LLSpellChecker::checkSpelling(const std::string& word) const
|
||||
{
|
||||
if ( (!mHunspell) || (word.length() < 3) || (0 != mHunspell->spell(word.c_str())) )
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public:
|
|||
protected:
|
||||
void addToDictFile(const std::string& dict_path, const std::string& word);
|
||||
void initHunspell(const std::string& dict_language);
|
||||
void initSingleton(); // <FS:Ansariel> FIRE-29649: Crash when opening spellcheck settings
|
||||
|
||||
public:
|
||||
typedef std::list<std::string> dict_list_t;
|
||||
|
|
|
|||
|
|
@ -120,9 +120,6 @@ MediaPluginBase(host_send_func, host_user_data)
|
|||
mPluginsEnabled = false;
|
||||
mJavascriptEnabled = true;
|
||||
mDisableGPU = false;
|
||||
#ifdef LL_LINUX // <FS:ND> Do not use GPU on Linux, using GPU messes with some window managers (https://bitbucket.org/NickyD/phoenix-firestorm-lgpl-linux/commits/14c936db5a02cf0f3ff24eb7f1c92136#comment-6048984)
|
||||
mDisableGPU = true;
|
||||
#endif
|
||||
mUserAgentSubtring = "";
|
||||
mAuthUsername = "";
|
||||
mAuthPassword = "";
|
||||
|
|
@ -519,7 +516,13 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
settings.flip_mouse_y = false;
|
||||
settings.flip_pixels_y = true;
|
||||
settings.frame_rate = 60;
|
||||
settings.force_wave_audio = true;
|
||||
|
||||
// <FS:ND> With the latest CEF this does more worse than good. It will allow the viewer to control the audio level (apparently); But it will also break a lot of sites (among then twitch, netflix, spotify).
|
||||
// Right now with the choice between lots of broken sites or volumes for me it's rather the sites being usable.
|
||||
// settings.force_wave_audio = true;
|
||||
settings.force_wave_audio = false;
|
||||
// </FS:ND>
|
||||
|
||||
settings.initial_height = 1024;
|
||||
settings.initial_width = 1024;
|
||||
settings.java_enabled = false;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ include(DirectX)
|
|||
include(DragDrop)
|
||||
include(EXPAT)
|
||||
include(FMODSTUDIO)
|
||||
include(FMODEX)
|
||||
include(GLOD)
|
||||
include(Hunspell)
|
||||
include(JsonCpp)
|
||||
|
|
@ -79,10 +78,6 @@ if(FMODSTUDIO)
|
|||
include_directories(${FMODSTUDIO_INCLUDE_DIR})
|
||||
endif(FMODSTUDIO)
|
||||
|
||||
if(FMODEX)
|
||||
include_directories(${FMODEX_INCLUDE_DIR})
|
||||
endif(FMODEX)
|
||||
|
||||
include_directories(
|
||||
${DBUSGLIB_INCLUDE_DIRS}
|
||||
${JSONCPP_INCLUDE_DIR}
|
||||
|
|
@ -2131,15 +2126,11 @@ if (FMODSTUDIO)
|
|||
set(FMODWRAPPER_LIBRARY ${FMODSTUDIO_LIBRARY})
|
||||
endif (FMODSTUDIO)
|
||||
|
||||
if (FMODEX)
|
||||
set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX")
|
||||
set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY})
|
||||
endif (FMODEX)
|
||||
|
||||
# <FS:Ansariel> Output device selection
|
||||
# set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
|
||||
set_source_files_properties(llstartup.cpp llfloaterpreference.cpp llfloaterabout.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
|
||||
set_source_files_properties(llstartup.cpp llfloaterpreference.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
|
||||
# </FS:Ansariel>
|
||||
set_source_files_properties(llprogressview.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
|
||||
|
||||
list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES})
|
||||
|
||||
|
|
@ -2177,12 +2168,6 @@ else (OPENSIM)
|
|||
set(ND_VIEWER_FLAVOR "hvk")
|
||||
endif (OPENSIM)
|
||||
|
||||
if (FMODSTUDIO)
|
||||
set(FMODVERSION "fmodstudio")
|
||||
elseif (FMODEX)
|
||||
set(FMODVERSION "fmodex")
|
||||
endif (FMODSTUDIO)
|
||||
|
||||
if (WINDOWS)
|
||||
set_target_properties(${VIEWER_BINARY_NAME}
|
||||
PROPERTIES
|
||||
|
|
@ -2267,19 +2252,11 @@ if (WINDOWS)
|
|||
|
||||
if (FMODSTUDIO)
|
||||
list(APPEND COPY_INPUT_DEPENDENCIES
|
||||
${SHARED_LIB_STAGING_DIR}/Release/fmod.dll
|
||||
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll
|
||||
${SHARED_LIB_STAGING_DIR}/Debug/fmodL.dll
|
||||
)
|
||||
endif (FMODSTUDIO)
|
||||
|
||||
if (FMODEX)
|
||||
list(APPEND COPY_INPUT_DEPENDENCIES
|
||||
${SHARED_LIB_STAGING_DIR}/Release/fmodex.dll
|
||||
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmodex.dll
|
||||
${SHARED_LIB_STAGING_DIR}/Debug/fmodexL.dll
|
||||
${SHARED_LIB_STAGING_DIR}/Release/fmod.dll
|
||||
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll
|
||||
${SHARED_LIB_STAGING_DIR}/Debug/fmodL.dll
|
||||
)
|
||||
endif (FMODEX)
|
||||
endif (FMODSTUDIO)
|
||||
|
||||
if (OPENAL)
|
||||
list(APPEND COPY_INPUT_DEPENDENCIES
|
||||
|
|
@ -2297,6 +2274,7 @@ if (WINDOWS)
|
|||
--arch=${ARCH}
|
||||
--artwork=${ARTWORK_DIR}
|
||||
"--bugsplat=${BUGSPLAT_DB}"
|
||||
"--fmodstudio=${FMODSTUDIO}"
|
||||
"--openal=${OPENAL}"
|
||||
--build=${CMAKE_CURRENT_BINARY_DIR}
|
||||
--buildtype=${CMAKE_BUILD_TYPE}
|
||||
|
|
@ -2308,7 +2286,6 @@ if (WINDOWS)
|
|||
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat
|
||||
--versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
|
||||
--viewer_flavor=${ND_VIEWER_FLAVOR}
|
||||
--fmodversion=${FMODVERSION}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
|
||||
stage_third_party_libs
|
||||
|
|
@ -2361,6 +2338,7 @@ if (WINDOWS)
|
|||
--arch=${ARCH}
|
||||
--artwork=${ARTWORK_DIR}
|
||||
"--bugsplat=${BUGSPLAT_DB}"
|
||||
"--fmodstudio=${FMODSTUDIO}"
|
||||
"--openal=${OPENAL}"
|
||||
--build=${CMAKE_CURRENT_BINARY_DIR}
|
||||
--buildtype=${CMAKE_BUILD_TYPE}
|
||||
|
|
@ -2372,7 +2350,6 @@ if (WINDOWS)
|
|||
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat
|
||||
--versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
|
||||
--viewer_flavor=${ND_VIEWER_FLAVOR}
|
||||
--fmodversion=${FMODVERSION}
|
||||
DEPENDS
|
||||
${VIEWER_BINARY_NAME}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
|
||||
|
|
@ -2534,6 +2511,7 @@ endif (NOT ENABLE_MEDIA_PLUGINS)
|
|||
--arch=${ARCH}
|
||||
--artwork=${ARTWORK_DIR}
|
||||
"--bugsplat=${BUGSPLAT_DB}"
|
||||
"--fmodstudio=${FMODSTUDIO}"
|
||||
"--openal=${OPENAL}"
|
||||
--build=${CMAKE_CURRENT_BINARY_DIR}
|
||||
--buildtype=${CMAKE_BUILD_TYPE}
|
||||
|
|
@ -2545,7 +2523,6 @@ endif (NOT ENABLE_MEDIA_PLUGINS)
|
|||
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched
|
||||
--versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
|
||||
--viewer_flavor=${ND_VIEWER_FLAVOR}
|
||||
--fmodversion=${FMODVERSION}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
|
||||
${COPY_INPUT_DEPENDENCIES}
|
||||
|
|
@ -2561,6 +2538,7 @@ endif (NOT ENABLE_MEDIA_PLUGINS)
|
|||
--arch=${ARCH}
|
||||
--artwork=${ARTWORK_DIR}
|
||||
"--bugsplat=${BUGSPLAT_DB}"
|
||||
"--fmodstudio=${FMODSTUDIO}"
|
||||
"--openal=${OPENAL}"
|
||||
--build=${CMAKE_CURRENT_BINARY_DIR}
|
||||
--buildtype=${CMAKE_BUILD_TYPE}
|
||||
|
|
@ -2571,7 +2549,6 @@ endif (NOT ENABLE_MEDIA_PLUGINS)
|
|||
--source=${CMAKE_CURRENT_SOURCE_DIR}
|
||||
--versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
|
||||
--viewer_flavor=${ND_VIEWER_FLAVOR}
|
||||
--fmodversion=${FMODVERSION}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
|
||||
${COPY_INPUT_DEPENDENCIES}
|
||||
|
|
@ -2645,6 +2622,7 @@ if (DARWIN)
|
|||
--arch=${ARCH}
|
||||
--artwork=${ARTWORK_DIR}
|
||||
"--bugsplat=${BUGSPLAT_DB}"
|
||||
"--fmodstudio=${FMODSTUDIO}"
|
||||
"--openal=${OPENAL}"
|
||||
--build=${CMAKE_CURRENT_BINARY_DIR}
|
||||
--buildtype=${CMAKE_BUILD_TYPE}
|
||||
|
|
@ -2656,7 +2634,6 @@ if (DARWIN)
|
|||
--source=${CMAKE_CURRENT_SOURCE_DIR}
|
||||
--versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
|
||||
--viewer_flavor=${ND_VIEWER_FLAVOR}
|
||||
--fmodversion=${FMODVERSION}
|
||||
DEPENDS
|
||||
${VIEWER_BINARY_NAME}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
|
||||
|
|
@ -2682,6 +2659,7 @@ if (DARWIN)
|
|||
--arch=${ARCH}
|
||||
--artwork=${ARTWORK_DIR}
|
||||
"--bugsplat=${BUGSPLAT_DB}"
|
||||
"--fmodstudio=${FMODSTUDIO}"
|
||||
"--openal=${OPENAL}"
|
||||
--build=${CMAKE_CURRENT_BINARY_DIR}
|
||||
--buildtype=${CMAKE_BUILD_TYPE}
|
||||
|
|
@ -2693,7 +2671,6 @@ if (DARWIN)
|
|||
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched
|
||||
--versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
|
||||
--viewer_flavor=${ND_VIEWER_FLAVOR}
|
||||
--fmodversion=${FMODVERSION}
|
||||
${SIGNING_SETTING}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
6.4.3
|
||||
6.4.4
|
||||
|
|
|
|||
|
|
@ -131,12 +131,6 @@ void FloaterAO::updateList()
|
|||
mReloadButton->setEnabled(TRUE);
|
||||
mImportRunning = FALSE;
|
||||
|
||||
std::string currentSetName = mSetSelector->getSelectedItemLabel();
|
||||
if (currentSetName.empty())
|
||||
{
|
||||
currentSetName = AOEngine::instance().getCurrentSetName();
|
||||
}
|
||||
|
||||
// Lambda provides simple Alpha sorting, note this is case sensitive.
|
||||
auto sortRuleLambda = [](const AOSet* s1, const AOSet* s2) -> bool
|
||||
{
|
||||
|
|
@ -146,6 +140,9 @@ void FloaterAO::updateList()
|
|||
mSetList=AOEngine::instance().getSetList();
|
||||
std::sort(mSetList.begin(), mSetList.end(), sortRuleLambda);
|
||||
|
||||
// remember currently selected animation set name
|
||||
std::string currentSetName = mSetSelector->getSelectedItemLabel();
|
||||
|
||||
mSetSelector->removeall();
|
||||
mSetSelectorSmall->removeall();
|
||||
mSetSelector->clear();
|
||||
|
|
@ -166,6 +163,21 @@ void FloaterAO::updateList()
|
|||
return;
|
||||
}
|
||||
|
||||
// make sure we have an animation set name to display
|
||||
if (currentSetName.empty())
|
||||
{
|
||||
// selected animation set was empty, get the currently active animation set from the engine
|
||||
currentSetName = AOEngine::instance().getCurrentSetName();
|
||||
LL_DEBUGS("AOEngine") << "Current set name was empty, fetched name \"" << currentSetName << "\" from AOEngine" << LL_ENDL;
|
||||
|
||||
if(currentSetName.empty())
|
||||
{
|
||||
// selected animation set was empty, get the name of the first animation set in the list
|
||||
currentSetName = mSetList[0]->getName();
|
||||
LL_DEBUGS("AOEngine") << "Current set name still empty, fetched first set's name \"" << currentSetName << "\"" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
for (U32 index = 0; index < mSetList.size(); ++index)
|
||||
{
|
||||
std::string setName = mSetList[index]->getName();
|
||||
|
|
|
|||
|
|
@ -16417,17 +16417,6 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>HUDScaleFactor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Scale of HUD attachments</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>UIScaleFactor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -20647,7 +20636,7 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>FMODProfilerEnable</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable profiler tool if using FMOD</string>
|
||||
<string>Enable profiler tool if using FMOD Studio</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -20658,7 +20647,7 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>FMODDecodeBufferSize</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Sets the streaming decode buffer size (in milliseconds)</string>
|
||||
<string>Sets the streaming decode buffer size (in milliseconds) for FMOD Studio</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -20669,7 +20658,7 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>FMODStreamBufferSize</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Sets the streaming buffer size (in milliseconds)</string>
|
||||
<string>Sets the streaming buffer size (in milliseconds) for FMOD Studio</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -20680,7 +20669,7 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>FMODResampleMethod</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Sets the method used for internal resampler 0(Linear), 1(Cubic), 2(Spline)</string>
|
||||
<string>Sets the method used for internal resampler 0(Linear), 1(Cubic), 2(Spline) for FMOD Studio</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
|
|||
|
|
@ -81,6 +81,18 @@ const F32 MIN_DISTANCE_MOVED = 1.0f;
|
|||
const F32 REQUEST_TIMEOUT = 30.0f;
|
||||
|
||||
|
||||
F32 calculateObjectDistance(LLVector3d agent_pos, LLViewerObject* object)
|
||||
{
|
||||
if (object->isHUDAttachment())
|
||||
{
|
||||
return 0.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dist_vec(agent_pos, object->getPositionGlobal());
|
||||
}
|
||||
}
|
||||
|
||||
class FSAreaSearch::FSParcelChangeObserver : public LLParcelObserver
|
||||
{
|
||||
public:
|
||||
|
|
@ -624,8 +636,8 @@ void FSAreaSearch::requestObjectProperties(const std::vector<U32>& request_list,
|
|||
msg->newMessageFast(_PREHASH_ObjectDeselect);
|
||||
}
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
|
||||
select_count++;
|
||||
start_new_message = false;
|
||||
}
|
||||
|
|
@ -777,7 +789,7 @@ void FSAreaSearch::matchObject(FSObjectProperties& details, LLViewerObject* obje
|
|||
|
||||
if (mFilterDistance)
|
||||
{
|
||||
S32 distance = dist_vec(mPanelList->getAgentLastPosition(), objectp->getPositionGlobal());// used mAgentLastPosition instead of gAgent->getPositionGlobal for performace
|
||||
S32 distance = (S32)calculateObjectDistance(mPanelList->getAgentLastPosition(), objectp);// used mAgentLastPosition instead of gAgent->getPositionGlobal for performace
|
||||
if (!(distance >= mFilterDistanceMin && distance <= mFilterDistanceMax))
|
||||
{
|
||||
return;
|
||||
|
|
@ -989,7 +1001,7 @@ void FSAreaSearch::matchObject(FSObjectProperties& details, LLViewerObject* obje
|
|||
row_params.value = object_id.asString();
|
||||
|
||||
cell_params.column = "distance";
|
||||
cell_params.value = llformat("%1.0f m", dist_vec(mPanelList->getAgentLastPosition(), objectp->getPositionGlobal())); // used mAgentLastPosition instead of gAgent->getPositionGlobal for performace
|
||||
cell_params.value = llformat("%1.0f m", calculateObjectDistance(mPanelList->getAgentLastPosition(), objectp)); // used mAgentLastPosition instead of gAgent->getPositionGlobal for performace
|
||||
row_params.columns.add(cell_params);
|
||||
|
||||
cell_params.column = "name";
|
||||
|
|
@ -1471,7 +1483,7 @@ void FSPanelAreaSearchList::updateScrollList()
|
|||
{
|
||||
if (agent_moved && distance_column)
|
||||
{
|
||||
item->getColumn(distance_column->mIndex)->setValue(LLSD(llformat("%1.0f m", dist_vec(current_agent_position, objectp->getPositionGlobal()))));
|
||||
item->getColumn(distance_column->mIndex)->setValue(LLSD(llformat("%1.0f m", calculateObjectDistance(current_agent_position, objectp))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1614,7 +1626,7 @@ bool FSPanelAreaSearchList::onContextMenuItemEnable(const LLSD& userdata)
|
|||
{
|
||||
LLUUID object_id = mResultList->getFirstSelected()->getUUID();
|
||||
LLViewerObject* objectp = gObjectList.findObject(object_id);
|
||||
return (objectp && dist_vec_squared(gAgent.getPositionGlobal(), objectp->getPositionGlobal()) < gAgentCamera.mDrawDistance * gAgentCamera.mDrawDistance);
|
||||
return (objectp && calculateObjectDistance(gAgent.getPositionGlobal(), objectp) < gAgentCamera.mDrawDistance);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1978,8 +1990,8 @@ void FSPanelAreaSearchList::sitOnObject(FSObjectProperties& details, LLViewerObj
|
|||
{
|
||||
gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
|
||||
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
|
||||
gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_TargetID, objectp->mID);
|
||||
gMessageSystem->addVector3Fast(_PREHASH_Offset, LLVector3::zero);
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ FSFloaterSearch::~FSFloaterSearch()
|
|||
{
|
||||
delete mRemoteParcelObserver;
|
||||
delete mAvatarPropertiesObserver;
|
||||
gGenericDispatcher.addHandler("classifiedclickthrough", NULL);
|
||||
gGenericDispatcher.addHandler("classifiedclickthrough", nullptr);
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
@ -314,17 +314,13 @@ BOOL FSFloaterSearch::postBuild()
|
|||
mDetailSnapshot = getChild<LLTextureCtrl>("snapshot");
|
||||
mDetailMaturity = getChild<LLIconCtrl>("maturity_icon");
|
||||
mTabContainer = getChild<LLTabContainer>("ls_tabs");
|
||||
if (mTabContainer)
|
||||
{
|
||||
mTabContainer->setCommitCallback(boost::bind(&FSFloaterSearch::onTabChange, this));
|
||||
}
|
||||
|
||||
mTabContainer->setCommitCallback(boost::bind(&FSFloaterSearch::onTabChange, this));
|
||||
|
||||
flushDetails();
|
||||
|
||||
if (mDetailsPanel)
|
||||
{
|
||||
mDetailsPanel->setVisible(false);
|
||||
}
|
||||
mDetailsPanel->setVisible(false);
|
||||
|
||||
mHasSelection = false;
|
||||
|
||||
if (!mTabContainer->selectTab(gSavedSettings.getS32("FSLastSearchTab")))
|
||||
|
|
@ -344,7 +340,7 @@ void FSFloaterSearch::onTabChange()
|
|||
mDetailsPanel->setVisible(false);
|
||||
mPanelWeb->resetFocusOnLoad();
|
||||
}
|
||||
// <KC> If on legacy preople search and skin uses full profile preview, hide preview panel
|
||||
// <KC> If on legacy people search and skin uses full profile preview, hide preview panel
|
||||
else if (active_panel == mPanelPeople && mPanelProfile)
|
||||
{
|
||||
mDetailsPanel->setVisible(false);
|
||||
|
|
@ -356,16 +352,17 @@ void FSFloaterSearch::onTabChange()
|
|||
}
|
||||
|
||||
//static
|
||||
LLPanel* FSFloaterSearch::getSearchPanel(std::string panel_name)
|
||||
template <class T>
|
||||
T* FSFloaterSearch::getSearchPanel(const std::string& panel_name)
|
||||
{
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::getTypedInstance<FSFloaterSearch>("search");
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
|
||||
if (search_instance && search_instance->mTabContainer)
|
||||
{
|
||||
return search_instance->mTabContainer->getPanelByName(panel_name);
|
||||
return dynamic_cast<T*>(search_instance->mTabContainer->getPanelByName(panel_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -452,7 +449,7 @@ void FSFloaterSearch::displayParcelDetails(const LLParcelData& parcel_data)
|
|||
map["LOCATION"] = llformat("%s (%d, %d, %d)", parcel_data.sim_name.c_str(), region_x, region_y, region_z);
|
||||
|
||||
mParcelGlobal = LLVector3d(parcel_data.global_x, parcel_data.global_y, parcel_data.global_z);
|
||||
mDetailsPanel->setVisible(true);
|
||||
mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_places" || mTabContainer->getCurrentPanel()->getName() == "panel_ls_land");
|
||||
mHasSelection = true;
|
||||
mDetailMaturity->setVisible(true);
|
||||
mDetailTitle->setValue(parcel_data.name);
|
||||
|
|
@ -478,7 +475,7 @@ void FSFloaterSearch::displayAvatarDetails(LLAvatarData*& avatar_data)
|
|||
mDetailAux2->setValue(getString("string.partner", map));
|
||||
}
|
||||
|
||||
mDetailsPanel->setVisible(true);
|
||||
mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_people");
|
||||
mHasSelection = true;
|
||||
mDetailTitle->setValue(LLTrans::getString("LoadingData"));
|
||||
mDetailDesc->setValue(avatar_data->about_text);
|
||||
|
|
@ -500,7 +497,7 @@ void FSFloaterSearch::displayGroupDetails(LLGroupMgrGroupData*& group_data)
|
|||
map["MEMBER_COUNT"] = llformat("%d",group_data->mMemberCount);
|
||||
map["FOUNDER"] = LLSLURL("agent", group_data->mFounderID, "inspect").getSLURLString();
|
||||
|
||||
mDetailsPanel->setVisible(true);
|
||||
mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_groups");
|
||||
mHasSelection = true;
|
||||
mDetailTitle->setValue(LLTrans::getString("LoadingData"));
|
||||
mDetailDesc->setValue(group_data->mCharter);
|
||||
|
|
@ -536,7 +533,7 @@ void FSFloaterSearch::displayClassifiedDetails(LLAvatarClassifiedInfo*& c_info)
|
|||
map["LISTING_PRICE"] = llformat("L$%d", c_info->price_for_listing);
|
||||
map["SLURL"] = LLSLURL("parcel", c_info->parcel_id, "about").getSLURLString();
|
||||
|
||||
mDetailsPanel->setVisible(true);
|
||||
mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_groupspanel_ls_classifieds");
|
||||
mHasSelection = true;
|
||||
mDetailMaturity->setVisible(true);
|
||||
mParcelGlobal = c_info->pos_global;
|
||||
|
|
@ -583,7 +580,7 @@ void FSFloaterSearch::displayEventDetails(U32 eventId, F64 eventEpoch, const std
|
|||
|
||||
mParcelGlobal = eventGlobalPos;
|
||||
mEventID = eventId;
|
||||
mDetailsPanel->setVisible(true);
|
||||
mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_events");
|
||||
mHasSelection = true;
|
||||
mDetailMaturity->setVisible(true);
|
||||
mDetailTitle->setValue(eventName);
|
||||
|
|
@ -728,7 +725,7 @@ void FSFloaterSearch::onBtnEventReminder()
|
|||
static LLPanelInjector<FSPanelSearchPeople> t_panel_fs_search_people("panel_ls_people");
|
||||
|
||||
FSPanelSearchPeople::FSPanelSearchPeople() : FSSearchPanelBase()
|
||||
, mQueryID(NULL)
|
||||
, mQueryID(nullptr)
|
||||
, mStartSearch(0)
|
||||
, mResultsReceived(0)
|
||||
, mResultsContent()
|
||||
|
|
@ -863,9 +860,11 @@ void FSPanelSearchPeople::onSelectItem()
|
|||
{
|
||||
return;
|
||||
}
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::getTypedInstance<FSFloaterSearch>("search");
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
|
||||
if (search_instance)
|
||||
{
|
||||
search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_AVATAR);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -886,10 +885,10 @@ void FSPanelSearchPeople::processSearchReply(LLMessageSystem* msg, void**)
|
|||
}
|
||||
LL_DEBUGS("Search") << "received search results - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
|
||||
|
||||
FSPanelSearchPeople* self = (FSPanelSearchPeople*)FSFloaterSearch::getSearchPanel("panel_ls_people");
|
||||
FSPanelSearchPeople* self = FSFloaterSearch::getSearchPanel<FSPanelSearchPeople>("panel_ls_people");
|
||||
|
||||
// floater is closed or these are not results from our last request
|
||||
if (NULL == self || query_id != self->getQueryID())
|
||||
if (!self || query_id != self->getQueryID())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -914,7 +913,7 @@ void FSPanelSearchPeople::processSearchReply(LLMessageSystem* msg, void**)
|
|||
search_results->setCommentText(LLTrans::getString("not_found", map));
|
||||
return;
|
||||
}
|
||||
else if(status & STATUS_SEARCH_PLACES_SHORTSTRING)
|
||||
else if (status & STATUS_SEARCH_PLACES_SHORTSTRING)
|
||||
{
|
||||
search_results->setEnabled(FALSE);
|
||||
search_results->setCommentText(LLTrans::getString("search_short"));
|
||||
|
|
@ -1004,7 +1003,7 @@ void FSPanelSearchPeople::processSearchReply(LLMessageSystem* msg, void**)
|
|||
static LLPanelInjector<FSPanelSearchGroups> t_panel_fs_search_groups("panel_ls_groups");
|
||||
|
||||
FSPanelSearchGroups::FSPanelSearchGroups() : FSSearchPanelBase()
|
||||
, mQueryID(NULL)
|
||||
, mQueryID(nullptr)
|
||||
, mStartSearch(0)
|
||||
, mResultsReceived(0)
|
||||
, mResultsContent()
|
||||
|
|
@ -1114,7 +1113,7 @@ void FSPanelSearchGroups::find()
|
|||
void FSPanelSearchGroups::onBtnFind()
|
||||
{
|
||||
std::string text = mSearchComboBox->getSimple();
|
||||
if(!text.empty())
|
||||
if (!text.empty())
|
||||
{
|
||||
LLSearchHistory::getInstance()->addEntry(text);
|
||||
}
|
||||
|
|
@ -1164,7 +1163,7 @@ void FSPanelSearchGroups::onSelectItem()
|
|||
{
|
||||
return;
|
||||
}
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::getTypedInstance<FSFloaterSearch>("search");
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
|
||||
if (search_instance)
|
||||
{
|
||||
search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_GROUP);
|
||||
|
|
@ -1191,10 +1190,10 @@ void FSPanelSearchGroups::processSearchReply(LLMessageSystem* msg, void**)
|
|||
}
|
||||
LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
|
||||
|
||||
FSPanelSearchGroups* self = (FSPanelSearchGroups*)FSFloaterSearch::getSearchPanel("panel_ls_groups");
|
||||
FSPanelSearchGroups* self = FSFloaterSearch::getSearchPanel<FSPanelSearchGroups>("panel_ls_groups");
|
||||
|
||||
// floater is closed or these are not results from our last request
|
||||
if (NULL == self || query_id != self->mQueryID)
|
||||
if (!self || query_id != self->mQueryID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1312,7 +1311,7 @@ void FSPanelSearchGroups::processSearchReply(LLMessageSystem* msg, void**)
|
|||
static LLPanelInjector<FSPanelSearchPlaces> t_panel_fs_search_places("panel_ls_places");
|
||||
|
||||
FSPanelSearchPlaces::FSPanelSearchPlaces() : FSSearchPanelBase()
|
||||
, mQueryID(NULL)
|
||||
, mQueryID(nullptr)
|
||||
, mStartSearch(0)
|
||||
, mResultsReceived(0)
|
||||
, mResultsContent()
|
||||
|
|
@ -1496,7 +1495,7 @@ void FSPanelSearchPlaces::onSelectItem()
|
|||
{
|
||||
return;
|
||||
}
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::getTypedInstance<FSFloaterSearch>("search");
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
|
||||
if (search_instance)
|
||||
{
|
||||
search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_PLACE);
|
||||
|
|
@ -1524,10 +1523,10 @@ void FSPanelSearchPlaces::processSearchReply(LLMessageSystem* msg, void**)
|
|||
}
|
||||
LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
|
||||
|
||||
FSPanelSearchPlaces* self = (FSPanelSearchPlaces*)FSFloaterSearch::getSearchPanel("panel_ls_places");
|
||||
FSPanelSearchPlaces* self = FSFloaterSearch::getSearchPanel<FSPanelSearchPlaces>("panel_ls_places");
|
||||
|
||||
// floater is closed or these are not results from our last request
|
||||
if (NULL == self || query_id != self->getQueryID())
|
||||
if (!self || query_id != self->getQueryID())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1665,7 +1664,7 @@ void FSPanelSearchPlaces::processSearchReply(LLMessageSystem* msg, void**)
|
|||
static LLPanelInjector<FSPanelSearchLand> t_panel_fs_search_land("panel_ls_land");
|
||||
|
||||
FSPanelSearchLand::FSPanelSearchLand() : FSSearchPanelBase()
|
||||
, mQueryID(NULL)
|
||||
, mQueryID(nullptr)
|
||||
, mStartSearch(0)
|
||||
, mResultsReceived(0)
|
||||
, mResultsContent()
|
||||
|
|
@ -1875,7 +1874,7 @@ void FSPanelSearchLand::onSelectItem()
|
|||
{
|
||||
return;
|
||||
}
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::getTypedInstance<FSFloaterSearch>("search");
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
|
||||
if (search_instance)
|
||||
{
|
||||
search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_PLACE);
|
||||
|
|
@ -1906,10 +1905,10 @@ void FSPanelSearchLand::processSearchReply(LLMessageSystem* msg, void**)
|
|||
}
|
||||
LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
|
||||
|
||||
FSPanelSearchLand* self = (FSPanelSearchLand*)FSFloaterSearch::getSearchPanel("panel_ls_land");
|
||||
FSPanelSearchLand* self = FSFloaterSearch::getSearchPanel<FSPanelSearchLand>("panel_ls_land");
|
||||
|
||||
// floater is closed or these are not results from our last request
|
||||
if (NULL == self || query_id != self->mQueryID)
|
||||
if (!self || query_id != self->mQueryID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1957,7 +1956,7 @@ void FSPanelSearchLand::processSearchReply(LLMessageSystem* msg, void**)
|
|||
LL_DEBUGS("Search") << "Got: " << name << " ClassifiedID: " << parcel_id << LL_ENDL;
|
||||
search_results->setEnabled(TRUE);
|
||||
found_one = true;
|
||||
if ( msg->getSizeFast(_PREHASH_QueryReplies, i, _PREHASH_ProductSKU) > 0 )
|
||||
if (msg->getSizeFast(_PREHASH_QueryReplies, i, _PREHASH_ProductSKU) > 0)
|
||||
{
|
||||
msg->getStringFast( _PREHASH_QueryReplies, _PREHASH_ProductSKU, land_sku, i);
|
||||
land_type = LLProductInfoRequestManager::instance().getDescriptionForSku(land_sku);
|
||||
|
|
@ -2064,7 +2063,7 @@ void FSPanelSearchLand::processSearchReply(LLMessageSystem* msg, void**)
|
|||
static LLPanelInjector<FSPanelSearchClassifieds> t_panel_fs_search_classifieds("panel_ls_classifieds");
|
||||
|
||||
FSPanelSearchClassifieds::FSPanelSearchClassifieds() : FSSearchPanelBase()
|
||||
, mQueryID(NULL)
|
||||
, mQueryID(nullptr)
|
||||
, mStartSearch(0)
|
||||
, mResultsReceived(0)
|
||||
, mResultsContent()
|
||||
|
|
@ -2173,7 +2172,7 @@ void FSPanelSearchClassifieds::find()
|
|||
void FSPanelSearchClassifieds::onBtnFind()
|
||||
{
|
||||
std::string text = mSearchComboBox->getSimple();
|
||||
if(!text.empty())
|
||||
if (!text.empty())
|
||||
{
|
||||
LLSearchHistory::getInstance()->addEntry(text);
|
||||
}
|
||||
|
|
@ -2223,7 +2222,7 @@ void FSPanelSearchClassifieds::onSelectItem()
|
|||
{
|
||||
return;
|
||||
}
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::getTypedInstance<FSFloaterSearch>("search");
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
|
||||
if (search_instance)
|
||||
{
|
||||
search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_CLASSIFIED);
|
||||
|
|
@ -2251,7 +2250,7 @@ void FSPanelSearchClassifieds::processSearchReply(LLMessageSystem* msg, void**)
|
|||
}
|
||||
LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
|
||||
|
||||
FSPanelSearchClassifieds* self = (FSPanelSearchClassifieds*)FSFloaterSearch::getSearchPanel("panel_ls_classifieds");
|
||||
FSPanelSearchClassifieds* self = FSFloaterSearch::getSearchPanel<FSPanelSearchClassifieds>("panel_ls_classifieds");
|
||||
|
||||
if (msg->getNumberOfBlocks("StatusData"))
|
||||
{
|
||||
|
|
@ -2264,7 +2263,7 @@ void FSPanelSearchClassifieds::processSearchReply(LLMessageSystem* msg, void**)
|
|||
}
|
||||
|
||||
// floater is closed or these are not results from our last request
|
||||
if (NULL == self || query_id != self->mQueryID)
|
||||
if (!self || query_id != self->mQueryID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -2379,7 +2378,7 @@ void FSPanelSearchClassifieds::processSearchReply(LLMessageSystem* msg, void**)
|
|||
static LLPanelInjector<FSPanelSearchEvents> t_panel_fs_search_events("panel_ls_events");
|
||||
|
||||
FSPanelSearchEvents::FSPanelSearchEvents() : FSSearchPanelBase()
|
||||
, mQueryID(NULL)
|
||||
, mQueryID(nullptr)
|
||||
, mResultsReceived(0)
|
||||
, mStartSearch(0)
|
||||
, mDay(0)
|
||||
|
|
@ -2617,7 +2616,7 @@ void FSPanelSearchEvents::onSelectItem()
|
|||
return;
|
||||
}
|
||||
S32 event_id = mSearchResults->getSelectedValue();
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::getTypedInstance<FSFloaterSearch>("search");
|
||||
FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
|
||||
if (search_instance)
|
||||
{
|
||||
search_instance->FSFloaterSearch::onSelectedEvent(event_id);
|
||||
|
|
@ -2643,10 +2642,10 @@ void FSPanelSearchEvents::processSearchReply(LLMessageSystem* msg, void**)
|
|||
}
|
||||
LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
|
||||
|
||||
FSPanelSearchEvents* self = (FSPanelSearchEvents*)FSFloaterSearch::getSearchPanel("panel_ls_events");
|
||||
FSPanelSearchEvents* self = FSFloaterSearch::getSearchPanel<FSPanelSearchEvents>("panel_ls_events");
|
||||
|
||||
// floater is closed or these are not results from our last request
|
||||
if (NULL == self || query_id != self->mQueryID)
|
||||
if (!self || query_id != self->mQueryID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -2741,7 +2740,7 @@ void FSPanelSearchEvents::processSearchReply(LLMessageSystem* msg, void**)
|
|||
// Skip empty events...
|
||||
if (owner_id.isNull())
|
||||
{
|
||||
LL_INFOS("Search") << "Skipped " << event_id << " because of a NULL owner result" << LL_ENDL;
|
||||
LL_INFOS("Search") << "Skipped " << event_id << " because of a nullptr owner result" << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
// Skips events that don't match our scope...
|
||||
|
|
@ -2817,7 +2816,7 @@ void FSPanelSearchEvents::processSearchReply(LLMessageSystem* msg, void**)
|
|||
static LLPanelInjector<FSPanelSearchWeb> t_panel_fs_search_web("panel_ls_web");
|
||||
|
||||
FSPanelSearchWeb::FSPanelSearchWeb() : FSSearchPanelBase()
|
||||
, mWebBrowser(NULL)
|
||||
, mWebBrowser(nullptr)
|
||||
, mResetFocusOnLoad(false)
|
||||
{
|
||||
// declare a map that transforms a category name into
|
||||
|
|
@ -2964,7 +2963,7 @@ std::string filterShortWords(std::string query_string)
|
|||
|
||||
void fillSearchComboBox(LLSearchComboBox* search_combo)
|
||||
{
|
||||
if (search_combo == NULL)
|
||||
if (search_combo == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -362,7 +362,9 @@ public:
|
|||
U32 eventCover,
|
||||
LLVector3d eventGlobalPos);
|
||||
void setLoadingProgress(bool started);
|
||||
static LLPanel* getSearchPanel(std::string panel_name);
|
||||
|
||||
template <class T>
|
||||
static T* getSearchPanel(const std::string& panel_name);
|
||||
|
||||
private:
|
||||
virtual void onClose(bool app_quitting);
|
||||
|
|
|
|||
|
|
@ -180,8 +180,8 @@ The 'firestorm' script which launches Firestorm contains some
|
|||
configuration options for advanced troubleshooters.
|
||||
|
||||
* AUDIO - Edit the 'secondlife' script and you will see these audio
|
||||
options: LL_BAD_OPENAL_DRIVER, LL_BAD_FMOD_ESD, LL_BAD_FMOD_OSS, and
|
||||
LL_BAD_FMOD_ALSA. Firestorm tries to use OpenAL, ESD, OSS, then ALSA
|
||||
options: LL_BAD_OPENAL_DRIVER, LL_BAD_FMODSTUDIO_DRIVER.
|
||||
Firestorm tries to use OpenAL, FMODSTUDIO (PULSEAUDIO, ALSA)
|
||||
audio drivers in this order; you may uncomment the corresponding LL_BAD_*
|
||||
option to skip an audio driver which you believe may be causing you trouble.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,18 +20,15 @@ exportMutliArchDRIPath() {
|
|||
## These options are for self-assisted troubleshooting during this beta
|
||||
## testing phase; you should not usually need to touch them.
|
||||
|
||||
## - Avoids using any FMOD Ex audio driver.
|
||||
#export LL_BAD_FMODEX_DRIVER=x
|
||||
|
||||
## - Avoids using any FMOD STUDIO audio driver.
|
||||
#export LL_BAD_FMODSTUDIO_DRIVER=x
|
||||
## - Avoids using any OpenAL audio driver.
|
||||
#export LL_BAD_OPENAL_DRIVER=x
|
||||
|
||||
## - Avoids using the FMOD Ex PulseAudio audio driver.
|
||||
## - Avoids using the FMOD Studio PulseAudio audio driver.
|
||||
#export LL_BAD_FMOD_PULSEAUDIO=x
|
||||
## - Avoids using the FMOD or FMOD Ex ALSA audio driver.
|
||||
## - Avoids using the FMOD Studio ALSA audio driver.
|
||||
#export LL_BAD_FMOD_ALSA=x
|
||||
## - Avoids using the FMOD or FMOD Ex OSS audio driver.
|
||||
#export LL_BAD_FMOD_OSS=x
|
||||
|
||||
## - Avoids the optional OpenGL extensions which have proven most problematic
|
||||
## on some hardware. Disabling this option may cause BETTER PERFORMANCE but
|
||||
|
|
|
|||
|
|
@ -1159,13 +1159,6 @@ void LLAgent::removeRegionChangedCallback(boost::signals2::connection callback)
|
|||
mRegionChangedSignal.disconnect(callback);
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Aurora sim windlight refresh
|
||||
void LLAgent::changeRegion()
|
||||
{
|
||||
mRegionChangedSignal();
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// inPrelude()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -280,9 +280,6 @@ public:
|
|||
// Capability
|
||||
std::string getRegionCapability(const std::string &name); // short hand for if (getRegion()) { getRegion()->getCapability(name) }
|
||||
|
||||
// <FS:Ansariel> Aurora sim windlight refresh
|
||||
void changeRegion();
|
||||
|
||||
/**
|
||||
* Register a boost callback to be called when the agent changes regions
|
||||
* Note that if you need to access a capability for the region, you may need to wait
|
||||
|
|
|
|||
|
|
@ -86,6 +86,14 @@
|
|||
#include "llagent.h" // for agent location
|
||||
#include "llviewerregion.h"
|
||||
#include "llvoavatarself.h" // for agent name
|
||||
#pragma optimize( "", off )
|
||||
|
||||
namespace FS
|
||||
{
|
||||
std::wstring LogfileIn;
|
||||
std::wstring LogfileOut;
|
||||
std::wstring DumpFile;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -125,6 +133,14 @@ namespace
|
|||
{
|
||||
if (nCode == MDSCB_EXCEPTIONCODE)
|
||||
{
|
||||
// <FS:ND> Save dump and log into unique crash dymp folder
|
||||
__wchar_t aBuffer[1024] = {};
|
||||
sBugSplatSender->getMinidumpPath(aBuffer, _countof(aBuffer));
|
||||
std::wstring strPath{ (wchar_t*)aBuffer };
|
||||
::CopyFileW(strPath.c_str(), FS::DumpFile.c_str(), FALSE);
|
||||
::CopyFileW(FS::LogfileIn.c_str(), FS::LogfileOut.c_str(), FALSE);
|
||||
// </FS:ND>
|
||||
|
||||
// send the main viewer log file
|
||||
// widen to wstring, convert to __wchar_t, then pass c_str()
|
||||
|
||||
|
|
@ -157,8 +173,9 @@ namespace
|
|||
sBugSplatSender->setDefaultUserEmail( WCSTR(STRINGIZE(LLOSInfo::instance().getOSStringSimple() << " (" << ADDRESS_SIZE << "-bit, flavor " << flavor <<")")));
|
||||
// </FS:ND>
|
||||
|
||||
//<FS:ND/> Clear out username first, as we get some crashes that has the OS set as username, let's see if this fixes it.
|
||||
sBugSplatSender->setDefaultUserName( WCSTR("<unset>") );
|
||||
//<FS:ND/> Clear out username first, as we get some crashes that has the OS set as username, let's see if this fixes it. Use Crash.Linden as a usr can never have a "Linden"
|
||||
// name and on the other hand a Linden will not likely ever crash on Firestom.
|
||||
sBugSplatSender->setDefaultUserName( WCSTR("Crash.Linden") );
|
||||
|
||||
if (gAgentAvatarp)
|
||||
{
|
||||
|
|
@ -687,10 +704,56 @@ LLAppViewerWin32::~LLAppViewerWin32()
|
|||
{
|
||||
}
|
||||
|
||||
// <FS:ND> Check if %TEMP% is defined and accessible (see FIRE-29623, sometimes BugSplat has problems to access TEMP, try to find out why)
|
||||
static void checkTemp()
|
||||
{
|
||||
char *pTemp{ getenv("TEMP") };
|
||||
if (!pTemp)
|
||||
{
|
||||
LL_WARNS() << "%TEMP% is not set" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "%TEMP%: " << pTemp << LL_ENDL;
|
||||
DWORD dwAttr = ::GetFileAttributesA(pTemp);
|
||||
DWORD dwLE = ::GetLastError();
|
||||
if (dwAttr == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
LL_WARNS() << "%TEMP%: " << pTemp << " GetFileAttributesA failed, last error: " << dwLE << LL_ENDL;
|
||||
}
|
||||
else if (0 == (dwAttr & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
LL_WARNS() << "%TEMP%: " << pTemp << " is not a directory" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLUUID id = LLUUID::generateNewID();
|
||||
std::string strFile{ pTemp };
|
||||
if (strFile[strFile.size() - 1] != '/' && strFile[strFile.size() - 1] != '\\')
|
||||
strFile += "\\";
|
||||
|
||||
strFile += id.asString();
|
||||
FILE *fp = fopen(strFile.c_str(), "w");
|
||||
if (!fp)
|
||||
{
|
||||
LL_WARNS() << "%TEMP%: " << pTemp << " cannot create file " << strFile << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(fp);
|
||||
remove(strFile.c_str());
|
||||
LL_INFOS() << "%TEMP%: " << pTemp << " successfully created file " << strFile << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// </FS:ND>
|
||||
|
||||
bool LLAppViewerWin32::init()
|
||||
{
|
||||
bool success{ false }; // <FS:ND/> For BugSplat we need to call base::init() early on or there's no access to settings.
|
||||
// Platform specific initialization.
|
||||
|
||||
|
||||
// Turn off Windows Error Reporting
|
||||
// (Don't send our data to Microsoft--at least until we are Logo approved and have a way
|
||||
// of getting the data back from them.)
|
||||
|
|
@ -712,7 +775,28 @@ bool LLAppViewerWin32::init()
|
|||
|
||||
#else // LL_BUGSPLAT
|
||||
#pragma message("Building with BugSplat")
|
||||
// <FS:ND> Pre BugSplat dance, make sure settings are valid, query crash behavior and then set up Bugsplat accordingly"
|
||||
success = LLAppViewer::init();
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
checkTemp(); // Always do and log this, no matter if using Bugsplat or not
|
||||
|
||||
// Save those early so we don't have to deal with the dynamic memory during in process crash handling.
|
||||
FS::LogfileIn = ll_convert_string_to_wide(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "Firestorm.log"));
|
||||
FS::LogfileOut = ll_convert_string_to_wide(gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "Firestorm.log"));
|
||||
FS::DumpFile = ll_convert_string_to_wide(gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "Firestorm.dmp"));
|
||||
|
||||
S32 nCrashSubmitBehavior = gCrashSettings.getS32("CrashSubmitBehavior");
|
||||
// Don't ever send? bail out!
|
||||
if (nCrashSubmitBehavior == 2 /*CRASH_BEHAVIOR_NEVER_SEND*/)
|
||||
return success;
|
||||
|
||||
DWORD dwAsk{ MDSF_NONINTERACTIVE };
|
||||
if (nCrashSubmitBehavior == 0 /*CRASH_BEHAVIOR_ASK*/)
|
||||
dwAsk = 0;
|
||||
// </FS:ND>
|
||||
|
||||
std::string build_data_fname(
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json"));
|
||||
// Use llifstream instead of std::ifstream because LL_PATH_EXECUTABLE
|
||||
|
|
@ -750,13 +834,26 @@ bool LLAppViewerWin32::init()
|
|||
LL_VIEWER_VERSION_BUILD));
|
||||
|
||||
// have to convert normal wide strings to strings of __wchar_t
|
||||
|
||||
// <FS:ND> Set up Bugsplat to ask or always send
|
||||
|
||||
// sBugSplatSender = new MiniDmpSender(
|
||||
// WCSTR(BugSplat_DB.asString()),
|
||||
// WCSTR(LL_TO_WSTRING(LL_VIEWER_CHANNEL)),
|
||||
// WCSTR(version_string),
|
||||
// nullptr, // szAppIdentifier -- set later
|
||||
// MDSF_NONINTERACTIVE | // automatically submit report without prompting
|
||||
// MDSF_PREVENTHIJACKING); // disallow swiping Exception filter
|
||||
|
||||
sBugSplatSender = new MiniDmpSender(
|
||||
WCSTR(BugSplat_DB.asString()),
|
||||
WCSTR(LL_TO_WSTRING(LL_VIEWER_CHANNEL)),
|
||||
WCSTR(version_string),
|
||||
nullptr, // szAppIdentifier -- set later
|
||||
MDSF_NONINTERACTIVE | // automatically submit report without prompting
|
||||
dwAsk |
|
||||
MDSF_PREVENTHIJACKING); // disallow swiping Exception filter
|
||||
// </FS:ND>
|
||||
|
||||
sBugSplatSender->setCallback(bugsplatSendLog);
|
||||
|
||||
// engage stringize() overload that converts from wstring
|
||||
|
|
@ -769,7 +866,12 @@ bool LLAppViewerWin32::init()
|
|||
#endif // LL_BUGSPLAT
|
||||
#endif // LL_SEND_CRASH_REPORTS
|
||||
|
||||
bool success = LLAppViewer::init();
|
||||
// <FS:ND> base::init() was potentially called earlier.
|
||||
// bool success = LLAppViewer::init();
|
||||
// </FS:ND>
|
||||
|
||||
if( !success )
|
||||
success = LLAppViewer::init();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,10 +143,6 @@ BOOL LLFloaterAbout::postBuild()
|
|||
// boost::bind(&LLFloaterAbout::onClickUpdateCheck, this));
|
||||
// </FS:Ansariel>
|
||||
|
||||
#if LL_FMODSTUDIO || LL_FMODEX
|
||||
childSetVisible("logos_panel", true);
|
||||
#endif
|
||||
|
||||
static const LLUIColor about_color = LLUIColorTable::instance().getColor("TextFgReadOnlyColor");
|
||||
|
||||
if (gAgent.getRegion())
|
||||
|
|
|
|||
|
|
@ -173,9 +173,9 @@ char const* const VISIBILITY_DEFAULT = "default";
|
|||
char const* const VISIBILITY_HIDDEN = "hidden";
|
||||
|
||||
//control value for middle mouse as talk2push button
|
||||
const static std::string MIDDLE_MOUSE_CV = "MiddleMouse"; // for voice client and redability
|
||||
const static std::string MOUSE_BUTTON_4_CV = "MouseButton4";
|
||||
const static std::string MOUSE_BUTTON_5_CV = "MouseButton5";
|
||||
//const static std::string MIDDLE_MOUSE_CV = "MiddleMouse"; // for voice client and redability
|
||||
//const static std::string MOUSE_BUTTON_4_CV = "MouseButton4";
|
||||
//const static std::string MOUSE_BUTTON_5_CV = "MouseButton5";
|
||||
|
||||
/// This must equal the maximum value set for the IndirectMaxComplexity slider in panel_preferences_graphics1.xml
|
||||
static const U32 INDIRECT_MAX_ARC_OFF = 101; // all the way to the right == disabled
|
||||
|
|
@ -441,7 +441,6 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
|
|||
mCommitCallbackRegistrar.add("Pref.ResetCache", boost::bind(&LLFloaterPreference::onClickResetCache, this));
|
||||
// mCommitCallbackRegistrar.add("Pref.ClickSkin", boost::bind(&LLFloaterPreference::onClickSkin, this,_1, _2));
|
||||
// mCommitCallbackRegistrar.add("Pref.SelectSkin", boost::bind(&LLFloaterPreference::onSelectSkin, this));
|
||||
mCommitCallbackRegistrar.add("Pref.VoiceSetClearKey", boost::bind(&LLFloaterPreference::onClickClearKey, this)); // <FS:Ansariel> FIRE-3803: Clear voice toggle button
|
||||
//<FS:KC> Handled centrally now
|
||||
// mCommitCallbackRegistrar.add("Pref.SetSounds", boost::bind(&LLFloaterPreference::onClickSetSounds, this));
|
||||
mCommitCallbackRegistrar.add("Pref.ClickEnablePopup", boost::bind(&LLFloaterPreference::onClickEnablePopup, this));
|
||||
|
|
@ -2638,13 +2637,6 @@ void LLFloaterPreference::onChangeQuality(const LLSD& data)
|
|||
refresh();
|
||||
}
|
||||
|
||||
// <FS:Ansariel> FIRE-3803: Clear voice toggle button
|
||||
void LLFloaterPreference::onClickClearKey()
|
||||
{
|
||||
gSavedSettings.setString("PushToTalkButton", "");
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
//<FS:KC> Handled centrally now
|
||||
/*
|
||||
void LLFloaterPreference::onClickSetSounds()
|
||||
|
|
@ -4998,6 +4990,10 @@ BOOL LLPanelPreferenceCrashReports::postBuild()
|
|||
|
||||
getChild<LLTextBox>("textInformation4")->setTextArg("[URL]", getString("PrivacyPolicyUrl"));
|
||||
|
||||
#if LL_SEND_CRASH_REPORTS && defined(LL_BUGSPLAT)
|
||||
childSetVisible("textRestartRequired", true);
|
||||
#endif
|
||||
|
||||
refresh();
|
||||
|
||||
return LLPanelPreference::postBuild();
|
||||
|
|
@ -5012,13 +5008,6 @@ void LLPanelPreferenceCrashReports::refresh()
|
|||
getChild<LLUICtrl>("checkSendCrashReportsAlwaysAsk")->setEnabled(fEnable);
|
||||
getChild<LLUICtrl>("checkSendSettings")->setEnabled(fEnable);
|
||||
getChild<LLUICtrl>("checkSendName")->setEnabled(fEnable);
|
||||
|
||||
// <FS:ND> Disable options not available when compiling with Bugsplat and set those to default values.
|
||||
#ifdef LL_BUGSPLAT
|
||||
getChild<LLUICtrl>("checkSendCrashReportsAlwaysAsk")->setEnabled(false);
|
||||
getChild<LLUICtrl>("checkSendCrashReportsAlwaysAsk")->setValue(false);
|
||||
#endif
|
||||
// </FS:ND>
|
||||
}
|
||||
|
||||
void LLPanelPreferenceCrashReports::apply()
|
||||
|
|
@ -6202,7 +6191,7 @@ BOOL FSPanelPreferenceSounds::postBuild()
|
|||
mOutputDevicePanel = findChild<LLPanel>("output_device_settings_panel");
|
||||
mOutputDeviceComboBox = findChild<LLComboBox>("sound_output_device");
|
||||
|
||||
#if LL_FMODSTUDIO || LL_FMODEX
|
||||
#if LL_FMODSTUDIO
|
||||
if (gAudiop && mOutputDevicePanel && mOutputDeviceComboBox)
|
||||
{
|
||||
gSavedSettings.getControl("FSOutputDeviceUUID")->getSignal()->connect(boost::bind(&FSPanelPreferenceSounds::onOutputDeviceChanged, this, _2));
|
||||
|
|
|
|||
|
|
@ -192,7 +192,6 @@ public:
|
|||
void onClickBrowseSettingsDir();
|
||||
void onClickSkin(LLUICtrl* ctrl,const LLSD& userdata);
|
||||
void onSelectSkin();
|
||||
void onClickClearKey(); // <FS:Ansariel> FIRE-3803: Clear voice toggle button
|
||||
// void onClickSetSounds(); //<FS:KC> Handled centrally now
|
||||
void onClickPreviewUISound(const LLSD& ui_sound_id); // <FS:PP> FIRE-8190: Preview function for "UI Sounds" Panel
|
||||
void setPreprocInclude();
|
||||
|
|
|
|||
|
|
@ -90,10 +90,9 @@ void LLFloaterPreferenceViewAdvanced::onSavePreset()
|
|||
LLFloaterReg::hideInstance("load_pref_preset", PRESETS_CAMERA);
|
||||
|
||||
LLSD key;
|
||||
key["subdirectory"] = PRESETS_CAMERA;
|
||||
std::string current_preset = gSavedSettings.getString("PresetCameraActive");
|
||||
bool is_custom_preset = current_preset != "" && !LLPresetsManager::getInstance()->isDefaultCameraPreset(current_preset);
|
||||
key["index"] = is_custom_preset ? 1 : 0;
|
||||
LLFloaterReg::showInstance("save_pref_preset", key);
|
||||
LLFloaterReg::showInstance("save_camera_preset", key);
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
|
|
|||
|
|
@ -4409,6 +4409,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
|
||||
const LLUUID &favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
|
||||
const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &outfits_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); // <FS:Ansariel> Fix "outfits" context menu
|
||||
|
||||
// <FS:Ansariel> FIRE-11628: Option to delete broken links from AO folder
|
||||
if (mUUID == AOEngine::instance().getAOFolder())
|
||||
|
|
@ -4416,6 +4417,12 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
items.push_back(std::string("Cleanup broken Links"));
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
// <FS:Ansariel> Fix "outfits" context menu
|
||||
if (outfits_id == mUUID)
|
||||
{
|
||||
items.push_back(std::string("New Outfit"));
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
if (lost_and_found_id == mUUID)
|
||||
{
|
||||
// This is the lost+found folder.
|
||||
|
|
@ -4519,7 +4526,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
// Not sure what the right thing is to do here.
|
||||
if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
|
||||
{
|
||||
if (!isInboxFolder()) // don't allow creation in inbox
|
||||
// <FS:Ansariel> Fix "outfits" context menu
|
||||
//if (!isInboxFolder()) // don't allow creation in inbox
|
||||
if (!isInboxFolder() && outfits_id != mUUID) // don't allow creation in inbox
|
||||
// </FS:Ansariel>
|
||||
{
|
||||
// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
|
||||
if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
|
||||
|
|
@ -8574,6 +8584,7 @@ void LLWornItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
|||
items.erase(std::remove(items.begin(), items.end(), std::string("New Gesture")), items.end());
|
||||
items.erase(std::remove(items.begin(), items.end(), std::string("New Script")), items.end());
|
||||
items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end());
|
||||
items.erase(std::remove(items.begin(), items.end(), std::string("New Settings")), items.end()); // <FS:Ansariel> Don't allow creating settings on the "worn" tab
|
||||
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4634,19 +4634,6 @@ LLMeshCostData::LLMeshCostData()
|
|||
std::fill(mEstTrisByLOD.begin(), mEstTrisByLOD.end(), 0.f);
|
||||
}
|
||||
|
||||
// <FS:ND> Guard against medium/low/lowest LOD missing and crashing the viewer
|
||||
S32 getSize( std::string aLOD, const LLSD &aHeader )
|
||||
{
|
||||
if( !aHeader.has( aLOD ) )
|
||||
return 0;
|
||||
|
||||
if( !aHeader[ aLOD ].has( "size" ) )
|
||||
return 0;
|
||||
|
||||
return aHeader[ aLOD ][ "size" ].asInteger();
|
||||
}
|
||||
// </FS:ND>
|
||||
|
||||
bool LLMeshCostData::init(const LLSD& header)
|
||||
{
|
||||
mSizeByLOD.resize(4);
|
||||
|
|
@ -4655,40 +4642,22 @@ bool LLMeshCostData::init(const LLSD& header)
|
|||
std::fill(mSizeByLOD.begin(), mSizeByLOD.end(), 0);
|
||||
std::fill(mEstTrisByLOD.begin(), mEstTrisByLOD.end(), 0.f);
|
||||
|
||||
// <FS:ND> Guard against medium/low/lowest LOD missing and crashing the viewer
|
||||
|
||||
// S32 bytes_high = header["high_lod"]["size"].asInteger();
|
||||
// S32 bytes_med = header["medium_lod"]["size"].asInteger();
|
||||
// if (bytes_med == 0)
|
||||
// {
|
||||
// bytes_med = bytes_high;
|
||||
// }
|
||||
// S32 bytes_low = header["low_lod"]["size"].asInteger();
|
||||
// if (bytes_low == 0)
|
||||
// {
|
||||
// bytes_low = bytes_med;
|
||||
// }
|
||||
// S32 bytes_lowest = header["lowest_lod"]["size"].asInteger();
|
||||
// if (bytes_lowest == 0)
|
||||
// {
|
||||
// bytes_lowest = bytes_low;
|
||||
// }
|
||||
|
||||
S32 bytes_high = getSize( "high_lod", header ),
|
||||
bytes_med = getSize( "medium_lod", header ),
|
||||
bytes_low = getSize( "low_lod", header ),
|
||||
bytes_lowest = getSize( "lowest_lod", header );
|
||||
|
||||
S32 bytes_high = header["high_lod"]["size"].asInteger();
|
||||
S32 bytes_med = header["medium_lod"]["size"].asInteger();
|
||||
if (bytes_med == 0)
|
||||
{
|
||||
bytes_med = bytes_high;
|
||||
|
||||
}
|
||||
S32 bytes_low = header["low_lod"]["size"].asInteger();
|
||||
if (bytes_low == 0)
|
||||
{
|
||||
bytes_low = bytes_med;
|
||||
|
||||
}
|
||||
S32 bytes_lowest = header["lowest_lod"]["size"].asInteger();
|
||||
if (bytes_lowest == 0)
|
||||
{
|
||||
bytes_lowest = bytes_low;
|
||||
|
||||
// </FS:ND>
|
||||
}
|
||||
|
||||
mSizeByLOD[0] = bytes_lowest;
|
||||
mSizeByLOD[1] = bytes_low;
|
||||
|
|
@ -4828,13 +4797,8 @@ bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data)
|
|||
LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
|
||||
if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
|
||||
{
|
||||
// <FS:ND> Make a copy of the header rather than holding on to the referece.
|
||||
// Assumption: mMeshHeader gets modified in another thread, invalidating iter and thus causing a lot of crashed down the line
|
||||
|
||||
// LLSD& header = iter->second;
|
||||
LLSD header = iter->second;
|
||||
|
||||
// </FS:ND>
|
||||
// <FS:ND/> TODO - come to this back later. From all known so far it's not a simply race condition but LLSD being not multi thread safe at all. (which in fact it isn't).
|
||||
LLSD& header = iter->second;
|
||||
|
||||
bool header_invalid = (header.has("404")
|
||||
|| !header.has("lowest_lod")
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ void LLProgressView::setStartupComplete()
|
|||
mFadeToWorldTimer.start();
|
||||
}
|
||||
|
||||
// NickyD: FIRE-3063; Enable Audio for all media sources again. They got disabled during postBuild(), but as we never reach LLProgressView::draw
|
||||
// <FS:NickyD> FIRE-3063; Enable Audio for all media sources again. They got disabled during postBuild(), but as we never reach LLProgressView::draw
|
||||
// if the progress is disabled, we would never get media audio back.
|
||||
LLViewerMedia::getInstance()->setOnlyAudibleMediaTextureID(LLUUID::null);
|
||||
}
|
||||
|
|
@ -255,7 +255,7 @@ void LLProgressView::setVisible(BOOL visible)
|
|||
}
|
||||
}
|
||||
|
||||
// ## Zi: Fade teleport screens
|
||||
// <FS:Zi> Fade teleport screens
|
||||
void LLProgressView::fade(BOOL in)
|
||||
{
|
||||
if(in)
|
||||
|
|
@ -271,7 +271,7 @@ void LLProgressView::fade(BOOL in)
|
|||
// set visibility will be done in the draw() method after fade
|
||||
}
|
||||
}
|
||||
// ## Zi: Fade teleport screens
|
||||
// </FS:Zi> Fade teleport screens
|
||||
|
||||
void LLProgressView::drawStartTexture(F32 alpha)
|
||||
{
|
||||
|
|
@ -308,6 +308,33 @@ void LLProgressView::drawStartTexture(F32 alpha)
|
|||
gGL.popMatrix();
|
||||
}
|
||||
|
||||
void LLProgressView::drawLogos(F32 alpha)
|
||||
{
|
||||
if (mLogosList.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// logos are tied to label,
|
||||
// due to potential resizes we have to figure offsets out on draw or resize
|
||||
LLTextBox *logos_label = getChild<LLTextBox>("logos_lbl");
|
||||
S32 offset_x, offset_y;
|
||||
logos_label->localPointToScreen(0, 0, &offset_x, &offset_y);
|
||||
std::vector<TextureData>::const_iterator iter = mLogosList.begin();
|
||||
std::vector<TextureData>::const_iterator end = mLogosList.end();
|
||||
for (; iter != end; iter++)
|
||||
{
|
||||
gl_draw_scaled_image_with_border(iter->mDrawRect.mLeft + offset_x,
|
||||
iter->mDrawRect.mBottom + offset_y,
|
||||
iter->mDrawRect.getWidth(),
|
||||
iter->mDrawRect.getHeight(),
|
||||
iter->mTexturep.get(),
|
||||
UI_VERTEX_COLOR % alpha,
|
||||
FALSE,
|
||||
iter->mClipRect,
|
||||
iter->mOffsetRect);
|
||||
}
|
||||
}
|
||||
|
||||
void LLProgressView::draw()
|
||||
{
|
||||
|
|
@ -324,6 +351,7 @@ void LLProgressView::draw()
|
|||
}
|
||||
|
||||
LLPanel::draw();
|
||||
drawLogos(alpha);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -336,6 +364,7 @@ void LLProgressView::draw()
|
|||
|
||||
drawStartTexture(alpha);
|
||||
LLPanel::draw();
|
||||
drawLogos(alpha);
|
||||
|
||||
// faded out completely - remove panel and reveal world
|
||||
if (mFadeToWorldTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME )
|
||||
|
|
@ -362,7 +391,7 @@ void LLProgressView::draw()
|
|||
// FIXME: this causes a crash that i haven't been able to fix
|
||||
mMediaCtrl->unloadMediaSource();
|
||||
|
||||
gStartTexture = NULL;
|
||||
releaseTextures();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -370,6 +399,7 @@ void LLProgressView::draw()
|
|||
drawStartTexture(1.0f);
|
||||
// draw children
|
||||
LLPanel::draw();
|
||||
drawLogos(1.0f);
|
||||
}
|
||||
|
||||
void LLProgressView::setText(const std::string& text)
|
||||
|
|
@ -388,6 +418,199 @@ void LLProgressView::setMessage(const std::string& msg)
|
|||
mMessageText->setValue(mMessage);
|
||||
}
|
||||
|
||||
void LLProgressView::loadLogo(const std::string &path,
|
||||
const U8 image_codec,
|
||||
const LLRect &pos_rect,
|
||||
const LLRectf &clip_rect,
|
||||
const LLRectf &offset_rect)
|
||||
{
|
||||
// We need these images very early, so we have to force-load them, otherwise they might not load in time.
|
||||
if (!gDirUtilp->fileExists(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLPointer<LLImageFormatted> start_image_frmted = LLImageFormatted::createFromType(image_codec);
|
||||
if (!start_image_frmted->load(path))
|
||||
{
|
||||
LL_WARNS("AppInit") << "Image load failed: " << path << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw;
|
||||
if (!start_image_frmted->decode(raw, 0.0f))
|
||||
{
|
||||
LL_WARNS("AppInit") << "Image decode failed " << path << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
// HACK: getLocalTexture allows only power of two dimentions
|
||||
raw->expandToPowerOfTwo();
|
||||
|
||||
TextureData data;
|
||||
data.mTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
|
||||
data.mDrawRect = pos_rect;
|
||||
data.mClipRect = clip_rect;
|
||||
data.mOffsetRect = offset_rect;
|
||||
mLogosList.push_back(data);
|
||||
}
|
||||
|
||||
void LLProgressView::initLogos()
|
||||
{
|
||||
mLogosList.clear();
|
||||
|
||||
const U8 image_codec = IMG_CODEC_PNG;
|
||||
const LLRectf default_clip(0.f, 1.f, 1.f, 0.f);
|
||||
const S32 default_height = 28;
|
||||
const S32 default_pad = 15;
|
||||
|
||||
S32 icon_width, icon_height;
|
||||
|
||||
// We don't know final screen rect yet, so we can't precalculate position fully
|
||||
LLTextBox *logos_label = getChild<LLTextBox>("logos_lbl");
|
||||
S32 texture_start_x = logos_label->getFont()->getWidthF32(logos_label->getText()) + default_pad;
|
||||
S32 texture_start_y = -7;
|
||||
|
||||
// Normally we would just preload these textures from textures.xml,
|
||||
// and display them via icon control, but they are only needed on
|
||||
// startup and preloaded/UI ones stay forever
|
||||
// (and this code was done already so simply reused it)
|
||||
std::string temp_str = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "textures", "3p_icons");
|
||||
|
||||
temp_str += gDirUtilp->getDirDelimiter();
|
||||
|
||||
#ifdef LL_FMODSTUDIO
|
||||
// original image size is 264x96, it is on longer side but
|
||||
// with no internal paddings so it gets additional padding
|
||||
icon_width = 77;
|
||||
icon_height = 21;
|
||||
S32 pad_y = 4;
|
||||
texture_start_x++;
|
||||
loadLogo(temp_str + "fmod_logo.png",
|
||||
image_codec,
|
||||
LLRect(texture_start_x, texture_start_y + pad_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_y),
|
||||
default_clip,
|
||||
default_clip);
|
||||
|
||||
texture_start_x += icon_width + default_pad + 1;
|
||||
#endif
|
||||
|
||||
#ifdef HAVOK_TPV // <FS:Ansariel> Don't show on non-Havok builds
|
||||
// original image size is 342x113, central element is on a larger side
|
||||
// plus internal padding, so it gets slightly more height than desired 32
|
||||
icon_width = 88;
|
||||
icon_height = 29;
|
||||
pad_y = -1;
|
||||
loadLogo(temp_str + "havok_logo.png",
|
||||
image_codec,
|
||||
LLRect(texture_start_x, texture_start_y + pad_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_y),
|
||||
default_clip,
|
||||
default_clip);
|
||||
|
||||
texture_start_x += icon_width + default_pad;
|
||||
#endif // <FS:Ansariel> Don't show on non-Havok builds
|
||||
|
||||
// 108x41
|
||||
icon_width = 74;
|
||||
loadLogo(temp_str + "vivox_logo.png",
|
||||
image_codec,
|
||||
LLRect(texture_start_x, texture_start_y + default_height, texture_start_x + icon_width, texture_start_y),
|
||||
default_clip,
|
||||
default_clip);
|
||||
}
|
||||
|
||||
void LLProgressView::initStartTexture(S32 location_id, bool is_in_production)
|
||||
{
|
||||
if (gStartTexture.notNull())
|
||||
{
|
||||
gStartTexture = NULL;
|
||||
LL_INFOS("AppInit") << "re-initializing start screen" << LL_ENDL;
|
||||
}
|
||||
|
||||
LL_DEBUGS("AppInit") << "Loading startup bitmap..." << LL_ENDL;
|
||||
|
||||
U8 image_codec = IMG_CODEC_PNG;
|
||||
std::string temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter();
|
||||
|
||||
if ((S32)START_LOCATION_ID_LAST == location_id)
|
||||
{
|
||||
temp_str += LLStartUp::getScreenLastFilename();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string path = temp_str + LLStartUp::getScreenHomeFilename();
|
||||
|
||||
if (!gDirUtilp->fileExists(path) && is_in_production)
|
||||
{
|
||||
// Fallback to old file, can be removed later
|
||||
// Home image only sets when user changes home, so it will take time for users to switch to pngs
|
||||
temp_str += "screen_home.bmp";
|
||||
image_codec = IMG_CODEC_BMP;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_str = path;
|
||||
}
|
||||
}
|
||||
|
||||
LLPointer<LLImageFormatted> start_image_frmted = LLImageFormatted::createFromType(image_codec);
|
||||
|
||||
// Turn off start screen to get around the occasional readback
|
||||
// driver bug
|
||||
if (!gSavedSettings.getBOOL("UseStartScreen"))
|
||||
{
|
||||
LL_INFOS("AppInit") << "Bitmap load disabled" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
else if (!start_image_frmted->load(temp_str))
|
||||
{
|
||||
LL_WARNS("AppInit") << "Bitmap load failed" << LL_ENDL;
|
||||
gStartTexture = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gStartImageWidth = start_image_frmted->getWidth();
|
||||
gStartImageHeight = start_image_frmted->getHeight();
|
||||
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw;
|
||||
if (!start_image_frmted->decode(raw, 0.0f))
|
||||
{
|
||||
LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL;
|
||||
gStartTexture = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// HACK: getLocalTexture allows only power of two dimentions
|
||||
raw->expandToPowerOfTwo();
|
||||
gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (gStartTexture.isNull())
|
||||
{
|
||||
gStartTexture = LLViewerTexture::sBlackImagep;
|
||||
gStartImageWidth = gStartTexture->getWidth();
|
||||
gStartImageHeight = gStartTexture->getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
void LLProgressView::initTextures(S32 location_id, bool is_in_production)
|
||||
{
|
||||
initStartTexture(location_id, is_in_production);
|
||||
initLogos();
|
||||
|
||||
childSetVisible("panel_icons", mLogosList.empty() ? FALSE : TRUE);
|
||||
childSetVisible("panel_top_spacer", mLogosList.empty() ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
void LLProgressView::releaseTextures()
|
||||
{
|
||||
gStartTexture = NULL;
|
||||
mLogosList.clear();
|
||||
|
||||
childSetVisible("panel_top_spacer", TRUE);
|
||||
childSetVisible("panel_icons", FALSE);
|
||||
}
|
||||
|
||||
void LLProgressView::setCancelButtonVisible(BOOL b, const std::string& label)
|
||||
{
|
||||
mCancelBtn->setVisible( b );
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
class LLImageRaw;
|
||||
class LLButton;
|
||||
class LLProgressBar;
|
||||
class LLViewerTexture;
|
||||
class LLTextBox;
|
||||
|
||||
class LLProgressView :
|
||||
|
|
@ -52,6 +53,7 @@ public:
|
|||
|
||||
/*virtual*/ void draw();
|
||||
void drawStartTexture(F32 alpha);
|
||||
void drawLogos(F32 alpha);
|
||||
|
||||
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
|
||||
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
|
||||
|
|
@ -73,6 +75,10 @@ public:
|
|||
|
||||
void setStartupComplete();
|
||||
|
||||
// we have to preload local textures to make sure they won't be grey
|
||||
void initTextures(S32 location_id, bool is_in_production);
|
||||
void releaseTextures();
|
||||
|
||||
void setCancelButtonVisible(BOOL b, const std::string& label);
|
||||
|
||||
static void onCancelButtonClicked( void* );
|
||||
|
|
@ -100,6 +106,25 @@ protected:
|
|||
|
||||
bool handleUpdate(const LLSD& event_data);
|
||||
static void onIdle(void* user_data);
|
||||
void loadLogo(const std::string &path, const U8 image_codec, const LLRect &pos_rect, const LLRectf &clip_rect, const LLRectf &offset_rect);
|
||||
// logos have unusual location and need to be preloaded to not appear grey, then deleted
|
||||
void initLogos();
|
||||
// Loads a bitmap to display during load
|
||||
void initStartTexture(S32 location_id, bool is_in_production);
|
||||
|
||||
private:
|
||||
// We need to draw textures on login, but only once.
|
||||
// So this vector gets filled up for textures to render and gets cleaned later
|
||||
// Some textures have unusual requirements, so we are rendering directly
|
||||
class TextureData
|
||||
{
|
||||
public:
|
||||
LLPointer<LLViewerTexture> mTexturep;
|
||||
LLRect mDrawRect;
|
||||
LLRectf mClipRect;
|
||||
LLRectf mOffsetRect;
|
||||
};
|
||||
std::vector<TextureData> mLogosList;
|
||||
};
|
||||
|
||||
class LLProgressViewMini :
|
||||
|
|
|
|||
|
|
@ -43,10 +43,6 @@
|
|||
# include "llaudioengine_fmodstudio.h"
|
||||
#endif
|
||||
|
||||
#ifdef LL_FMODEX
|
||||
# include "llaudioengine_fmodex.h"
|
||||
#endif
|
||||
|
||||
#ifdef LL_OPENAL
|
||||
#include "llaudioengine_openal.h"
|
||||
#endif
|
||||
|
|
@ -988,20 +984,11 @@ bool idle_startup()
|
|||
|
||||
#ifdef LL_FMODSTUDIO
|
||||
#if !LL_WINDOWS
|
||||
if (NULL == getenv("LL_BAD_FMODSTUDIO_DRIVER"))
|
||||
if (NULL == getenv("LL_BAD_FMODSTUDIO_DRIVER"))
|
||||
#endif // !LL_WINDOWS
|
||||
{
|
||||
gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODSTUDIO(gSavedSettings.getBOOL("FMODProfilerEnable"), gSavedSettings.getU32("FMODResampleMethod"));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LL_FMODEX
|
||||
#if !LL_WINDOWS
|
||||
if (NULL == getenv("LL_BAD_FMODEX_DRIVER"))
|
||||
#endif // !LL_WINDOWS
|
||||
{
|
||||
gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("FMODProfilerEnable"));
|
||||
}
|
||||
{
|
||||
gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODSTUDIO(gSavedSettings.getBOOL("FMODProfilerEnable"), gSavedSettings.getU32("FMODResampleMethod"));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LL_OPENAL
|
||||
|
|
@ -1023,7 +1010,7 @@ bool idle_startup()
|
|||
#else
|
||||
void* window_handle = NULL;
|
||||
#endif
|
||||
bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle);
|
||||
bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle, LLAppViewer::instance()->getSecondLifeTitle());
|
||||
if(init)
|
||||
{
|
||||
// <FS:Ansariel> Output device selection
|
||||
|
|
@ -1567,9 +1554,8 @@ bool idle_startup()
|
|||
|
||||
gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
|
||||
|
||||
init_start_screen(agent_location_id);
|
||||
|
||||
// Display the startup progress bar.
|
||||
gViewerWindow->initTextures(agent_location_id);
|
||||
gViewerWindow->setShowProgress(TRUE,!gSavedSettings.getBOOL("FSDisableLoginScreens"));
|
||||
gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit"));
|
||||
|
||||
|
|
@ -3650,84 +3636,6 @@ std::string LLStartUp::getUserId()
|
|||
return gUserCredential->userID();
|
||||
}
|
||||
|
||||
// Loads a bitmap to display during load
|
||||
void init_start_screen(S32 location_id)
|
||||
{
|
||||
if (gStartTexture.notNull())
|
||||
{
|
||||
gStartTexture = NULL;
|
||||
LL_INFOS("AppInit") << "re-initializing start screen" << LL_ENDL;
|
||||
}
|
||||
|
||||
LL_DEBUGS("AppInit") << "Loading startup bitmap..." << LL_ENDL;
|
||||
|
||||
U8 image_codec = IMG_CODEC_PNG;
|
||||
std::string temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter();
|
||||
|
||||
if ((S32)START_LOCATION_ID_LAST == location_id)
|
||||
{
|
||||
temp_str += LLStartUp::getScreenLastFilename();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string path = temp_str + LLStartUp::getScreenHomeFilename();
|
||||
|
||||
// <FS:Ansariel> OpenSim support
|
||||
//if (!gDirUtilp->fileExists(path) && LLGridManager::getInstance()->isInProductionGrid())
|
||||
if (!gDirUtilp->fileExists(path) && LLGridManager::getInstance()->isInSLMain())
|
||||
// </FS:Ansariel>
|
||||
{
|
||||
// Fallback to old file, can be removed later
|
||||
// Home image only sets when user changes home, so it will take time for users to switch to pngs
|
||||
temp_str += "screen_home.bmp";
|
||||
image_codec = IMG_CODEC_BMP;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_str = path;
|
||||
}
|
||||
}
|
||||
|
||||
LLPointer<LLImageFormatted> start_image_frmted = LLImageFormatted::createFromType(image_codec);
|
||||
|
||||
// Turn off start screen to get around the occasional readback
|
||||
// driver bug
|
||||
if(!gSavedSettings.getBOOL("UseStartScreen"))
|
||||
{
|
||||
LL_INFOS("AppInit") << "Bitmap load disabled" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
else if(!start_image_frmted->load(temp_str) )
|
||||
{
|
||||
LL_WARNS("AppInit") << "Bitmap load failed" << LL_ENDL;
|
||||
gStartTexture = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gStartImageWidth = start_image_frmted->getWidth();
|
||||
gStartImageHeight = start_image_frmted->getHeight();
|
||||
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw;
|
||||
if (!start_image_frmted->decode(raw, 0.0f))
|
||||
{
|
||||
LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL;
|
||||
gStartTexture = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
raw->expandToPowerOfTwo();
|
||||
gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE) ;
|
||||
}
|
||||
}
|
||||
|
||||
if(gStartTexture.isNull())
|
||||
{
|
||||
gStartTexture = LLViewerTexture::sBlackImagep ;
|
||||
gStartImageWidth = gStartTexture->getWidth() ;
|
||||
gStartImageHeight = gStartTexture->getHeight() ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// frees the bitmap
|
||||
void release_start_screen()
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@
|
|||
#include "lldrawpoolbump.h"
|
||||
#include "llpostprocess.h"
|
||||
#include "llscenemonitor.h"
|
||||
|
||||
#include "llenvironment.h"
|
||||
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a)
|
||||
#include "rlvhandler.h"
|
||||
#include "rlvlocks.h"
|
||||
|
|
@ -83,10 +85,6 @@
|
|||
#include "llpresetsmanager.h"
|
||||
#include "fsdata.h"
|
||||
|
||||
#include "llenvironment.h"
|
||||
|
||||
#include "llenvironment.h"
|
||||
|
||||
extern LLPointer<LLViewerTexture> gStartTexture;
|
||||
extern bool gShiftFrame;
|
||||
|
||||
|
|
|
|||
|
|
@ -5237,8 +5237,12 @@ void handle_reset_view()
|
|||
}
|
||||
|
||||
// <FS:Zi> Added optional V1 behavior so the avatar turns into camera direction after hitting ESC
|
||||
if(gSavedSettings.getBOOL("ResetViewTurnsAvatar"))
|
||||
gAgentCamera.resetView();
|
||||
if (!gSavedSettings.getBOOL("ResetViewTurnsAvatar"))
|
||||
{
|
||||
// The only thing we actually want to do here is set LLAgent::mFocusOnAvatar to TRUE,
|
||||
// since this prevents the avatar from turning.
|
||||
gAgentCamera.setFocusOnAvatar(TRUE, FALSE, FALSE);
|
||||
}
|
||||
// </FS:Zi>
|
||||
|
||||
reset_view_final( TRUE );
|
||||
|
|
|
|||
|
|
@ -1984,7 +1984,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
|
|||
// If there is a new music URL and it's valid, play it.
|
||||
if (music_url.size() > 12)
|
||||
{
|
||||
if (music_url.substr(0, 7) == "http://")
|
||||
if (music_url.substr(0, 7) == "http://"
|
||||
|| music_url.substr(0, 8) == "https://")
|
||||
{
|
||||
LLViewerRegion *region = LLWorld::getInstance()->getRegion(msg->getSender());
|
||||
optionally_start_music(music_url, parcel->mLocalID, region->getRegionID());
|
||||
|
|
|
|||
|
|
@ -6322,7 +6322,18 @@ void LLViewerWindow::revealIntroPanel()
|
|||
}
|
||||
}
|
||||
|
||||
void LLViewerWindow::setShowProgress(const BOOL show,BOOL fullscreen)
|
||||
void LLViewerWindow::initTextures(S32 location_id)
|
||||
{
|
||||
if (mProgressView)
|
||||
{
|
||||
// <FS:Ansariel> OpenSim support
|
||||
//mProgressView->initTextures(location_id, LLGridManager::getInstance()->isInProductionGrid());
|
||||
mProgressView->initTextures(location_id, LLGridManager::getInstance()->isInSLMain());
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerWindow::setShowProgress(const BOOL show, BOOL fullscreen)
|
||||
{
|
||||
if(show)
|
||||
{
|
||||
|
|
@ -6407,7 +6418,6 @@ void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string&
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
LLProgressView *LLViewerWindow::getProgressView() const
|
||||
{
|
||||
return mProgressView;
|
||||
|
|
|
|||
|
|
@ -305,7 +305,8 @@ public:
|
|||
BOOL getCursorHidden() { return mCursorHidden; }
|
||||
void moveCursorToCenter(); // move to center of window
|
||||
|
||||
void setShowProgress(const BOOL show,BOOL fullscreen);
|
||||
void initTextures(S32 location_id);
|
||||
void setShowProgress(const BOOL show, BOOL fullscreen);
|
||||
BOOL getShowProgress() const;
|
||||
void setProgressString(const std::string& string);
|
||||
void setProgressPercent(const F32 percent);
|
||||
|
|
|
|||
|
|
@ -265,6 +265,22 @@ void LLXMLRPCTransaction::Handler::onCompleted(LLCore::HttpHandle handle,
|
|||
// the contents of a buffer array are potentially noncontiguous, so we
|
||||
// will need to copy them into an contiguous block of memory for XMLRPC.
|
||||
LLCore::BufferArray *body = response->getBody();
|
||||
|
||||
//<FS:Beq> crash in transaction completion (see bugsplat https://app.bugsplat.com/v2/keycrash?database=fs_windows&stackKeyId=13)
|
||||
if(body == nullptr)
|
||||
{
|
||||
// status should be 0 but log it anyway
|
||||
// everything past this point appears to depend on the body data
|
||||
// so log the issues and return.
|
||||
LL_WARNS()
|
||||
<< "LLXMLRPCTransaction response has no body. status="
|
||||
<< status.toHex() << ": " << status.toString() << LL_ENDL;
|
||||
LL_WARNS()
|
||||
<< "LLXMLRPCTransaction request URI: "
|
||||
<< mImpl->mURI << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
//</FS:Beq>
|
||||
char * bodydata = new char[body->size()];
|
||||
|
||||
body->read(0, bodydata, body->size());
|
||||
|
|
@ -302,8 +318,7 @@ void LLXMLRPCTransaction::Handler::onCompleted(LLCore::HttpHandle handle,
|
|||
<< faultString << LL_ENDL;
|
||||
LL_WARNS() << "LLXMLRPCTransaction request URI: "
|
||||
<< mImpl->mURI << LL_ENDL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ void LLPipeline::init()
|
|||
sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
|
||||
sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
|
||||
LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
|
||||
LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
|
||||
// <FS:Ansariel> Vertex Array Objects are required in OpenGL core profile
|
||||
//LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
|
||||
LLVertexBuffer::sUseVAO = LLRender::sGLCoreProfile ? TRUE : gSavedSettings.getBOOL("RenderUseVAO");
|
||||
// </FS:Ansariel>
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@
|
|||
<menu_item_call name="inventory_new_hair" label="Nowe włosy" />
|
||||
<menu_item_call name="inventory_new_eyes" label="Nowe oczy" />
|
||||
</menu>
|
||||
<menu label="Nowe otoczenie" name="New Settings">
|
||||
<menu_item_call label="Nowe niebo" name="New Sky" />
|
||||
<menu_item_call label="Nowa woda" name="New Water" />
|
||||
<menu_item_call label="Nowy cykl dnia" name="New Day Cycle" />
|
||||
</menu>
|
||||
</menu>
|
||||
<menu label="Porządkuj" name="inventory_sort_menu">
|
||||
<menu_item_check name="inventory_sort_by_name" label="Po nazwie" />
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.6 KiB |
|
|
@ -584,6 +584,7 @@ with the same filename but different name
|
|||
<texture name="Music_Press" file_name="icons/Music_Press.png" preload="true" />
|
||||
|
||||
<texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />
|
||||
<texture name="ProgressBarSolid" file_name="widgets/ProgressBarSolid.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />
|
||||
<texture name="ProgressTrack" file_name="widgets/ProgressTrack.png" preload="true" scale.left="4" scale.top="13" scale.right="148" scale.bottom="2" />
|
||||
|
||||
<texture name="PushButton_Disabled" file_name="widgets/PushButton_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
|
||||
|
|
@ -1048,7 +1049,6 @@ with the same filename but different name
|
|||
<texture name="Icon_DialogStack" file_name="icons/Icon_DialogStack.png" preload="false" />
|
||||
|
||||
<texture name="Command_Discord_Icon" file_name="toolbar_icons/discord.png" preload="true" />
|
||||
<texture name="FMOD_Logo" file_name="icons/FMOD_logo.png" preload="true" />
|
||||
|
||||
<!-- Higher Resolution 200px Loading Progress Indicator -->
|
||||
<texture name="ProgressLarge_1" file_name="icons/ProgressLarge_1.png" preload="true" />
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 208 B |
|
|
@ -44,6 +44,37 @@ UI-Künstler und Designer:
|
|||
</scroll_container>
|
||||
</panel>
|
||||
<panel label="Lizenzen" name="licenses_panel">
|
||||
<text_editor name="licenses_editor">
|
||||
3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion.
|
||||
APR Copyright (C) 2011 The Apache Software Foundation
|
||||
Collada DOM Copyright 2006 Sony Computer Entertainment Inc.
|
||||
cURL Copyright (C) 1996-2010, Daniel Stenberg (daniel@haxx.se).
|
||||
DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
|
||||
expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
|
||||
FMOD Sound System Copyright (C) Firelight Technologies Pty, Ltd., 1994-2020
|
||||
FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm und Werner Lemberg.
|
||||
GL Copyright (C) 1999-2004 Brian Paul.
|
||||
GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University sowie David Luebke, Brenden Schubert, University of Virginia.
|
||||
Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
|
||||
HACD Copyright (C) 2011, Khaled Mamou (kmamou@gmail.com)
|
||||
jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW).
|
||||
jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
ogg/vorbis Copyright (C) 2002, Xiphophorus.
|
||||
OpenSSL Copyright (C) 1998-2008 The OpenSSL Project.
|
||||
PCRE Copyright (c) 1997-2012 University of Cambridge.
|
||||
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga.
|
||||
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com).
|
||||
xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
|
||||
zlib Copyright (C) 1995-2012 Jean-loup Gailly und Mark Adler.
|
||||
|
||||
Second Life Viewer verwendet Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (und Lizenzgeber). Alle Rechte vorbehalten. Details siehe www.havok.com.
|
||||
|
||||
Diese Software enthält von der NVIDIA Corporation bereitgestellten Quellcode.
|
||||
|
||||
Alle Rechte vorbehalten. Details siehe licenses.txt.
|
||||
|
||||
Audiocodierung für Voice-Chat: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
|
||||
</text_editor>
|
||||
</panel>
|
||||
</tab_container>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<floater name="Delete Pref Preset" title="Voreinstellung löschen">
|
||||
<floater name="delete_pref_preset" title="Voreinstellung löschen">
|
||||
<string name="title_graphic">
|
||||
Grafik-Voreinstellung löschen
|
||||
</string>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<floater name="save_pref_preset" title="Grafikvoreinstellung speichern">
|
||||
<string name="title_graphic">
|
||||
Grafikvoreinstellung speichern
|
||||
</string>
|
||||
<string name="title_camera">
|
||||
Kameravoreinstellung speichern
|
||||
</string>
|
||||
<text name="Preset">
|
||||
Geben Sie einen Namen für die Voreinstellung ein oder wählen Sie eine vorhandene Voreinstellung aus.
|
||||
</text>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
<menu_item_call label="Papierkorb ausleeren" name="Empty Trash"/>
|
||||
<menu_item_call label="Fundstücke ausleeren" name="Empty Lost And Found"/>
|
||||
<menu_item_call label="Neuer Ordner" name="New Folder"/>
|
||||
<menu_item_call label="Neues Outfit" name="New Outfit"/>
|
||||
<menu_item_call label="Neues Skript" name="New Script"/>
|
||||
<menu_item_call label="Neue Notizkarte" name="New Note"/>
|
||||
<menu_item_call label="Neue Geste" name="New Gesture"/>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
<text name="textSendName">
|
||||
(für eventuelle Rückfragen)
|
||||
</text>
|
||||
<text name="textRestartRequired">
|
||||
Änderungen an jeglichen Einstellungen werden erst nach einem Neustart aktiv.
|
||||
</text>
|
||||
<text name="textInformation1">
|
||||
Sofern nicht ausgewählt, enthalten die Meldungen nur absturzrelevante Informationen.
|
||||
</text>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<panel name="login_progress_panel">
|
||||
<layout_stack name="horizontal_centering">
|
||||
<layout_panel name="center">
|
||||
<layout_stack name="vertical_centering">
|
||||
<layout_panel name="panel4">
|
||||
<layout_stack name="vertical_centering">
|
||||
<layout_panel name="panel_login">
|
||||
<text name="login_text">
|
||||
Anmeldung...
|
||||
</text>
|
||||
</layout_panel>
|
||||
<layout_panel name="panel_icons">
|
||||
<text name="logos_lbl">
|
||||
[APP_NAME] verwendet
|
||||
</text>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</panel>
|
||||
|
|
@ -227,40 +227,17 @@ Adam Frisby, Alexandrea Fride, DarkAgent Baphomet, David Rowe, Digital Scribe, H
|
|||
label="Licenses"
|
||||
help_topic="about_licenses_tab"
|
||||
name="licenses_panel">
|
||||
|
||||
<layout_stack
|
||||
border_size="0"
|
||||
animate="false"
|
||||
follows="all"
|
||||
clip="true"
|
||||
bottom="-1"
|
||||
right="-4"
|
||||
layout="topleft"
|
||||
orientation="vertical"
|
||||
name="license_layout_stack"
|
||||
top="10"
|
||||
left="0">
|
||||
<layout_panel
|
||||
auto_resize="true"
|
||||
user_resize="false"
|
||||
name="licenses_panel"
|
||||
top="0"
|
||||
layout="topleft"
|
||||
height="400"
|
||||
right="-4"
|
||||
follows="all">
|
||||
|
||||
<text_editor
|
||||
enabled="false"
|
||||
follows="all"
|
||||
bottom="-10"
|
||||
follows="left|top"
|
||||
height="532"
|
||||
bg_readonly_color="Transparent"
|
||||
left="0"
|
||||
left="4"
|
||||
text_color="LtGray"
|
||||
max_length="65536"
|
||||
name="licenses_editor"
|
||||
top="0"
|
||||
right="-1"
|
||||
top="16"
|
||||
width="474"
|
||||
word_wrap="true">
|
||||
3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion
|
||||
APR Copyright (C) 2011 The Apache Software Foundation
|
||||
|
|
@ -293,70 +270,6 @@ All rights reserved. See licenses.txt for details.
|
|||
|
||||
Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
|
||||
</text_editor>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
visible="false"
|
||||
auto_resize="true"
|
||||
user_resize="false"
|
||||
name="logos_panel"
|
||||
top="0"
|
||||
layout="topleft"
|
||||
height="50"
|
||||
left_pad="0"
|
||||
right="-1"
|
||||
follows="all">
|
||||
<layout_stack
|
||||
border_size="0"
|
||||
animate="false"
|
||||
follows="all"
|
||||
clip="true"
|
||||
bottom="-1"
|
||||
right="-1"
|
||||
layout="topleft"
|
||||
orientation="horizontal"
|
||||
name="logos_layout_stack"
|
||||
top="0"
|
||||
left="0">
|
||||
<layout_panel
|
||||
auto_resize="true"
|
||||
user_resize="false"
|
||||
name="left_center_helper_panel"
|
||||
top="0"
|
||||
layout="topleft"
|
||||
height="100"
|
||||
width="200"
|
||||
follows="all"/>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
user_resize="false"
|
||||
name="fmod_logo_panel"
|
||||
top="0"
|
||||
layout="topleft"
|
||||
height="100"
|
||||
width="182"
|
||||
follows="all">
|
||||
<icon
|
||||
visible="true"
|
||||
follows="left|right|top"
|
||||
image_name="FMOD_Logo"
|
||||
left="0"
|
||||
name="fmod_logo"
|
||||
top="1"
|
||||
height="48"
|
||||
width="182"/>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="true"
|
||||
user_resize="false"
|
||||
name="right_center_helper_panel"
|
||||
top="0"
|
||||
layout="topleft"
|
||||
height="100"
|
||||
width="200"
|
||||
follows="all"/>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</panel>
|
||||
</tab_container>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
name="delete_pref_preset"
|
||||
save_rect="true"
|
||||
title="Delete Pref Preset"
|
||||
width="300">
|
||||
width="240">
|
||||
|
||||
<string name="title_graphic">Delete Graphic Preset</string>
|
||||
<string name="title_camera">Delete Camera Preset</string>
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
follows="top|left|right"
|
||||
height="10"
|
||||
layout="topleft"
|
||||
left="20"
|
||||
left="10"
|
||||
name="Preset"
|
||||
top="30"
|
||||
width="200">
|
||||
|
|
@ -25,19 +25,19 @@
|
|||
<combo_box
|
||||
follows="top|left"
|
||||
layout="topleft"
|
||||
left="20"
|
||||
left="10"
|
||||
name="preset_combo"
|
||||
top_delta="20"
|
||||
width="200"/>
|
||||
width="220"/>
|
||||
<button
|
||||
follows="top|left"
|
||||
height="23"
|
||||
label="Delete"
|
||||
layout="topleft"
|
||||
top_delta="40"
|
||||
left="20"
|
||||
left="10"
|
||||
name="delete"
|
||||
width="70"/>
|
||||
width="100"/>
|
||||
<button
|
||||
follows="top|left"
|
||||
height="23"
|
||||
|
|
@ -45,5 +45,5 @@
|
|||
layout="topleft"
|
||||
left_pad="20"
|
||||
name="cancel"
|
||||
width="70"/>
|
||||
width="100"/>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@
|
|||
name="only_list"
|
||||
height="15"
|
||||
follows="top|left"
|
||||
right="-5"
|
||||
left="5">
|
||||
Only list objects that are:
|
||||
</text>
|
||||
|
|
@ -541,6 +542,7 @@
|
|||
height="15"
|
||||
top_pad="5"
|
||||
follows="top|left"
|
||||
right="-5"
|
||||
left="5">
|
||||
Exclude objects that are:
|
||||
</text>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<floater
|
||||
legacy_header_height="18"
|
||||
height="185"
|
||||
height="180"
|
||||
help_topic="floater_save_preset"
|
||||
layout="topleft"
|
||||
name="save_camera_preset"
|
||||
save_rect="true"
|
||||
title="Save Camera Preset"
|
||||
width="280">
|
||||
width="240">
|
||||
|
||||
<string name="btn_label_save">Save</string>
|
||||
<string name="btn_label_replace">Replace</string>
|
||||
<radio_group
|
||||
height="85"
|
||||
layout="topleft"
|
||||
left="20"
|
||||
left="5"
|
||||
top="15"
|
||||
width="150"
|
||||
name="radio_save_preset">
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
follows="top|left"
|
||||
height="23"
|
||||
layout="topleft"
|
||||
left="41"
|
||||
left="26"
|
||||
name="preset_txt_editor"
|
||||
width="200"
|
||||
top="45"/>
|
||||
|
|
@ -48,9 +48,9 @@
|
|||
label="Save"
|
||||
layout="topleft"
|
||||
top="145"
|
||||
left="25"
|
||||
left="10"
|
||||
name="save"
|
||||
width="110"/>
|
||||
width="100"/>
|
||||
<button
|
||||
follows="bottom|right"
|
||||
height="25"
|
||||
|
|
@ -58,12 +58,12 @@
|
|||
layout="topleft"
|
||||
left_pad="20"
|
||||
name="cancel"
|
||||
width="110"/>
|
||||
width="100"/>
|
||||
<!-- *HACK to correctly draw drop-down list over the buttons-->
|
||||
<combo_box
|
||||
follows="top|left"
|
||||
layout="topleft"
|
||||
left="41"
|
||||
left="26"
|
||||
name="preset_combo"
|
||||
top_delta="-40"
|
||||
width="200"/>
|
||||
|
|
|
|||
|
|
@ -1,42 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<floater
|
||||
legacy_header_height="18"
|
||||
height="145"
|
||||
height="140"
|
||||
help_topic="floater_save_preset"
|
||||
layout="topleft"
|
||||
name="save_pref_preset"
|
||||
save_rect="true"
|
||||
title="Save Graphic Preset"
|
||||
width="300">
|
||||
width="245">
|
||||
|
||||
<text
|
||||
follows="top|left|right"
|
||||
height="32"
|
||||
layout="topleft"
|
||||
word_wrap="true"
|
||||
left="20"
|
||||
left="10"
|
||||
name="Preset"
|
||||
top="30"
|
||||
width="200">
|
||||
width="220">
|
||||
Type a name for the preset or choose an existing preset.
|
||||
</text>
|
||||
<combo_box
|
||||
follows="top|left"
|
||||
layout="topleft"
|
||||
left="20"
|
||||
left="10"
|
||||
name="preset_combo"
|
||||
top_delta="35"
|
||||
allow_text_entry="true"
|
||||
width="200"/>
|
||||
width="220"/>
|
||||
<button
|
||||
follows="top|left"
|
||||
height="23"
|
||||
label="Save"
|
||||
layout="topleft"
|
||||
top_delta="40"
|
||||
left="20"
|
||||
left="10"
|
||||
name="save"
|
||||
width="70"/>
|
||||
width="100"/>
|
||||
<button
|
||||
follows="bottom|right"
|
||||
height="23"
|
||||
|
|
@ -44,5 +44,5 @@
|
|||
layout="topleft"
|
||||
left_pad="20"
|
||||
name="cancel"
|
||||
width="70"/>
|
||||
width="100"/>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -151,6 +151,14 @@
|
|||
function="Inventory.DoCreate"
|
||||
parameter="category" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="New Outfit"
|
||||
layout="topleft"
|
||||
name="New Outfit">
|
||||
<menu_item_call.on_click
|
||||
function="Inventory.DoCreate"
|
||||
parameter="outfit" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="New Script"
|
||||
layout="topleft"
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
height="20"
|
||||
width="230"
|
||||
text_color="White_25">
|
||||
(contains Second Life name)
|
||||
(contains username)
|
||||
</text>
|
||||
|
||||
<check_box
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
left="60"
|
||||
top_pad="0"
|
||||
height="16"
|
||||
label="Include Second Life name"
|
||||
label="Include username"
|
||||
name="checkSendName"
|
||||
width="160"
|
||||
enabled="false" />
|
||||
|
|
@ -77,6 +77,21 @@
|
|||
(used to ask for additional information if needed)
|
||||
</text>
|
||||
|
||||
<text
|
||||
layout="topleft"
|
||||
follows="top|left"
|
||||
left="30"
|
||||
type="string"
|
||||
length="1"
|
||||
height="10"
|
||||
mouse_opaque="false"
|
||||
name="textRestartRequired"
|
||||
top_pad="10"
|
||||
visible="false"
|
||||
width="475">
|
||||
Changes made to any setting require a restart to become effective.
|
||||
</text>
|
||||
|
||||
<text
|
||||
layout="topleft"
|
||||
follows="top|left"
|
||||
|
|
@ -86,7 +101,7 @@
|
|||
height="10"
|
||||
mouse_opaque="false"
|
||||
name="textInformation1"
|
||||
top_pad="30"
|
||||
top_pad="20"
|
||||
width="475">
|
||||
Unless checked above crash reports only contain information relevant to the crash.
|
||||
</text>
|
||||
|
|
@ -100,7 +115,7 @@
|
|||
mouse_opaque="false"
|
||||
name="textInformation2"
|
||||
width="475" >
|
||||
Second Life logs are not sent, please review the contents and email separately
|
||||
Logs are not sent, please review the contents and email separately
|
||||
</text>
|
||||
<text
|
||||
layout="topleft"
|
||||
|
|
|
|||
|
|
@ -44,68 +44,128 @@
|
|||
width="670" />
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
height="250"
|
||||
height="275"
|
||||
layout="topleft"
|
||||
min_height="250"
|
||||
min_height="275"
|
||||
name="panel4"
|
||||
width="670">
|
||||
<icon
|
||||
color="LoginProgressBoxCenterColor"
|
||||
follows="left|right|bottom|top"
|
||||
height="250"
|
||||
height="275"
|
||||
image_name="Rounded_Square"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
top="0"
|
||||
width="670" />
|
||||
<text
|
||||
follows="left|right|top"
|
||||
font="SansSerifHuge"
|
||||
font_shadow="none"
|
||||
halign="left"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
left_delta="47"
|
||||
name="title_text"
|
||||
text_color="LoginProgressBoxTextColor"
|
||||
top_delta="50"
|
||||
right="-47"/>
|
||||
<text
|
||||
follows="left|right|top"
|
||||
font="SansSerif"
|
||||
font_shadow="none"
|
||||
halign="left"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
name="progress_text"
|
||||
text_color="LoginProgressBoxTextColor"
|
||||
top_pad="5"
|
||||
right="-47"
|
||||
word_wrap="true"/>
|
||||
<progress_bar
|
||||
bottom="115"
|
||||
color_bar="1 1 1 0.96"
|
||||
follows="left|right|top"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
left="45"
|
||||
name="login_progress_bar"
|
||||
right="-45" />
|
||||
<text
|
||||
<layout_stack
|
||||
follows="left|right|top|bottom"
|
||||
font="SansSerifLarge"
|
||||
font_shadow="none"
|
||||
halign="left"
|
||||
height="100"
|
||||
height="275"
|
||||
layout="topleft"
|
||||
left="45"
|
||||
line_spacing.pixels="2"
|
||||
name="message_text"
|
||||
text_color="LoginProgressBoxTextColor"
|
||||
top="145"
|
||||
right="-90"
|
||||
word_wrap="true"/>
|
||||
left="0"
|
||||
orientation="vertical"
|
||||
name="vertical_centering"
|
||||
animate="false"
|
||||
top="0"
|
||||
width="670">
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
height="30"
|
||||
layout="topleft"
|
||||
min_height="30"
|
||||
name="panel_top_spacer"
|
||||
width="670">
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
height="100"
|
||||
layout="topleft"
|
||||
min_height="100"
|
||||
name="panel_login"
|
||||
width="670">
|
||||
<text
|
||||
follows="left|right|top"
|
||||
layout="topleft"
|
||||
font="SansSerifHuge"
|
||||
font_shadow="none"
|
||||
halign="left"
|
||||
height="20"
|
||||
left="47"
|
||||
top="32"
|
||||
right="-47"
|
||||
name="title_text"
|
||||
text_color="LoginProgressBoxTextColor"/>
|
||||
<text
|
||||
follows="left|right|top"
|
||||
layout="topleft"
|
||||
font="SansSerif"
|
||||
font_shadow="none"
|
||||
halign="left"
|
||||
height="20"
|
||||
top_pad="5"
|
||||
right="-47"
|
||||
left_delta="0"
|
||||
name="progress_text"
|
||||
text_color="LoginProgressBoxTextColor"
|
||||
word_wrap="true"/>
|
||||
<progress_bar
|
||||
color_bar="1 1 1 0.96"
|
||||
follows="left|right|top"
|
||||
layout="topleft"
|
||||
height="16"
|
||||
left="45"
|
||||
top_pad="5"
|
||||
name="login_progress_bar"
|
||||
right="-45" />
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
height="110"
|
||||
layout="topleft"
|
||||
min_height="110"
|
||||
name="panel_motd"
|
||||
width="670">
|
||||
<text
|
||||
follows="left|right|top|bottom"
|
||||
font="SansSerifLarge"
|
||||
font_shadow="none"
|
||||
halign="left"
|
||||
valign="center"
|
||||
height="100"
|
||||
layout="topleft"
|
||||
left="45"
|
||||
line_spacing.pixels="2"
|
||||
name="message_text"
|
||||
text_color="LoginProgressBoxTextColor"
|
||||
top="7"
|
||||
right="-90"
|
||||
word_wrap="true"/>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
height="40"
|
||||
layout="topleft"
|
||||
min_height="40"
|
||||
name="panel_icons"
|
||||
width="670">
|
||||
<!--Logos are tied to following label from code-->
|
||||
<text
|
||||
follows="left|right|top"
|
||||
layout="topleft"
|
||||
font="SansSerifLarge"
|
||||
font_shadow="none"
|
||||
halign="left"
|
||||
height="16"
|
||||
width="240"
|
||||
left="47"
|
||||
top="6"
|
||||
line_spacing.pixels="2"
|
||||
name="logos_lbl"
|
||||
text_color="LoginProgressBoxTextColor">
|
||||
[APP_NAME] uses
|
||||
</text>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
height="200"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
<string name="str_label_use_region">Use Region Settings</string>
|
||||
<string name="str_altitude_desription">Sky [INDEX]([ALTITUDE]m)</string>
|
||||
<string name="str_no_parcel">No parcel is selected. Environmental settings are disabled.</string>
|
||||
<string name="str_cross_region">Environmental settings are not available across region boundries.</string>
|
||||
<string name="str_cross_region">Environmental settings are not available across region boundaries.</string>
|
||||
<string name="str_legacy">Environmental settings are not available on this region.</string>
|
||||
<string name="str_disallowed">The estate manager does not allow changing parcel environments in this region.</string>
|
||||
<string name="str_too_small">The parcel must be at least 128 square meters to support an environment.</string>
|
||||
|
|
|
|||
|
|
@ -369,17 +369,6 @@ to notecards on this region.
|
|||
<string name="TooltipNotecardOwnerRestrictedDrop">
|
||||
Only items with unrestricted
|
||||
'next owner' permissions
|
||||
"can be attached to notecards.
|
||||
</string>
|
||||
|
||||
<!-- ToolTips for notecards -->
|
||||
<string name="TooltipNotecardNotAllowedTypeDrop">
|
||||
Items of this type can't be attached
|
||||
to notecards on this region.
|
||||
</string>
|
||||
<string name="TooltipNotecardOwnerRestrictedDrop">
|
||||
Only items with unrestricted
|
||||
'next owner' permissions
|
||||
can be attached to notecards.
|
||||
</string>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
follows="left|top"
|
||||
height="11"
|
||||
layout="topleft"
|
||||
name="exponential_term_label"
|
||||
left="15"
|
||||
top_pad="-5"
|
||||
width="120">
|
||||
|
|
@ -45,6 +46,7 @@ Exponential Term
|
|||
follows="left|top"
|
||||
height="11"
|
||||
layout="topleft"
|
||||
name="exponential_scale_factor_label"
|
||||
left="15"
|
||||
top_pad="-5"
|
||||
width="120">
|
||||
|
|
@ -69,6 +71,7 @@ Exponential Scale Factor
|
|||
follows="left|top"
|
||||
height="11"
|
||||
layout="topleft"
|
||||
name="linear_term_label"
|
||||
left="15"
|
||||
top_pad="-5"
|
||||
width="120">
|
||||
|
|
@ -93,6 +96,7 @@ Linear Term
|
|||
follows="left|top"
|
||||
height="11"
|
||||
layout="topleft"
|
||||
name="constant_term_label"
|
||||
left="15"
|
||||
top_pad="-5"
|
||||
width="120">
|
||||
|
|
@ -117,6 +121,7 @@ Constant Term
|
|||
follows="left|top"
|
||||
height="11"
|
||||
layout="topleft"
|
||||
name="max_altitude_label"
|
||||
left="15"
|
||||
top_pad="15"
|
||||
width="80">
|
||||
|
|
|
|||
|
|
@ -83,6 +83,38 @@ Artistas y Diseñadores de la interfaz:
|
|||
</scroll_container>
|
||||
</panel>
|
||||
<panel label="Licencias" name="licenses_panel">
|
||||
<text_editor name="licenses_editor">
|
||||
3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion
|
||||
APR Copyright (C) 2011 The Apache Software Foundation
|
||||
Collada DOM Copyright 2006 Sony Computer Entertainment Inc.
|
||||
cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se)
|
||||
DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
|
||||
expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
|
||||
FMOD Sound System, Copyright (C) Firelight Technologies Pty, Ltd., 1994-2020
|
||||
FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, y Werner Lemberg.
|
||||
GL Copyright (C) 1999-2004 Brian Paul.
|
||||
GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
|
||||
Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
|
||||
HACD Copyright (C) 2011, Khaled Mamou (kmamou@gmail.com)
|
||||
jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
|
||||
jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
ogg/vorbis Copyright (C) 2002, Xiphophorus
|
||||
OpenSSL Copyright (C) 1998-2008 The OpenSSL Project.
|
||||
PCRE Copyright (c) 1997-2012 University of Cambridge
|
||||
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
|
||||
zlib Copyright (C) 1995-2012 Jean-loup Gailly y Mark Adler.
|
||||
Algunos iconos por Joseph Wain / glyphish.com
|
||||
|
||||
Second Life Viewer usa Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (y sus licenciadores). Todos los derechos reservados. Ver www.havok.com para más detalles.
|
||||
|
||||
Este software contiene código fuente proporcionado por NVIDIA Corporation.
|
||||
|
||||
Todos los derechos reservados. Ver licenses.txt para más detalles.
|
||||
|
||||
Codificación de audio del chat de voz: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
|
||||
</text_editor>
|
||||
</panel>
|
||||
</tab_container>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -64,6 +64,37 @@ con contributi open source da:
|
|||
</text_editor>
|
||||
</panel>
|
||||
<panel label="Licenze" name="licenses_panel">
|
||||
<text_editor name="licenses_editor">
|
||||
3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion
|
||||
APR Copyright (C) 2011 The Apache Software Foundation
|
||||
Collada DOM Copyright 2006 Sony Computer Entertainment Inc.
|
||||
cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se)
|
||||
DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
|
||||
expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
|
||||
FMOD Sound System Copyright (C) Firelight Technologies Pty, Ltd., 1994-2020
|
||||
FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg.
|
||||
GL Copyright (C) 1999-2004 Brian Paul.
|
||||
GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
|
||||
Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
|
||||
HACD Copyright (C) 2011, Khaled Mamou (kmamou@gmail.com)
|
||||
jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
|
||||
jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
ogg/vorbis Copyright (C) 2002, Xiphophorus
|
||||
OpenSSL Copyright (C) 1998-2008 The OpenSSL Project.
|
||||
PCRE Copyright (c) 1997-2012 University of Cambridge
|
||||
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
|
||||
zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler.
|
||||
|
||||
Il Viewer Second Life utilizza Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (e licenziatari). Tutti i diritti riservati. Per informazioni dettagliate, vedere www.havok.com.
|
||||
|
||||
Questo software contiene codice sorgente fornito da NVIDIA Corporation.
|
||||
|
||||
Tutti i diritti riservati. Per informazioni dettagliate, vedere licenses.txt.
|
||||
|
||||
Codifica audio chat vocale: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
|
||||
</text_editor>
|
||||
</panel>
|
||||
</tab_container>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,34 @@
|
|||
<text_editor name="contrib_names">Dummy Name は実行時間に置き換え</text_editor>
|
||||
</panel>
|
||||
<panel label="ライセンス" name="licenses_panel">
|
||||
<text_editor name="licenses_editor">3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion
|
||||
APR Copyright (C) 2011 The Apache Software Foundation
|
||||
Collada DOM Copyright 2006 Sony Computer Entertainment Inc.
|
||||
cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se)
|
||||
DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
|
||||
expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
|
||||
FMOD Sound System Copyright (C) Firelight Technologies Pty, Ltd., 1994-2020
|
||||
FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg.
|
||||
GL Copyright (C) 1999-2004 Brian Paul.
|
||||
GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
|
||||
Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
|
||||
jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
|
||||
jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
ogg/vorbis Copyright (C) 2002, Xiphophorus
|
||||
OpenSSL Copyright (C) 1998-2008 The OpenSSL Project.
|
||||
PCRE Copyright (c) 1997-2012 University of Cambridge
|
||||
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
|
||||
zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler.
|
||||
|
||||
Second Life ビューワでは Havok (TM) Physics が使用されています。(c)Copyright 1999-2010 Havok.com Inc. (and its Licensors).無断複写・複製・転載を禁じます。詳細については www.havok.com をご参照ください。
|
||||
|
||||
このソフトウェアには、NVIDIA Corporation によるソースコードが含まれます。
|
||||
|
||||
無断複写・複製・転載を禁じます。詳細については licenses.txt をご参照ください。
|
||||
|
||||
ボイスチャットのオーディオコーディング:Polycom(R) Siren14(TM) (ITU-T Rec.G.722.1 Annex C)</text_editor>
|
||||
</panel>
|
||||
</tab_container>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -452,5 +452,6 @@ teksturę:
|
|||
</panel>
|
||||
</panel>
|
||||
<panel label="Przygody" name="land_experiences_panel"/>
|
||||
<panel label="Otoczenie" name="land_environment_panel" />
|
||||
</tab_container>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<floater name="env_adjust_snapshot" title="Własne oświetlenie">
|
||||
<layout_stack name="outer_stack">
|
||||
<layout_panel name="env_controls">
|
||||
<layout_stack name="settings_stack">
|
||||
<layout_panel name="lp_1">
|
||||
<text name="ambient_lbl">
|
||||
Otoczenie:
|
||||
</text>
|
||||
<text name="blue_horizon_lbl">
|
||||
Hor. błękitu:
|
||||
</text>
|
||||
<text name="blue_density_lbl">
|
||||
Gęst. błękitu:
|
||||
</text>
|
||||
<button label="Reset" tool_tip="Zamknij i zresetuj do otoczenia współdzielonego" name="btn_reset" />
|
||||
<text name="sun_color_lbl">
|
||||
Kolor Słońca:
|
||||
</text>
|
||||
<text name="cloud_color_lbl">
|
||||
Kolor chmur:
|
||||
</text>
|
||||
<text name="cloud_map_label">
|
||||
Obraz chmur:
|
||||
</text>
|
||||
<text name="water_map_label">
|
||||
Obraz wody:
|
||||
</text>
|
||||
</layout_panel>
|
||||
<layout_panel name="lp_2">
|
||||
<text name="haze_horizon_label">
|
||||
Horyzont mgły:
|
||||
</text>
|
||||
<text name="haze_density_label">
|
||||
Gęstość mgły:
|
||||
</text>
|
||||
<text name="cloud_coverage_label">
|
||||
Zachmurzenie:
|
||||
</text>
|
||||
<text name="cloud_scale_label">
|
||||
Rozmiar chmur:
|
||||
</text>
|
||||
<text name="scene_gamma_label">
|
||||
Gamma sceny:
|
||||
</text>
|
||||
</layout_panel>
|
||||
<layout_panel name="lp_3">
|
||||
<text name="label">
|
||||
Słońce:
|
||||
</text>
|
||||
<check_box label="Pokaż emiter" name="sunbeacon" />
|
||||
<text name="scale_label">
|
||||
Rozmiar:
|
||||
</text>
|
||||
<text name="glow_focus_label">
|
||||
Ostrość blasku:
|
||||
</text>
|
||||
<text name="glow_size_label">
|
||||
Rozmiar blasku:
|
||||
</text>
|
||||
<text name="star_brightness_label">
|
||||
Jasność gwiazd:
|
||||
</text>
|
||||
</layout_panel>
|
||||
<layout_panel name="lp_4">
|
||||
<text name="label">
|
||||
Księżyc:
|
||||
</text>
|
||||
<check_box label="Pokaż emiter" name="moonbeacon" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</floater>
|
||||
|
|
@ -20,5 +20,10 @@
|
|||
<check_box label="Źródeł dźwięku" name="sounds"/>
|
||||
<check_box label="Źródeł cząsteczek" name="particles"/>
|
||||
<check_box label="Źródeł mediów" name="moapbeacon"/>
|
||||
<text name="label_objects">
|
||||
Pokazuj kierunek:
|
||||
</text>
|
||||
<check_box label="Słońce" name="sun" />
|
||||
<check_box label="Księżyc" name="moon" />
|
||||
</panel>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@ Zapisz, kiedy skończysz.
|
|||
<button label="Zapisz" name="beamshape_save" />
|
||||
<button label="Wczytaj" name="beamshape_load" />
|
||||
<button label="Wyczyść" name="beamshape_clear" />
|
||||
<button label="Anuluj" name="cancel" />
|
||||
</floater>
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
<icon name="icon_script" tool_tip="Skrypty"/>
|
||||
<icon name="icon_sound" tool_tip="Dźwięki"/>
|
||||
<icon name="icon_texture" tool_tip="Tekstury"/>
|
||||
<icon name="icon_setting" tool_tip="Ustawienia otoczenia" />
|
||||
<button label="√ Wszystkie" name="check_all"/>
|
||||
<button label="Żadne" label_selected="Żadne" name="check_none"/>
|
||||
<text name="newperms">
|
||||
|
|
|
|||
|
|
@ -9,27 +9,31 @@
|
|||
<floater.string name="move_tooltip">
|
||||
Poruszaj kamerą w górę, w dół, w lewo i w prawo
|
||||
</floater.string>
|
||||
<panel name="zoom">
|
||||
<layout_stack name="camera_view_layout_stack">
|
||||
<layout_panel name="camera_rotate_layout_panel">
|
||||
<joystick_rotate name="cam_rotate_stick" tool_tip="Obróć kamerę wokół punktu skupienia"/>
|
||||
</layout_panel>
|
||||
<layout_panel name="camera_zoom_layout_panel">
|
||||
<slider_bar name="zoom_slider" tool_tip="Przybliż kamerę do punktu skupienia"/>
|
||||
</layout_panel>
|
||||
<layout_panel name="panel_track">
|
||||
<joystick_track name="cam_track_stick" tool_tip="Poruszaj kamerą w górę, w dół, w lewo i w prawo"/>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
<floater.string name="free_mode_title">
|
||||
Pokaż obiekt
|
||||
</floater.string>
|
||||
<string name="inactive_combo_text">
|
||||
Użyj ustawienia
|
||||
</string>
|
||||
<panel name="controls">
|
||||
<panel name="zoom">
|
||||
<joystick_rotate name="cam_rotate_stick" tool_tip="Obróć kamerę wokół punktu skupienia"/>
|
||||
<slider_bar name="zoom_slider" tool_tip="Przybliż kamerę do punktu skupienia"/>
|
||||
<joystick_track name="cam_track_stick" tool_tip="Poruszaj kamerą w górę, w dół, w lewo i w prawo"/>
|
||||
</panel>
|
||||
</panel>
|
||||
<panel name="buttons_view">
|
||||
<panel name="buttons_panel">
|
||||
<panel_camera_item name="front_view" tool_tip="Widok od przodu"/>
|
||||
<panel_camera_item name="group_view" tool_tip="Widok ponad ramieniem"/>
|
||||
<panel_camera_item name="rear_view" tool_tip="Widok od tyłu"/>
|
||||
</panel>
|
||||
<panel name="buttons">
|
||||
<panel_camera_item name="object_view" tool_tip="Pokazywanie obiektu"/>
|
||||
<panel_camera_item name="mouselook_view" tool_tip="Widok pierwszoosobowy"/>
|
||||
<panel_camera_item name="reset_view" tool_tip="Resetuj widok"/>
|
||||
</panel>
|
||||
<combo_box name="preset_combo">
|
||||
<combo_box.item label="Użyj ustawienia" name="Use preset" />
|
||||
</combo_box>
|
||||
<button name="gear_btn" tool_tip="Ustawienia kamery" />
|
||||
<!-- <button label="Zapisz jako ustawienie" name="save_preset_btn" /> -->
|
||||
<button label="Pozycja kamery" name="camera_position_btn" />
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater title="Ustawienia kamery" name="floater_camera_presets" />
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater name="Edit Day cycle" title="Edytuj cykl dnia">
|
||||
<string name="title_new">Stwórz nowy cykl dnia</string>
|
||||
<string name="title_edit">Edytuj cykl dnia</string>
|
||||
<string name="hint_new">Nazwij cykl dnia, ustaw co trzeba i kliknij na "Zapisz".</string>
|
||||
<string name="hint_edit">Aby edytować cykl dnia ustaw co trzeba i kliknij na "Zapisz".</string>
|
||||
<string name="combo_label">-Wybierz Ustawienie-</string>
|
||||
<text name="label">
|
||||
Nazwa:
|
||||
</text>
|
||||
<text name="note">
|
||||
Uwaga: jeśli zmienisz nazwę Ustawienia, to zaczniesz tworzyć nowe, a obecne pozostanie bez zmian.
|
||||
</text>
|
||||
<text name="hint_item1">
|
||||
- Kliknij na zakładce, aby edytować ustawienia nieba i czas.
|
||||
</text>
|
||||
<text name="hint_item2">
|
||||
- Klikaj i przeciągaj zakładki, aby ustawić czasy przejść.
|
||||
</text>
|
||||
<text name="hint_item3">
|
||||
- Użyj suwaka, aby podglądać cykl dnia.
|
||||
</text>
|
||||
<panel name="day_cycle_slider_panel">
|
||||
<button label="Dodaj zakł." label_selected="Dodaj zakł." name="WLAddKey" />
|
||||
<button label="Usuń zakł." label_selected="Usuń zakł." name="WLDeleteKey" />
|
||||
<text name="WL12am">
|
||||
24:00
|
||||
</text>
|
||||
<text name="WL3am">
|
||||
3:00
|
||||
</text>
|
||||
<text name="WL6am">
|
||||
6:00
|
||||
</text>
|
||||
<text name="WL9amHash">
|
||||
9:00
|
||||
</text>
|
||||
<text name="WL12pmHash">
|
||||
12:00
|
||||
</text>
|
||||
<text name="WL3pm">
|
||||
15:00
|
||||
</text>
|
||||
<text name="WL6pm">
|
||||
18:00
|
||||
</text>
|
||||
<text name="WL9pm">
|
||||
21:00
|
||||
</text>
|
||||
<text name="WL12am2">
|
||||
24:00
|
||||
</text>
|
||||
</panel>
|
||||
<text name="WLCurKeyPresetText">
|
||||
Niebo:
|
||||
</text>
|
||||
<combo_box label="Ustawienie" name="WLSkyPresets" />
|
||||
<text name="WLCurKeyTimeText">
|
||||
Czas:
|
||||
</text>
|
||||
<time name="time" value="6:00"/>
|
||||
<check_box label="Ustaw jako mój cykl dnia" name="make_default_cb"/>
|
||||
<button label="Zapisz" name="save"/>
|
||||
<button label="Anuluj" name="cancel"/>
|
||||
</floater>
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater name="env_edit_extdaycycle" title="Edytuj cykl dnia">
|
||||
<string name="title_new">Stwórz nowy cykl dnia</string>
|
||||
<string name="title_edit">Edytuj cykl dnia</string>
|
||||
<string name="hint_new">Nazwij cykl dnia, ustaw co trzeba i kliknij na "Zapisz".</string>
|
||||
<string name="hint_edit">Aby edytować cykl dnia ustaw co trzeba i kliknij na "Zapisz".</string>
|
||||
<string name="sky_track_label">Niebo [ALT]</string>
|
||||
<string name="sky_label">Niebo</string>
|
||||
<string name="water_label">Woda</string>
|
||||
<string name="commit_parcel">Zastosuj do działki</string>
|
||||
<string name="commit_region">Zastosuj do regionu</string>
|
||||
<layout_stack name="outer_stack">
|
||||
<layout_panel name="name_and_import">
|
||||
<text name="label">
|
||||
Nazwa cyklu dnia:
|
||||
</text>
|
||||
<button label="Importuj" name="btn_import" tool_tip="Zaimportuj starsze ustawienia z dysku." />
|
||||
</layout_panel>
|
||||
<layout_panel name="content">
|
||||
<layout_stack name="content_stack">
|
||||
<layout_panel name="timeline_track_selection">
|
||||
<panel name="timeline_layers">
|
||||
<button label="Niebo 4" name="sky4_track" />
|
||||
<button label="Niebo 3" name="sky3_track" />
|
||||
<button label="Niebo 2" name="sky2_track" />
|
||||
<button label="Poziom ziemi" name="sky1_track" />
|
||||
<button label="Woda" name="water_track" />
|
||||
</panel>
|
||||
<panel name="timeline">
|
||||
<layout_stack name="track_options_ls">
|
||||
<layout_panel name="track_options_lp">
|
||||
<button label="Klonuj ścieżkę z" name="copy_track" />
|
||||
<button label="Wczytaj ścieżkę z" name="load_track" />
|
||||
<button label="Czyść ścieżkę" name="clear_track" />
|
||||
</layout_panel>
|
||||
<layout_panel name="track_progress_lp">
|
||||
<layout_stack name="progress_control">
|
||||
<layout_panel name="skip_back">
|
||||
<button name="skip_back_btn" tool_tip="Krok wstecz" />
|
||||
</layout_panel>
|
||||
<layout_panel name="skip_forward">
|
||||
<button name="skip_forward_btn" tool_tip="Krok w przód" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
<layout_panel name="frames_lp">
|
||||
<button label="Dodaj [FRAME]" name="add_frame" />
|
||||
<button label="Wczytaj [FRAME]" name="btn_load_frame" />
|
||||
<button label="Usuń [FRAME]" name="delete_frame" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</panel>
|
||||
</layout_panel>
|
||||
<layout_panel name="frame_edit_controls">
|
||||
<text name="icn_lock_edit">
|
||||
Wybierz klatkę kluczową z osi czasu, aby edytować ustawienia.
|
||||
</text>
|
||||
</layout_panel>
|
||||
<layout_panel name="frame_settings_water">
|
||||
<tab_container name="water_tabs">
|
||||
<panel label="Woda" name="water_panel" />
|
||||
</tab_container>
|
||||
</layout_panel>
|
||||
<layout_panel name="frame_settings_sky">
|
||||
<tab_container name="sky_tabs">
|
||||
<panel label="Atmosfera i oświetlenie" name="atmosphere_panel" />
|
||||
<panel label="Chmury" name="clouds_panel" />
|
||||
<panel label="Słońce i Księżyc" name="moon_panel" />
|
||||
<!-- <panel label="Gęstość" name="density_panel" /> -->
|
||||
</tab_container>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
<layout_panel name="buttons">
|
||||
<button label="Zapisz" name="save_btn" />
|
||||
<button label="Anuluj" name="cancel_btn" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</floater>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater name="HoverHeight" title="Ustaw uniesienie">
|
||||
<slider label="Unieś" name="HoverHeightSlider" />
|
||||
<check_box label="Wpływ na widok kamery" name="BindCameraCheck" />
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -1,109 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater name="Edit Sky Preset" title="Edytuj ustawienie nieba">
|
||||
<string name="title_new">
|
||||
Stwórz nowe Ustawienie nieba
|
||||
</string>
|
||||
<string name="title_edit">
|
||||
Edytuj Ustawienie nieba
|
||||
</string>
|
||||
<string name="combo_label">
|
||||
-Wybierz Ustawienie-
|
||||
</string>
|
||||
<panel name="P_Presetname">
|
||||
<text name="hint">
|
||||
Aby edytować Ustawienie ustaw co trzeba i kliknij na "Zapisz".
|
||||
</text>
|
||||
<text name="label">
|
||||
Nazwa:
|
||||
</text>
|
||||
</panel>
|
||||
<tab_container name="Main_Tab">
|
||||
<panel label="Atmosfera i Słońce" name="ASUN">
|
||||
<panel name="P_Atmosphere_Header">
|
||||
<text name="T_Atmosphere_Header">
|
||||
Ustawienia atmosfery
|
||||
</text>
|
||||
</panel>
|
||||
<panel name="P_Blue_Horizon">
|
||||
<text name="BHText" tool_tip="Horyzont błękitu: Kolor nieba. W ujęciu meteorologicznym to ustawienie wpływa na 'rozpraszanie atmosferyczne'.">
|
||||
Kolor
|
||||
</text>
|
||||
<text name="BDensText2" tool_tip="Gęstość błękitu: Wpływa na ogólne nasycenie kolorów nieba. Jeśli przesuniesz suwak Intensywności w górę, to kolory staną się jaśniejsze i bardziej żywe. W miarę przesuwania go w dół kolory będą stawać się ciemniejsze, w końcu zanikną w czerń i biel. Jeśli chcesz lepiej dostroić balans kolorów nieba możesz skonfigurować poszczególne elementy nasycenia za pomocą wartości kolorów czerwonego, zielonego i niebieskiego.">
|
||||
Gęstość
|
||||
</text>
|
||||
</panel>
|
||||
<panel name="P_Atmosphere_OtherSettings">
|
||||
<slider label="HorMgły" name="WLHazeHorizon" tool_tip="Horyzont mgły: Wpływa na wysokość mgły na horyzoncie. Przy wyższych ustawieniach mgła dotrze do nieba i zacznie przesłaniać rzeczywisty horyzont. Mgła na horyzoncie może przyczynić się do podkreślenia Słońca i stworzenia zakurzonej, przydymionej, wilgotnej atmosfery. To ustawienie nie będzie działać, jeśli Gęstość Mgły jest ustawiona na zero."/>
|
||||
<slider label="GęstMgły" name="WLHazeDensity" tool_tip="Gęstość mgły: Wpływa na ilość mgły widocznej w atmosferze. Niższe ustawienia sprawdzają się na zewnątrz, w środowisku zapylonym lub tropikalnym dając wspaniałe widoki, a wyższe mogą stworzyć gęstą, zasłaniającą wszystko, nieprzebytą mgłę. Jeśli ustawisz Gęstość Mgły na zero, to ustawienie Horyzontu Mgły nie będzie miało żadnego efektu."/>
|
||||
<slider label="MnżGęst" name="WLDensityMult" tool_tip="Mnożnik gęstości: Wpływa to na ogólną gęstość atmosfery. Przy niższych ustawieniach stwarza efekt czystego, 'lekkiego' powietrza, a na wyższych bardzo 'ciężkiego' smogu."/>
|
||||
<slider label="MnżOdl" name="WLDistanceMult" tool_tip="Mnożnik odległości: Wpływa na postrzeganą jasność/czystość w atmosferze. Aby wszystko wyglądało mgliste i odlegle przesuń suwak w prawo. Jeśli chcesz całkowicie usunąć skutki 'Ustawienia Nieba' z terenu i obiektów należy ustawić suwak na zero."/>
|
||||
<slider label="MaksWys" name="WLMaxAltitude" tool_tip="Maks. wysokość: Reguluje wysokość przeliczania, na której Second Life przetwarza dane dla nastrojowego oświetlenia. W późniejszych porach dnia ta opcja może być przydatna do obliczania jak 'głęboko' pojawia się zachód słońca, a w południe może być stosowany w celu uzyskania odpowiedniej wartości jasności."/>
|
||||
</panel>
|
||||
<panel name="P_Sun_and_Moon_Header">
|
||||
<text name="T_Sun_and_Moon_Header">
|
||||
Słońce i Księżyc
|
||||
</text>
|
||||
</panel>
|
||||
<panel name="P_SM_Color">
|
||||
<text name="SLCText" tool_tip="Kolor Słońca/Księżyca - Wpływa na kolor światła emitowanego przez Słońce i Księżyc. Należy pamiętać, że światło słoneczne/księżycowe wpłynie na kolor nieba!">
|
||||
Kolor
|
||||
</text>
|
||||
<text name="WLAmbientText" tool_tip="Otoczenie - Reguluje kolor i intensywność oświetlenia otoczenia w atmosferze. Jest to wykorzystywane do symulacji, jak światło słoneczne jest rozpraszane przez atmosferę i inne obiekty zanim dotrze do Ziemi. Możesz stworzyć bardzo jasne Słońce i stosunkowo ciemny świat (pomyśl o zachodzie słońca!) z Otoczeniem ustawionym na zero, ale jeśli chcesz zasymulować oświetlenie południa wraz ze Słońcem zawieszonym nisko na niebie musisz zwiększyć ustawienie Otoczenia.">
|
||||
Otocz.
|
||||
</text>
|
||||
</panel>
|
||||
<panel name="P_SM_OtherSettings">
|
||||
<slider label="BS.Skup" name="WLGlowB" tool_tip="Blask Słońca: Skupienie - Reguluje jak mocno blask Słońca rozpościera się na niebie. Przy ustawieniach wysokich Skupienie może spowodować, że Słońce całkowicie przesłoni część nieba jasnym światłem, a na zerowych, że Słońce (ale nie światło, które rzuca) zniknie zupełnie z nieba."/>
|
||||
<slider label="BS.Rozm" name="WLGlowR" tool_tip="Blask Słońca: Rozmiar - Określa rozmiar obrazu Słońca."/>
|
||||
<slider label="Gwiazdy" name="WLStarAlpha" tool_tip="Jasność gwiazd - Określa jak bardzo gwiazdy są widoczne na niebie. Jeśli będziesz się bawić tym suwakiem podczas gdy Słońce będzie na niebie, to gwiazdy pojawią się w środku dnia."/>
|
||||
<slider label="Gamma" name="WLGamma" tool_tip="Gamma sceny - Regulacja dystrybucją produkcji światła i ciemności na ekranie. Niższe ustawienia spowodują, że wszystko będzie wyglądać dość 'słabo' i ciemno, natomiast wyższe mogą wyszarzyć scenę i 'wypłowić' kolory. Wpływa tylko na widok 3D, nie na menu i resztę ekranu komputera. UWAGA: Wartość 1.0 jest domyślna."/>
|
||||
</panel>
|
||||
<panel name="P_WL_Daycycle">
|
||||
<icon name="SkyDayCycle" tool_tip="Pozycja Słońca/Księżyca - Wpływa na pionowe położenie Słońca i Księżyca, od wschodu (0.0) poprzez południe (0.25), zachód (0.5), północ (0.75) z powrotem do wschodu (1.0)."/>
|
||||
<time name="WLDayTime" tool_tip="Pozycja Słońca/Księżyca - Wpływa na pionowe położenie Słońca i Księżyca, od wschodu (0.0) poprzez południe (0.25), zachód (0.5), północ (0.75) z powrotem do wschodu (1.0)."/>
|
||||
<slider label="Kąt wsch." name="WLEastAngle" tool_tip="Kąt wschodu - Zmienia azymut wschodu Słońca zgodnie z ruchem wskazówek zegara, relatywnie do kierunku wschodniego na mapie. Przy ustawieniu 0,5 Słońce wzejdzie na zachodzie i zajdzie na wschodzie, przy 0.25 wzejdzie na południu i zajdzie na północy itd."/>
|
||||
</panel>
|
||||
</panel>
|
||||
<panel name="P_Clouds" label="Chmury">
|
||||
<panel name="P_Clouds_Header">
|
||||
<text name="T_Clouds_Header">
|
||||
Ustawienia chmur
|
||||
</text>
|
||||
</panel>
|
||||
<panel name="P_Cloud_Color">
|
||||
<text name="WLCloudColorText" tool_tip="Kolor chmur - Wpływa na kolor Twoich chmur, jeśli jakieś masz. Użyj suwaków Czerwieni/Zieleni/Błękitu do zmiany koloru indywidualnie lub suwaka natężenia (I) do regulacji wszystkich trzech na raz.">
|
||||
Kolor
|
||||
</text>
|
||||
</panel>
|
||||
<panel name="P_Cloud_Density">
|
||||
<text name="WLCloudColorText2" tool_tip="Gęstość chmur XY - Użyj suwaków X oraz Y aby zmienić pozycję poziomą wszystkich chmur na niebie. Suwak G dotyczy ogólnej gęstości poszczególnych chmur; przy niskich ustawieniach widać cienkie, delikatne chmury, a na wyższych grubsze, bardziej masywne.">
|
||||
Gęstość chmur XY
|
||||
</text>
|
||||
<slider label="G" name="WLCloudDensity"/>
|
||||
</panel>
|
||||
<panel name="P_Cloud_CovScale">
|
||||
<slider label="Zachm." name="WLCloudCoverage" tool_tip="Zachmurzenie - Reguluje częstość pokrycia nieba chmurami."/>
|
||||
<slider label="Rozmiar" name="WLCloudScale" tool_tip="Rozmiar chmur: Reguluje odczuwalną wielkość chmur."/>
|
||||
</panel>
|
||||
<panel name="P_Cloud_Detail">
|
||||
<text name="WLCloudDetailText" tool_tip="Detale chmur (XY/Gęstość) - Wpływa na pozycję i szczegółowość chmur. Suwaki X oraz Y przesuwają je w poziomie, a suwak G kontroluje jak bardzo są puszyste/poszarpane.">
|
||||
Detale chmur (XY/Gęstość)
|
||||
</text>
|
||||
<slider label="G" name="WLCloudDetailDensity"/>
|
||||
</panel>
|
||||
<panel name="P_Cloud_Scroll">
|
||||
<text name="WLCloudScrollXText" tool_tip="Przesuwanie X - Wpływa na kierunek i prędkość, z jaką poruszają się chmury na niebie wzdłuż osi X.">
|
||||
Przesuwanie X
|
||||
</text>
|
||||
<check_box label="Blokada przesuwania" name="WLCloudLockX" tool_tip="Blokada przesuwania - Chmury nie mogą poruszać się wzdłuż wybranej osi."/>
|
||||
<text name="WLCloudScrollYText" tool_tip="Przesuwanie Y - Wpływa na kierunek i prędkość, z jaką poruszają się chmury na niebie wzdłuż osi Y.">
|
||||
Przesuwanie Y
|
||||
</text>
|
||||
<check_box label="Blokada przesuwania" name="WLCloudLockY" tool_tip="Blokada przesuwania - Chmury nie mogą poruszać się wzdłuż wybranej osi."/>
|
||||
</panel>
|
||||
</panel>
|
||||
</tab_container>
|
||||
<check_box label="Ustaw jako moje Ustawienie Nieba" name="make_default_cb"/>
|
||||
<button label="Zapisz" name="save"/>
|
||||
<button label="Anuluj" name="cancel"/>
|
||||
</floater>
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater name="Edit Water Preset" title="Edytuj ustawienie wody">
|
||||
<string name="title_new">
|
||||
Stwórz nowe Ustawienie wody
|
||||
</string>
|
||||
<string name="title_edit">
|
||||
Edytuj Ustawienie wody
|
||||
</string>
|
||||
<string name="combo_label">
|
||||
-Wybierz Ustawienie-
|
||||
</string>
|
||||
<panel name="P_Presetname">
|
||||
<text name="label">
|
||||
Nazwa:
|
||||
</text>
|
||||
</panel>
|
||||
<tab_container name="Main_Tab">
|
||||
<panel name="P_Fog_and_Wave" label="Mgła i fale">
|
||||
<panel name="P_Water_Fog">
|
||||
<text name="water_color_label" tool_tip="Kolor mgły wody - Reguluje kolor zabarwienia wody, zasadniczo określa kolor samej wody. Jeśli woda nie ma mgły będzie wyglądać na krystalicznie czystą i bezbarwną.">
|
||||
Kolor mgły wody
|
||||
</text>
|
||||
<text name="BHText3" tool_tip="Mapa wektorów normalnych - Obraz służący do określenia odbić i załamań. Każda tekstura może być użyta w tym miejscu, ale prawdziwe mapy wektorów normalnych działają najlepiej. Spróbuj wstawić tutaj skórę węża, płytki lub jakąkolwiek inną mapę wektorów normalnych, aby uzyskać różne zwariowane efekty!">
|
||||
Mapa normalnych
|
||||
</text>
|
||||
</panel>
|
||||
<panel name="P_Fog_Settings">
|
||||
<text tool_tip="Gęstość mgły - Reguluje gęstość Twojej mgły wodnej; To ustawienie określa, jak głęboko pod taflę wody jesteś w stanie zobaczyć patrząc od góry." name="water_fog_density_label">
|
||||
Gęstość mgły
|
||||
</text>
|
||||
<text tool_tip="Modyfikator mgły pod wodą - Reguluje jak zmienia się gęstość mgły wodnej, gdy jesteś pod powierzchnią wody. Przydatne do umożliwiania patrzenia daleko spod tafli wody przy zachowaniu samej powierzchni dość nieprzejrzystej. Na przykład przy ustawieniu 0,25 mgła wodna jest pod wodą gęsta w 1/4 tego, niż by to wynikało podczas patrzenia znad powierzchni." name="underwater_fog_modifier_label">
|
||||
Modyfikator mgły pod wodą
|
||||
</text>
|
||||
</panel>
|
||||
<panel name="P_Wave_Settings">
|
||||
<text name="BHText" tool_tip="Kierunek Wielkiej Fali - Kontroluje kierunek i prędkość X oraz Y obrazu Wielkiej Fali.">
|
||||
Kierunek Wielkiej Fali
|
||||
</text>
|
||||
<text name="BHText2" tool_tip="Kierunek Małej Fali - Kontroluje kierunek i prędkość X oraz Y obrazu Małej Fali.">
|
||||
Kierunek Małej Fali
|
||||
</text>
|
||||
</panel>
|
||||
</panel>
|
||||
<panel name="P_Reflection" label="Odbicia">
|
||||
<panel name="P_Wavelet">
|
||||
<text name="BDensText" tool_tip="Skala odbicia falkowego - Kontroluje skalę trzech falek, które tworzą powierzchnię wody.">
|
||||
Skala odbicia falkowego
|
||||
</text>
|
||||
</panel>
|
||||
<panel name="P_Other_Settings">
|
||||
<text name="HDText" tool_tip="Skala Fresnela - Określa, jak mocno światło odbija się pod różnymi kątami; Zwiększenie wartości tego suwaka zmniejsza efekty wizualne odbić na powierzchni wody.">
|
||||
Skala Fresnela
|
||||
</text>
|
||||
<text name="FresnelOffsetText" tool_tip="Przesunięcie Fresnela - Określa, jak dużo światła ogółem jest odbijanego; Zwiększenie wartości tego suwaka zwiększa ilość światła odbitego od powierzchni wody.">
|
||||
Przesunięcie Fresnela
|
||||
</text>
|
||||
<text name="DensMultText" tool_tip="Skala załamania ponad - Kontroluje ilość wizualnego załamania, jakie można zobaczyć patrząc z góry na powierzchnię wody; To jest efekt 'chybotania' gdy patrzy się na obiekt znajdujący się pod powierzchnią wody.">
|
||||
Skala załamania ponad
|
||||
</text>
|
||||
<text name="WaterScaleBelowText" tool_tip="Skala załamania poniżej - Kontroluje ilość wizualnego załamania, jakie można zobaczyć patrząc od spodu na powierzchnię wody. To jest efekt 'chybotania' gdy patrzy się na obiekt znajdujący się nad powierzchnią wody.">
|
||||
Skala załamania poniżej
|
||||
</text>
|
||||
<text name="MaxAltText" tool_tip="Mnożnik rozmycia - Kontroluje sposób, w jaki fale i odbicia są z sobą mieszane. Podniesienie wartości tego ustawienia zwiększy stopień zniekształceń widoczny w wyniku działania fal.">
|
||||
Mnożnik rozmycia
|
||||
</text>
|
||||
</panel>
|
||||
</panel>
|
||||
</tab_container>
|
||||
<check_box label="Ustaw jako moje Ustawienie Wody" name="make_default_cb"/>
|
||||
<button label="Zapisz" name="save"/>
|
||||
<button label="Anuluj" name="cancel"/>
|
||||
</floater>
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater name="Environment Editor Floater" title="Ustawienia otoczenia">
|
||||
<check_box label="Zawsze używaj ustawień działki/regionu." name="use_env_from_region_always" tool_tip="Zaznaczenie tej opcji spowoduje, że otoczenie zawsze będzie używać poniższych ustawień."/>
|
||||
<radio_group name="region_settings_radio_group">
|
||||
<radio_item label="Użyj ustawień regionu" name="use_region_settings"/>
|
||||
<radio_item label="Dostosuj otoczenie" name="use_my_settings"/>
|
||||
</radio_group>
|
||||
<panel name="user_environment_settings">
|
||||
<text name="note1">
|
||||
UWAGA: Twoje ustawienia będą
|
||||
</text>
|
||||
<text name="note2">
|
||||
niewidoczne dla innych.
|
||||
</text>
|
||||
<text name="water_settings_title">
|
||||
Ustaw. wody
|
||||
</text>
|
||||
<combo_box name="water_settings_preset_combo">
|
||||
<combo_box.item label="-Wybierz Ustawienie-" name="item0"/>
|
||||
</combo_box>
|
||||
<text name="sky_dayc_settings_title">
|
||||
Ustaw. nieba (stałe lub cykliczne):
|
||||
</text>
|
||||
<radio_group name="sky_dayc_settings_radio_group">
|
||||
<radio_item label="Stałe" name="my_sky_settings"/>
|
||||
<radio_item label="Cykl dnia" name="my_dayc_settings"/>
|
||||
</radio_group>
|
||||
<combo_box name="sky_settings_preset_combo">
|
||||
<combo_box.item label="-Wybierz Ustawienie-" name="item0"/>
|
||||
</combo_box>
|
||||
<combo_box name="dayc_settings_preset_combo">
|
||||
<combo_box.item label="-Wybierz Ustawienie-" name="item0"/>
|
||||
</combo_box>
|
||||
</panel>
|
||||
<button label="Gotowe" name="ok_btn"/>
|
||||
<button label="Anuluj" name="cancel_btn"/>
|
||||
</floater>
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater name="Fixed Environment" title="Stałe otoczenie">
|
||||
<string name="edit_sky">
|
||||
Edytuj niebo:
|
||||
</string>
|
||||
<string name="edit_water">
|
||||
Edytuj wodę:
|
||||
</string>
|
||||
<layout_stack name="floater_stack">
|
||||
<layout_panel name="info_panel">
|
||||
<text>
|
||||
Nazwa:
|
||||
</text>
|
||||
<button label="Wczytaj" name="btn_load" tool_tip="Wczytaj ustawienia z szafy" />
|
||||
<button label="Importuj" name="btn_import" tool_tip="Zaimportuj starsze ustawienia z dysku." />
|
||||
</layout_panel>
|
||||
<layout_panel name="button_panel">
|
||||
<layout_stack name="button_bar_ls">
|
||||
<layout_panel name="save_btn_lp">
|
||||
<button label="Zapisz" name="btn_commit" />
|
||||
</layout_panel>
|
||||
<layout_panel name="revert_btn_lp">
|
||||
<button label="Anuluj" name="btn_cancel" tool_tip="Przywróć ostatnią zapisaną wersję" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</floater>
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
<check_box label="Dźwięki" name="check_sound" />
|
||||
<check_box label="Tekstury" name="check_texture" />
|
||||
<check_box label="Zdjęcia" name="check_snapshot" />
|
||||
<check_box label="Otoczenia" name="check_settings" />
|
||||
<button label="Wszystko" label_selected="Wszystko" name="All" />
|
||||
<button label="Żadne" label_selected="Żadne" name="None" />
|
||||
<check_box label="Tylko transferowalne" name="check_transferable" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<floater name="Load Pref Preset" title="Wczytaj ustawienie">
|
||||
<floater name="load_pref_preset" title="Wczytaj ustawienie">
|
||||
<string name="title_graphic">
|
||||
Wczytaj ustawienie graficzne
|
||||
</string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<floater name="my_environments" title="Moje otoczenia">
|
||||
<layout_stack name="main_layout">
|
||||
<layout_panel name="filter_panel" label="Filtr">
|
||||
<check_box label="Dzień" name="chk_days" />
|
||||
<check_box label="Niebo" name="chk_skies" />
|
||||
<check_box label="Woda" name="chk_water" />
|
||||
<filter_editor label="Filtruj otoczenia" name="flt_search" />
|
||||
</layout_panel>
|
||||
<layout_panel name="list_panel" label="Otoczenia" />
|
||||
<layout_panel name="lp_showfolders">
|
||||
<check_box label="Wszystkie foldery" name="chk_showfolders" />
|
||||
</layout_panel>
|
||||
<layout_panel name="pnl_control">
|
||||
<panel name="pnl_bottom">
|
||||
<menu_button name="btn_gear" tool_tip="Więcej opcji" />
|
||||
<menu_button name="btn_newsettings" tool_tip="Stwórz nowe ustawienie" />
|
||||
<button name="btn_del" tool_tip="Usuń wybrany element" />
|
||||
</panel>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</floater>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue