feat: GnuDB fallback with retries when abcde CDDB lookup returns nothing

- New module cddb.py: direct GnuDB/FreeDB HTTP lookup using CDDB protocol,
  with same retry+random-delay logic as MusicBrainz barcode lookup
- get_discid() reads disc fingerprint via cd-discid before ripping
- If abcde returns no CDDB track data, lookup_by_discid() queries GnuDB
  directly (up to 3 retries, 2-6 s random pause between attempts)
- TrackInfo moved from ripper.py to models.py to break circular import
  (cddb.py and ripper.py both use TrackInfo)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-02-18 07:24:16 +01:00
commit e75e5d7de0
4 changed files with 229 additions and 11 deletions

View file

@ -6,14 +6,15 @@ import logging
import re
import subprocess
from pathlib import Path
from typing import NamedTuple
from pydantic import BaseModel
from musiksammlung.cddb import get_discid, lookup_by_discid
from musiksammlung.config import AudioFormat
from musiksammlung.models import Album as AlbumModel
from musiksammlung.models import Disc as DiscModel
from musiksammlung.models import Track as TrackModel
from musiksammlung.models import TrackInfo
from musiksammlung.musicbrainz import lookup_by_barcode
logger = logging.getLogger(__name__)
@ -22,14 +23,6 @@ logger = logging.getLogger(__name__)
_ANSI_ESC = re.compile(r"(\x1b|\^)\[[\d;]*[A-Za-z@]?")
class TrackInfo(NamedTuple):
"""Track information from abcde."""
track_number: int
artist: str
title: str
class RipperConfig(BaseModel):
"""Configuration for ripping process."""
@ -331,6 +324,9 @@ def _rip_with_abcde(
if use_pipes:
cmd.append("-P")
# Disc-Fingerprint vor dem Ripping holen (für GnuDB-Fallback)
discid_line = get_discid(device)
print(f"\n Command: {' '.join(cmd)}", flush=True)
logger.info("Starting abcde: %s", " ".join(cmd))
@ -355,6 +351,14 @@ def _rip_with_abcde(
else:
print("\n CDDB: no track data found", flush=True)
logger.warning("CDDB lookup returned no track data")
# Fallback: GnuDB direkt anfragen (mit Retries + Zufallspause)
if discid_line:
print(" GnuDB-Fallback: direkter Lookup mit Retries...", flush=True)
tracks = lookup_by_discid(discid_line) or None
if tracks:
print(f" GnuDB: {len(tracks)} Tracks gefunden", flush=True)
else:
print(" GnuDB: kein Treffer.", flush=True)
# Extract track files from abcde's temp dir into output_dir (flat)
audio_files = _extract_tracks(output_dir, audio_format)