Refactor player service to diminish play complexity
All checks were successful
Backend CI / test (push) Successful in 4m53s
All checks were successful
Backend CI / test (push) Successful in 4m53s
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user