Update playlist_manager.py
This commit is contained in:
@@ -1,11 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
|
||||||
Playlist and Library Management Module.
|
|
||||||
|
|
||||||
This module handles the music library (scanning, metadata extraction),
|
|
||||||
the playback queue, and playlist operations. It differentiates between
|
|
||||||
a static playlist and a priority queue.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
@@ -27,21 +20,14 @@ except ImportError:
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PlaybackMode(Enum):
|
class PlaybackMode(Enum):
|
||||||
SEQUENTIAL = "sequential"
|
SEQUENTIAL = "sequential"
|
||||||
RANDOM = "random"
|
RANDOM = "random"
|
||||||
REPEAT_ONE = "repeat_one"
|
REPEAT_ONE = "repeat_one"
|
||||||
REPEAT_ALL = "repeat_all"
|
REPEAT_ALL = "repeat_all"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(slots=True)
|
@dataclass(slots=True)
|
||||||
class Track:
|
class Track:
|
||||||
"""
|
|
||||||
Represents a single music track.
|
|
||||||
|
|
||||||
Uses slots to reduce memory footprint for large libraries.
|
|
||||||
"""
|
|
||||||
path: str
|
path: str
|
||||||
filename: str
|
filename: str
|
||||||
title: str = ""
|
title: str = ""
|
||||||
@@ -73,10 +59,8 @@ class Track:
|
|||||||
'format': self.format
|
'format': self.format
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Playlist:
|
class Playlist:
|
||||||
"""Represents a collection of tracks with a playback state."""
|
|
||||||
name: str
|
name: str
|
||||||
tracks: List[Track] = field(default_factory=list)
|
tracks: List[Track] = field(default_factory=list)
|
||||||
current_index: int = 0
|
current_index: int = 0
|
||||||
@@ -111,7 +95,6 @@ class Playlist:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def next_track(self) -> Optional[Track]:
|
def next_track(self) -> Optional[Track]:
|
||||||
"""Calculates the next track based on playback mode."""
|
|
||||||
if not self.tracks:
|
if not self.tracks:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -151,13 +134,7 @@ class Playlist:
|
|||||||
return self.current_track
|
return self.current_track
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class MusicQueue:
|
class MusicQueue:
|
||||||
"""
|
|
||||||
Priority queue system.
|
|
||||||
|
|
||||||
Tracks in this queue take precedence over the standard playlist.
|
|
||||||
"""
|
|
||||||
MAX_QUEUE_SIZE = 100
|
MAX_QUEUE_SIZE = 100
|
||||||
MAX_HISTORY_SIZE = 50
|
MAX_HISTORY_SIZE = 50
|
||||||
|
|
||||||
@@ -241,11 +218,7 @@ class MusicQueue:
|
|||||||
return track
|
return track
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class PlaylistManager:
|
class PlaylistManager:
|
||||||
"""
|
|
||||||
Coordinating class for library, playlists, and playback queue.
|
|
||||||
"""
|
|
||||||
SUPPORTED_FORMATS = {'.mp3', '.ogg', '.flac', '.wav', '.m4a', '.opus', '.aac', '.wma'}
|
SUPPORTED_FORMATS = {'.mp3', '.ogg', '.flac', '.wav', '.m4a', '.opus', '.aac', '.wma'}
|
||||||
MAX_LIBRARY_SIZE = 10000
|
MAX_LIBRARY_SIZE = 10000
|
||||||
|
|
||||||
@@ -268,7 +241,6 @@ class PlaylistManager:
|
|||||||
self.current_playlist = self.playlists['default']
|
self.current_playlist = self.playlists['default']
|
||||||
|
|
||||||
async def scan_library(self) -> int:
|
async def scan_library(self) -> int:
|
||||||
"""Asynchronously scans the music directory for supported files."""
|
|
||||||
self.library.clear()
|
self.library.clear()
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
|
||||||
@@ -291,7 +263,7 @@ class PlaylistManager:
|
|||||||
if count % 500 == 0:
|
if count % 500 == 0:
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
|
||||||
logger.info(f"Library scanned: {count} tracks")
|
logger.info(f"🎵 Library scanned: {count} tracks")
|
||||||
return count
|
return count
|
||||||
|
|
||||||
async def _create_track(self, filepath: str) -> Optional[Track]:
|
async def _create_track(self, filepath: str) -> Optional[Track]:
|
||||||
@@ -390,14 +362,9 @@ class PlaylistManager:
|
|||||||
self.current_playlist.mode = mode
|
self.current_playlist.mode = mode
|
||||||
|
|
||||||
def get_current_track(self) -> Optional[Track]:
|
def get_current_track(self) -> Optional[Track]:
|
||||||
"""Returns the currently playing track from Queue or Playlist."""
|
|
||||||
return self.queue.current or (self.current_playlist.current_track if self.current_playlist else None)
|
return self.queue.current or (self.current_playlist.current_track if self.current_playlist else None)
|
||||||
|
|
||||||
def next_track(self) -> Optional[Track]:
|
def next_track(self) -> Optional[Track]:
|
||||||
"""
|
|
||||||
Determines the next track to play.
|
|
||||||
Logic: Queue priority > Playlist > None
|
|
||||||
"""
|
|
||||||
queued = self.queue.pop()
|
queued = self.queue.pop()
|
||||||
if queued:
|
if queued:
|
||||||
self.queue.current = queued
|
self.queue.current = queued
|
||||||
|
|||||||
Reference in New Issue
Block a user