diff --git a/src/managers/playback_manager.py b/src/managers/playback_manager.py index b4e83ed..ebede61 100644 --- a/src/managers/playback_manager.py +++ b/src/managers/playback_manager.py @@ -6,6 +6,7 @@ from __future__ import annotations from typing import Callable, List, Optional import random +import time from PySide6.QtCore import QObject, QUrl, Signal from PySide6.QtMultimedia import QAudioOutput, QMediaPlayer @@ -43,6 +44,11 @@ class PlaybackManager(QObject): self._shuffleOrder: List[int] = [] self._shufflePosition: int = -1 + # Error debouncing to prevent spawning multiple dialogs for the same error + self._lastErrorMessage: str = "" + self._lastErrorTime: float = 0.0 + self._errorDebounceSeconds: float = 2.0 + self.player.playbackStateChanged.connect(self._handlePlaybackStateChanged) self.player.positionChanged.connect(self._handlePositionChanged) self.player.mediaStatusChanged.connect(self._handleMediaStatus) @@ -315,7 +321,22 @@ class PlaybackManager(QObject): self.next(fromAuto=True) def _handleError(self, error) -> None: - """Surface player errors to the UI.""" - if error: - description = self.player.errorString() or str(error) - self.errorOccurred.emit(description) + """Surface player errors to the UI with debouncing to prevent dialog spam.""" + if not error: + return + + description = self.player.errorString() or str(error) + currentTime = time.monotonic() + + # Debounce: skip if same error within debounce window + if (description == self._lastErrorMessage and + currentTime - self._lastErrorTime < self._errorDebounceSeconds): + return + + self._lastErrorMessage = description + self._lastErrorTime = currentTime + + # Stop playback to prevent further cascading errors + self.player.stop() + + self.errorOccurred.emit(description)