diff --git a/lib/screens/video_player_screen.dart b/lib/screens/video_player_screen.dart index c6a8746d..3d27731f 100644 --- a/lib/screens/video_player_screen.dart +++ b/lib/screens/video_player_screen.dart @@ -598,6 +598,11 @@ class VideoPlayerScreenState extends State with WidgetsBindin DiscordRPCService.instance.updatePosition(position); }); + // Listen to playback rate changes for Discord Rich Presence + player!.streams.rate.listen((rate) { + DiscordRPCService.instance.updatePlaybackSpeed(rate); + }); + // Start Discord Rich Presence for current media if (client != null) { DiscordRPCService.instance.startPlayback(widget.metadata, client); diff --git a/lib/services/discord_rpc_service.dart b/lib/services/discord_rpc_service.dart index ff6eb4a3..f442caab 100644 --- a/lib/services/discord_rpc_service.dart +++ b/lib/services/discord_rpc_service.dart @@ -47,6 +47,7 @@ class DiscordRPCService { DateTime? _playbackStartTime; Duration? _mediaDuration; Duration? _currentPosition; + double _playbackSpeed = 1.0; Timer? _reconnectTimer; DateTime? _lastPresenceUpdate; StreamSubscription? _readySubscription; @@ -106,6 +107,7 @@ class DiscordRPCService { _mediaDuration = metadata.duration != null ? Duration(milliseconds: metadata.duration!) : null; _currentPosition = Duration.zero; _cachedThumbnailUrl = null; + _playbackSpeed = 1.0; if (_isEnabled && _isConnected) { // Upload thumbnail in background, don't block playback @@ -133,6 +135,15 @@ class DiscordRPCService { } } + /// Update current playback speed (for accurate remaining time calculation) + void updatePlaybackSpeed(double speed) { + if (_playbackSpeed == speed) return; + _playbackSpeed = speed; + if (_isEnabled && _isConnected && _playbackStartTime != null) { + _updatePresence(); + } + } + /// Resume playback (restore timestamp) Future resumePlayback() async { if (_currentMetadata == null) return; @@ -161,6 +172,7 @@ class DiscordRPCService { _currentClient = null; _playbackStartTime = null; _cachedThumbnailUrl = null; + _playbackSpeed = 1.0; if (_isEnabled && _isConnected) { await clearPresence(); @@ -357,11 +369,15 @@ class DiscordRPCService { final now = DateTime.now(); final position = _currentPosition ?? Duration.zero; - // Calculate when playback "started" (now minus current position) - final effectiveStart = now.subtract(position); + // Calculate remaining time accounting for playback speed + final remainingDuration = _mediaDuration! - position; + final adjustedRemaining = Duration(microseconds: (remainingDuration.inMicroseconds / _playbackSpeed).round()); - // Calculate when playback will "end" (start + total duration) - final effectiveEnd = effectiveStart.add(_mediaDuration!); + // Calculate total adjusted duration for progress bar + final adjustedTotal = Duration(microseconds: (_mediaDuration!.inMicroseconds / _playbackSpeed).round()); + + final effectiveEnd = now.add(adjustedRemaining); + final effectiveStart = effectiveEnd.subtract(adjustedTotal); return DiscordTimestamps.range(effectiveStart, effectiveEnd); }