diff --git a/Jellyfin.Plugin.JellyLMS/Services/LmsSessionController.cs b/Jellyfin.Plugin.JellyLMS/Services/LmsSessionController.cs index ddd4d53..f754b52 100644 --- a/Jellyfin.Plugin.JellyLMS/Services/LmsSessionController.cs +++ b/Jellyfin.Plugin.JellyLMS/Services/LmsSessionController.cs @@ -59,6 +59,9 @@ public class LmsSessionController : ISessionController, IDisposable _libraryManager = libraryManager; _stateMachine = new PlaybackStateMachine(logger); _statusPoller = new LmsStatusPoller(lmsClient, logger); + + // Start status polling immediately to keep volume in sync + StartProgressTimer(); } private static PluginConfiguration Config => Plugin.Instance?.Configuration ?? new PluginConfiguration(); @@ -295,7 +298,7 @@ public class LmsSessionController : ISessionController, IDisposable // Stop any existing timer _progressTimer?.Dispose(); - // Report progress every 2 seconds + // Poll status every 2 seconds (for progress reporting when playing and volume sync always) _progressTimer = new Timer( async _ => await ReportPlaybackProgressAsync().ConfigureAwait(false), null, @@ -305,32 +308,37 @@ public class LmsSessionController : ISessionController, IDisposable private void StopProgressTimer() { - _progressTimer?.Dispose(); - _progressTimer = null; + // Don't actually stop the timer - keep polling for volume updates + // This ensures Jellyfin stays in sync with the device volume + // even when not playing media } private async Task ReportPlaybackProgressAsync() { - // Don't report during Loading, Seeking, or Error states - var currentState = _stateMachine.CurrentState; - if (currentState == PlaybackState.Loading - || currentState == PlaybackState.Seeking - || currentState == PlaybackState.Error - || currentState == PlaybackState.Stopped - || currentState == PlaybackState.Idle - || !CurrentItemId.HasValue) - { - return; - } - try { + // Always poll status to keep volume in sync, even when not playing var status = await _lmsClient.GetPlayerStatusAsync(_player.MacAddress).ConfigureAwait(false); if (status == null) { return; } + // Update cached volume so Jellyfin stays in sync with device + _player.Volume = status.Volume; + + // Don't report playback progress during Loading, Seeking, Error, Stopped, or Idle states + var currentState = _stateMachine.CurrentState; + if (currentState == PlaybackState.Loading + || currentState == PlaybackState.Seeking + || currentState == PlaybackState.Error + || currentState == PlaybackState.Stopped + || currentState == PlaybackState.Idle + || !CurrentItemId.HasValue) + { + return; + } + // LMS reports time relative to the current stream, but after seeking // we're playing a transcoded stream that starts at the seek position. // Add the seek offset to get the actual track position. @@ -812,7 +820,9 @@ public class LmsSessionController : ISessionController, IDisposable _cancellationTokenSource.Cancel(); _cancellationTokenSource.Dispose(); - StopProgressTimer(); + // Actually stop the timer when disposing + _progressTimer?.Dispose(); + _progressTimer = null; // Reset state machine _stateMachine.Reset();