2026-02-15 00:47:54 +01:00
|
|
|
"""M3U-Playlist-Generierung für Jellyfin."""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
from musiksammlung.models import Album
|
|
|
|
|
from musiksammlung.organizer import _sanitize_filename
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate_playlist(album: Album, album_dir: Path) -> Path:
|
|
|
|
|
"""Erzeugt eine M3U-Playlist für das gesamte Album.
|
|
|
|
|
|
|
|
|
|
Die Playlist liegt im Album-Root und referenziert alle Tracks
|
|
|
|
|
über relative Pfade (CD1/01 Titel.flac, CD2/01 Titel.flac, ...).
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Pfad zur erzeugten Playlist-Datei.
|
|
|
|
|
"""
|
|
|
|
|
playlist_name = _sanitize_filename(album.album) + ".m3u"
|
|
|
|
|
playlist_path = album_dir / playlist_name
|
|
|
|
|
multi_disc = len(album.discs) > 1
|
|
|
|
|
|
|
|
|
|
lines = ["#EXTM3U"]
|
|
|
|
|
|
|
|
|
|
for disc in album.discs:
|
|
|
|
|
if multi_disc:
|
|
|
|
|
disc_prefix = f"CD{disc.disc_number}/"
|
|
|
|
|
else:
|
|
|
|
|
disc_prefix = ""
|
|
|
|
|
|
|
|
|
|
for track in disc.tracks:
|
|
|
|
|
safe_title = _sanitize_filename(track.title)
|
|
|
|
|
# Audiodatei im Zielverzeichnis finden
|
2026-02-17 23:34:16 +01:00
|
|
|
pattern = f"{track.track_number:02d}_{safe_title}.*"
|
2026-02-15 00:47:54 +01:00
|
|
|
if multi_disc:
|
|
|
|
|
search_dir = album_dir / f"CD{disc.disc_number}"
|
|
|
|
|
else:
|
|
|
|
|
search_dir = album_dir
|
|
|
|
|
|
|
|
|
|
matches = list(search_dir.glob(pattern))
|
|
|
|
|
if matches:
|
|
|
|
|
filename = matches[0].name
|
|
|
|
|
else:
|
|
|
|
|
# Fallback: generischer Name mit .flac
|
2026-02-17 23:34:16 +01:00
|
|
|
filename = f"{track.track_number:02d}_{safe_title}.flac"
|
2026-02-15 00:47:54 +01:00
|
|
|
logger.warning("Datei nicht gefunden, Fallback: %s", filename)
|
|
|
|
|
|
|
|
|
|
lines.append(f"#EXTINF:0,{track.title}")
|
|
|
|
|
lines.append(f"{disc_prefix}{filename}")
|
|
|
|
|
|
|
|
|
|
playlist_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
|
|
|
logger.info("Playlist erstellt: %s", playlist_path)
|
|
|
|
|
return playlist_path
|