diff --git a/Dotnet/AppApi/AppApi.cs b/Dotnet/AppApi/AppApi.cs
index bed870cb..1cc134e2 100644
--- a/Dotnet/AppApi/AppApi.cs
+++ b/Dotnet/AppApi/AppApi.cs
@@ -40,6 +40,11 @@ namespace VRCX
ProcessMonitor.Instance.ProcessExited += Instance.OnProcessStateChanged;
}
+ public void Init()
+ {
+ // Create Instance before Cef tries to bind it
+ }
+
///
/// Computes the MD5 hash of the file represented by the specified base64-encoded string.
///
diff --git a/Dotnet/AppApi/AppApiVr.cs b/Dotnet/AppApi/AppApiVr.cs
index b17b88b2..361233be 100644
--- a/Dotnet/AppApi/AppApiVr.cs
+++ b/Dotnet/AppApi/AppApiVr.cs
@@ -9,20 +9,15 @@ namespace VRCX
public class AppApiVr
{
public static readonly AppApiVr Instance;
- private static readonly PerformanceCounter Uptime;
static AppApiVr()
{
Instance = new AppApiVr();
+ }
- try
- {
- Uptime = new PerformanceCounter("System", "System Up Time");
- }
- catch
- {
- Uptime = null;
- }
+ public void Init()
+ {
+ // Create Instance before Cef tries to bind it
}
public void VrInit()
@@ -31,13 +26,18 @@ namespace VRCX
MainForm.Instance.Browser.ExecuteScriptAsync("$app.vrInit", "");
}
+ public void ToggleSystemMonitor(bool enabled)
+ {
+ SystemMonitor.Instance.Start(enabled);
+ }
+
///
/// Returns the current CPU usage as a percentage.
///
/// The current CPU usage as a percentage.
public float CpuUsage()
{
- return CpuMonitor.Instance.CpuUsage;
+ return SystemMonitor.Instance.CpuUsage;
}
///
@@ -56,11 +56,7 @@ namespace VRCX
/// The number of milliseconds that the system has been running.
public double GetUptime()
{
- if (Uptime == null)
- return 0;
-
- Uptime.NextValue();
- return TimeSpan.FromSeconds(Uptime.NextValue()).TotalMilliseconds;
+ return SystemMonitor.Instance.UpTime;
}
///
diff --git a/Dotnet/Cef/CefCustomDownloadHandler.cs b/Dotnet/Cef/CefCustomDownloadHandler.cs
index c58ce9a8..3a43b02c 100644
--- a/Dotnet/Cef/CefCustomDownloadHandler.cs
+++ b/Dotnet/Cef/CefCustomDownloadHandler.cs
@@ -15,10 +15,10 @@ namespace VRCX
return true;
}
- public void OnBeforeDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
+ public bool OnBeforeDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
{
if (callback.IsDisposed)
- return;
+ return true;
using (callback)
{
@@ -27,6 +27,8 @@ namespace VRCX
showDialog: true
);
}
+
+ return true;
}
public void OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
diff --git a/Dotnet/CpuMonitor.cs b/Dotnet/CpuMonitor.cs
deleted file mode 100644
index ab4154f2..00000000
--- a/Dotnet/CpuMonitor.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright(c) 2019-2022 pypy, Natsumi and individual contributors.
-// All rights reserved.
-//
-// This work is licensed under the terms of the MIT license.
-// For a copy, see .
-
-using System.Diagnostics;
-using System.Threading;
-
-namespace VRCX
-{
- public class CpuMonitor
- {
- public static readonly CpuMonitor Instance;
- public float CpuUsage;
- private readonly PerformanceCounter _performanceCounter;
- private readonly Timer _timer;
-
- static CpuMonitor()
- {
- Instance = new CpuMonitor();
- }
-
- public CpuMonitor()
- {
- try
- {
- _performanceCounter = new PerformanceCounter(
- "Processor Information",
- "% Processor Utility",
- "_Total",
- true
- );
- }
- catch
- {
- }
-
- // fallback
- if (_performanceCounter == null)
- {
- try
- {
- _performanceCounter = new PerformanceCounter(
- "Processor",
- "% Processor Time",
- "_Total",
- true
- );
- }
- catch
- {
- }
- }
-
- _timer = new Timer(TimerCallback, null, -1, -1);
- }
-
- internal void Init()
- {
- _timer.Change(1000, 1000);
- }
-
- internal void Exit()
- {
- lock (this)
- {
- _timer.Change(-1, -1);
- _performanceCounter?.Dispose();
- }
- }
-
- private void TimerCallback(object state)
- {
- lock (this)
- {
- try
- {
- if (_performanceCounter != null)
- {
- CpuUsage = _performanceCounter.NextValue();
- }
- }
- catch
- {
- }
- }
- }
- }
-}
diff --git a/Dotnet/Discord.cs b/Dotnet/Discord.cs
index 9b1f1646..4841d8e6 100644
--- a/Dotnet/Discord.cs
+++ b/Dotnet/Discord.cs
@@ -65,7 +65,7 @@ namespace VRCX
if (m_Client == null && m_Active)
{
m_Client = new DiscordRpcClient(DiscordAppId);
- if (m_Client.Initialize() == false)
+ if (!m_Client.Initialize())
{
m_Client.Dispose();
m_Client = null;
@@ -117,18 +117,18 @@ namespace VRCX
public void SetText(string details, string state)
{
- if (m_Client != null && !m_Lock.IsReadLockHeld)
+ if (m_Client == null || m_Lock.IsReadLockHeld)
+ return;
+
+ m_Lock.EnterWriteLock();
+ try
{
- m_Lock.EnterWriteLock();
- try
- {
- m_Presence.Details = LimitByteLength(details, 127);
- m_Presence.State = LimitByteLength(state, 127);
- }
- finally
- {
- m_Lock.ExitWriteLock();
- }
+ m_Presence.Details = LimitByteLength(details, 127);
+ m_Presence.State = LimitByteLength(state, 127);
+ }
+ finally
+ {
+ m_Lock.ExitWriteLock();
}
}
@@ -137,17 +137,15 @@ namespace VRCX
m_Lock.EnterWriteLock();
try
{
- if (string.IsNullOrEmpty(largeKey) == true &&
- string.IsNullOrEmpty(smallKey) == true)
+ if (string.IsNullOrEmpty(largeKey) &&
+ string.IsNullOrEmpty(smallKey))
{
m_Presence.Assets = null;
}
else
{
- if (m_Presence.Assets == null)
- m_Presence.Assets = new Assets();
- if (m_Presence.Party == null)
- m_Presence.Party = new Party();
+ m_Presence.Assets ??= new Assets();
+ m_Presence.Party ??= new Party();
m_Presence.Assets.LargeImageKey = largeKey;
m_Presence.Assets.LargeImageText = largeText;
m_Presence.Assets.SmallImageKey = smallKey;
@@ -155,15 +153,15 @@ namespace VRCX
m_Presence.Party.ID = partyId;
m_Presence.Party.Size = partySize;
m_Presence.Party.Max = partyMax;
- Button[] Buttons = { };
+ Button[] buttons = [];
if (!string.IsNullOrEmpty(buttonUrl))
{
- Buttons = new Button[]
- {
- new Button() { Label = buttonText, Url = buttonUrl }
- };
+ buttons =
+ [
+ new Button { Label = buttonText, Url = buttonUrl }
+ ];
}
- m_Presence.Buttons = Buttons;
+ m_Presence.Buttons = buttons;
if (DiscordAppId != appId)
{
DiscordAppId = appId;
@@ -181,7 +179,7 @@ namespace VRCX
m_Lock.ExitWriteLock();
}
}
-
+
public void SetTimestamps(double startUnixMilliseconds, double endUnixMilliseconds)
{
var _startUnixMilliseconds = (ulong)startUnixMilliseconds;
@@ -196,11 +194,7 @@ namespace VRCX
}
else
{
- if (m_Presence.Timestamps == null)
- {
- m_Presence.Timestamps = new Timestamps();
- }
-
+ m_Presence.Timestamps ??= new Timestamps();
m_Presence.Timestamps.StartUnixMilliseconds = _startUnixMilliseconds;
if (_endUnixMilliseconds == 0)
diff --git a/Dotnet/Program.cs b/Dotnet/Program.cs
index aa53ec07..036b3f6a 100644
--- a/Dotnet/Program.cs
+++ b/Dotnet/Program.cs
@@ -144,7 +144,8 @@ namespace VRCX
ProcessMonitor.Instance.Init();
VRCXStorage.Load();
SQLiteLegacy.Instance.Init();
- CpuMonitor.Instance.Init();
+ AppApi.Instance.Init();
+ AppApiVr.Instance.Init();
Discord.Instance.Init();
WorldDBManager.Instance.Init();
WebApi.Instance.Init();
@@ -166,7 +167,7 @@ namespace VRCX
WorldDBManager.Instance.Stop();
Discord.Instance.Exit();
- CpuMonitor.Instance.Exit();
+ SystemMonitor.Instance.Exit();
VRCXStorage.Save();
SQLiteLegacy.Instance.Exit();
ProcessMonitor.Instance.Exit();
diff --git a/Dotnet/SystemMonitor.cs b/Dotnet/SystemMonitor.cs
new file mode 100644
index 00000000..b473f340
--- /dev/null
+++ b/Dotnet/SystemMonitor.cs
@@ -0,0 +1,151 @@
+// Copyright(c) 2019-2022 pypy, Natsumi and individual contributors.
+// All rights reserved.
+//
+// This work is licensed under the terms of the MIT license.
+// For a copy, see .
+
+using System;
+using System.Diagnostics;
+using System.Threading;
+using NLog;
+
+namespace VRCX
+{
+ public class SystemMonitor
+ {
+ public static readonly SystemMonitor Instance;
+ public float CpuUsage;
+ public double UpTime;
+ private bool _enabled;
+ private PerformanceCounter _performanceCounterCpuUsage;
+ private PerformanceCounter _performanceCounterUpTime;
+ private Thread _thread;
+ private static readonly NLog.Logger logger = NLog.LogManager.GetLogger("VRCX");
+
+ static SystemMonitor()
+ {
+ Instance = new SystemMonitor();
+ }
+
+ public void Start(bool enabled)
+ {
+ if (enabled == _enabled)
+ return;
+
+ _enabled = enabled;
+ if (enabled)
+ StartThread();
+ else
+ Exit();
+ }
+
+ internal void Exit()
+ {
+ CpuUsage = 0;
+ UpTime = 0;
+ try
+ {
+ if (_thread != null)
+ {
+ _thread.Interrupt();
+ _thread.Join();
+ _thread = null;
+ }
+ }
+ catch (ThreadInterruptedException)
+ {
+ }
+
+ _performanceCounterCpuUsage?.Dispose();
+ _performanceCounterCpuUsage = null;
+ _performanceCounterUpTime?.Dispose();
+ _performanceCounterUpTime = null;
+ }
+
+ private void StartThread()
+ {
+ Exit();
+
+ try
+ {
+ _performanceCounterCpuUsage = new PerformanceCounter(
+ "Processor Information",
+ "% Processor Utility",
+ "_Total",
+ true
+ );
+ _performanceCounterCpuUsage?.NextValue();
+ }
+ catch (Exception ex)
+ {
+ logger.Warn($"Failed to create \"Processor Utility\" PerformanceCounter ${ex}");
+ }
+
+ // fallback
+ if (_performanceCounterCpuUsage == null)
+ {
+ try
+ {
+ _performanceCounterCpuUsage = new PerformanceCounter(
+ "Processor",
+ "% Processor Time",
+ "_Total",
+ true
+ );
+ _performanceCounterCpuUsage?.NextValue();
+ }
+ catch (Exception ex)
+ {
+ logger.Warn($"Failed to create \"Processor Time\" PerformanceCounter ${ex}");
+ }
+ }
+
+ try
+ {
+ _performanceCounterUpTime = new PerformanceCounter("System", "System Up Time");
+ _performanceCounterUpTime?.NextValue();
+ }
+ catch
+ {
+ logger.Warn("Failed to create \"System Up Time\" PerformanceCounter");
+ }
+
+ if (_performanceCounterCpuUsage == null &&
+ _performanceCounterUpTime == null)
+ {
+ logger.Error("Failed to create any PerformanceCounter");
+ return;
+ }
+ logger.Info("SystemMonitor started");
+
+ _thread = new Thread(ThreadProc)
+ {
+ IsBackground = true
+ };
+ _thread.Start();
+ }
+
+ private void ThreadProc()
+ {
+ try
+ {
+ while (_enabled)
+ {
+ if (_performanceCounterCpuUsage != null)
+ CpuUsage = _performanceCounterCpuUsage.NextValue();
+
+ if (_performanceCounterUpTime != null)
+ UpTime = TimeSpan.FromSeconds(_performanceCounterUpTime.NextValue()).TotalMilliseconds;
+
+ Thread.Sleep(1000);
+ }
+ }
+ catch (Exception ex)
+ {
+ logger.Warn($"SystemMonitor thread exception: {ex}");
+ }
+
+ Exit();
+ }
+ }
+}
diff --git a/VRCX.csproj b/VRCX.csproj
index 0cb5913d..65cf1c41 100644
--- a/VRCX.csproj
+++ b/VRCX.csproj
@@ -119,8 +119,8 @@
-
-
+
+
diff --git a/html/src/app.js b/html/src/app.js
index 6fb10797..4fd63ee7 100644
--- a/html/src/app.js
+++ b/html/src/app.js
@@ -15225,8 +15225,8 @@ speechSynthesis.getVoices();
'VRCX_hideDevicesFromFeed',
false
);
- $app.data.hideCpuUsageFromFeed = await configRepository.getBool(
- 'VRCX_hideCpuUsageFromFeed',
+ $app.data.vrOverlayCpuUsage = await configRepository.getBool(
+ 'VRCX_vrOverlayCpuUsage',
false
);
$app.data.hideUptimeFromFeed = await configRepository.getBool(
@@ -15429,8 +15429,8 @@ speechSynthesis.getVoices();
this.hideDevicesFromFeed
);
await configRepository.setBool(
- 'VRCX_hideCpuUsageFromFeed',
- this.hideCpuUsageFromFeed
+ 'VRCX_vrOverlayCpuUsage',
+ this.vrOverlayCpuUsage
);
await configRepository.setBool(
'VRCX_hideUptimeFromFeed',
@@ -16155,7 +16155,7 @@ speechSynthesis.getVoices();
var VRConfigVars = {
overlayNotifications: this.overlayNotifications,
hideDevicesFromFeed: this.hideDevicesFromFeed,
- hideCpuUsageFromFeed: this.hideCpuUsageFromFeed,
+ vrOverlayCpuUsage: this.vrOverlayCpuUsage,
minimalFeed: this.minimalFeed,
notificationPosition: this.notificationPosition,
notificationTimeout: this.notificationTimeout,
diff --git a/html/src/localization/en/en.json b/html/src/localization/en/en.json
index 858c8b73..c747e1c3 100644
--- a/html/src/localization/en/en.json
+++ b/html/src/localization/en/en.json
@@ -374,7 +374,7 @@
"background_color": "Background Color",
"minimal_feed_icons": "Minimal Feed Icons",
"hide_vr_devices": "Hide VR Devices",
- "hide_cpu_usage": "Hide CPU Usage",
+ "show_cpu_usage": "Show CPU Usage",
"hide_game_uptime": "Hide Game Uptime",
"show_pc_uptime": "Show PC Uptime",
"wrist_feed_filters": "Wrist Feed Filters"
diff --git a/html/src/mixins/tabs/settings.pug b/html/src/mixins/tabs/settings.pug
index c84bb367..92a4c8b0 100644
--- a/html/src/mixins/tabs/settings.pug
+++ b/html/src/mixins/tabs/settings.pug
@@ -372,8 +372,8 @@ mixin settingsTab()
span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.hide_vr_devices') }}
el-switch(v-model="hideDevicesFromFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
div.options-container-item
- span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.hide_cpu_usage') }}
- el-switch(v-model="hideCpuUsageFromFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
+ span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.show_cpu_usage') }}
+ el-switch(v-model="vrOverlayCpuUsage" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
div.options-container-item
span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.hide_game_uptime') }}
el-switch(v-model="hideUptimeFromFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
diff --git a/html/src/vr.js b/html/src/vr.js
index c862b23d..926332e4 100644
--- a/html/src/vr.js
+++ b/html/src/vr.js
@@ -194,8 +194,11 @@ Vue.component('marquee-text', MarqueeText);
// 2 = 항상 화면에 보이는 거
appType: location.href.substr(-1),
appLanguage: 'en',
+ currentCulture: 'en-nz',
currentTime: new Date().toJSON(),
+ cpuUsageEnabled: false,
cpuUsage: 0,
+ pcUptimeEnabled: false,
pcUptime: '',
customInfo: '',
config: {},
@@ -351,6 +354,16 @@ Vue.component('marquee-text', MarqueeText);
this.setDatetimeFormat();
this.setAppLanguage(this.config.appLanguage);
this.updateFeedLength();
+ if (
+ this.config.vrOverlayCpuUsage !== this.cpuUsageEnabled ||
+ this.config.pcUptimeOnFeed !== this.pcUptimeEnabled
+ ) {
+ this.cpuUsageEnabled = this.config.vrOverlayCpuUsage;
+ this.pcUptimeEnabled = this.config.pcUptimeOnFeed;
+ AppApiVr.ToggleSystemMonitor(
+ this.cpuUsageEnabled || this.pcUptimeEnabled
+ );
+ }
};
$app.methods.updateOnlineFriendCount = function (count) {
@@ -435,7 +448,7 @@ Vue.component('marquee-text', MarqueeText);
.replace(' PM', ' pm')
.replace(',', '');
- if (!this.config.hideCpuUsageFromFeed) {
+ if (this.cpuUsageEnabled) {
var cpuUsage = await AppApiVr.CpuUsage();
this.cpuUsage = cpuUsage.toFixed(0);
}
@@ -802,8 +815,6 @@ Vue.component('marquee-text', MarqueeText);
this.hudTimeout = JSON.parse(json);
};
- $app.data.currentCulture = await AppApiVr.CurrentCulture();
-
$app.methods.setDatetimeFormat = async function () {
this.currentCulture = await AppApiVr.CurrentCulture();
var formatDate = function (date) {
diff --git a/html/src/vr.pug b/html/src/vr.pug
index 3f53cdca..f57b11ee 100644
--- a/html/src/vr.pug
+++ b/html/src/vr.pug
@@ -532,7 +532,7 @@ html
span(style="display:inline-block;font-weight:bold") {{ lastLocation.friendList.length !== 0 ? ` (${lastLocation.friendList.length})` : ''}}
br
span(style="float:right") {{ currentTime }}
- span(v-if="config && !config.hideCpuUsageFromFeed" style="display:inline-block;margin-right:5px") {{ $t('vr.status.cpu') }} {{ cpuUsage }}%
+ span(v-if="config && cpuUsageEnabled" style="display:inline-block;margin-right:5px") {{ $t('vr.status.cpu') }} {{ cpuUsage }}%
span(style="display:inline-block") {{ $t('vr.status.online') }} {{ onlineFriendCount }} {{ customInfo }}
template(v-else)
svg(class="np-progress-circle")