Skip to content

Commit fd4601f

Browse files
committed
Update 5.2.0 - See changelog.txt for details
1 parent ac4958a commit fd4601f

File tree

11 files changed

+1024
-31
lines changed

11 files changed

+1024
-31
lines changed

Installer.iss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
; =====================================================
2-
; StreamTweak v5.1.1 - GitHub Release Installer
2+
; StreamTweak v5.2.0 - GitHub Release Installer
33
; =====================================================
44
#define MyAppName "StreamTweak"
5-
#define MyAppVersion "5.1.1"
5+
#define MyAppVersion "5.2.0"
66
#define MyAppPublisher "FoggyBytes"
77
#define MyAppExeName "StreamTweak.exe"
88
#define MyAppURL "https://github.com/FoggyBytes/StreamTweak"

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,17 @@ StreamLight and StreamTweak are designed to work together, giving you full contr
6666

6767
### 📚 System Info & Diagnostics
6868
- **Logs Tab:** Full session history — every streaming session is recorded regardless of whether NIC throttle was applied, with NIC Throttle (Yes/No), Original NIC Speed, and timestamped date including year.
69+
- **Session quality report:** click the chart button on any session row to open a full-panel telemetry overlay with CLIENT stats (FPS, Drops, RTT, Decode, Bitrate), HOST stats (GPU, Encoder, GPU Temp, CPU, Net TX), four time-series sparkline charts with axes and scale labels, and a quality grade badge (High / Medium / Low).
6970
- **Home Dashboard:** Version info, GitHub link, license badge, donation button, and a real-time status overview for all six managed settings — all in the Home panel.
7071

71-
## ✨ What's New in Version 5.1.1 — The "Code Quality Update"
72+
## ✨ What's New in Version 5.2.0 — The "Session Quality Update"
73+
74+
* **Session quality report —** click the chart button on any session row in the Logs tab to open a full-panel telemetry overlay; CLIENT stats (FPS, Drops, RTT, Decode, Bitrate) and HOST stats (GPU, Encoder, GPU Temp, CPU, Net TX) appear side by side, followed by four time-series sparkline charts and a quality grade badge
75+
* **Four sparkline charts —** FPS, RTT (ms), Drops, and Bitrate (Mbps) rendered with Cartesian axes, Y-scale labels (max/mid/min), and X-axis time labels; the section is clearly labeled CLIENT (StreamLight) to distinguish client-side data from host metrics
76+
* **Quality grade system —** sessions are graded Excellent, Accettable, or Poor based on drop rate, RTT, and GPU encoder utilization; FPS is excluded because static screens and loading screens produce artificially low frame counts that do not reflect actual streaming quality
77+
* **Animated overlay —** the telemetry panel opens and closes with a smooth CubicEase animation (200 ms / 150 ms) and covers the full Logs panel with an opaque background
78+
79+
### Previously in 5.1.1 — The "Code Quality Update"
7280

7381
* **Bug fixes and hardening —** resource leaks, thread-safety issues, sync reentrancy guards, WQL/PowerShell injection prevention, and atomic file writes for cover art cache
7482
* **Dead code removed —** unused methods, orphan variables and comments cleaned up
@@ -315,7 +323,7 @@ LogParser.FindStreamingAppInfo()
315323

316324
## 📝 Installation
317325
1. Go to the **Releases** page of this repository.
318-
2. Download the latest `StreamTweak_5.1.1_Installer.exe`
326+
2. Download the latest `StreamTweak_5.2.0_Installer.exe`
319327
3. Run the installer and enjoy seamless streaming.
320328

321329
## 🙏 Support the Project

StreamTweak/App.xaml.cs

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public partial class App : Application
5555
// Real-time host metrics (GPU, CPU, VRAM, network) for the STATS command
5656
private readonly HostMetricsCollector _metricsCollector = new();
5757

58+
// Session quality telemetry — accumulates client metrics sent by StreamLight
59+
private readonly TelemetryAccumulator _telemetryAccumulator = new();
60+
5861
// Inactivity timer — prevents restoring speed on temporary reconnect disconnects
5962
private System.Windows.Threading.DispatcherTimer? inactivityTimer = null;
6063
private const int INACTIVITY_TIMEOUT_MS = 30000;
@@ -86,8 +89,9 @@ protected override void OnStartup(StartupEventArgs e)
8689
_ = InitHdrStateAsync();
8790

8891
// Start Moonlight fork TCP bridge
89-
_bridge.PrepareRequested += OnBridgePrepareRequested;
90-
_bridge.RestoreRequested += OnBridgeRestoreRequested;
92+
_bridge.PrepareRequested += OnBridgePrepareRequested;
93+
_bridge.RestoreRequested += OnBridgeRestoreRequested;
94+
_bridge.SessionDataReceived += OnSessionDataReceived;
9195
_bridge.Start();
9296
_bridge.StatusProvider = () => {
9397
var (mbps, connected) = GetCurrentSpeed();
@@ -613,8 +617,9 @@ private void MenuExit_Click(object sender, RoutedEventArgs e)
613617
{
614618
if (_isAutoSessionActive)
615619
SessionLogger.EndSession("App Closed");
616-
_bridge.PrepareRequested -= OnBridgePrepareRequested;
617-
_bridge.RestoreRequested -= OnBridgeRestoreRequested;
620+
_bridge.PrepareRequested -= OnBridgePrepareRequested;
621+
_bridge.RestoreRequested -= OnBridgeRestoreRequested;
622+
_bridge.SessionDataReceived -= OnSessionDataReceived;
618623
_bridge.Dispose();
619624
_metricsCollector.Dispose();
620625
StopLogMonitorForced();
@@ -744,6 +749,7 @@ private async void HandleAutoStreamStart(bool skipNicThrottle = false)
744749
}
745750

746751
// Always log the session, with or without NIC throttle
752+
_telemetryAccumulator.Reset();
747753
_appsToRelaunch = ManagedAppController.KillRunning();
748754
_isAutoSessionActive = true;
749755
UpdateTrayIcon();
@@ -788,6 +794,19 @@ private async void HandleAutoStreamStop(string endReason = "User")
788794

789795
if (_isAutoSessionActive)
790796
{
797+
// Persist telemetry before EndSession clears the active session ID
798+
string? sessionId = SessionLogger.ActiveSessionId;
799+
if (sessionId != null)
800+
{
801+
var (stats, fpsSeries, rttSeries, dropsSeries, bitrateSeries) = _telemetryAccumulator.Finalize();
802+
if (stats.SampleCount >= 2)
803+
{
804+
var grade = QualityGradeCalculator.Evaluate(stats, _telemetryAccumulator.TargetFps);
805+
SessionLogger.UpdateSessionTelemetry(sessionId, stats, grade, fpsSeries, rttSeries, dropsSeries, bitrateSeries);
806+
}
807+
_telemetryAccumulator.Reset();
808+
}
809+
791810
SessionLogger.EndSession(endReason);
792811
ManagedAppController.StartApps(_appsToRelaunch);
793812
_appsToRelaunch.Clear();
@@ -878,6 +897,7 @@ private void OnBridgePrepareRequested()
878897
isAutoStreamingActive = true;
879898
isStreamingModeActive = true;
880899
_isAutoSessionActive = true;
900+
_telemetryAccumulator.Reset();
881901
SaveStreamingStateToConfig(true, originalSpeedForAutoStreaming ?? string.Empty);
882902
_appsToRelaunch = ManagedAppController.KillRunning();
883903
SessionLogger.StartSession("Bridge", originalSpeedForAutoStreaming ?? string.Empty);
@@ -906,6 +926,29 @@ private void OnBridgePrepareRequested()
906926
});
907927
}
908928

