diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1334c3fbc4d452f50482d04ad07a116ddc945256..44d26507c1b09d23ef934e0aa746cfdf14b39b8d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,7 @@ repos: - id: indent-with-spaces files: \.(cpp|c|h|inl|py|glsl|cmake)$ - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: check-xml - id: mixed-line-ending diff --git a/autobuild.xml b/autobuild.xml index a5e0412de0e4a011a200c544eda0b41d5713cec4..322aa8fcd16370ab43ec3d2852738008d8d66eab 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -9,6 +9,16 @@ <map> <key>SDL2</key> <map> + <key>copyright</key> + <string>Copyright (C) 1997-2022 Sam Lantinga (slouken@libsdl.org)</string> + <key>description</key> + <string>Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer.</string> + <key>license</key> + <string>lgpl</string> + <key>license_file</key> + <string>LICENSES/SDL2.txt</string> + <key>name</key> + <string>SDL2</string> <key>platforms</key> <map> <key>darwin64</key> @@ -16,11 +26,11 @@ <key>archive</key> <map> <key>hash</key> - <string>b2981cbc72e966b75ef587fb55c5e8fcf829aaa390fcd3365de209b4366bb056cca04f02eb3179193ca941a0214d6bc9362b9a281179976b8c4cb0053caca23e</string> + <string>a6aa829c1e7f193b624f05415588e4d727454c8f</string> <key>hash_algorithm</key> - <string>blake2b</string> + <string>sha1</string> <key>url</key> - <string>https://github.com/AlchemyViewer/3p-sdl2/releases/download/v2.30.0-958285a/SDL2-2.30.0-darwin64-9459243145.tar.zst</string> + <string>https://github.com/secondlife/3p-sdl2/releases/download/v2.30.9-r1/SDL2-2.30.9-r1-darwin64-11943333704.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -30,11 +40,11 @@ <key>archive</key> <map> <key>hash</key> - <string>fe47b8bff02bba3bff2d07194769bd79d80900509f30fdabbf5f73849a582ced9ccbeaa4a4f0bd724df34b6dc0e354109a8bde81b389a1568c3ce822f36cde48</string> + <string>ad1b738a7cef16d5cec63ab99b1c80146626f47b</string> <key>hash_algorithm</key> - <string>blake2b</string> + <string>sha1</string> <key>url</key> - <string>https://github.com/AlchemyViewer/3p-sdl2/releases/download/v2.30.0-958285a/SDL2-2.30.0-linux64-9459243145.tar.zst</string> + <string>https://github.com/secondlife/3p-sdl2/releases/download/v2.30.9-r1/SDL2-2.30.9-r1-linux64-11943333704.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -44,28 +54,18 @@ <key>archive</key> <map> <key>hash</key> - <string>d94e4a57dedf71905365c56f9ecffd12aa94d30c9bd9de70874bfd26d6e9805a988fb537db6678d7f807bd7f21d648faf491c93b0da9e43d6a4c4b71a5cb6694</string> + <string>97153f9d302f964142df971b57680724824f458f</string> <key>hash_algorithm</key> - <string>blake2b</string> + <string>sha1</string> <key>url</key> - <string>https://github.com/AlchemyViewer/3p-sdl2/releases/download/v2.30.0-958285a/SDL2-2.30.0-windows64-9459243145.tar.zst</string> + <string>https://github.com/secondlife/3p-sdl2/releases/download/v2.30.9-r1/SDL2-2.30.9-r1-windows64-11943333704.tar.zst</string> </map> <key>name</key> <string>windows64</string> </map> </map> - <key>license</key> - <string>lgpl</string> - <key>license_file</key> - <string>LICENSES/SDL2.txt</string> - <key>copyright</key> - <string>Copyright (C) 1997-2024 Sam Lantinga (slouken@libsdl.org)</string> <key>version</key> - <string>2.30.0</string> - <key>name</key> - <string>SDL2</string> - <key>description</key> - <string>Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer.</string> + <string>2.30.9-r1</string> </map> <key>apr_suite</key> <map> @@ -1970,11 +1970,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>0f97bd114ccbcb67f15caa16c837e7b294d720c05d6a2cd99c939f5618b8a65798772c0a157c2367b1f6b50c1b2f7bb209f03ddddd9ca2c2dc16eb66634e875c</string> + <string>a93b63fc4e5aa3e226b819fb02ce9a05b00dfea1</string> <key>hash_algorithm</key> - <string>blake2b</string> + <string>sha1</string> <key>url</key> - <string>https://github.com/AlchemyViewer/3p-open-libndofdev/releases/download/v0.14.0-a377d1a/open_libndofdev-0.14.0-linux64-9459328666.tar.zst</string> + <string>https://github.com/secondlife/3p-open-libndofdev/releases/download/v1.14-r5/open_libndofdev-0.14.11968684513-linux64-11968684513.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -1987,7 +1987,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>copyright</key> <string>Copyright (c) 2008, Jan Ciger (jan.ciger (at) gmail.com)</string> <key>version</key> - <string>0.14.0</string> + <string>0.14.11968684513</string> <key>name</key> <string>open-libndofdev</string> <key>description</key> @@ -2002,11 +2002,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>1b876fc7046470ddfda2fb74ef7d653643a40c4668f8ca276f56535afa1d93fafb05cae77ccadbffebf7ee1ce3dab90c4b7d4f4a56b8461688b61f19550751ac</string> + <string>9250e12d4d88f0a437e49be2b32d107f6b4270d0</string> <key>hash_algorithm</key> - <string>blake2b</string> + <string>sha1</string> <key>url</key> - <string>https://github.com/AlchemyViewer/3p-openal-soft/releases/download/v1.23.1-13e162a/openal-1.23.1-darwin64-9458147120.tar.zst</string> + <string>https://github.com/secondlife/3p-openal-soft/releases/download/v1.24.0-r1/openal-1.24.0-r1-darwin64-11968917548.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -2016,11 +2016,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>2552fc42e102e38d506569aa22b88a06712c976b93b8cfb2644c4decbf11bc463d239061d0a1bc5e76337f9dec9f5efe00bbaf9102ea926949b930cb2a92b6ce</string> + <string>1e50db24586fba434a2be62f94fdc687569379ca</string> <key>hash_algorithm</key> - <string>blake2b</string> + <string>sha1</string> <key>url</key> - <string>https://github.com/AlchemyViewer/3p-openal-soft/releases/download/v1.23.1-13e162a/openal-1.23.1-linux64-9458147120.tar.zst</string> + <string>https://github.com/secondlife/3p-openal-soft/releases/download/v1.24.0-r1/openal-1.24.0-r1-linux64-11968917548.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -2030,11 +2030,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>c2f9c3551b1691d0b8cf49560ef10fd48e1fb515c2d9a0f777ffb71709bb9efcf7b12a625391bbc3fc369888061c8a0f989ec58a3887b658e6c1353053aa6ea7</string> + <string>2ec7b2b1f4c37e5bd1b473e4a26935ec374ee208</string> <key>hash_algorithm</key> - <string>blake2b</string> + <string>sha1</string> <key>url</key> - <string>https://github.com/AlchemyViewer/3p-openal-soft/releases/download/v1.23.1-13e162a/openal-1.23.1-windows64-9458147120.tar.zst</string> + <string>https://github.com/secondlife/3p-openal-soft/releases/download/v1.24.0-r1/openal-1.24.0-r1-windows64-11968917548.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -2047,7 +2047,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>copyright</key> <string>Copyright (C) 1999-2007 by authors.</string> <key>version</key> - <string>1.23.1</string> + <string>1.24.0-r1</string> <key>name</key> <string>openal</string> <key>description</key> @@ -2676,11 +2676,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>3570b6442d472cd97bad8622c2ec2571d72218a0</string> + <string>6314fdcee81a3538a7d960178ade66301c2fa002</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.72-test/webrtc-m114.5735.08.72-test.10444682919-darwin64-10444682919.tar.zst</string> + <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.73-alpha/webrtc-m114.5735.08.73-alpha.11958809572-darwin64-11958809572.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -2690,11 +2690,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>eadf6aa99313940ded11801d42c11375669f1628</string> + <string>95d7730a3d6955697e043f3fdf20ebdcc0c71fc0</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.72-test/webrtc-m114.5735.08.72-test.10444682919-linux64-10444682919.tar.zst</string> + <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.73-alpha/webrtc-m114.5735.08.73-alpha.11958809572-linux64-11958809572.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -2704,11 +2704,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>0081fd35290adbc8e66dd366535fb6cd8a966f1e</string> + <string>c7b329d6409576af6eb5b80655b007f52639c43b</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.72-test/webrtc-m114.5735.08.72-test.10444682919-windows64-10444682919.tar.zst</string> + <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.73-alpha/webrtc-m114.5735.08.73-alpha.11958809572-windows64-11958809572.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -2721,7 +2721,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>copyright</key> <string>Copyright (c) 2011, The WebRTC project authors. All rights reserved.</string> <key>version</key> - <string>m114.5735.08.72-test.10444682919</string> + <string>m114.5735.08.73-alpha.11958809572</string> <key>name</key> <string>webrtc</string> <key>vcs_branch</key> diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index f53c74c4a3fe4f22d6171bbebaeddea63a0c393f..22fc774479594b15d0442edb82d2e9188197fbec 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -678,6 +678,10 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) // We do the somewhat sketchy operation of blocking in here until the error handler // has gracefully stopped the app. + // FIXME(brad) - we are using this handler for asynchronous signals as well, so sLogInSignal is currently + // disabled for safety. we need to find a way to selectively reenable it when it is safe. + // see issue secondlife/viewer#2566 + if (LLApp::sLogInSignal) { LL_INFOS() << "Signal handler - Got signal " << signum << " - " << apr_signal_description_get(signum) << LL_ENDL; @@ -687,9 +691,10 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) switch (signum) { case SIGCHLD: + case SIGHUP: if (LLApp::sLogInSignal) { - LL_INFOS() << "Signal handler - Got SIGCHLD from " << info->si_pid << LL_ENDL; + LL_INFOS() << "Signal handler - Got SIGCHLD or SIGHUP from " << info->si_pid << LL_ENDL; } return; @@ -704,11 +709,10 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) raise(signum); return; case SIGINT: - case SIGHUP: case SIGTERM: if (LLApp::sLogInSignal) { - LL_WARNS() << "Signal handler - Got SIGINT, HUP, or TERM, exiting gracefully" << LL_ENDL; + LL_WARNS() << "Signal handler - Got SIGINT, or TERM, exiting gracefully" << LL_ENDL; } // Graceful exit // Just set our state to quitting, not error @@ -755,6 +759,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) { LL_WARNS() << "Signal handler - Handling fatal signal!" << LL_ENDL; } + if (LLApp::isError()) { // Received second fatal signal while handling first, just die right now @@ -792,11 +797,11 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) clear_signals(); raise(signum); return; - } else { - if (LLApp::sLogInSignal) - { - LL_INFOS() << "Signal handler - Unhandled signal " << signum << ", ignoring!" << LL_ENDL; - } + } + + if (LLApp::sLogInSignal) + { + LL_INFOS() << "Signal handler - Unhandled signal " << signum << ", ignoring!" << LL_ENDL; } } } diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 7636884f679708c39765087efa8915753e4b152f..f406d80851bb99106b4a794df727c6e2202b2302 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -61,6 +61,23 @@ #include <excpt.h> #endif +// static +bool LLCoros::on_main_coro() +{ + if (!LLCoros::instanceExists() || LLCoros::getName().empty()) + { + return true; + } + + return false; +} + +// static +bool LLCoros::on_main_thread_main_coro() +{ + return on_main_coro() && on_main_thread(); +} + // static LLCoros::CoroData& LLCoros::get_CoroData(const std::string& caller) { @@ -362,7 +379,8 @@ void LLCoros::toplevel(std::string name, callable_t callable) { // Stash any OTHER kind of uncaught exception in the rethrow() queue // to be rethrown by the main fiber. - LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); + LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine " + << name << LL_ENDL; LLCoros::instance().saveException(name, std::current_exception()); } } diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index fdd00cf62c729ea41ef02c92100b0930c15af2df..f32e90e0f87d7b553cdd5a7f3478a7992900534a 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -31,8 +31,9 @@ #include "llexception.h" #include <boost/fiber/fss.hpp> -#include <boost/fiber/future/promise.hpp> #include <boost/fiber/future/future.hpp> +#include <boost/fiber/future/promise.hpp> +#include <boost/fiber/recursive_mutex.hpp> #include "mutex.h" #include "llsingleton.h" #include "llinstancetracker.h" @@ -94,6 +95,16 @@ class LL_COMMON_API LLCoros final : public LLSingleton<LLCoros> void cleanupSingleton() override; public: + // For debugging, return true if on the main coroutine for the current thread + // Code that should not be executed from a coroutine should be protected by + // llassert(LLCoros::on_main_coro()) + static bool on_main_coro(); + + // For debugging, return true if on the main thread and not in a coroutine + // Non-thread-safe code in the main loop should be protected by + // llassert(LLCoros::on_main_thread_main_coro()) + static bool on_main_thread_main_coro(); + /// The viewer's use of the term "coroutine" became deeply embedded before /// the industry term "fiber" emerged to distinguish userland threads from /// simpler, more transient kinds of coroutines. Semantically they've @@ -297,6 +308,12 @@ class LL_COMMON_API LLCoros final : public LLSingleton<LLCoros> // use mutex, lock, condition_variable suitable for coroutines using Mutex = boost::fibers::mutex; + using RMutex = boost::fibers::recursive_mutex; + // With C++17, LockType is deprecated: at this point we can directly + // declare 'std::unique_lock lk(some_mutex)' without explicitly stating + // the mutex type. Sadly, making LockType an alias template for + // std::unique_lock doesn't work the same way: Class Template Argument + // Deduction only works for class templates, not alias templates. using LockType = std::unique_lock<Mutex>; using cv_status = boost::fibers::cv_status; using ConditionVariable = boost::fibers::condition_variable; diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index ac32c67a74ccb58cc1b5168a6c78058c64c5b025..3c68ca12ef7d28f0b554e6a887d3eaabf48a1c1c 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -526,7 +526,7 @@ namespace LLError::TimeFunction mTimeFunction; Recorders mRecorders; - LLMutex mRecorderMutex; + LLCoros::RMutex mRecorderMutex; int mShouldLogCallCounter; @@ -549,7 +549,6 @@ namespace mCrashFunction(NULL), mTimeFunction(NULL), mRecorders(), - mRecorderMutex(), mShouldLogCallCounter(0) { } @@ -706,7 +705,7 @@ namespace LLError CallSite::~CallSite() { - delete[] mTags; + delete []mTags; } void CallSite::invalidate() @@ -720,7 +719,7 @@ namespace bool shouldLogToStderr() { #if LL_DARWIN - // On Mac OS X, stderr from apps launched from the Finder goes to the + // On macOS, stderr from apps launched from the Finder goes to the // console log. It's generally considered bad form to spam too much // there. That scenario can be detected by noticing that stderr is a // character device (S_IFCHR). @@ -1059,7 +1058,7 @@ namespace LLError return; } SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); - LLMutexLock lock(&s->mRecorderMutex); + std::unique_lock lock(s->mRecorderMutex); s->mRecorders.push_back(std::move(recorder)); } @@ -1070,7 +1069,7 @@ namespace LLError return; } SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); - LLMutexLock lock(&s->mRecorderMutex); + std::unique_lock lock(s->mRecorderMutex); s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder), s->mRecorders.end()); } @@ -1119,7 +1118,7 @@ namespace LLError std::shared_ptr<RECORDER> findRecorder() { SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); - LLMutexLock lock(&s->mRecorderMutex); + std::unique_lock lock(s->mRecorderMutex); return findRecorderPos<RECORDER>(s).first; } @@ -1130,7 +1129,7 @@ namespace LLError bool removeRecorder() { SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); - LLMutexLock lock(&s->mRecorderMutex); + std::unique_lock lock(s->mRecorderMutex); auto found = findRecorderPos<RECORDER>(s); if (found.first) { @@ -1236,7 +1235,7 @@ namespace std::string escaped_message; - LLMutexLock lock(&s->mRecorderMutex); + std::unique_lock lock(s->mRecorderMutex); for (LLError::RecorderPtr& r : s->mRecorders) { if (!r->enabled()) @@ -1505,6 +1504,7 @@ namespace LLError static std::string newview_prefix = "newview/../"; f = removePrefix(f, newview_prefix); #endif + return f; } diff --git a/indra/llcommon/llsdjson.cpp b/indra/llcommon/llsdjson.cpp index 16ab2d5a453f419554cf844a4c2f6c41a87e49cb..542a3c26e34daba87f31897fbb5fb86ebe156494 100644 --- a/indra/llcommon/llsdjson.cpp +++ b/indra/llcommon/llsdjson.cpp @@ -26,11 +26,12 @@ // Must turn on conditional declarations in header file so definitions end up // with proper linkage. - +#define LLSD_DEBUG_INFO #include "linden_common.h" #include "llsdjson.h" +#include "llsdutil.h" #include "llerror.h" #include <boost/json/src.hpp> @@ -59,12 +60,21 @@ LLSD LlsdFromJson(const boost::json::value& val) result = LLSD(val.as_bool()); break; case boost::json::kind::array: + { result = LLSD::emptyArray(); - for (const auto &element : val.as_array()) + const boost::json::array& array = val.as_array(); + size_t size = array.size(); + // allocate elements 0 .. (size() - 1) to avoid incremental allocation + if (! array.empty()) { - result.append(LlsdFromJson(element)); + result[size - 1] = LLSD(); + } + for (size_t i = 0; i < size; i++) + { + result[i] = (LlsdFromJson(array[i])); } break; + } case boost::json::kind::object: result = LLSD::emptyMap(); for (const auto& element : val.as_object()) @@ -104,7 +114,8 @@ boost::json::value LlsdToJson(const LLSD &val) case LLSD::TypeMap: { boost::json::object& obj = result.emplace_object(); - for (const auto& llsd_dat : val.asMap()) + obj.reserve(val.size()); + for (const auto& llsd_dat : llsd::inMap(val)) { obj[llsd_dat.first] = LlsdToJson(llsd_dat.second); } @@ -113,7 +124,8 @@ boost::json::value LlsdToJson(const LLSD &val) case LLSD::TypeArray: { boost::json::array& json_array = result.emplace_array(); - for (const auto& llsd_dat : val.asArray()) + json_array.reserve(val.size()); + for (const auto& llsd_dat : llsd::inArray(val)) { json_array.push_back(LlsdToJson(llsd_dat)); } @@ -121,7 +133,8 @@ boost::json::value LlsdToJson(const LLSD &val) } case LLSD::TypeBinary: default: - LL_ERRS("LlsdToJson") << "Unsupported conversion to JSON from LLSD type (" << val.type() << ")." << LL_ENDL; + LL_ERRS("LlsdToJson") << "Unsupported conversion to JSON from LLSD type (" + << val.type() << ")." << LL_ENDL; break; } diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index 302bbe6f8d26a1962f003204bb88062df6fde683..451e60c0832eaa0f4f8f8bcb6e268cd59d441110 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -110,6 +110,10 @@ void LL::ThreadPoolBase::start() LL::ThreadPoolBase::~ThreadPoolBase() { close(); + if (!LLEventPumps::wasDeleted()) + { + LLEventPumps::instance().obtain("LLApp").stopListening(mName); + } } void LL::ThreadPoolBase::close() diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 18f796b3816122394a2b994fc17d8805c477c94e..a6a30cebb9658f05c0522c2b8502bde2571308e8 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -66,7 +66,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) ////////////////////////////////////// // NOTE order of shader object attaching is VERY IMPORTANT!!! - if (features->calculatesAtmospherics) + if (features->calculatesAtmospherics || features->hasGamma || features->isDeferred) { if (!shader->attachVertexObject("windlight/atmosphericsVarsV.glsl")) { diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 4e85ceaf1697a3bb72133d2275499bafd08f9f68..b2fd864629b2ff525b007f91969bf9f88856953a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5147,10 +5147,7 @@ void LLAppViewer::sendLogoutRequest() gLogoutMaxTime = LOGOUT_REQUEST_TIME; mLogoutRequestSent = TRUE; - if(LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->setVoiceEnabled(false); - } + LLVoiceClient::setVoiceEnabled(false); } } diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index 715649e8443917fe7e9924aaee3b4a15267d7548..c33e70bd579082d9bae38e0c1072764b6cd5edc2 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -31,6 +31,7 @@ // Viewer includes #include "llagent.h" #include "llagentpicksinfo.h" +#include "llappviewer.h" #include "lldateutil.h" #include "llviewergenericmessage.h" #include "llstartup.h" @@ -41,6 +42,7 @@ #include "lltrans.h" #include "llui.h" // LLUI::getLanguage() #include "message.h" +#include "llappviewer.h" LLAvatarPropertiesProcessor::LLAvatarPropertiesProcessor() { @@ -367,7 +369,11 @@ void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_ur avatar_data.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString()); } - inst.notifyObservers(avatar_id, &avatar_data, type); + LLAppViewer::instance()->postToMainCoro([=]() + { + LLAvatarData av_data = avatar_data; + instance().notifyObservers(avatar_id, &av_data, type); + }); } void LLAvatarPropertiesProcessor::processAvatarLegacyPropertiesReply(LLMessageSystem* msg, void**) diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index a68a28738d9089a7828f292a326e7e3ca4f30fd1..3e2a2fa6f1cb58e4473f177216efd06dd245bcbe 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -231,13 +231,11 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(std::string url, U { LLVOAvatar* avatar = static_cast<LLVOAvatar*>(*iter); if (avatar && - avatar->getRezzedStatus() >= 2 && // Mostly rezzed (maybe without baked textures downloaded) !avatar->isDead() && // Not dead yet !avatar->isControlAvatar() && // Not part of an animated object + avatar->getRezzedStatus() >= 2 && // Mostly rezzed (maybe without baked textures downloaded) avatar->getObjectHost() == regionp->getHost()) // Ensure it's on the same region { - avatar->calculateUpdateRenderComplexity(); // Make sure the numbers are up-to-date - LLSD info = LLSD::emptyMap(); U32 avatar_complexity = avatar->getVisualComplexity(); if (avatar_complexity > 0) @@ -245,11 +243,11 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(std::string url, U // the weight/complexity is unsigned, but LLSD only stores signed integers, // so if it's over that (which would be ridiculously high), just store the maximum signed int value info[KEY_WEIGHT] = (S32)(avatar_complexity < S32_MAX ? avatar_complexity : S32_MAX); - info[KEY_TOO_COMPLEX] = LLSD::Boolean(avatar->isTooComplex()); + info[KEY_TOO_COMPLEX] = LLSD::Boolean(avatar->isTooComplex()); agents[avatar->getID().asString()] = info; LL_DEBUGS("AvatarRenderInfo") << "Sending avatar render info for " << avatar->getID() - << ": " << info << LL_ENDL; + << ": " << info << LL_ENDL; num_avs++; } } diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index f8f3425a4a5823b19062a3c790363ff4c8206b0f..35c207133a54edd33eaf4022be9de45a857d0260 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -112,12 +112,17 @@ void LLConversation::onIMFloaterShown(const LLUUID& session_id) // static const std::string LLConversation::createTimestamp(const U64Seconds& utc_time) { - static const std::string time_fmt_str = fmt::format(FMT_STRING("[{:s}]/[{:s}]/[{:s}] [{:s}]:[{:s}]"), LLTrans::getString("TimeMonth"), LLTrans::getString("TimeDay"), LLTrans::getString("TimeYear"), LLTrans::getString("TimeHour"), LLTrans::getString("TimeMin")); - - std::string timeStr = time_fmt_str; + std::string timeStr; LLSD substitution; substitution["datetime"] = (S32)utc_time.value(); + timeStr = "["+LLTrans::getString ("TimeMonth")+"]/[" + +LLTrans::getString ("TimeDay")+"]/[" + +LLTrans::getString ("TimeYear")+"] [" + +LLTrans::getString ("TimeHour")+"]:[" + +LLTrans::getString ("TimeMin")+"]"; + + LLStringUtil::format (timeStr, substitution); return timeStr; } @@ -183,6 +188,22 @@ LLConversationLog::LLConversationLog() : { } +LLConversationLog::~LLConversationLog() +{ + if (mLoggingEnabled) + { + if (LLIMMgr::instanceExists()) + { + LLIMMgr::instance().removeSessionObserver(this); + } + LLAvatarTracker::instance().removeObserver(mFriendObserver); + } + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } +} + void LLConversationLog::enableLogging(S32 log_mode) { mLoggingEnabled = log_mode > 0; diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 598e98ecbd854741b5a4dde4dc6628186ec20ab4..befb03460ade1f3a4155b839a1394886ca9ba856 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -126,10 +126,10 @@ class LLConversationLog final : public LLSingleton<LLConversationLog>, LLIMSessi // LLIMSessionObserver triggers virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) override; - virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) override {}; // Stub - virtual void sessionRemoved(const LLUUID& session_id) override {} // Stub - virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) override {}; // Stub - virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) override {}; // Stub + virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) override {}; // Stub + virtual void sessionRemoved(const LLUUID& session_id) override{} // Stub + virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) override{}; // Stub + virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) override{}; // Stub void notifyObservers(); @@ -166,13 +166,7 @@ class LLConversationLog final : public LLSingleton<LLConversationLog>, LLIMSessi private: - virtual ~LLConversationLog() - { - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - } + virtual ~LLConversationLog(); void enableLogging(S32 log_mode); diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 46e7949e5624effb68a52ecbb4bb83fb0c1216af..d9d50a21902c9a4cd2029b48a38e366d2beed24b 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1971,7 +1971,10 @@ void LLEnvironment::requestParcel(S32 parcel_id, environment_apply_fn cb) LLEnvironmentRequest::initiate(cb); } else if (cb) + { cb(parcel_id, EnvironmentInfo::ptr_t()); + } + return; } @@ -1981,16 +1984,14 @@ void LLEnvironment::requestParcel(S32 parcel_id, environment_apply_fn cb) cb = [this, transition](S32 pid, EnvironmentInfo::ptr_t envinfo) { recordEnvironment(pid, envinfo, transition); }; } - std::string coroname = - LLCoros::instance().launch("LLEnvironment::coroRequestEnvironment", + LLCoros::instance().launch("LLEnvironment::coroRequestEnvironment", [this, parcel_id, cb]() { coroRequestEnvironment(parcel_id, cb); }); } void LLEnvironment::updateParcel(S32 parcel_id, const LLUUID &asset_id, std::string display_name, S32 track_num, S32 day_length, S32 day_offset, U32 flags, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb) { UpdateInfo::ptr_t updates(std::make_shared<UpdateInfo>(asset_id, display_name, day_length, day_offset, altitudes, flags)); - std::string coroname = - LLCoros::instance().launch("LLEnvironment::coroUpdateEnvironment", + LLCoros::instance().launch("LLEnvironment::coroUpdateEnvironment", [this, parcel_id, track_num, updates, cb]() { coroUpdateEnvironment(parcel_id, track_num, updates, cb); }); } @@ -2040,8 +2041,7 @@ void LLEnvironment::updateParcel(S32 parcel_id, const LLSettingsDay::ptr_t &pday { UpdateInfo::ptr_t updates(std::make_shared<UpdateInfo>(pday, day_length, day_offset, altitudes)); - std::string coroname = - LLCoros::instance().launch("LLEnvironment::coroUpdateEnvironment", + LLCoros::instance().launch("LLEnvironment::coroUpdateEnvironment", [this, parcel_id, track_num, updates, cb]() { coroUpdateEnvironment(parcel_id, track_num, updates, cb); }); } @@ -2050,12 +2050,9 @@ void LLEnvironment::updateParcel(S32 parcel_id, const LLSettingsDay::ptr_t &pday updateParcel(parcel_id, pday, NO_TRACK, day_length, day_offset, altitudes, cb); } - - void LLEnvironment::resetParcel(S32 parcel_id, environment_apply_fn cb) { - std::string coroname = - LLCoros::instance().launch("LLEnvironment::coroResetEnvironment", + LLCoros::instance().launch("LLEnvironment::coroResetEnvironment", [this, parcel_id, cb]() { coroResetEnvironment(parcel_id, NO_TRACK, cb); }); } @@ -2074,8 +2071,10 @@ void LLEnvironment::coroRequestEnvironment(S32 parcel_id, LLEnvironment::environ if (parcel_id != INVALID_PARCEL_ID) { - url.append("?parcelid="); - url.append(fmt::to_string(parcel_id)); + std::stringstream query; + + query << "?parcelid=" << parcel_id; + url += query.str(); } LLSD result = httpAdapter->getAndSuspend(httpRequest, url); @@ -2096,11 +2095,13 @@ void LLEnvironment::coroRequestEnvironment(S32 parcel_id, LLEnvironment::environ LLSD environment = result[KEY_ENVIRONMENT]; if (environment.isDefined() && apply) { - EnvironmentInfo::ptr_t envinfo = LLEnvironment::EnvironmentInfo::extract(environment); - apply(parcel_id, envinfo); + LLAppViewer::instance()->postToMainCoro([=]() + { + EnvironmentInfo::ptr_t envinfo = LLEnvironment::EnvironmentInfo::extract(environment); + apply(parcel_id, envinfo); + }); } } - } void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInfo::ptr_t updates, environment_apply_fn apply) @@ -2120,9 +2121,14 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf if (track_no == NO_TRACK) { // day length and offset are only applicable if we are addressing the entire day cycle. if (updates->mDayLength > 0) + { body[KEY_ENVIRONMENT][KEY_DAYLENGTH] = updates->mDayLength; + } + if (updates->mDayOffset > 0) + { body[KEY_ENVIRONMENT][KEY_DAYOFFSET] = updates->mDayOffset; + } if ((parcel_id == INVALID_PARCEL_ID) && (updates->mAltitudes.size() == 3)) { // only test for altitude changes if we are changing the region. @@ -2135,12 +2141,16 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf } if (updates->mDayp) + { body[KEY_ENVIRONMENT][KEY_DAYCYCLE] = updates->mDayp->getSettings(); + } else if (!updates->mSettingsAsset.isNull()) { body[KEY_ENVIRONMENT][KEY_DAYASSET] = updates->mSettingsAsset; if (!updates->mDayName.empty()) + { body[KEY_ENVIRONMENT][KEY_DAYNAME] = updates->mDayName; + } } body[KEY_ENVIRONMENT][KEY_FLAGS] = LLSD::Integer(updates->mFlags); @@ -2158,22 +2168,27 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf if (track_no != NO_TRACK) query << "&"; } + if (track_no != NO_TRACK) { query << "trackno=" << track_no; } + url += query.str(); } LLSD result = httpAdapter->putAndSuspend(httpRequest, url, body); // results that come back may contain the new settings + if (LLApp::isExiting()) + return; + LLSD notify; LLSD httpResults = result["http_result"]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - if ((!status) || !result["success"].asBoolean()) + if (!status || !result["success"].asBoolean()) { LL_WARNS("ENVIRONMENT") << "Couldn't update Windlight settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL; @@ -2188,10 +2203,6 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf notify["FAIL_REASON"] = reason; } } - else if (LLApp::isExiting()) - { - return; - } else { LLSD environment = result[KEY_ENVIRONMENT]; @@ -2242,34 +2253,26 @@ void LLEnvironment::coroResetEnvironment(S32 parcel_id, S32 track_no, environmen LLSD result = httpAdapter->deleteAndSuspend(httpRequest, url); // results that come back may contain the new settings + if (LLApp::isExiting()) + return; + LLSD notify; LLSD httpResults = result["http_result"]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - if ((!status) || !result["success"].asBoolean()) + if (!status || !result["success"].asBoolean()) { LL_WARNS("ENVIRONMENT") << "Couldn't reset Windlight settings in " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL; notify = LLSD::emptyMap(); std::string reason = result["message"].asString(); - if (reason.empty()) - { - notify["FAIL_REASON"] = status.toString(); - } - else - { - notify["FAIL_REASON"] = reason; - } + notify["FAIL_REASON"] = reason.empty() ? status.toString() : reason; } - else if (LLApp::isExiting()) + else if (apply) { - return; - } - else - { - LLSD environment = result[KEY_ENVIRONMENT]; - if (environment.isDefined() && apply) + LLSD environment = result[KEY_ENVIRONMENT]; + if (environment.isDefined()) { EnvironmentInfo::ptr_t envinfo = LLEnvironment::EnvironmentInfo::extract(environment); apply(parcel_id, envinfo); @@ -2281,7 +2284,6 @@ void LLEnvironment::coroResetEnvironment(S32 parcel_id, S32 track_no, environmen LLNotificationsUtil::add("WLRegionApplyFail", notify); //LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false); } - } @@ -2407,7 +2409,6 @@ LLEnvironment::EnvironmentInfo::ptr_t LLEnvironment::EnvironmentInfo::extractLeg pinfo->mAltitudes[2] = 10002; pinfo->mAltitudes[3] = 10003; - return pinfo; } diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 3e547e6a6227f8988e26d8544aaa3314cca188f3..ab1fc3a645ec76e813d2baddb003dfaeb19188ac 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -790,6 +790,7 @@ void LLFloaterIMSession::onClose(bool app_quitting) // Last change: // EXT-3516 X Button should end IM session, _ button should hide gIMMgr->leaveSession(mSessionID); + mSession = nullptr; // leaveSession should have deleted it. // *TODO: Study why we need to restore the floater before we close it. // Might be because we want to save some state data in some clean open state. LLFloaterIMSessionTab::restoreFloater(); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index aec6310a42711f116ec197bcc33938d2c12d9354..bc4cf60600e049b7e18bd008f2ce3196bd1070b4 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -80,6 +80,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) { setAutoFocus(FALSE); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + LLIMMgr::instance().addSessionObserver(this); mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLFloaterIMSessionTab::onIMSessionMenuItemClicked, this, _2)); @@ -102,6 +103,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) LLFloaterIMSessionTab::~LLFloaterIMSessionTab() { delete mRefreshTimer; + LLIMMgr::instance().removeSessionObserver(this); LLFloaterIMContainer* im_container = LLFloaterIMContainer::findInstance(); if (im_container) @@ -441,7 +443,10 @@ void LLFloaterIMSessionTab::enableDisableCallBtn() bool enable = false; - if (mSessionID.notNull() && mSession && mSession->mSessionInitialized && mSession->mCallBackEnabled) + if (mSessionID.notNull() + && mSession + && mSession->mSessionInitialized + && mSession->mCallBackEnabled) { if (mVoiceButtonHangUpMode) { @@ -451,8 +456,10 @@ void LLFloaterIMSessionTab::enableDisableCallBtn() else { // We allow to start call from this state only - if (mSession->mVoiceChannel->getState() == LLVoiceChannel::STATE_NO_CHANNEL_INFO && - LLVoiceClient::instanceExists()) + if (LLVoiceClient::instanceExists() && + mSession->mVoiceChannel && + !mSession->mVoiceChannel->callStarted() + ) { LLVoiceClient* client = LLVoiceClient::getInstance(); if (client->voiceEnabled() && client->isVoiceWorking()) @@ -495,10 +502,7 @@ void LLFloaterIMSessionTab::onCallButtonClicked() } else { - LLVoiceChannel::EState channel_state = mSession && mSession->mVoiceChannel ? - mSession->mVoiceChannel->getState() : LLVoiceChannel::STATE_NO_CHANNEL_INFO; - // We allow to start call from this state only - if (channel_state == LLVoiceChannel::STATE_NO_CHANNEL_INFO) + if (mSession->mVoiceChannel && !mSession->mVoiceChannel->callStarted()) { gIMMgr->startCall(mSessionID); } @@ -1408,6 +1412,14 @@ LLView* LLFloaterIMSessionTab::getChatHistory() return mChatHistory; } +void LLFloaterIMSessionTab::sessionRemoved(const LLUUID& session_id) +{ + if (session_id == mSessionID) + { + mSession = nullptr; + } +} + void LLFloaterIMSessionTab::applyMUPose(std::string& text) { if (!gSavedSettings.getBOOL("EnableMUPoseChat")) diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 61cc4f0614e71424cfb0ee60ab08003c8205757a..8478fd879c792b19eea2a243e57100584cac066a 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -48,6 +48,7 @@ class LLPanelEmojiComplete; class LLFloaterIMSessionTab : public LLTransientDockableFloater + , public LLIMSessionObserver { // [RLVa:KB] - @shownames friend struct RlvCommandHandler<RLV_TYPE_ADDREM, RLV_BHVR_SHOWNAMES>; @@ -83,13 +84,13 @@ class LLFloaterIMSessionTab bool isNearbyChat() {return mIsNearbyChat;} // LLFloater overrides - /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ BOOL postBuild(); - /*virtual*/ void draw(); - /*virtual*/ void setVisible(BOOL visible); - /*virtual*/ void setFocus(BOOL focus); - /*virtual*/ void closeFloater(bool app_quitting = false); - /*virtual*/ void deleteAllChildren(); + void onOpen(const LLSD& key) override; + BOOL postBuild() override; + void draw() override; + void setVisible(BOOL visible) override; + void setFocus(BOOL focus) override; + void closeFloater(bool app_quitting = false) override; + void deleteAllChildren() override; // Handle the left hand participant list widgets void addConversationViewParticipant(LLConversationItem* item, bool update_view = true); @@ -115,6 +116,13 @@ class LLFloaterIMSessionTab LLView* getChatHistory(); + // LLIMSessionObserver triggers + virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) override {}; // Stub + virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) override {}; // Stub + virtual void sessionRemoved(const LLUUID& session_id) override; + virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) override {}; // Stub + virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) override {}; // Stub + protected: // callback for click on any items of the visual states menu @@ -146,8 +154,8 @@ class LLFloaterIMSessionTab virtual void enableDisableCallBtn(); // process focus events to set a currently active session - /* virtual */ void onFocusReceived(); - /* virtual */ void onFocusLost(); + void onFocusReceived() override; + void onFocusLost() override; // prepare chat's params and out one message to chatHistory void appendMessage(const LLChat& chat, const LLSD& args = LLSD()); @@ -225,7 +233,7 @@ class LLFloaterIMSessionTab void getSelectedUUIDs(uuid_vec_t& selected_uuids); /// Refreshes the floater at a constant rate. - virtual void refresh() = 0; + virtual void refresh() override = 0; /** * Adjusts chat history height to fit vertically with input chat field diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index 0c2ff1bb32969dd46cdab7b36c19caef960a90f4..cf2e35f3c79a0764a0a419e604cc785586f92e4a 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -1963,23 +1963,29 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url) { session_id = message_data["asset_id"].asUUID(); } - LLIMProcessing::processNewMessage( - message_data["from_agent_id"].asUUID(), - from_group, - message_data["to_agent_id"].asUUID(), - message_data.has("offline") ? static_cast<U8>(message_data["offline"].asInteger()) : IM_OFFLINE, - dialog, - session_id, - static_cast<U32>(message_data["timestamp"].asInteger()), - message_data["from_agent_name"].asString(), - message_data["message"].asString(), - static_cast<U32>((message_data.has("parent_estate_id")) ? message_data["parent_estate_id"].asInteger() : 1), // 1 - IMMainland - message_data["region_id"].asUUID(), - position, - bin_bucket.data(), - bin_bucket.size(), - sender, - message_data["asset_id"].asUUID()); + + LLAppViewer::instance()->postToMainCoro([=]() + { + std::vector<U8> local_bin_bucket = bin_bucket; + LLHost local_sender = sender; + LLIMProcessing::processNewMessage( + message_data["from_agent_id"].asUUID(), + from_group, + message_data["to_agent_id"].asUUID(), + message_data.has("offline") ? static_cast<U8>(message_data["offline"].asInteger()) : IM_OFFLINE, + dialog, + session_id, + static_cast<U32>(message_data["timestamp"].asInteger()), + message_data["from_agent_name"].asString(), + message_data["message"].asString(), + static_cast<U32>((message_data.has("parent_estate_id")) ? message_data["parent_estate_id"].asInteger() : 1), // 1 - IMMainland + message_data["region_id"].asUUID(), + position, + local_bin_bucket.data(), + S32(local_bin_bucket.size()), + local_sender, + message_data["asset_id"].asUUID()); + }); } } diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 69da7b965e97cf8d7d12014189726a61e66034ca..156352759ddbf943b083919a47c722117ce803c3 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -607,7 +607,7 @@ void LLReflectionMapManager::deleteProbe(U32 i) LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; LLReflectionMap* probe = mProbes[i]; - llassert(probe != mDefaultProbe); + llassert(probe != mDefaultProbe.get()); if (probe->mCubeIndex != -1) { // mark the cube index used by this probe as being free diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index b27f7898e367eadae57e61dcc254eca1eea3d7a6..00dc2595a4aa208a67f0c1ba60320f29173d2b44 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -538,7 +538,7 @@ void LLSpeakerMgr::updateSpeakerList() mSpeakerListUpdated = true; } } - else if (mSpeakers.empty()) + else if (mSpeakers.size() == 0) { // For all other session type (ad-hoc, P2P), we use the initial participants targets list for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) @@ -598,7 +598,7 @@ bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id) LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id) { //In some conditions map causes crash if it is empty(Windows only), adding check (EK) - if (mSpeakers.empty()) + if (mSpeakers.size() == 0) return NULL; speaker_map_t::iterator found_it = mSpeakers.find(speaker_id); if (found_it == mSpeakers.end()) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index f4fe10b4b128f43abcdc04942ee2d4e120c9aa74..f82b912dbb67f606ec898f2b224b1396d57a3cc3 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -347,10 +347,18 @@ void update_texture_fetch() void set_flags_and_update_appearance() { - LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); - LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op); + // this may be called from a coroutine but has many side effects + // in non-thread-safe classes, post to main loop + auto work = []() + { + LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); + LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op); + + LLInventoryModelBackgroundFetch::instance().start(); + }; + + LLAppViewer::instance()->postToMainCoro(work); - LLInventoryModelBackgroundFetch::instance().start(); } // Returns false to skip other idle processing. Should only return diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 576a17fc2f00b92190b63247fb430f53bfea0223..8e2032e2e9145c382887ccccdbde86875cb6f7c9 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1249,42 +1249,46 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url) hostEnd = authority.size(); } - LLViewerMedia* inst = getInstance(); if (url.length()) { - LLMediaCtrl* media_instance = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents"); - if (media_instance) - { - std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart); - std::string cookie_name = ""; - std::string cookie_value = ""; - std::string cookie_path = ""; - bool httponly = true; - bool secure = true; - if (inst->parseRawCookie(inst->mOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure) && - media_instance->getMediaPlugin()) + LLAppViewer::instance()->postToMainCoro([=]() { - // MAINT-5711 - inexplicably, the CEF setCookie function will no longer set the cookie if the - // url and domain are not the same. This used to be my.sl.com and id.sl.com respectively and worked. - // For now, we use the URL for the OpenID POST request since it will have the same authority - // as the domain field. - // (Feels like there must be a less dirty way to construct a URL from component LLURL parts) - // MAINT-6392 - Rider: Do not change, however, the original URI requested, since it is used further - // down. - std::string cefUrl(std::string(inst->mOpenIDURL.mURI) + "://" + std::string(inst->mOpenIDURL.mAuthority)); - - media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host, - cookie_path, httponly, secure); - - // Now that we have parsed the raw cookie, we must store it so that each new media instance - // can also get a copy and faciliate logging into internal SL sites. - media_instance->getMediaPlugin()->storeOpenIDCookie(cefUrl, cookie_name, cookie_value, - cookie_host, cookie_path, httponly, secure); - } - } - LLFloaterReg::hideInstance("destinations"); + LLMediaCtrl* media_instance = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents"); + if (media_instance) + { + LLViewerMedia* inst = getInstance(); + std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart); + std::string cookie_name = ""; + std::string cookie_value = ""; + std::string cookie_path = ""; + bool httponly = true; + bool secure = true; + if (inst->parseRawCookie(inst->mOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure) && + media_instance->getMediaPlugin()) + { + // MAINT-5711 - inexplicably, the CEF setCookie function will no longer set the cookie if the + // url and domain are not the same. This used to be my.sl.com and id.sl.com respectively and worked. + // For now, we use the URL for the OpenID POST request since it will have the same authority + // as the domain field. + // (Feels like there must be a less dirty way to construct a URL from component LLURL parts) + // MAINT-6392 - Rider: Do not change, however, the original URI requested, since it is used further + // down. + std::string cefUrl(std::string(inst->mOpenIDURL.mURI) + "://" + std::string(inst->mOpenIDURL.mAuthority)); + + media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host, + cookie_path, httponly, secure); + + // Now that we have parsed the raw cookie, we must store it so that each new media instance + // can also get a copy and faciliate logging into internal SL sites. + media_instance->getMediaPlugin()->storeOpenIDCookie(cefUrl, cookie_name, cookie_value, + cookie_host, cookie_path, httponly, secure); + } + } + }); } + LLViewerMedia* inst = getInstance(); + // Note: Rider: MAINT-6392 - Some viewer code requires access to the my.sl.com openid cookie for such // actions as posting snapshots to the feed. This is handled through HTTPCore rather than CEF and so // we must learn to SHARE the cookies. @@ -2680,7 +2684,13 @@ void LLViewerMediaImpl::mimeDiscoveryCoro(std::string url) { if (initializeMedia(mimeType)) { - loadURI(); + ref(); + LLAppViewer::instance()->postToMainCoro([this]() + { + loadURI(); + unref(); + }); + } } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e6ca095c8eaedd8420a6f976e41bbbc8a392da9a..c1af50147bcdaca488d70497d53114ce3eef4ddc 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2677,11 +2677,8 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) } }; - auto workqueue = LL::WorkQueue::getInstance("mainloop"); - if (workqueue) - { - LL::WorkQueue::postMaybe(workqueue, work); - } + + LLAppViewer::instance()->postToMainCoro(work); } //this is called when the parent is not cacheable. diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 754f5107703384e94cdb701df7ccfa01c325340b..54188a8c38c689323a0ad5148e8ba5b6bffb0000 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2360,6 +2360,8 @@ void LLViewerWindow::initBase() // Hide the toolbars for the moment: we'll make them visible after logging in world (see LLViewerWindow::initWorldUI()) gToolBarView->setVisible(FALSE); + mFloaterSnapRegion = gToolBarView->getChild<LLView>("floater_snap_region"); + mChicletContainer = gToolBarView->getChild<LLPanel>("chiclet_container"); // Constrain floaters to inside the menu and status bar regions. gFloaterView = main_view->getChild<LLFloaterView>("Floater View"); for (S32 i = 0; i < LLToolBarEnums::TOOLBAR_COUNT; ++i) @@ -2370,8 +2372,6 @@ void LLViewerWindow::initBase() toolbarp->getCenterLayoutPanel()->setReshapeCallback(boost::bind(&LLFloaterView::setToolbarRect, gFloaterView, _1, _2)); } } - mChicletContainer = getRootView()->getChild<LLPanel>("chiclet_container"); - mFloaterSnapRegion = main_view->getChild<LLView>("floater_snap_region"); gFloaterView->setFloaterSnapView(mFloaterSnapRegion->getHandle()); gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View"); @@ -2463,25 +2463,33 @@ void LLViewerWindow::initWorldUI() // Force gFloaterTools to initialize LLFloaterReg::getInstance("build"); - // Status bar - mStatusBarContainer = getRootView()->getChild<LLPanel>("status_bar_container"); - gStatusBar = new LLStatusBar(mStatusBarContainer->getLocalRect()); - gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_RIGHT); - gStatusBar->setShape(mStatusBarContainer->getLocalRect()); - // sync bg color with menu bar - gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() ); - // add InBack so that gStatusBar won't be drawn over menu - mStatusBarContainer->addChildInBack(gStatusBar, 2/*tab order, after menu*/); - mStatusBarContainer->setVisible(TRUE); - - // Navigation bar - mNavBarBarContainer = getRootView()->getChild<LLView>("nav_bar_container"); - LLNavigationBar* navbar = LLNavigationBar::getInstance(); - navbar->setShape(mNavBarBarContainer->getLocalRect()); - navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get()); - mNavBarBarContainer->addChild(navbar); - mNavBarBarContainer->setVisible(TRUE); + if (!gStatusBar) + { + // Status bar + mStatusBarContainer = getRootView()->getChild<LLPanel>("status_bar_container"); + gStatusBar = new LLStatusBar(mStatusBarContainer->getLocalRect()); + gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_RIGHT); + gStatusBar->setShape(mStatusBarContainer->getLocalRect()); + // sync bg color with menu bar + gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() ); + // add InBack so that gStatusBar won't be drawn over menu + mStatusBarContainer->addChildInBack(gStatusBar, 2/*tab order, after menu*/); + mStatusBarContainer->setVisible(TRUE); + + // Navigation bar + mNavBarBarContainer = getRootView()->getChild<LLView>("nav_bar_container"); + + navbar->setShape(mNavBarBarContainer->getLocalRect()); + navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get()); + mNavBarBarContainer->addChild(navbar); + mNavBarBarContainer->setVisible(TRUE); + } + else + { + mStatusBarContainer->setVisible(true); + mNavBarBarContainer->setVisible(true); + } const U32 location_bar = gSavedSettings.getU32("NavigationBarStyle"); if (location_bar != 2) @@ -2823,12 +2831,11 @@ void LLViewerWindow::setNormalControlsVisible( BOOL visible ) gStatusBar->setEnabled( visible ); } - LLNavigationBar* navbarp = LLUI::getRootView()->findChild<LLNavigationBar>("navigation_bar"); - if (navbarp) + if (mNavBarBarContainer) { // when it's time to show navigation bar we need to ensure that the user wants to see it // i.e. ShowNavbarNavigationPanel option is true - navbarp->setVisible( visible && (gSavedSettings.getU32("NavigationBarStyle") == 2)); + mNavBarBarContainer->setVisible( visible && (gSavedSettings.getU32("NavigationBarStyle") == 2)); } } diff --git a/indra/newview/llvoicecallhandler.cpp b/indra/newview/llvoicecallhandler.cpp index 92f3543517b5577e42b5ccbb3ab59b229c217935..04a143b62ce5e18f88941a2f8defcdf8107431f9 100644 --- a/indra/newview/llvoicecallhandler.cpp +++ b/indra/newview/llvoicecallhandler.cpp @@ -48,7 +48,7 @@ class LLVoiceCallAvatarHandler : public LLCommandHandler //Get the ID LLUUID id; - if (!id.set(params[0].asStringRef(), FALSE )) + if (!id.set(params[0].asString(), FALSE )) { return false; } diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 55769f567bb88f106be5d0b30c5b96597238767a..cf128f381a0d393d6877a2dbf748a87ead1ad676 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -80,9 +80,8 @@ LLVoiceChannel::~LLVoiceChannel() if (sCurrentVoiceChannel == this) { sCurrentVoiceChannel = NULL; - // Must check instance exists here, the singleton MAY have already been destroyed. - LLVoiceClient::removeObserver(this); } + LLVoiceClient::removeObserver(this); sVoiceChannelMap.erase(mSessionID); } diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index fb7929a219922f493b83a8505a861b3cb819ffed..76df5c74d6fe83a74b70bbd2696d8cd2e972d548 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -170,7 +170,11 @@ void LLVoiceClient::init(LLPumpIO *pump) void LLVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &agentID) { - gAgent.addRegionChangedCallback(boost::bind(&LLVoiceClient::onRegionChanged, this)); + if (mRegionChangedCallbackSlot.connected()) + { + mRegionChangedCallbackSlot.disconnect(); + } + mRegionChangedCallbackSlot = gAgent.addRegionChangedCallback(boost::bind(&LLVoiceClient::onRegionChanged, this)); LLWebRTCVoiceClient::getInstance()->userAuthorized(user_id, agentID); LLVivoxVoiceClient::getInstance()->userAuthorized(user_id, agentID); } @@ -607,8 +611,14 @@ bool LLVoiceClient::voiceEnabled() void LLVoiceClient::setVoiceEnabled(bool enabled) { - LLWebRTCVoiceClient::getInstance()->setVoiceEnabled(enabled); - LLVivoxVoiceClient::getInstance()->setVoiceEnabled(enabled); + if (LLWebRTCVoiceClient::instanceExists()) + { + LLWebRTCVoiceClient::getInstance()->setVoiceEnabled(enabled); + } + if (LLVivoxVoiceClient::instanceExists()) + { + LLVivoxVoiceClient::getInstance()->setVoiceEnabled(enabled); + } } void LLVoiceClient::updateMicMuteLogic() diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index ebd43047b43a8bfd850e65c85537fe4ed0c82827..1e073209858a613c4857d584a8049ee2cc2aaa74 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -438,7 +438,7 @@ class LLVoiceClient: public LLParamSingleton<LLVoiceClient> bool getUserPTTState(); void toggleUserPTTState(void); void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs - void setVoiceEnabled(bool enabled); + static void setVoiceEnabled(bool enabled); void setUsePTT(bool usePTT); void setPTTIsToggle(bool PTTIsToggle); @@ -519,6 +519,7 @@ class LLVoiceClient: public LLParamSingleton<LLVoiceClient> LLPumpIO *m_servicePump; boost::signals2::connection mSimulatorFeaturesReceivedSlot; + boost::signals2::connection mRegionChangedCallbackSlot; LLCachedControl<bool> mVoiceEffectEnabled; LLCachedControl<std::string> mVoiceEffectDefault; diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 8a7925674af944bfeaed7ee009138aeac090aed2..0981b6ac19f4d4d5c6b082bb4f4fcf451aac530b 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -338,11 +338,14 @@ void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah ) //--------------------------------------------------- void LLVoiceVisualizer::render() { - if ( ! mVoiceEnabled || ALCinematicMode::isEnabled()) + static LLCachedControl<bool> show_visualizer(gSavedSettings, "VoiceVisualizerEnabled", true); + if ( ! mVoiceEnabled || !show_visualizer || ALCinematicMode::isEnabled()) { return; } + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + if ( mSoundSymbol.mActive ) { mPreviousTime = mCurrentTime; diff --git a/indra/newview/llvoicevisualizer.h b/indra/newview/llvoicevisualizer.h index 03ab6cf95a2edab66ed09fe9e6e0b30d306d7c8a..4e7548293d7993737b1a43ee9feea09e40ff6b0f 100644 --- a/indra/newview/llvoicevisualizer.h +++ b/indra/newview/llvoicevisualizer.h @@ -100,6 +100,8 @@ class LLVoiceVisualizer final : public LLHUDEffect void setMaxGesticulationAmplitude(); void setMinGesticulationAmplitude(); + static bool getLipSyncEnabled() { return sLipSyncEnabled; } + //--------------------------------------------------- // private members //--------------------------------------------------- diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 5bad4006b4d7161a40da39335a0a4e4ce5393b42..c72eec189672685a77e8586e9827edbbef959c17 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -2090,23 +2090,48 @@ bool LLVivoxVoiceClient::waitForChannel() llcoro::suspend(); break; } - sessionStatePtr_t joinSession = mNextAudioSession; - mNextAudioSession.reset(); - mIsProcessingChannels = true; - if (!runSession(joinSession)) //suspends + + try { - mIsProcessingChannels = false; - LL_DEBUGS("Voice") << "runSession returned false; leaving inner loop" << LL_ENDL; - break; + sessionStatePtr_t joinSession = mNextAudioSession; + mNextAudioSession.reset(); + mIsProcessingChannels = true; + if (!runSession(joinSession)) //suspends + { + mIsProcessingChannels = false; + LL_DEBUGS("Voice") << "runSession returned false; leaving inner loop" << LL_ENDL; + break; + } + else + { + mIsProcessingChannels = false; + LL_DEBUGS("Voice") + << "runSession returned true to inner loop" + << " RelogRequested=" << mRelogRequested + << " VoiceEnabled=" << mVoiceEnabled + << LL_ENDL; + } } - else + catch (const LLCoros::Stop&) + { + LL_DEBUGS("LLVivoxVoiceClient") << "Received a shutdown exception" << LL_ENDL; + } + catch (const LLContinueError&) { - mIsProcessingChannels = false; - LL_DEBUGS("Voice") - << "runSession returned true to inner loop" - << " RelogRequested=" << mRelogRequested - << " VoiceEnabled=" << mVoiceEnabled + LOG_UNHANDLED_EXCEPTION("LLVivoxVoiceClient"); + } + catch (...) + { + // Ideally for Windows need to log SEH exception instead or to set SEH + // handlers but bugsplat shows local variables for windows, which should + // be enough + LL_WARNS("Voice") << "voiceControlStateMachine crashed in state VOICE_CHANNEL_STATE_PROCESS_CHANNEL" + << " mRelogRequested " << mRelogRequested + << " mVoiceEnabled " << mVoiceEnabled + << " mIsProcessingChannels " << mIsProcessingChannels + << " mProcessChannels " << mProcessChannels << LL_ENDL; + throw; } } @@ -5105,8 +5130,7 @@ bool LLVivoxVoiceClient::isVoiceWorking() const //Added stateSessionTerminated state to avoid problems with call in parcels with disabled voice (EXT-4758) // Condition with joining spatial num was added to take into account possible problems with connection to voice // server(EXT-4313). See bug descriptions and comments for MAX_NORMAL_JOINING_SPATIAL_NUM for more info. - return (mSpatialJoiningNum < MAX_NORMAL_JOINING_SPATIAL_NUM) && mIsProcessingChannels; -// return (mSpatialJoiningNum < MAX_NORMAL_JOINING_SPATIAL_NUM) && (stateLoggedIn <= mState) && (mState <= stateSessionTerminated); + return (mSpatialJoiningNum < MAX_NORMAL_JOINING_SPATIAL_NUM) && mIsLoggedIn; } // Returns true if the indicated participant in the current audio session is really an SL avatar. @@ -6731,12 +6755,9 @@ void LLVivoxVoiceClient::expireVoiceFonts() } } - static const std::string voice_morphing_url = LLTrans::getString("voice_morphing_url"); - static const std::string premium_voice_morphing_url = LLTrans::getString("premium_voice_morphing_url"); - LLSD args; - args["URL"] = voice_morphing_url; - args["PREMIUM_URL"] = premium_voice_morphing_url; + args["URL"] = LLTrans::getString("voice_morphing_url"); + args["PREMIUM_URL"] = LLTrans::getString("premium_voice_morphing_url"); // Give a notification if any voice fonts have expired. if (have_expired) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 4528b57061698ebb773931797949a2552af5f3db..b2e5de537194ea4c2fd014c3015c84840ca593c2 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -87,6 +87,8 @@ namespace { const F32 SPEAKING_AUDIO_LEVEL = 0.30; + const uint32_t PEER_GAIN_CONVERSION_FACTOR = 220; + static const std::string REPORTED_VOICE_SERVER_TYPE = "Secondlife WebRTC Gateway"; // Don't send positional updates more frequently than this: @@ -256,6 +258,8 @@ void LLWebRTCVoiceClient::cleanupSingleton() } cleanUp(); sessionState::clearSessions(); + + mStatusObservers.clear(); } //--------------------------------------------------- @@ -401,8 +405,9 @@ void LLWebRTCVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::ESt LL_DEBUGS("Voice") << "( " << LLVoiceClientStatusObserver::status2string(status) << " )" << " mSession=" << mSession << LL_ENDL; + bool in_spatial_channel = inSpatialChannel(); LL_DEBUGS("Voice") << " " << LLVoiceClientStatusObserver::status2string(status) << ", session channelInfo " - << getAudioSessionChannelInfo() << ", proximal is " << inSpatialChannel() << LL_ENDL; + << getAudioSessionChannelInfo() << ", proximal is " << in_spatial_channel << LL_ENDL; mIsProcessingChannels = status == LLVoiceClientStatusObserver::STATUS_JOINED; @@ -410,7 +415,7 @@ void LLWebRTCVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::ESt for (status_observer_set_t::iterator it = mStatusObservers.begin(); it != mStatusObservers.end();) { LLVoiceClientStatusObserver *observer = *it; - observer->onChange(status, channelInfo, inSpatialChannel()); + observer->onChange(status, channelInfo, in_spatial_channel); // In case onError() deleted an entry. it = mStatusObservers.upper_bound(observer); } @@ -420,7 +425,7 @@ void LLWebRTCVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::ESt status != LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL && status != LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED) { - bool voice_status = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); + bool voice_status = LLVoiceClient::getInstance()->voiceEnabled() && mIsProcessingChannels; gAgent.setVoiceConnected(voice_status); @@ -1335,7 +1340,10 @@ bool LLWebRTCVoiceClient::startAdHocSession(const LLSD& channelInfo, bool notify bool LLWebRTCVoiceClient::isVoiceWorking() const { - return mIsProcessingChannels; + // webrtc is working if the coroutine is active in the case of + // webrtc. WebRTC doesn't need to connect to a secondary process + // or a login server to become active. + return mIsCoroutineActive; } // Returns true if calling back the session URI after the session has closed is possible. @@ -2440,7 +2448,7 @@ void LLVoiceWebRTCConnection::setSpeakerVolume(F32 volume) void LLVoiceWebRTCConnection::setUserVolume(const LLUUID& id, F32 volume) { - boost::json::object root = {{"ug", {id.asString(), (uint32_t) (volume * 200)}}}; + boost::json::object root = { { "ug", { { id.asString(), (uint32_t)(volume * PEER_GAIN_CONVERSION_FACTOR) } } } }; std::string json_data = boost::json::serialize(root); if (mWebRTCDataInterface) { @@ -2450,7 +2458,7 @@ void LLVoiceWebRTCConnection::setUserVolume(const LLUUID& id, F32 volume) void LLVoiceWebRTCConnection::setUserMute(const LLUUID& id, bool mute) { - boost::json::object root = {{"m", {id.asString(), mute}}}; + boost::json::object root = { { "m", { { id.asString(), mute } } } }; std::string json_data = boost::json::serialize(root); if (mWebRTCDataInterface) { @@ -2983,7 +2991,9 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b // we got a 'power' update. if (participant_obj.contains("p") && participant_obj["p"].is_number()) { - participant->mLevel = (F32)participant_obj["p"].as_int64(); + // server sends up power as an integer which is level * 128 to save + // character count. + participant->mLevel = (F32)participant_obj["p"].as_int64()/128.0f; } if (participant_obj.contains("v") && participant_obj["v"].is_bool()) @@ -2991,10 +3001,9 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b participant->mIsSpeaking = participant_obj["v"].as_bool(); } - if (participant_obj.contains("v") && participant_obj["m"].is_bool()) + if (participant_obj.contains("m") && participant_obj["m"].is_bool()) { participant->mIsModeratorMuted = participant_obj["m"].as_bool(); - ; } } } diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index f3bd5bc23a7b43127cb162e6327cb4874f23dcf1..0c6ed678ca8495cf8064a14136f019ddad1f825c 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -36,6 +36,7 @@ #include "llnotificationsutil.h" #include "llinventorymodel.h" #include "lltrans.h" +#include "llappviewer.h" // Callback struct struct LLWearableArrivedData @@ -81,9 +82,7 @@ void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& weara LLViewerWearable* instance = get_if_there(mList, assetID, (LLViewerWearable*)NULL ); if( instance ) { -#ifdef SHOW_DEBUG LL_DEBUGS("Avatar") << "wearable " << assetID << " found in LLWearableList" << LL_ENDL; -#endif asset_arrived_callback( instance, userdata ); } else @@ -99,6 +98,22 @@ void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& weara // static void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID& uuid, void* userdata, S32 status, LLExtStat ext_status ) { + if (!LLCoros::on_main_coro()) + { + // if triggered from a coroutine, dispatch to main thread before accessing app state + std::string filename_in = filename; + LLUUID uuid_in = uuid; + + LLAppViewer::instance()->postToMainCoro([=]() + { + processGetAssetReply(filename_in.c_str(), uuid_in, userdata, status, ext_status); + }); + + return; + } + + LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; + BOOL isNewWearable = FALSE; LLWearableArrivedData* data = (LLWearableArrivedData*) userdata; // LLViewerWearable* wearable = NULL; // NULL indicates failure @@ -203,10 +218,8 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID if (wearable) // success { LLWearableList::instance().mList[ uuid ] = wearable; -#ifdef SHOW_DEBUG LL_DEBUGS("Wearable") << "processGetAssetReply()" << LL_ENDL; LL_DEBUGS("Wearable") << wearable << LL_ENDL; -#endif } else { @@ -239,9 +252,7 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID LLViewerWearable* LLWearableList::createCopy(const LLViewerWearable* old_wearable, const std::string& new_name) { -#ifdef SHOW_DEBUG LL_DEBUGS() << "LLWearableList::createCopy()" << LL_ENDL; -#endif LLViewerWearable *wearable = generateNewWearable(); wearable->copyDataFrom(old_wearable); @@ -260,9 +271,7 @@ LLViewerWearable* LLWearableList::createCopy(const LLViewerWearable* old_wearabl LLViewerWearable* LLWearableList::createNewWearable( LLWearableType::EType type, LLAvatarAppearance *avatarp ) { -#ifdef SHOW_DEBUG LL_DEBUGS() << "LLWearableList::createNewWearable()" << LL_ENDL; -#endif LLViewerWearable *wearable = generateNewWearable(); wearable->setType( type, avatarp ); diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 65f0de00863585fabf5089242c8382bb44accc63..c3a927398834d7ef534b0b1c49e5da43198779a8 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -46,7 +46,7 @@ left="25" mouse_opaque="true" name="github_icon" - tool_tip="[APP_NAME] on Discord" + tool_tip="[APP_NAME] on GitHub" top="140" width="41"> <icon.commit_callback @@ -62,7 +62,7 @@ left_pad="10" mouse_opaque="true" name="bsky_icon" - tool_tip="[APP_NAME] on Mastodon" + tool_tip="[APP_NAME] on Bluesky" top="140" width="42"> <icon.commit_callback diff --git a/indra/newview/skins/default/xui/fr/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/fr/panel_outfits_inventory.xml index 05c689dd3443d53e7aed0a82a7963ce660940dfe..4dfe724894c72cb17192bba827aeb8fc44b451ad 100644 --- a/indra/newview/skins/default/xui/fr/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/fr/panel_outfits_inventory.xml @@ -14,7 +14,10 @@ <panel name="bottom_panel"> <layout_stack name="bottom_panel_ls"> <layout_panel name="save_btn_lp"> - <button label="Enregistrer sous" name="save_btn"/> + <button label="Enregistrer" name="save_btn"/> + </layout_panel> + <layout_panel name="save_as_btn_lp"> + <button label="Enregistrer sous..." name="save_as_btn"/> </layout_panel> <layout_panel name="wear_btn_lp"> <button label="Porter" name="wear_btn"/> diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index b9fffb4637abbb03b30decd832de544411106c1a..40e5eacf3762cd5c0e885965d599b3ab109d4b5a 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -61,6 +61,16 @@ class LLLogin::Impl LLEventPump& getEventPump() { return mPump; } private: + LLSD hidePasswd(const LLSD& data) + { + LLSD result(data); + if (result.has("params") && result["params"].has("passwd")) + { + result["params"]["passwd"] = "*******"; + } + return result; + } + LLSD getProgressEventLLSD(const std::string& state, const std::string& change, const LLSD& data = LLSD()) { @@ -69,15 +79,16 @@ class LLLogin::Impl status_data["change"] = change; status_data["progress"] = 0.0f; - if(mAuthResponse.has("transfer_rate")) + if (mAuthResponse.has("transfer_rate")) { status_data["transfer_rate"] = mAuthResponse["transfer_rate"]; } - if(data.isDefined()) + if (data.isDefined()) { status_data["data"] = data; } + return status_data; } @@ -114,17 +125,18 @@ class LLLogin::Impl void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params) { - LL_DEBUGS("LLLogin") << " connect with uri '" << uri << "', login_params " << login_params << LL_ENDL; + LL_DEBUGS("LLLogin") << " connect with uri '" << uri << "', login_params " << login_params << LL_ENDL; // Launch a coroutine with our login_() method. Run the coroutine until // its first wait; at that point, return here. std::string coroname = - LLCoros::instance().launch("LLLogin::Impl::login_", - boost::bind(&Impl::loginCoro, this, uri, login_params)); - LL_DEBUGS("LLLogin") << " connected with uri '" << uri << "', login_params " << login_params << LL_ENDL; + LLCoros::instance().launch("LLLogin::Impl::login_", [=]() { loginCoro(uri, login_params); }); + + LL_DEBUGS("LLLogin") << " connected with uri '" << uri << "', login_params " << login_params << LL_ENDL; } -namespace { +namespace +{ // Instantiate this rendezvous point at namespace scope so it's already // present no matter how early the updater might post to it. // Use an LLEventMailDrop, which has future-like semantics: regardless of the @@ -135,12 +147,8 @@ static LLEventMailDrop sSyncPoint("LoginSync"); void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params) { - LLSD printable_params = login_params; - if (printable_params.has("params") - && printable_params["params"].has("passwd")) - { - printable_params["params"]["passwd"] = "*******"; - } + LLSD printable_params = hidePasswd(login_params); + try { LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::getName() @@ -166,12 +174,7 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params) ++attempts; LLSD progress_data; progress_data["attempt"] = attempts; - progress_data["request"] = request; - if (progress_data["request"].has("params") - && progress_data["request"]["params"].has("passwd")) - { - progress_data["request"]["params"]["passwd"] = "*******"; - } + progress_data["request"] = hidePasswd(request); sendProgressEvent("offline", "authenticating", progress_data); // We expect zero or more "Downloading" status events, followed by