diff options
| author | Dave Houlton <euclid@lindenlab.com> | 2020-06-19 17:18:18 +0000 | 
|---|---|---|
| committer | Dave Houlton <euclid@lindenlab.com> | 2020-06-19 17:18:18 +0000 | 
| commit | 5df284b23a2e7db47cf89de72044fe5d3df1ccf4 (patch) | |
| tree | a543deec1323c4dc1cc42207277d0c47bbebdb66 | |
| parent | b84e79e0f206ac49aa57c4ad2d8d3dd7b5d2fc4d (diff) | |
| parent | ba6a0f3f332ffc659b00ca4c298b96efe56c6b81 (diff) | |
Merged in merge-6.4.4 (pull request #167)
Merge master 6.4.4 into DRTVWR-510
41 files changed, 1927 insertions, 1778 deletions
| diff --git a/.gitignore b/.gitignore index 27b629a578..2d32e94c78 100755 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@  *.bak  *.diff  *.orig +*.patch  *.pyc  *.rej  *.swp diff --git a/autobuild.xml b/autobuild.xml index 1f1db48bdc..9041b8488f 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -729,38 +729,28 @@          <key>version</key>          <string>2.1.1.500375</string>        </map> -      <key>fmodex</key> +      <key>fmodstudio</key>        <map>          <key>copyright</key> -        <string>COPYRIGHT 2014 FIRELIGHT TECHNOLOGIES PTY LTD. ALL RIGHTS RESERVED</string> +        <string>FMOD Studio by Firelight Technologies Pty Ltd.</string> +        <key>description</key> +        <string>FMOD Studio API</string>          <key>license</key> -        <string>fmodex</string> +        <string>fmod</string>          <key>license_file</key> -        <string>LICENSES/fmodex.txt</string> +        <string>LICENSES/fmodstudio.txt</string>          <key>name</key> -        <string>fmodex</string> +        <string>fmodstudio</string>          <key>platforms</key>          <map> -          <key>darwin</key> -          <map> -            <key>archive</key> -            <map> -              <key>hash</key> -              <string>ed0d8767652aecd65a7fef3e28645bad</string> -              <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/fmodex_3p-update-fmodex/rev/297261/arch/Darwin/installer/fmodex-4.44.31.297261-darwin-297261.tar.bz2</string> -            </map> -            <key>name</key> -            <string>darwin</string> -          </map>            <key>darwin64</key>            <map>              <key>archive</key>              <map>                <key>hash</key> -              <string>93257fce19120c01751362775a01b925</string> +              <string>dc4c9122de8bf77f34cfc8227d10a272</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1545/3481/fmodex-4.44.64.501533-darwin64-501533.tar.bz2</string> +              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59038/554626/fmodstudio-2.00.07.541681-darwin64-541681.tar.bz2</string>              </map>              <key>name</key>              <string>darwin64</string> @@ -770,9 +760,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>b847ec838da1ad1dd646df9d74e9b395</string> +              <string>c491bdc1690f3d920c66be509ccc6ef2</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_3p-fmodex/rev/314207/arch/Linux/installer/fmodex-4.44.61.314207-linux-314207.tar.bz2</string> +              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59039/554632/fmodstudio-2.00.07.541681-linux-541681.tar.bz2</string>              </map>              <key>name</key>              <string>linux</string> @@ -782,9 +772,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>89a75d8719f7b2cbe1e54cd8407bb992</string> +              <string>ae75cdb1cc9da824c9e270bf97bfdd6c</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1544/3476/fmodex-4.44.64.501533-linux64-501533.tar.bz2</string> +              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/54589/506866/fmodstudio-2.00.07.538806-linux64-538806.tar.bz2</string>              </map>              <key>name</key>              <string>linux64</string> @@ -794,9 +784,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>601c2fc41a18812a45678ef9a87ef772</string> +              <string>7f0294b038eab2d89ecc73bbf08b6d94</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1546/3486/fmodex-4.44.64.501533-windows-501533.tar.bz2</string> +              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59042/554668/fmodstudio-2.00.07.541681-windows-541681.tar.bz2</string>              </map>              <key>name</key>              <string>windows</string> @@ -806,16 +796,16 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>e5cde35ae26ebfa256cfe670986e152e</string> +              <string>da2e8e2b809d8fe635ee437baa2a7386</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1547/3487/fmodex-4.44.64.501533-windows64-501533.tar.bz2</string> +              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59041/554656/fmodstudio-2.00.07.541681-windows64-541681.tar.bz2</string>              </map>              <key>name</key>              <string>windows64</string>            </map>          </map>          <key>version</key> -        <string>4.44.64.501533</string> +        <string>2.00.07.541681</string>        </map>        <key>fontconfig</key>        <map> diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 84e1c5d6fd..3a14bf522f 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -28,7 +28,6 @@ set(cmake_SOURCE_FILES      FindAPR.cmake      FindAutobuild.cmake      FindBerkeleyDB.cmake -    FindFMODEX.cmake      FindGLH.cmake      FindGoogleBreakpad.cmake      FindHUNSPELL.cmake @@ -39,7 +38,7 @@ set(cmake_SOURCE_FILES      FindURIPARSER.cmake      FindXmlRpcEpi.cmake      FindZLIB.cmake -    FMODEX.cmake +    FMODSTUDIO.cmake      FreeType.cmake      GLEXT.cmake      GLH.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index c73a1fdb47..82cd5d62e8 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -62,14 +62,10 @@ if(WINDOWS)        endif(ADDRESS_SIZE EQUAL 32)      endif (BUGSPLAT_DB) -    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 (FMODSTUDIO) +        set(debug_files ${debug_files} fmodL.dll) +        set(release_files ${release_files} fmod.dll) +    endif (FMODSTUDIO)      #*******************************      # Copy MS C runtime dlls, required for packaging. @@ -192,10 +188,10 @@ elseif(DARWIN)          libnghttp2.14.14.0.dylib         ) -    if (FMODEX) -      set(debug_files ${debug_files} libfmodexL.dylib) -      set(release_files ${release_files} libfmodex.dylib) -    endif (FMODEX) +    if (FMODSTUDIO) +      set(debug_files ${debug_files} libfmodL.dylib) +      set(release_files ${release_files} libfmod.dylib) +    endif (FMODSTUDIO)  elseif(LINUX)      # linux is weird, multiple side by side configurations aren't supported @@ -242,10 +238,10 @@ elseif(LINUX)          libfontconfig.so.1         ) -    if (FMODEX) -      set(debug_files ${debug_files} "libfmodexL.so") -      set(release_files ${release_files} "libfmodex.so") -    endif (FMODEX) +    if (FMODSTUDIO) +      set(debug_files ${debug_files} "libfmodL.so") +      set(release_files ${release_files} "libfmod.so") +    endif (FMODSTUDIO)  else(WINDOWS)      message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...") diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake deleted file mode 100644 index 720933d1b7..0000000000 --- a/indra/cmake/FMODEX.cmake +++ /dev/null @@ -1,46 +0,0 @@ -# -*- cmake -*- - -# FMOD can be set when launching the make using the argument -DFMOD: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 (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) -        set(FMODEX_LIBRARY  -            debug fmodexL_vc -            optimized fmodex_vc) -      elseif (DARWIN) -        set(FMODEX_LIBRARY  -            debug fmodexL -            optimized fmodex) -      elseif (LINUX) -        set(FMODEX_LIBRARY  -            debug fmodexL -            optimized fmodex) -      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) - diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake new file mode 100644 index 0000000000..8840354ac6 --- /dev/null +++ b/indra/cmake/FMODSTUDIO.cmake @@ -0,0 +1,38 @@ +# -*- cmake -*- + +# FMODSTUDIO can be set when launching the make using the argument -DFMODSTUDIO:BOOL=ON +# When building using proprietary binaries though (i.e. having access to LL private servers), +# we always build with FMODSTUDIO. +if (INSTALL_PROPRIETARY) +  set(FMODSTUDIO ON CACHE BOOL "Using FMODSTUDIO sound library.") +endif (INSTALL_PROPRIETARY) + +if (FMODSTUDIO) +  if (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR) +    # If the path have been specified in the arguments, use that +    set(FMODSTUDIO_LIBRARIES ${FMODSTUDIO_LIBRARY}) +  else (FMODSTUDIO_LIBRARY AND FMODSTUDIO_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(fmodstudio) +    if (WINDOWS) +      set(FMODSTUDIO_LIBRARY +          debug fmodL_vc +          optimized fmod_vc) +    elseif (DARWIN) +      #despite files being called libfmod.dylib, we are searching for fmod +      set(FMODSTUDIO_LIBRARY +          debug fmodL +          optimized fmod) +    elseif (LINUX) +      set(FMODSTUDIO_LIBRARY +          debug fmodL +          optimized fmod) +    endif (WINDOWS) +    set(FMODSTUDIO_LIBRARIES ${FMODSTUDIO_LIBRARY}) +    set(FMODSTUDIO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodstudio) +  endif (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR) +endif (FMODSTUDIO) + diff --git a/indra/cmake/FindFMODEX.cmake b/indra/cmake/FindFMODEX.cmake deleted file mode 100644 index b621727c0e..0000000000 --- a/indra/cmake/FindFMODEX.cmake +++ /dev/null @@ -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 -  ) diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt index e943dd5d5c..8b628a058e 100644 --- a/indra/llaudio/CMakeLists.txt +++ b/indra/llaudio/CMakeLists.txt @@ -4,7 +4,7 @@ project(llaudio)  include(00-Common)  include(LLAudio) -include(FMODEX) +include(FMODSTUDIO)  include(OPENAL)  include(LLCommon)  include(LLMath) @@ -42,22 +42,22 @@ set(llaudio_HEADER_FILES      llwindgen.h      ) -if (FMODEX) +if (FMODSTUDIO)      include_directories( -        ${FMODEX_INCLUDE_DIR} +        ${FMODSTUDIO_INCLUDE_DIR}          )      list(APPEND llaudio_SOURCE_FILES -         llaudioengine_fmodex.cpp -         lllistener_fmodex.cpp -         llstreamingaudio_fmodex.cpp +         llaudioengine_fmodstudio.cpp +         lllistener_fmodstudio.cpp +         llstreamingaudio_fmodstudio.cpp           )      list(APPEND llaudio_HEADER_FILES -         llaudioengine_fmodex.h -         lllistener_fmodex.h -         llstreamingaudio_fmodex.h +         llaudioengine_fmodstudio.h +         lllistener_fmodstudio.h +         llstreamingaudio_fmodstudio.h           ) -endif (FMODEX) +endif (FMODSTUDIO)  if (OPENAL)    list(APPEND llaudio_SOURCE_FILES diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index f49028aad5..1d447f32ae 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -111,7 +111,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(); diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index f1e1b4e308..97674f15f7 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -99,7 +99,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(); diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp deleted file mode 100644 index 7e65a05e48..0000000000 --- a/indra/llaudio/llaudioengine_fmodex.cpp +++ /dev/null @@ -1,767 +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" - -FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels); - -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(); -} - - -LLAudioEngine_FMODEX::~LLAudioEngine_FMODEX() -{ -	delete mWindDSPDesc; -} - - -inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) -{ -	if(result == FMOD_OK) -		return false; -	LL_DEBUGS() << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; -	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() << "Strean 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"); - -	U32 fmod_flags = FMOD_INIT_NORMAL; -	if(mEnableProfiler) -	{ -		fmod_flags |= FMOD_INIT_ENABLE_PROFILE; -		mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]); -		mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]); -		mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]); -		mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]); -	} - -#if LL_LINUX -	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; -			if(mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK && -				(result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) -			{ -				LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY"	<< LL_ENDL; -				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; -			if(mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK && -			    (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) -			{ -				LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; -				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; -			if(mSystem->setOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK && -			    (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) -			{ -				LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; -				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; -	mSystem->getOutput(&output_type); -	switch (output_type) -	{ -		case FMOD_OUTPUTTYPE_NOSOUND:  -			LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; -		case FMOD_OUTPUTTYPE_PULSEAUDIO:	 -			LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break; -		case FMOD_OUTPUTTYPE_ALSA:  -			LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; -		case FMOD_OUTPUTTYPE_OSS:	 -			LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break; -		default: -			LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; -	}; -#else // LL_LINUX - -	// initialize the FMOD engine -	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 - -	// 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; - -	return true; -} - - -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() -{ -	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 -	{ -		mSystem->close(); -		mSystem->release(); -	} -	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) -	{ -		mWindDSP->remove(); -		mWindDSP->release(); -		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; -	mSystem->getMasterChannelGroup(&master_group); - -	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; -	mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES); - -	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; -	} - -	Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause"); - -	getSource()->setPlayedOnce(true); - -	if(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]) -		mChannelp->setChannelGroup(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]); -} - - -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; -	mChannelp->getPaused(&paused); -	mChannelp->isPlaying(&playing); -	return !paused && playing; -} - - -// -// LLAudioChannelFMODEX implementation -// - - -LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : mSystemp(system), mSoundp(NULL) -{ -} - - -LLAudioBufferFMODEX::~LLAudioBufferFMODEX() -{ -	if(mSoundp) -	{ -		mSoundp->release(); -		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; -	} - -	if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) -	{ -		// File not found, abort. -		return false; -	} -	 -	if (mSoundp) -	{ -		// If there's already something loaded in this buffer, clean it up. -		mSoundp->release(); -		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; -	mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES); -	return length; -} - - -void LLAudioChannelFMODEX::set3DMode(bool use3d) -{ -	FMOD_MODE current_mode; -	if(mChannelp->getMode(¤t_mode) != FMOD_OK) -		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) -	{ -		mChannelp->setMode(new_mode); -	} -} - -// *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); -	S32 channels, configwidth, configheight; -	thisdsp->getInfo(0, 0, &channels, &configwidth, &configheight); -	 -	windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length); - -	return FMOD_OK; -} diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp new file mode 100644 index 0000000000..70b3a08473 --- /dev/null +++ b/indra/llaudio/llaudioengine_fmodstudio.cpp @@ -0,0 +1,753 @@ +/**  + * @file audioengine_fmodstudio.cpp + * @brief Implementation of LLAudioEngine class abstracting the audio  + * support as a FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * 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 + * 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_fmodstudio.h" + +#include "llaudioengine_fmodstudio.h" +#include "lllistener_fmodstudio.h" + +#include "llerror.h" +#include "llmath.h" +#include "llrand.h" + +#include "fmodstudio/fmod.hpp" +#include "fmodstudio/fmod_errors.h" +#include "lldir.h" +#include "llapr.h" + +#include "sound_ids.h" + +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels); + +FMOD::ChannelGroup *LLAudioEngine_FMODSTUDIO::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0}; + +LLAudioEngine_FMODSTUDIO::LLAudioEngine_FMODSTUDIO(bool enable_profiler) +:   mInited(false), +    mWindGen(NULL), +    mWindDSP(NULL), +    mSystem(NULL), +    mEnableProfiler(enable_profiler), +    mWindDSPDesc(NULL) +{ +} + + +LLAudioEngine_FMODSTUDIO::~LLAudioEngine_FMODSTUDIO() +{ +    // mWindDSPDesc, mWindGen and mWindDSP get cleaned up on cleanupWind in LLAudioEngine::shutdown() +    // mSystem gets cleaned up at shutdown() +} + + +static inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) +{ +    if (result == FMOD_OK) +        return false; +    LL_DEBUGS("FMOD") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; +    return true; +} + +bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, const std::string &app_title) +{ +    U32 version; +    FMOD_RESULT result; + +    LL_DEBUGS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() initializing FMOD" << LL_ENDL; + +    result = FMOD::System_Create(&mSystem); +    if (Check_FMOD_Error(result, "FMOD::System_Create")) +        return false; + +    //will call LLAudioEngine_FMODSTUDIO::allocateListener, which needs a valid mSystem pointer. +    LLAudioEngine::init(num_channels, userdata, app_title); + +    result = mSystem->getVersion(&version); +    Check_FMOD_Error(result, "FMOD::System::getVersion"); + +    if (version < FMOD_VERSION) +    { +        LL_WARNS("AppInit") << "FMOD Studio version mismatch, actual: " << version +            << " expected:" << FMOD_VERSION << LL_ENDL; +    } + +    // 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"); + +    FMOD_ADVANCEDSETTINGS settings; +    memset(&settings, 0, sizeof(settings)); +    settings.cbSize = sizeof(FMOD_ADVANCEDSETTINGS); +    settings.resamplerMethod = FMOD_DSP_RESAMPLER_LINEAR; + +    result = mSystem->setAdvancedSettings(&settings); +    Check_FMOD_Error(result, "FMOD::System::setAdvancedSettings"); + +    // FMOD_INIT_THREAD_UNSAFE Disables thread safety for API calls. +    // Only use this if FMOD is being called from a single thread, and if Studio API is not being used. +    U32 fmod_flags = FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_THREAD_UNSAFE; +    if (mEnableProfiler) +    { +        fmod_flags |= FMOD_INIT_PROFILE_ENABLE; +    } + +#if LL_LINUX +    bool audio_ok = false; + +    if (!audio_ok) +    { +        const char* env_string = getenv("LL_BAD_FMOD_PULSEAUDIO"); +        if (NULL == env_string) +        { +            LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL; +            if (mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK && +                (result = mSystem->init(num_channels + 2, fmod_flags, const_cast<char*>(app_title.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) +    { +        const char* env_string = getenv("LL_BAD_FMOD_ALSA"); +        if (NULL == env_string) +        { +            LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; +            if (mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK && +                (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) +            { +                LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; +                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) +    { +        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; +    mSystem->getOutput(&output_type); +    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; +    default: +        LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; +    }; +#else // LL_LINUX + +    // initialize the FMOD engine +    // number of channel in this case looks to be identiacal to number of max simultaneously +    // playing objects and we can set practically any number +    result = mSystem->init(num_channels + 2, fmod_flags, 0); +    if (Check_FMOD_Error(result, "Error initializing FMOD Studio with default settins, retrying with other format")) +    { +        result = mSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_STEREO, 0/*- ignore*/); +        if (Check_FMOD_Error(result, "Error setting sotware format. Can't init.")) +        { +            return false; +        } +        result = mSystem->init(num_channels + 2, fmod_flags, 0); +    } +    if (Check_FMOD_Error(result, "Error initializing FMOD Studio")) +    { +        // If it fails here and (result == FMOD_ERR_OUTPUT_CREATEBUFFER), +        // we can retry with other settings +        return false; +    } +#endif + +    // set up our favourite FMOD-native streaming audio implementation if none has already been added +    if (!getStreamingAudioImpl()) // no existing implementation added +        setStreamingAudioImpl(new LLStreamingAudio_FMODSTUDIO(mSystem)); + +    LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() FMOD Studio initialized correctly" << LL_ENDL; + +    int r_numbuffers, r_samplerate, r_channels; +    unsigned int r_bufferlength; +    char r_name[512]; +    int latency = 100; +    mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers); +    LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_bufferlength=" << r_bufferlength << " bytes" << LL_ENDL; +    LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_numbuffers=" << r_numbuffers << LL_ENDL; + +    mSystem->getDriverInfo(0, r_name, 511, NULL, &r_samplerate, NULL, &r_channels); +    r_name[511] = '\0'; +    LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_name=\"" << r_name << "\"" << LL_ENDL; + +    if (r_samplerate != 0) +        latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate); +    LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): latency=" << latency << "ms" << LL_ENDL; + +    mInited = true; + +    LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): initialization complete." << LL_ENDL; + +    return true; +} + + +std::string LLAudioEngine_FMODSTUDIO::getDriverName(bool verbose) +{ +    llassert_always(mSystem); +    if (verbose) +    { +        U32 version; +        if (!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion")) +        { +            return llformat("FMOD Studio %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); +        } +    } +    return "FMOD STUDIO"; +} + + +void LLAudioEngine_FMODSTUDIO::allocateListener(void) +{ +    mListenerp = (LLListener *) new LLListener_FMODSTUDIO(mSystem); +    if (!mListenerp) +    { +        LL_WARNS("FMOD") << "Listener creation failed" << LL_ENDL; +    } +} + + +void LLAudioEngine_FMODSTUDIO::shutdown() +{ +    stopInternetStream(); + +    LL_INFOS("FMOD") << "About to LLAudioEngine::shutdown()" << LL_ENDL; +    LLAudioEngine::shutdown(); + +    LL_INFOS("FMOD") << "LLAudioEngine_FMODSTUDIO::shutdown() closing FMOD Studio" << LL_ENDL; +    if (mSystem) +    { +        mSystem->close(); +        mSystem->release(); +    } +    LL_INFOS("FMOD") << "LLAudioEngine_FMODSTUDIO::shutdown() done closing FMOD Studio" << LL_ENDL; + +    delete mListenerp; +    mListenerp = NULL; +} + + +LLAudioBuffer * LLAudioEngine_FMODSTUDIO::createBuffer() +{ +    return new LLAudioBufferFMODSTUDIO(mSystem); +} + + +LLAudioChannel * LLAudioEngine_FMODSTUDIO::createChannel() +{ +    return new LLAudioChannelFMODSTUDIO(mSystem); +} + +bool LLAudioEngine_FMODSTUDIO::initWind() +{ +    mNextWindUpdate = 0.0; + +    if (!mWindDSPDesc) +    { +        mWindDSPDesc = new FMOD_DSP_DESCRIPTION(); +    } + +    if (!mWindDSP) +    { +        memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc));	//Set everything to zero +        strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name)); +        mWindDSPDesc->pluginsdkversion = FMOD_PLUGIN_SDK_VERSION; +        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; + +        int frequency = 44100; + +        FMOD_SPEAKERMODE mode; +        if (Check_FMOD_Error(mSystem->getSoftwareFormat(&frequency, &mode, nullptr), "FMOD::System::getSoftwareFormat")) +        { +            cleanupWind(); +            return false; +        } + +        mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency); + +        if (Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData")) +        { +            cleanupWind(); +            return false; +        } +        if (Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat")) +        { +            cleanupWind(); +            return false; +        } +    } + +    // *TODO:  Should this guard against multiple plays? +    if (Check_FMOD_Error(mSystem->playDSP(mWindDSP, nullptr, false, nullptr), "FMOD::System::playDSP")) +    { +        cleanupWind(); +        return false; +    } +    return true; +} + + +void LLAudioEngine_FMODSTUDIO::cleanupWind() +{ +    if (mWindDSP) +    { +        FMOD::ChannelGroup* master_group = NULL; +        if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup") +            && master_group) +        { +            master_group->removeDSP(mWindDSP); +        } +        mWindDSP->release(); +        mWindDSP = NULL; +    } + +    delete mWindDSPDesc; +    mWindDSPDesc = NULL; + +    delete mWindGen; +    mWindGen = NULL; +} + + +//----------------------------------------------------------------------- +void LLAudioEngine_FMODSTUDIO::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_FMODSTUDIO::setInternalGain(F32 gain) +{ +    if (!mInited) +    { +        return; +    } + +    gain = llclamp(gain, 0.0f, 1.0f); + +    FMOD::ChannelGroup* master_group = NULL; +    if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup") +        && master_group) +    { +        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()); +    } +} + +// +// LLAudioChannelFMODSTUDIO implementation +// + +LLAudioChannelFMODSTUDIO::LLAudioChannelFMODSTUDIO(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0) +{ +} + + +LLAudioChannelFMODSTUDIO::~LLAudioChannelFMODSTUDIO() +{ +    cleanup(); +} + +bool LLAudioChannelFMODSTUDIO::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 +        // set up the channel for a different buffer. + +        LLAudioBufferFMODSTUDIO *bufferp = (LLAudioBufferFMODSTUDIO *)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(soundp, NULL /*free channel?*/, true, &mChannelp); +            Check_FMOD_Error(result, "FMOD::System::playSound"); +        } + +        // Setting up channel mChannelID +    } + +    // 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 LLAudioChannelFMODSTUDIO::update3DPosition() +{ +    if (!mChannelp) +    { +        // We're not actually a live channel (i.e., we're not playing back anything) +        return; +    } + +    LLAudioBufferFMODSTUDIO  *bufferp = (LLAudioBufferFMODSTUDIO  *)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 LLAudioChannelFMODSTUDIO::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; +    mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES); + +    if (cur_pos < (U32)mLastSamplePos) +    { +        mLoopedThisFrame = true; +    } +    mLastSamplePos = cur_pos; +} + + +void LLAudioChannelFMODSTUDIO::cleanup() +{ +    if (!mChannelp) +    { +        // Aborting cleanup with no channel handle. +        return; +    } + +    //Cleaning up channel mChannelID +    Check_FMOD_Error(mChannelp->stop(), "FMOD::Channel::stop"); + +    mCurrentBufferp = NULL; +    mChannelp = NULL; +} + + +void LLAudioChannelFMODSTUDIO::play() +{ +    if (!mChannelp) +    { +        LL_WARNS() << "Playing without a channel handle, aborting" << LL_ENDL; +        return; +    } + +    Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause"); + +    getSource()->setPlayedOnce(true); + +    if (LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]) +        mChannelp->setChannelGroup(LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]); +} + + +void LLAudioChannelFMODSTUDIO::playSynced(LLAudioChannel *channelp) +{ +    LLAudioChannelFMODSTUDIO *fmod_channelp = (LLAudioChannelFMODSTUDIO*)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 LLAudioChannelFMODSTUDIO::isPlaying() +{ +    if (!mChannelp) +    { +        return false; +    } + +    bool paused, playing; +    mChannelp->getPaused(&paused); +    mChannelp->isPlaying(&playing); +    return !paused && playing; +} + + +// +// LLAudioChannelFMODSTUDIO implementation +// + + +LLAudioBufferFMODSTUDIO::LLAudioBufferFMODSTUDIO(FMOD::System *system) : mSystemp(system), mSoundp(NULL) +{ +} + + +LLAudioBufferFMODSTUDIO::~LLAudioBufferFMODSTUDIO() +{ +    if (mSoundp) +    { +        mSoundp->release(); +        mSoundp = NULL; +    } +} + + +bool LLAudioBufferFMODSTUDIO::loadWAV(const std::string& filename) +{ +    // Try to open a wav file from disk.  This will eventually go away, as we don't +    // really want to block doing this. +    if (filename.empty()) +    { +        // invalid filename, abort. +        return false; +    } + +    if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) +    { +        // File not found, abort. +        return false; +    } + +    if (mSoundp) +    { +        // If there's already something loaded in this buffer, clean it up. +        mSoundp->release(); +        mSoundp = NULL; +    } + +    FMOD_MODE base_mode = FMOD_LOOP_NORMAL; +    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 (since 1.05 fmod studio expects everything in UTF-8) +    FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp); + +    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 LLAudioBufferFMODSTUDIO::getLength() +{ +    if (!mSoundp) +    { +        return 0; +    } + +    U32 length; +    mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES); +    return length; +} + + +void LLAudioChannelFMODSTUDIO::set3DMode(bool use3d) +{ +    FMOD_MODE current_mode; +    if (mChannelp->getMode(¤t_mode) != FMOD_OK) +        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) +    { +        mChannelp->setMode(new_mode); +    } +} + +// *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 *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels) +{ +    // inbuffer = fmod's original mixbuffer. +    // outbuffer = the buffer passed from the previous DSP unit. +    // length = length in samples at this mix time. + +    LLWindGen<LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT> *windgen = NULL; +    FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance; + +    thisdsp->getUserData((void **)&windgen); + +    if (windgen) +    { +        windgen->windGenerate((LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT *)outbuffer, length); +    } + +    return FMOD_OK; +} diff --git a/indra/llaudio/llaudioengine_fmodex.h b/indra/llaudio/llaudioengine_fmodstudio.h index ca389d489f..f2361df1b6 100644 --- a/indra/llaudio/llaudioengine_fmodex.h +++ b/indra/llaudio/llaudioengine_fmodstudio.h @@ -1,11 +1,11 @@  /**  - * @file audioengine_fmodex.h + * @file audioengine_fmodstudio.h   * @brief Definition of LLAudioEngine class abstracting the audio  - * support as a FMODEX 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 @@ -25,14 +25,14 @@   * $/LicenseInfo$   */ -#ifndef LL_AUDIOENGINE_FMODEX_H -#define LL_AUDIOENGINE_FMODEX_H +#ifndef LL_AUDIOENGINE_FMODSTUDIO_H +#define LL_AUDIOENGINE_FMODSTUDIO_H  #include "llaudioengine.h"  #include "llwindgen.h"  //Stubs -class LLAudioStreamManagerFMODEX; +class LLAudioStreamManagerFMODSTUDIO;  namespace FMOD  {  	class System; @@ -44,14 +44,14 @@ namespace FMOD  typedef struct FMOD_DSP_DESCRIPTION FMOD_DSP_DESCRIPTION;  //Interfaces -class LLAudioEngine_FMODEX : public LLAudioEngine  +class LLAudioEngine_FMODSTUDIO : public LLAudioEngine   {  public: -	LLAudioEngine_FMODEX(bool enable_profiler); -	virtual ~LLAudioEngine_FMODEX(); +	LLAudioEngine_FMODSTUDIO(bool enable_profiler); +	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(); @@ -85,11 +85,11 @@ public:  }; -class LLAudioChannelFMODEX : public LLAudioChannel +class LLAudioChannelFMODSTUDIO : public LLAudioChannel  {  public: -	LLAudioChannelFMODEX(FMOD::System *audioengine); -	virtual ~LLAudioChannelFMODEX(); +    LLAudioChannelFMODSTUDIO(FMOD::System *audioengine); +    virtual ~LLAudioChannelFMODSTUDIO();  protected:  	/*virtual*/ void play(); @@ -110,15 +110,15 @@ protected:  }; -class LLAudioBufferFMODEX : public LLAudioBuffer +class LLAudioBufferFMODSTUDIO : public LLAudioBuffer  {  public: -	LLAudioBufferFMODEX(FMOD::System *audioengine); -	virtual ~LLAudioBufferFMODEX(); +    LLAudioBufferFMODSTUDIO(FMOD::System *audioengine); +    virtual ~LLAudioBufferFMODSTUDIO();  	/*virtual*/ bool loadWAV(const std::string& filename);  	/*virtual*/ U32 getLength(); -	friend class LLAudioChannelFMODEX; +	friend class LLAudioChannelFMODSTUDIO;  protected:  	FMOD::System *getSystem()	const {return mSystemp;}  	FMOD::System *mSystemp; @@ -127,4 +127,4 @@ protected:  }; -#endif // LL_AUDIOENGINE_FMODEX_H +#endif // LL_AUDIOENGINE_FMODSTUDIO_H diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp index e6ac586618..a38d8291fa 100644 --- a/indra/llaudio/llaudioengine_openal.cpp +++ b/indra/llaudio/llaudioengine_openal.cpp @@ -52,7 +52,7 @@ 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); @@ -239,6 +239,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 diff --git a/indra/llaudio/llaudioengine_openal.h b/indra/llaudio/llaudioengine_openal.h index 6639d9dfe6..366f9259e3 100644 --- a/indra/llaudio/llaudioengine_openal.h +++ b/indra/llaudio/llaudioengine_openal.h @@ -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(); diff --git a/indra/llaudio/lllistener_fmodex.cpp b/indra/llaudio/lllistener_fmodex.cpp deleted file mode 100644 index 31ab47a635..0000000000 --- a/indra/llaudio/lllistener_fmodex.cpp +++ /dev/null @@ -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; -} - - diff --git a/indra/llaudio/lllistener_fmodstudio.cpp b/indra/llaudio/lllistener_fmodstudio.cpp new file mode 100644 index 0000000000..abd5e345b5 --- /dev/null +++ b/indra/llaudio/lllistener_fmodstudio.cpp @@ -0,0 +1,136 @@ +/**  + * @file listener_fmodstudio.cpp + * @brief Implementation of LISTENER class abstracting the audio + * support as a FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * 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 + * 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_fmodstudio.h" +#include "fmodstudio/fmod.hpp" + +//----------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------- +LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system) +{ +    mSystem = system; +    init(); +} + +//----------------------------------------------------------------------- +LLListener_FMODSTUDIO::~LLListener_FMODSTUDIO() +{ +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::init(void) +{ +    // do inherited +    LLListener::init(); +    mDopplerFactor = 1.0f; +    mRolloffFactor = 1.0f; +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::translate(LLVector3 offset) +{ +    LLListener::translate(offset); + +    mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::setPosition(LLVector3 pos) +{ +    LLListener::setPosition(pos); + +    mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::setVelocity(LLVector3 vel) +{ +    LLListener::setVelocity(vel); + +    mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::orient(LLVector3 up, LLVector3 at) +{ +    LLListener::orient(up, at); + +    // 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; +    } + +    mSystem->update(); +} + + +void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor) +{ +    //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; +} + + +void LLListener_FMODSTUDIO::setDopplerFactor(F32 factor) +{ +    mDopplerFactor = factor; +    mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); +} + + +F32 LLListener_FMODSTUDIO::getDopplerFactor() +{ +    return mDopplerFactor; +} diff --git a/indra/llaudio/lllistener_fmodex.h b/indra/llaudio/lllistener_fmodstudio.h index 073b65d53a..6ad85d9700 100644 --- a/indra/llaudio/lllistener_fmodex.h +++ b/indra/llaudio/lllistener_fmodstudio.h @@ -1,11 +1,11 @@  /**  - * @file listener_fmodex.h + * @file listener_fmodstudio.h   * @brief Description of LISTENER class abstracting the audio support - * as an FMOD 3D 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 @@ -25,8 +25,8 @@   * $/LicenseInfo$   */ -#ifndef LL_LISTENER_FMODEX_H -#define LL_LISTENER_FMODEX_H +#ifndef LL_LISTENER_FMODSTUDIO_H +#define LL_LISTENER_FMODSTUDIO_H  #include "lllistener.h" @@ -37,27 +37,27 @@ namespace FMOD  }  //Interfaces -class LLListener_FMODEX : public LLListener +class LLListener_FMODSTUDIO : public LLListener  { - public:   -	LLListener_FMODEX(FMOD::System *system); -	virtual ~LLListener_FMODEX(); -	virtual void init();   +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 diff --git a/indra/llaudio/llstreamingaudio_fmodex.cpp b/indra/llaudio/llstreamingaudio_fmodex.cpp deleted file mode 100644 index 9c9e85c00c..0000000000 --- a/indra/llaudio/llstreamingaudio_fmodex.cpp +++ /dev/null @@ -1,392 +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" - - -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; } - -	FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL); -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) -{ -	// Number of milliseconds of audio to buffer for the audio card. -	// Must be larger than the usual Second Life frame stutter time. -	const U32 buffer_seconds = 10;		//sec -	const U32 estimated_bitrate = 128;	//kbit/sec -	mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES); - -	// 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() -{ -	// nothing interesting/safe to do. -} - - -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()) -	{ -		LL_INFOS() << "Starting internet stream: " << url << LL_ENDL; -		mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url); -		mURL = url; -	} -	else -	{ -		LL_INFOS() << "Set internet stream to null" << LL_ENDL; -		mURL.clear(); -	} -} - - -void LLStreamingAudio_FMODEX::update() -{ -	// Kill dead internet streams, if possible -	std::list<LLAudioStreamManagerFMODEX *>::iterator iter; -	for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) -	{ -		LLAudioStreamManagerFMODEX *streamp = *iter; -		if (streamp->stopStream()) -		{ -			LL_INFOS() << "Closed dead stream" << LL_ENDL; -			delete streamp; -			mDeadStreams.erase(iter++); -		} -		else -		{ -			iter++; -		} -	} - -	// Don't do anything if there are no streams playing -	if (!mCurrentInternetStreamp) -	{ -		return; -	} - -	unsigned int progress; -	bool starving; -	bool diskbusy; -	FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy); - -	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()); -			mFMODInternetStreamChannelp->setPaused(false); -		} -	} -	else if(open_state == FMOD_OPENSTATE_ERROR) -	{ -		stop(); -		return; -	} - -	if(mFMODInternetStreamChannelp) -	{ -		FMOD::Sound *sound = NULL; - -		if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound) -		{ -			FMOD_TAG tag; -			S32 tagcount, dirtytagcount; - -			if(sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount) -			{ -				for(S32 i = 0; i < tagcount; ++i) -				{ -					if(sound->getTag(NULL, i, &tag)!=FMOD_OK) -						continue; - -					if (tag.type == 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; -					} -				} -			} - -			if(starving) -			{ -				bool paused = false; -				mFMODInternetStreamChannelp->getPaused(&paused); -				if(!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; -					mFMODInternetStreamChannelp->setPaused(true); -				} -			} -			else if(progress > 80) -			{ -				mFMODInternetStreamChannelp->setPaused(false); -			} -		} -	} -} - -void LLStreamingAudio_FMODEX::stop() -{ -	if (mFMODInternetStreamChannelp) -	{ -		mFMODInternetStreamChannelp->setPaused(true); -		mFMODInternetStreamChannelp->setPriority(0); -		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 -	} -	else if (!mURL.empty()) -	{ -		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? - -		mFMODInternetStreamChannelp->setVolume(vol); -	} -} - -/////////////////////////////////////////////////////// -// 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. -	if (!mInternetStream || getOpenState() != 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. - -	mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel); -	return mStreamChannel; -} - -bool LLAudioStreamManagerFMODEX::stopStream() -{ -	if (mInternetStream) -	{ - - -		bool close = true; -		switch (getOpenState()) -		{ -		case FMOD_OPENSTATE_CONNECTING: -			close = false; -			break; -		default: -			close = true; -		} - -		if (close) -		{ -			mInternetStream->release(); -			mStreamChannel = NULL; -			mInternetStream = NULL; -			return true; -		} -		else -		{ -			return false; -		} -	} -	else -	{ -		return true; -	} -} - -FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy) -{ -	FMOD_OPENSTATE state; -	mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy); -	return state; -} - -void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime) -{ -	mSystem->setStreamBufferSize(streambuffertime/1000*128*128, FMOD_TIMEUNIT_RAWBYTES); -	FMOD_ADVANCEDSETTINGS settings; -	memset(&settings,0,sizeof(settings)); -	settings.cbsize=sizeof(settings); -	settings.defaultDecodeBufferSize = decodebuffertime;//ms -	mSystem->setAdvancedSettings(&settings); -} diff --git a/indra/llaudio/llstreamingaudio_fmodex.h b/indra/llaudio/llstreamingaudio_fmodex.h deleted file mode 100644 index 2787840ba1..0000000000 --- a/indra/llaudio/llstreamingaudio_fmodex.h +++ /dev/null @@ -1,73 +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); -private: -	FMOD::System *mSystem; - -	LLAudioStreamManagerFMODEX *mCurrentInternetStreamp; -	FMOD::Channel *mFMODInternetStreamChannelp; -	std::list<LLAudioStreamManagerFMODEX *> mDeadStreams; - -	std::string mURL; -	F32 mGain; -}; - - -#endif // LL_STREAMINGAUDIO_FMODEX_H diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.cpp b/indra/llaudio/llstreamingaudio_fmodstudio.cpp new file mode 100644 index 0000000000..08d19209aa --- /dev/null +++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp @@ -0,0 +1,392 @@ +/**  + * @file streamingaudio_fmodstudio.cpp + * @brief LLStreamingAudio_FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * 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 + * 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 "fmodstudio/fmod.hpp" +#include "fmodstudio/fmod_errors.h" + +#include "llstreamingaudio_fmodstudio.h" + + +class LLAudioStreamManagerFMODSTUDIO +{ +public: +    LLAudioStreamManagerFMODSTUDIO(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; } + +    FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL); +protected: +    FMOD::System* mSystem; +    FMOD::Channel* mStreamChannel; +    FMOD::Sound* mInternetStream; +    bool mReady; + +    std::string mInternetStreamURL; +}; + + + +//--------------------------------------------------------------------------- +// Internet Streaming +//--------------------------------------------------------------------------- +LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) : +mSystem(system), +mCurrentInternetStreamp(NULL), +mFMODInternetStreamChannelp(NULL), +mGain(1.0f) +{ +    // Number of milliseconds of audio to buffer for the audio card. +    // Must be larger than the usual Second Life frame stutter time. +    const U32 buffer_seconds = 10;		//sec +    const U32 estimated_bitrate = 128;	//kbit/sec +    mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES); + +    // 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_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO() +{ +    // nothing interesting/safe to do. +} + + +void LLStreamingAudio_FMODSTUDIO::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()) +    { +        LL_INFOS() << "Starting internet stream: " << url << LL_ENDL; +        mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, url); +        mURL = url; +    } +    else +    { +        LL_INFOS() << "Set internet stream to null" << LL_ENDL; +        mURL.clear(); +    } +} + + +void LLStreamingAudio_FMODSTUDIO::update() +{ +    // 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++; +        } +    } + +    // Don't do anything if there are no streams playing +    if (!mCurrentInternetStreamp) +    { +        return; +    } + +    unsigned int progress; +    bool starving; +    bool diskbusy; +    FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy); + +    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()); +            mFMODInternetStreamChannelp->setPaused(false); +        } +    } +    else if (open_state == FMOD_OPENSTATE_ERROR) +    { +        stop(); +        return; +    } + +    if (mFMODInternetStreamChannelp) +    { +        FMOD::Sound *sound = NULL; + +        if (mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound) +        { +            FMOD_TAG tag; +            S32 tagcount, dirtytagcount; + +            if (sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount) +            { +                for (S32 i = 0; i < tagcount; ++i) +                { +                    if (sound->getTag(NULL, i, &tag) != FMOD_OK) +                        continue; + +                    if (tag.type == 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; +                    } +                } +            } + +            if (starving) +            { +                bool paused = false; +                mFMODInternetStreamChannelp->getPaused(&paused); +                if (!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; +                    mFMODInternetStreamChannelp->setPaused(true); +                } +            } +            else if (progress > 80) +            { +                mFMODInternetStreamChannelp->setPaused(false); +            } +        } +    } +} + +void LLStreamingAudio_FMODSTUDIO::stop() +{ +    if (mFMODInternetStreamChannelp) +    { +        mFMODInternetStreamChannelp->setPaused(true); +        mFMODInternetStreamChannelp->setPriority(0); +        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_FMODSTUDIO::pause(int pauseopt) +{ +    if (pauseopt < 0) +    { +        pauseopt = mCurrentInternetStreamp ? 1 : 0; +    } + +    if (pauseopt) +    { +        if (mCurrentInternetStreamp) +        { +            stop(); +        } +    } +    else +    { +        start(getURL()); +    } +} + + +// A stream is "playing" if it has been requested to start.  That +// doesn't necessarily mean audio is coming out of the speakers. +int LLStreamingAudio_FMODSTUDIO::isPlaying() +{ +    if (mCurrentInternetStreamp) +    { +        return 1; // Active and playing +    } +    else if (!mURL.empty()) +    { +        return 2; // "Paused" +    } +    else +    { +        return 0; +    } +} + + +F32 LLStreamingAudio_FMODSTUDIO::getGain() +{ +    return mGain; +} + + +std::string LLStreamingAudio_FMODSTUDIO::getURL() +{ +    return mURL; +} + + +void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol) +{ +    mGain = vol; + +    if (mFMODInternetStreamChannelp) +    { +        vol = llclamp(vol * vol, 0.f, 1.f);	//should vol be squared here? + +        mFMODInternetStreamChannelp->setVolume(vol); +    } +} + +/////////////////////////////////////////////////////// +// manager of possibly-multiple internet audio streams + +LLAudioStreamManagerFMODSTUDIO::LLAudioStreamManagerFMODSTUDIO(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 *LLAudioStreamManagerFMODSTUDIO::startStream() +{ +    // We need a live and opened stream before we try and play it. +    if (!mInternetStream || getOpenState() != 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. + +    mSystem->playSound(mInternetStream, NULL, true, &mStreamChannel); +    return mStreamChannel; +} + +bool LLAudioStreamManagerFMODSTUDIO::stopStream() +{ +    if (mInternetStream) +    { + + +        bool close = true; +        switch (getOpenState()) +        { +        case FMOD_OPENSTATE_CONNECTING: +            close = false; +            break; +        default: +            close = true; +        } + +        if (close) +        { +            mInternetStream->release(); +            mStreamChannel = NULL; +            mInternetStream = NULL; +            return true; +        } +        else +        { +            return false; +        } +    } +    else +    { +        return true; +    } +} + +FMOD_OPENSTATE LLAudioStreamManagerFMODSTUDIO::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy) +{ +    FMOD_OPENSTATE state; +    mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy); +    return state; +} + +void LLStreamingAudio_FMODSTUDIO::setBufferSizes(U32 streambuffertime, U32 decodebuffertime) +{ +    mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES); +    FMOD_ADVANCEDSETTINGS settings; +    memset(&settings, 0, sizeof(settings)); +    settings.cbSize = sizeof(settings); +    settings.defaultDecodeBufferSize = decodebuffertime;//ms +    mSystem->setAdvancedSettings(&settings); +} diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.h b/indra/llaudio/llstreamingaudio_fmodstudio.h new file mode 100644 index 0000000000..1fc3c54d79 --- /dev/null +++ b/indra/llaudio/llstreamingaudio_fmodstudio.h @@ -0,0 +1,73 @@ +/**  + * @file streamingaudio_fmodstudio.h + * @brief Definition of LLStreamingAudio_FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * 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 + * 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_FMODSTUDIO_H +#define LL_STREAMINGAUDIO_FMODSTUDIO_H + +#include "stdtypes.h" // from llcommon + +#include "llstreamingaudio.h" +#include "lltimer.h" + +//Stubs +class LLAudioStreamManagerFMODSTUDIO; +namespace FMOD +{ +	class System; +	class Channel; +} + +//Interfaces +class LLStreamingAudio_FMODSTUDIO : public LLStreamingAudioInterface +{ +public: +    LLStreamingAudio_FMODSTUDIO(FMOD::System *system); +    /*virtual*/ ~LLStreamingAudio_FMODSTUDIO(); + +    /*virtual*/ void start(const std::string& url); +    /*virtual*/ void stop(); +    /*virtual*/ void pause(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); +private: +    FMOD::System *mSystem; + +    LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp; +    FMOD::Channel *mFMODInternetStreamChannelp; +    std::list<LLAudioStreamManagerFMODSTUDIO *> mDeadStreams; + +    std::string mURL; +    F32 mGain; +}; + + +#endif // LL_STREAMINGAUDIO_FMODSTUDIO_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f76012bdfa..33fa186a2e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -18,7 +18,7 @@ include(DBusGlib)  include(DirectX)  include(DragDrop)  include(EXPAT) -include(FMODEX) +include(FMODSTUDIO)  include(GLOD)  include(Hunspell)  include(JsonCpp) @@ -63,9 +63,9 @@ if (NOT HAVOK_TPV)     add_subdirectory(${LLPHYSICSEXTENSIONS_SRC_DIR} llphysicsextensions)  endif (NOT HAVOK_TPV) -if(FMODEX) -  include_directories(${FMODEX_INCLUDE_DIR}) -endif(FMODEX) +if(FMODSTUDIO) +  include_directories(${FMODSTUDIO_INCLUDE_DIR}) +endif(FMODSTUDIO)  include_directories(      ${DBUSGLIB_INCLUDE_DIRS} @@ -1722,12 +1722,13 @@ if (OPENAL)    set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL")  endif (OPENAL) -if (FMODEX) -  set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") -  set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY}) -endif (FMODEX) +if (FMODSTUDIO) +  set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODSTUDIO") +  set(FMODWRAPPER_LIBRARY ${FMODSTUDIO_LIBRARY}) +endif (FMODSTUDIO)  set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") +set_source_files_properties(llprogressview.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")  list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES}) @@ -1842,13 +1843,13 @@ if (WINDOWS)              )      endif (ADDRESS_SIZE EQUAL 64) -    if (FMODEX) +    if (FMODSTUDIO)        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)      add_custom_command(        OUTPUT  ${CMAKE_CFG_INTDIR}/copy_touched.bat @@ -1859,6 +1860,7 @@ if (WINDOWS)          --arch=${ARCH}          --artwork=${ARTWORK_DIR}          "--bugsplat=${BUGSPLAT_DB}" +        "--fmodstudio=${FMODSTUDIO}"          --build=${CMAKE_CURRENT_BINARY_DIR}          --buildtype=${CMAKE_BUILD_TYPE}          "--channel=${VIEWER_CHANNEL}" @@ -1920,6 +1922,7 @@ if (WINDOWS)            --arch=${ARCH}            --artwork=${ARTWORK_DIR}            "--bugsplat=${BUGSPLAT_DB}" +          "--fmodstudio=${FMODSTUDIO}"            --build=${CMAKE_CURRENT_BINARY_DIR}            --buildtype=${CMAKE_BUILD_TYPE}            "--channel=${VIEWER_CHANNEL}" @@ -2065,6 +2068,7 @@ if (LINUX)          --arch=${ARCH}          --artwork=${ARTWORK_DIR}          "--bugsplat=${BUGSPLAT_DB}" +        "--fmodstudio=${FMODSTUDIO}"          --build=${CMAKE_CURRENT_BINARY_DIR}          --buildtype=${CMAKE_BUILD_TYPE}          "--channel=${VIEWER_CHANNEL}" @@ -2091,6 +2095,7 @@ if (LINUX)        --arch=${ARCH}        --artwork=${ARTWORK_DIR}        "--bugsplat=${BUGSPLAT_DB}" +      "--fmodstudio=${FMODSTUDIO}"        --build=${CMAKE_CURRENT_BINARY_DIR}        --buildtype=${CMAKE_BUILD_TYPE}        "--channel=${VIEWER_CHANNEL}" @@ -2167,6 +2172,7 @@ if (DARWIN)        --arch=${ARCH}        --artwork=${ARTWORK_DIR}        "--bugsplat=${BUGSPLAT_DB}" +      "--fmodstudio=${FMODSTUDIO}"        --build=${CMAKE_CURRENT_BINARY_DIR}        --buildtype=${CMAKE_BUILD_TYPE}        --bundleid=${MACOSX_BUNDLE_GUI_IDENTIFIER} @@ -2201,6 +2207,7 @@ if (DARWIN)            --arch=${ARCH}            --artwork=${ARTWORK_DIR}            "--bugsplat=${BUGSPLAT_DB}" +          "--fmodstudio=${FMODSTUDIO}"            --build=${CMAKE_CURRENT_BINARY_DIR}            --buildtype=${CMAKE_BUILD_TYPE}            "--channel=${VIEWER_CHANNEL}" diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 133cad286f..49df80bfeb 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.4.3 +6.4.4 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 86c6b409de..e8f01f7a60 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -16384,7 +16384,7 @@    <key>FMODExProfilerEnable</key>    <map>      <key>Comment</key> -    <string>Enable profiler tool if using FMOD Ex</string> +    <string>Enable profiler tool if using FMOD Ex or FMOD Studio</string>      <key>Persist</key>      <integer>1</integer>      <key>Type</key> @@ -16395,7 +16395,7 @@    <key>FMODExDecodeBufferSize</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 Ex or FMOD Studio</string>      <key>Persist</key>      <integer>1</integer>      <key>Type</key> @@ -16406,7 +16406,7 @@    <key>FMODExStreamBufferSize</key>    <map>      <key>Comment</key> -    <string>Sets the streaming buffer size (in milliseconds)</string> +    <string>Sets the streaming buffer size (in milliseconds) for FMOD Ex or FMOD Studio</string>      <key>Persist</key>      <integer>1</integer>      <key>Type</key> diff --git a/indra/newview/linux_tools/client-readme.txt b/indra/newview/linux_tools/client-readme.txt index e01b9e4bc6..cb8d1af535 100644 --- a/indra/newview/linux_tools/client-readme.txt +++ b/indra/newview/linux_tools/client-readme.txt @@ -187,8 +187,8 @@ The 'secondlife' script which launches Second Life 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.  Second Life tries to use OpenAL, ESD, OSS, then ALSA +  options: LL_BAD_OPENAL_DRIVER, LL_BAD_FMODSTUDIO_DRIVER. +  Second Life 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. diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index c23401d5a6..eb3ead433b 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -4,17 +4,15 @@  ## 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 or FMOD Ex PulseAudio audio driver.  #export LL_BAD_FMOD_PULSEAUDIO=x -## - Avoids using the FMOD or FMOD Ex ALSA audio driver. +## - Avoids using the FMOD Studio or FMOD Ex 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 diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index 083a913ef8..e9feae3457 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -229,6 +229,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()  { @@ -245,6 +272,7 @@ void LLProgressView::draw()  		}  		LLPanel::draw(); +		drawLogos(alpha);  		return;  	} @@ -257,6 +285,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 ) @@ -283,7 +312,7 @@ void LLProgressView::draw()  			// FIXME: this causes a crash that i haven't been able to fix  			mMediaCtrl->unloadMediaSource();	 -			gStartTexture = NULL; +            releaseTextures();  		}  		return;  	} @@ -291,6 +320,7 @@ void LLProgressView::draw()  	drawStartTexture(1.0f);  	// draw children  	LLPanel::draw(); +	drawLogos(1.0f);  }  void LLProgressView::setText(const std::string& text) @@ -309,6 +339,196 @@ void LLProgressView::setMessage(const std::string& msg)  	getChild<LLUICtrl>("message_text")->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 +    // 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; + +    // 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 ); diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h index 813576b21d..56377a5889 100644 --- a/indra/newview/llprogressview.h +++ b/indra/newview/llprogressview.h @@ -35,6 +35,7 @@  class LLImageRaw;  class LLButton;  class LLProgressBar; +class LLViewerTexture;  class LLProgressView :   	public LLPanel, @@ -51,6 +52,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); @@ -70,6 +72,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* ); @@ -95,6 +101,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;  };  #endif // LL_LLPROGRESSVIEW_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index b532d9a9b4..1be1c4ba96 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -39,8 +39,8 @@  #include "llviewermedia_streamingaudio.h"  #include "llaudioengine.h" -#ifdef LL_FMODEX -# include "llaudioengine_fmodex.h" +#ifdef LL_FMODSTUDIO +# include "llaudioengine_fmodstudio.h"  #endif  #ifdef LL_OPENAL @@ -623,13 +623,13 @@ bool idle_startup()  			delete gAudiop;  			gAudiop = NULL; -#ifdef LL_FMODEX		 +#ifdef LL_FMODSTUDIO  #if !LL_WINDOWS -			if (NULL == getenv("LL_BAD_FMODEX_DRIVER")) +            if (NULL == getenv("LL_BAD_FMODSTUDIO_DRIVER"))  #endif // !LL_WINDOWS -			{ -				gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("FMODExProfilerEnable")); -			} +            { +                gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODSTUDIO(gSavedSettings.getBOOL("FMODExProfilerEnable")); +            }  #endif  #ifdef LL_OPENAL @@ -650,7 +650,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)  				{  					gAudiop->setMuted(TRUE); @@ -994,9 +994,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);  		gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit")); @@ -2717,81 +2716,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(); -		 -		if (!gDirUtilp->fileExists(path) && LLGridManager::getInstance()->isInProductionGrid()) -		{ -			// 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() diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index e197591ef8..c966b7d4f9 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1902,7 +1902,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()); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 09f86ae391..d8802d98a9 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -5235,6 +5235,14 @@ void LLViewerWindow::revealIntroPanel()  	}  } +void LLViewerWindow::initTextures(S32 location_id) +{ +    if (mProgressView) +    { +        mProgressView->initTextures(location_id, LLGridManager::getInstance()->isInProductionGrid()); +    } +} +  void LLViewerWindow::setShowProgress(const BOOL show)  {  	if (mProgressView) @@ -5288,7 +5296,6 @@ void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string&  	}  } -  LLProgressView *LLViewerWindow::getProgressView() const  {  	return mProgressView; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 385bbd57e5..44c1fbd066 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -303,6 +303,7 @@ public:  	BOOL            getCursorHidden() { return mCursorHidden; }  	void			moveCursorToCenter();								// move to center of window +	void			initTextures(S32 location_id);  	void			setShowProgress(const BOOL show);  	BOOL			getShowProgress() const;  	void			setProgressString(const std::string& string); diff --git a/indra/newview/skins/default/textures/3p_icons/fmod_logo.png b/indra/newview/skins/default/textures/3p_icons/fmod_logo.pngBinary files differ new file mode 100644 index 0000000000..5a50e0ad34 --- /dev/null +++ b/indra/newview/skins/default/textures/3p_icons/fmod_logo.png diff --git a/indra/newview/skins/default/textures/3p_icons/havok_logo.png b/indra/newview/skins/default/textures/3p_icons/havok_logo.pngBinary files differ new file mode 100644 index 0000000000..ff1ea3a72e --- /dev/null +++ b/indra/newview/skins/default/textures/3p_icons/havok_logo.png diff --git a/indra/newview/skins/default/textures/3p_icons/vivox_logo.png b/indra/newview/skins/default/textures/3p_icons/vivox_logo.pngBinary files differ new file mode 100644 index 0000000000..6f20e87b7a --- /dev/null +++ b/indra/newview/skins/default/textures/3p_icons/vivox_logo.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index b041e6197c..7325d836d2 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -497,6 +497,7 @@ with the same filename but different name    <texture name="Play_Press" file_name="icons/Play_Press.png" preload="false" />    <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" /> diff --git a/indra/newview/skins/default/textures/widgets/ProgressBarSolid.png b/indra/newview/skins/default/textures/widgets/ProgressBarSolid.pngBinary files differ new file mode 100644 index 0000000000..ec0926bfa1 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/ProgressBarSolid.png diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml index a8342e723b..d783d1e23c 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml @@ -2,7 +2,7 @@  <floater   legacy_header_height="18"   can_minimize="false" - height="488" + height="466"   layout="topleft"   name="Inventory Finder"   help_topic="inventory_finder" @@ -202,7 +202,7 @@       left="8"       mouse_opaque="true"       name="icon_settings" -     top="262" +     top="242"       width="16" />      <check_box       height="16" @@ -220,7 +220,7 @@       layout="topleft"       left="8"       name="All" -     top="282" +     top="262"       width="100" />      <button       height="20" @@ -368,6 +368,6 @@       layout="topleft"       name="Close"       right="-6" -     top="454" +     top="434"       width="76" />  </floater> diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml index 860caf2d21..e77d097d5f 100644 --- a/indra/newview/skins/default/xui/en/panel_progress.xml +++ b/indra/newview/skins/default/xui/en/panel_progress.xml @@ -44,68 +44,129 @@                   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="0 0.67 0.9 0.96" +                         follows="left|right|top" +                         layout="topleft" +                         image_fill="ProgressBarSolid" +                         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"> +                          Second Life uses +                        </text> +                      </layout_panel> +                    </layout_stack>                  </layout_panel>                  <layout_panel                   height="200" diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 82740c9623..4d6d75659f 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -516,14 +516,12 @@ class WindowsManifest(ViewerManifest):                  print err.message                  print "Skipping GLOD library (assumming linked statically)" -            # Get fmodex dll, continue if missing -            try: -                if(self.address_size == 64): -                    self.path("fmodex64.dll") +            # Get fmodstudio dll if needed +            if self.args['fmodstudio'] == 'ON': +                if(self.args['configuration'].lower() == 'debug'): +                    self.path("fmodL.dll")                  else: -                    self.path("fmodex.dll") -            except: -                print "Skipping fmodex audio library(assuming other audio engine)" +                    self.path("fmod.dll")              # For textures              self.path("openjpeg.dll") @@ -1049,17 +1047,18 @@ class DarwinManifest(ViewerManifest):                                  ):                      self.path2basename(relpkgdir, libfile) -                # dylibs that vary based on configuration -                if self.args['configuration'].lower() == 'debug': -                    for libfile in ( -                                "libfmodexL.dylib", -                                ): -                        dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile) -                else: -                    for libfile in ( -                                "libfmodex.dylib", -                                ): -                        dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile) +                # Fmod studio dylibs (vary based on configuration) +                if self.args['fmodstudio'] == 'ON': +                    if self.args['configuration'].lower() == 'debug': +                        for libfile in ( +                                    "libfmodL.dylib", +                                    ): +                            dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile) +                    else: +                        for libfile in ( +                                    "libfmod.dylib", +                                    ): +                            dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile)                  # our apps                  executable_path = {} @@ -1522,13 +1521,15 @@ class Linux_i686_Manifest(LinuxManifest):                  print "tcmalloc files not found, skipping"                  pass -            try: -                self.path("libfmodex-*.so") -                self.path("libfmodex.so") -                pass -            except: -                print "Skipping libfmodex.so - not found" -                pass +            if self.args['fmodstudio'] == 'ON': +                try: +                    self.path("libfmod.so.11.7") +                    self.path("libfmod.so.11") +                    self.path("libfmod.so") +                    pass +                except: +                    print "Skipping libfmod.so - not found" +                    pass          # Vivox runtimes @@ -1558,6 +1559,7 @@ if __name__ == "__main__":      extra_arguments = [          dict(name='bugsplat', description="""BugSplat database to which to post crashes,               if BugSplat crash reporting is desired""", default=''), +        dict(name='fmodstudio', description="""Indication if fmod studio libraries are needed""", default='OFF'),          ]      try:          main(extra=extra_arguments) | 