929+
/// <summary>
930+
/// Called on a thread-pool thread when StreamLight sends a SESSIONDATA batch.
931+
/// Guards on active session and session ID cross-check before accumulating.
932+
/// </summary>
933+
private void OnSessionDataReceived(ClientBatch batch)
934+
{
935+
try
936+
{
937+
// Accept batches whenever a session is being logged, regardless of NIC
938+
// throttle mode or _isAutoSessionActive state. This ensures telemetry
939+
// works even when auto streaming is disabled.
940+
if (SessionLogger.ActiveSessionId == null) return;
941+
942+
var hostSample = _metricsCollector.GetLatestSample();
943+
_telemetryAccumulator.AddBatch(batch, hostSample);
944+
DebugLog($"Bridge: SESSIONDATA received — {batch.Samples.Count} samples");
945+
}
946+
catch (Exception ex)
947+
{
948+
DebugLog($"Bridge: SESSIONDATA handler error — {ex.Message}");
949+
}
950+
}
951+
909952
/// <summary>
910953
/// Called when Moonlight fork sends RESTORE after session ends.
911954
/// Acts as an explicit fallback alongside the log monitor.

StreamTweak/SessionLogger.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,27 @@ public class SessionEntry
1717

1818
public string? EndReason { get; set; }
1919

20+
// ── Telemetria qualità sessione (null se nessun dato client ricevuto) ──
21+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
22+
public SessionQualityStats? QualityStats { get; set; }
23+
24+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
25+
public QualityGrade? Grade { get; set; }
26+
27+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
28+
public List<float>? FpsTimeSeries { get; set; }
29+
30+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
31+
public List<float>? RttTimeSeries { get; set; }
32+
33+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
34+
public List<float>? DropsTimeSeries { get; set; }
35+
36+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
37+
public List<float>? BitrateTimeSeries { get; set; }
38+
39+
// ── Display properties ────────────────────────────────────────────────
40+
2041
[JsonIgnore]
2142
public string DurationDisplay
2243
{
@@ -35,6 +56,19 @@ public string DurationDisplay
3556
[JsonIgnore]
3657
public string StartTimeDisplay => StartTime.ToString("dd/MM/yyyy HH:mm");
3758

59+
[JsonIgnore]
60+
public string TelemetryDurationDisplay
61+
{
62+
get
63+
{
64+
int secs = FpsTimeSeries?.Count ?? RttTimeSeries?.Count ?? 0;
65+
if (secs == 0) return DurationDisplay;
66+
return secs >= 60
67+
? $"{secs / 60}m {secs % 60}s"
68+
: $"{secs}s";
69+
}
70+
}
71+
3872
[JsonIgnore]
3973
public string NicThrottleDisplay => string.IsNullOrEmpty(OriginalSpeed) ? "No" : "Yes";
4074

@@ -51,6 +85,8 @@ public static class SessionLogger
5185

5286
private static string? _activeSessionId = null;
5387

88+
public static string? ActiveSessionId => _activeSessionId;
89+
5490
public static void StartSession(string triggerMode, string originalSpeed)
5591
{
5692
try
@@ -102,6 +138,32 @@ public static void Initialize()
102138
catch { }
103139
}
104140

141+
public static void UpdateSessionTelemetry(
142+
string sessionId,
143+
SessionQualityStats stats,
144+
QualityGrade grade,
145+
List<float> fpsSeries,
146+
List<float> rttSeries,
147+
List<float> dropsSeries,
148+
List<float> bitrateSeries)
149+
{
150+
try
151+
{
152+
var sessions = Load();
153+
var entry = sessions.FirstOrDefault(s => s.Id == sessionId);
154+
if (entry == null) return;
155+
156+
entry.QualityStats = stats;
157+
entry.Grade = grade;
158+
entry.FpsTimeSeries = fpsSeries.Count > 0 ? fpsSeries : null;
159+
entry.RttTimeSeries = rttSeries.Count > 0 ? rttSeries : null;
160+
entry.DropsTimeSeries = dropsSeries.Count > 0 ? dropsSeries : null;
161+
entry.BitrateTimeSeries = bitrateSeries.Count > 0 ? bitrateSeries : null;
162+
Save(sessions);
163+
}
164+
catch { }
165+
}
166+
105167
public static void EndSession(string endReason = "User")
106168
{
107169
// Atomically capture and clear the session ID so concurrent callers

0 commit comments

Comments
 (0)