summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llappviewer.cpp')
-rw-r--r--indra/newview/llappviewer.cpp273
1 files changed, 220 insertions, 53 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 2fa94cd27b..2c5c7b6348 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -268,6 +268,16 @@ using namespace LL;
#include "glib.h"
#endif // (LL_LINUX) && LL_GTK
+#ifdef LL_DISCORD
+#define DISCORDPP_IMPLEMENTATION
+#include <discordpp.h>
+static std::shared_ptr<discordpp::Client> gDiscordClient;
+static uint64_t gDiscordTimestampsStart;
+static std::string gDiscordActivityDetails;
+static int32_t gDiscordPartyCurrentSize;
+static int32_t gDiscordPartyMaxSize;
+#endif
+
static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
@@ -443,13 +453,28 @@ static bool app_metrics_qa_mode = false;
void idle_afk_check()
{
+ // Don't check AFK status during startup states
+ if (LLStartUp::getStartupState() < STATE_STARTED)
+ {
+ return;
+ }
+
// check idle timers
F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32();
static LLCachedControl<S32> afk_timeout(gSavedSettings, "AFKTimeout", 300);
- if (afk_timeout() && (current_idle > (F32)afk_timeout()) && !gAgent.getAFK())
+ if (afk_timeout() && (current_idle > afk_timeout()))
{
- LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
- gAgent.setAFK();
+ if (!gAgent.getAFK())
+ {
+ LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
+ gAgent.setAFK();
+ }
+ else
+ {
+ // Refresh timer so that random one click or hover won't clear the status.
+ // But expanding the window still should lift afk status
+ gAwayTimer.reset();
+ }
}
}
@@ -475,7 +500,7 @@ static void deferred_ui_audio_callback(const LLUUID& uuid)
bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
{
- if(!match || !base || base->getPlainText())
+ if (!match || match->getSkipProfileIcon() || !base || base->getPlainText())
return false;
LLUUID match_id = match->getID();
@@ -1321,6 +1346,13 @@ bool LLAppViewer::frame()
bool LLAppViewer::doFrame()
{
+#ifdef LL_DISCORD
+ {
+ LL_PROFILE_ZONE_NAMED("discord_callbacks");
+ discordpp::RunCallbacks();
+ }
+#endif
+
LL_RECORD_BLOCK_TIME(FTM_FRAME);
LL_PROFILE_GPU_ZONE("Frame");
{
@@ -1840,36 +1872,6 @@ bool LLAppViewer::cleanup()
// Clean up before GL is shut down because we might be holding on to objects with texture references
LLSelectMgr::cleanupGlobals();
- LL_INFOS() << "Shutting down OpenGL" << LL_ENDL;
-
- // Shut down OpenGL
- if( gViewerWindow)
- {
- gViewerWindow->shutdownGL();
-
- // Destroy window, and make sure we're not fullscreen
- // This may generate window reshape and activation events.
- // Therefore must do this before destroying the message system.
- delete gViewerWindow;
- gViewerWindow = NULL;
- LL_INFOS() << "ViewerWindow deleted" << LL_ENDL;
- }
-
- LLSplashScreen::show();
- LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
-
- LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL;
-
- // viewer UI relies on keyboard so keep it aound until viewer UI isa gone
- delete gKeyboard;
- gKeyboard = NULL;
-
- if (LLViewerJoystick::instanceExists())
- {
- // Turn off Space Navigator and similar devices
- LLViewerJoystick::getInstance()->terminate();
- }
-
LL_INFOS() << "Cleaning up Objects" << LL_ENDL;
LLViewerObject::cleanupVOClasses();
@@ -2030,6 +2032,36 @@ bool LLAppViewer::cleanup()
sTextureFetch->shutDownTextureCacheThread() ;
LLLFSThread::sLocal->shutdown();
+ LL_INFOS() << "Shutting down OpenGL" << LL_ENDL;
+
+ // Shut down OpenGL
+ if (gViewerWindow)
+ {
+ gViewerWindow->shutdownGL();
+
+ // Destroy window, and make sure we're not fullscreen
+ // This may generate window reshape and activation events.
+ // Therefore must do this before destroying the message system.
+ delete gViewerWindow;
+ gViewerWindow = NULL;
+ LL_INFOS() << "ViewerWindow deleted" << LL_ENDL;
+ }
+
+ LLSplashScreen::show();
+ LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
+
+ LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL;
+
+ // viewer UI relies on keyboard so keep it aound until viewer UI isa gone
+ delete gKeyboard;
+ gKeyboard = NULL;
+
+ if (LLViewerJoystick::instanceExists())
+ {
+ // Turn off Space Navigator and similar devices
+ LLViewerJoystick::getInstance()->terminate();
+ }
+
LL_INFOS() << "Shutting down message system" << LL_ENDL;
end_messaging_system();
@@ -2250,10 +2282,7 @@ void errorCallback(LLError::ELevel level, const std::string &error_string)
// Callback for LLError::LLUserWarningMsg
void errorHandler(const std::string& title_string, const std::string& message_string, S32 code)
{
- if (!message_string.empty())
- {
- OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
- }
+ // message is going to hang viewer, create marker first
switch (code)
{
case LLError::LLUserWarningMsg::ERROR_OTHER:
@@ -2261,6 +2290,10 @@ void errorHandler(const std::string& title_string, const std::string& message_st
break;
case LLError::LLUserWarningMsg::ERROR_BAD_ALLOC:
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_BAD_ALLOC);
+ // When system run out of memory and errorHandler gets called from a thread,
+ // main thread might keep going while OSMessageBox freezes the caller.
+ // Todo: handle it better, but for now disconnect to avoid making things worse
+ gDisconnected = true;
break;
case LLError::LLUserWarningMsg::ERROR_MISSING_FILES:
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_MISSING_FILES);
@@ -2268,6 +2301,10 @@ void errorHandler(const std::string& title_string, const std::string& message_st
default:
break;
}
+ if (!message_string.empty())
+ {
+ OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
+ }
}
void LLAppViewer::initLoggingAndGetLastDuration()
@@ -3093,7 +3130,15 @@ bool LLAppViewer::initWindow()
.height(gSavedSettings.getU32("WindowHeight"))
.min_width(gSavedSettings.getU32("MinWindowWidth"))
.min_height(gSavedSettings.getU32("MinWindowHeight"))
+#ifdef LL_DARWIN
+ // Setting it to true causes black screen with no UI displayed.
+ // Given that it's a DEBUG settings and application goes fullscreen
+ // on mac simply by expanding it, it was decided to not support/use
+ // this setting on mac.
+ .fullscreen(false)
+#else // LL_DARWIN
.fullscreen(gSavedSettings.getBOOL("FullScreen"))
+#endif
.ignore_pixel_depth(ignorePixelDepth)
.first_run(mIsFirstRun);
@@ -4258,7 +4303,7 @@ U32 LLAppViewer::getTextureCacheVersion()
U32 LLAppViewer::getDiskCacheVersion()
{
// Viewer disk cache version intorduced in Simple Cache Viewer, change if the cache format changes.
- const U32 DISK_CACHE_VERSION = 2;
+ const U32 DISK_CACHE_VERSION = 3;
return DISK_CACHE_VERSION ;
}
@@ -4284,8 +4329,8 @@ bool LLAppViewer::initCache()
const std::string cache_dir_name = gSavedSettings.getString("DiskCacheDirName");
const U32 MB = 1024 * 1024;
- const uintmax_t MIN_CACHE_SIZE = 256 * MB;
- const uintmax_t MAX_CACHE_SIZE = 9984ll * MB;
+ const uintmax_t MIN_CACHE_SIZE = 896 * MB;
+ const uintmax_t MAX_CACHE_SIZE = 32768ll * MB;
const uintmax_t setting_cache_total_size = uintmax_t(gSavedSettings.getU32("CacheSize")) * MB;
const uintmax_t cache_total_size = llclamp(setting_cache_total_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE);
const F64 disk_cache_percent = gSavedSettings.getF32("DiskCachePercentOfTotal");
@@ -5691,9 +5736,31 @@ void LLAppViewer::forceErrorThreadCrash()
thread->start();
}
-void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
+void LLAppViewer::forceExceptionThreadCrash()
+{
+ class LLCrashTestThread : public LLThread
+ {
+ public:
+
+ LLCrashTestThread() : LLThread("Crash logging test thread")
+ {
+ }
+
+ void run()
+ {
+ const std::string exception_text = "This is a deliberate exception in a thread";
+ throw std::runtime_error(exception_text);
+ }
+ };
+
+ LL_WARNS() << "This is a deliberate exception in a thread" << LL_ENDL;
+ LLCrashTestThread* thread = new LLCrashTestThread();
+ thread->start();
+}
+
+void LLAppViewer::initMainloopTimeout(std::string_view state, F32 secs)
{
- if(!mMainloopTimeout)
+ if (!mMainloopTimeout)
{
mMainloopTimeout = new LLWatchdogTimeout();
resumeMainloopTimeout(state, secs);
@@ -5702,20 +5769,20 @@ void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
void LLAppViewer::destroyMainloopTimeout()
{
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
delete mMainloopTimeout;
- mMainloopTimeout = NULL;
+ mMainloopTimeout = nullptr;
}
}
-void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs)
+void LLAppViewer::resumeMainloopTimeout(std::string_view state, F32 secs)
{
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
- if(secs < 0.0f)
+ if (secs < 0.0f)
{
- static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
+ static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60.f);
secs = mainloop_timeout;
}
@@ -5726,19 +5793,19 @@ void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs)
void LLAppViewer::pauseMainloopTimeout()
{
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
mMainloopTimeout->stop();
}
}
-void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
+void LLAppViewer::pingMainloopTimeout(std::string_view state, F32 secs)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
- if(secs < 0.0f)
+ if (secs < 0.0f)
{
static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
secs = mainloop_timeout;
@@ -5866,3 +5933,103 @@ void LLAppViewer::metricsSend(bool enable_reporting)
gViewerAssetStats->restart();
}
+#ifdef LL_DISCORD
+
+void LLAppViewer::initDiscordSocial()
+{
+ gDiscordPartyCurrentSize = 1;
+ gDiscordPartyMaxSize = 0;
+ gDiscordTimestampsStart = time(nullptr);
+ gDiscordClient = std::make_shared<discordpp::Client>();
+ gDiscordClient->SetApplicationId(1394782217405862001);
+ updateDiscordActivity();
+}
+
+void LLAppViewer::updateDiscordActivity()
+{
+ LL_PROFILE_ZONE_SCOPED;
+
+ static LLCachedControl<bool> integration_enabled(gSavedSettings, "EnableDiscord", true);
+ if (!integration_enabled)
+ {
+ gDiscordClient->ClearRichPresence();
+ return;
+ }
+
+ discordpp::Activity activity;
+ activity.SetType(discordpp::ActivityTypes::Playing);
+ discordpp::ActivityTimestamps timestamps;
+ timestamps.SetStart(gDiscordTimestampsStart);
+ activity.SetTimestamps(timestamps);
+
+ if (gAgent.getID() == LLUUID::null)
+ {
+ gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {});
+ return;
+ }
+
+ static LLCachedControl<bool> show_details(gSavedSettings, "ShowDiscordActivityDetails", false);
+ if (show_details)
+ {
+ if (gDiscordActivityDetails.empty())
+ {
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(gAgent.getID(), &av_name);
+ gDiscordActivityDetails = av_name.getUserName();
+ auto displayName = av_name.getDisplayName();
+ if (gDiscordActivityDetails != displayName)
+ gDiscordActivityDetails = displayName + " (" + gDiscordActivityDetails + ")";
+ }
+ activity.SetDetails(gDiscordActivityDetails);
+ }
+
+ auto agent_pos_region = gAgent.getPositionAgent();
+ S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f);
+ S32 pos_y = S32(agent_pos_region.mV[VY] + 0.5f);
+ S32 pos_z = S32(agent_pos_region.mV[VZ] + 0.5f);
+ F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared();
+ const F32 FLY_CUTOFF = 6.f;
+ const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
+ const F32 WALK_CUTOFF = 1.5f;
+ const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
+ if (velocity_mag_sq > FLY_CUTOFF_SQ)
+ {
+ pos_x -= pos_x % 4;
+ pos_y -= pos_y % 4;
+ }
+ else if (velocity_mag_sq > WALK_CUTOFF_SQ)
+ {
+ pos_x -= pos_x % 2;
+ pos_y -= pos_y % 2;
+ }
+
+ std::string location = "Hidden Region";
+ static LLCachedControl<bool> show_state(gSavedSettings, "ShowDiscordActivityState", false);
+ if (show_state)
+ {
+ location = llformat("%s (%d, %d, %d)", gAgent.getRegion()->getName().c_str(), pos_x, pos_y, pos_z);
+ }
+ activity.SetState(location);
+
+ discordpp::ActivityParty party;
+ party.SetId(location);
+ party.SetCurrentSize(gDiscordPartyCurrentSize);
+ party.SetMaxSize(gDiscordPartyMaxSize);
+ activity.SetParty(party);
+
+ gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {});
+}
+
+void LLAppViewer::updateDiscordPartyCurrentSize(int32_t size)
+{
+ gDiscordPartyCurrentSize = size;
+ updateDiscordActivity();
+}
+
+void LLAppViewer::updateDiscordPartyMaxSize(int32_t size)
+{
+ gDiscordPartyMaxSize = size;
+ updateDiscordActivity();
+}
+
+#endif