From 627b95c961e564caa1fd20b3c33d5cd71ccdf9ec Mon Sep 17 00:00:00 2001 From: JSC Date: Sat, 12 Jul 2025 20:49:20 +0200 Subject: [PATCH] feat: Add 'single' play mode to music player and update related logic --- app/routes/player.py | 2 +- app/services/music_player_service.py | 36 +++++++++++++++++++++------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/app/routes/player.py b/app/routes/player.py index 0df64c0..7bd1b7f 100644 --- a/app/routes/player.py +++ b/app/routes/player.py @@ -141,7 +141,7 @@ def set_play_mode(): return jsonify({"error": "Mode required"}), 400 mode = data["mode"] - valid_modes = ["continuous", "loop-playlist", "loop-one", "random"] + valid_modes = ["continuous", "loop-playlist", "loop-one", "random", "single"] if mode not in valid_modes: return jsonify({"error": f"Mode must be one of: {', '.join(valid_modes)}"}), 400 diff --git a/app/services/music_player_service.py b/app/services/music_player_service.py index af7ebe4..e1930c3 100644 --- a/app/services/music_player_service.py +++ b/app/services/music_player_service.py @@ -42,7 +42,7 @@ class MusicPlayerService: ) # Store file paths for manual playlist management self.volume = 80 self.play_mode = ( - "continuous" # continuous, loop-playlist, loop-one, random + "continuous" # single, continuous, loop-playlist, loop-one, random ) self.is_playing = False self.current_time = 0 @@ -60,8 +60,12 @@ class MusicPlayerService: self._track_play_tracked = ( False # Flag to track if current track play has been logged ) - self._cumulative_play_time = 0 # Cumulative time actually played for current track - self._last_position_update = 0 # Last position for calculating continuous play time + self._cumulative_play_time = ( + 0 # Cumulative time actually played for current track + ) + self._last_position_update = ( + 0 # Last position for calculating continuous play time + ) def start_vlc_instance(self) -> bool: """Start a VLC instance with Python bindings.""" @@ -449,7 +453,13 @@ class MusicPlayerService: def set_play_mode(self, mode: str) -> bool: """Set play mode.""" try: - if mode in ["continuous", "loop-playlist", "loop-one", "random"]: + if mode in [ + "continuous", + "loop-playlist", + "loop-one", + "random", + "single", + ]: self.play_mode = mode self._emit_player_state() return True @@ -644,6 +654,11 @@ class MusicPlayerService: if self.play_mode == "loop-one": logger.info("Restarting track for loop-one mode") self.play_track_at_index(self.current_track_index) + elif self.play_mode == "single": + logger.info( + "Track ended in single mode - stopping playback" + ) + self.stop() elif self.play_mode in [ "continuous", "loop-playlist", @@ -667,20 +682,25 @@ class MusicPlayerService: if self._last_position_update > 0: time_diff = self.current_time - self._last_position_update # Only add time if it's a reasonable progression (not a big jump from seeking) - if 0 <= time_diff <= (self.sync_interval * 1000 * 2): # Max 2x sync interval + if ( + 0 <= time_diff <= (self.sync_interval * 1000 * 2) + ): # Max 2x sync interval self._cumulative_play_time += time_diff - + self._last_position_update = self.current_time elif self.is_playing and not old_playing: # Just started playing, initialize position tracking - self._last_position_update = self.current_time if self.current_time > 0 else 0 + self._last_position_update = ( + self.current_time if self.current_time > 0 else 0 + ) # Track play event when cumulative listening reaches 20% of track duration if ( self.is_playing and not self._track_play_tracked and self.duration > 0 - and self._cumulative_play_time >= (self.duration * PLAY_COMPLETION_THRESHOLD) + and self._cumulative_play_time + >= (self.duration * PLAY_COMPLETION_THRESHOLD) ): current_track = self.get_current_track() if current_track: