Refactor player service to diminish play complexity
All checks were successful
Backend CI / test (push) Successful in 4m53s

This commit is contained in:
JSC
2025-08-01 01:34:22 +02:00
parent a10111793c
commit 69cdc7567d

View File

@@ -166,20 +166,39 @@ class PlayerService:
async def play(self, index: int | None = None) -> None:
"""Play audio at specified index or current position."""
# Check if we're resuming from pause
is_resuming = (
if self._should_resume_playback(index):
await self._resume_playback()
return
await self._start_new_track(index)
def _should_resume_playback(self, index: int | None) -> bool:
"""Check if we should resume paused playback."""
return (
index is None
and self.state.status == PlayerStatus.PAUSED
and self.state.current_sound is not None
)
if is_resuming:
# Simply resume playback
async def _resume_playback(self) -> None:
"""Resume paused playback."""
result = self._player.play()
if result == 0: # VLC returns 0 on success
self.state.status = PlayerStatus.PLAYING
self._ensure_play_time_tracking_for_resume()
await self._broadcast_state()
# Ensure play time tracking is initialized for resumed track
sound_name = (
self.state.current_sound.name
if self.state.current_sound
else "Unknown"
)
logger.info("Resumed playing sound: %s", sound_name)
else:
logger.error("Failed to resume playback: VLC error code %s", result)
def _ensure_play_time_tracking_for_resume(self) -> None:
"""Ensure play time tracking is initialized for resumed track."""
if (
self.state.current_sound_id
and self.state.current_sound_id not in self._play_time_tracking
@@ -191,52 +210,85 @@ class PlayerService:
"threshold_reached": False,
}
await self._broadcast_state()
logger.info(
"Resumed playing sound: %s",
(
self.state.current_sound.name
if self.state.current_sound
else "Unknown"
),
)
else:
logger.error("Failed to resume playback: VLC error code %s", result)
async def _start_new_track(self, index: int | None) -> None:
"""Start playing a new track."""
if not self._prepare_sound_for_playback(index):
return
# Starting new track or changing track
if index is not None:
if index < 0 or index >= len(self.state.playlist_sounds):
msg = "Invalid sound index"
raise ValueError(msg)
self.state.current_sound_index = index
self.state.current_sound = self.state.playlist_sounds[index]
self.state.current_sound_id = self.state.current_sound.id
if not self._load_and_play_media():
return
await self._handle_successful_playback()
def _prepare_sound_for_playback(self, index: int | None) -> bool:
"""Prepare sound for playback, return True if ready."""
if index is not None and not self._set_sound_by_index(index):
return False
if not self.state.current_sound:
logger.warning("No sound to play")
return
return False
return self._validate_sound_file()
def _set_sound_by_index(self, index: int) -> bool:
"""Set current sound by index, return True if valid."""
if index < 0 or index >= len(self.state.playlist_sounds):
msg = "Invalid sound index"
raise ValueError(msg)
self.state.current_sound_index = index
self.state.current_sound = self.state.playlist_sounds[index]
self.state.current_sound_id = self.state.current_sound.id
return True
def _validate_sound_file(self) -> bool:
"""Validate sound file exists, return True if valid."""
if not self.state.current_sound:
return False
# Get sound file path
sound_path = get_sound_file_path(self.state.current_sound)
if not sound_path.exists():
logger.error("Sound file not found: %s", sound_path)
return
return False
return True
# Load and play media (new track)
def _load_and_play_media(self) -> bool:
"""Load media and start playback, return True if successful."""
if self._vlc_instance is None:
logger.error("VLC instance is not initialized. Cannot play media.")
return
return False
if not self.state.current_sound:
logger.error("No current sound to play")
return False
sound_path = get_sound_file_path(self.state.current_sound)
media = self._vlc_instance.media_new(str(sound_path))
self._player.set_media(media)
result = self._player.play()
if result == 0: # VLC returns 0 on success
if result != 0: # VLC returns 0 on success
logger.error("Failed to start playback: VLC error code %s", result)
return False
return True
async def _handle_successful_playback(self) -> None:
"""Handle successful playback start."""
if not self.state.current_sound:
logger.error("No current sound for successful playback")
return
self.state.status = PlayerStatus.PLAYING
self.state.current_sound_duration = self.state.current_sound.duration or 0
# Initialize play time tracking for new track
self._initialize_play_time_tracking()
await self._broadcast_state()
logger.info("Started playing sound: %s", self.state.current_sound.name)
def _initialize_play_time_tracking(self) -> None:
"""Initialize play time tracking for new track."""
if self.state.current_sound_id:
self._play_time_tracking[self.state.current_sound_id] = {
"total_time": 0,
@@ -250,11 +302,6 @@ class PlayerService:
self.state.current_sound_duration,
)
await self._broadcast_state()
logger.info("Started playing sound: %s", self.state.current_sound.name)
else:
logger.error("Failed to start playback: VLC error code %s", result)
async def pause(self) -> None:
"""Pause playback."""
if self.state.status == PlayerStatus.PLAYING: