fix(windows): Zweiter Rip startete waehrend der Kompression ins leere Laufwerk
Der Commander meldete einen Rip-Fehlschlag „bei der Komprimierung", obwohl
der Rip laengst durch war:
makemkvcon endete mit Code 11 — letzte Meldung:
Das Öffnen der Disk schlug fehl — keine MKV-Datei entstanden
Auffaellig war, was FEHLTE: kein „Ursache:". Waere der Geraetepfad schuld
gewesen, stuende dort MSG 2024. Bleibt: kein Datentraeger im Laufwerk.
Der Ablauf dahinter:
1. Rip fertig → Rippy wirft die Disc aus (Standardeinstellung)
2. Status wird auf `transcoding` gesetzt — ab hier sagte `has_active_job`
NEIN, das Laufwerk sei frei; es kennt nur pending/running
3. Die Disc-Wache sieht beim Auswurf einen Statuswechsel → „eingelegt"
4. Die Vollautomatik startet einen ZWEITEN Rip — auf ein Laufwerk, dessen
Schublade gerade herausfaehrt
Der zweite Rip lief in ein leeres Laufwerk. Auf dem Bildschirm sah das aus,
als sei die Kompression gescheitert — sie lief ungestoert weiter.
Drei Aenderungen:
* `store.job_offen` — der weitere Riegel (pending/running/transcoding/
canceling) fuer die Vollautomatik. `has_active_job` bleibt unveraendert:
Das fragt „haelt gerade jemand das Laufwerk?", und waehrend der Kompression
tut das niemand — ein Auswurf von Hand bleibt erlaubt.
* `ripping.disc_fehlt` — vor dem makemkvcon-Start nachsehen, ob ueberhaupt
eine Disc drin liegt. Statt zwei Minuten Warten und Code 11 gibt es einen
Satz, den man versteht. Ein FEHLGESCHLAGENER Blick verweigert nichts:
„ich weiss es nicht" darf nie zu „es geht nicht" werden.
* MSG 5010 in KRITISCHE_CODES — MakeMKVs Sammelmeldung sagt fuer sich nichts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f6f0a4ccb6
commit
f0f719ca12
@@ -780,6 +780,48 @@ def write_abcde_config(output_dir: str) -> str:
|
||||
return tmp.name
|
||||
|
||||
|
||||
def disc_fehlt(device_path: str, zustand=None) -> str:
|
||||
"""Liegt ueberhaupt eine Disc drin? Klartext-Grund oder "" (alles gut).
|
||||
|
||||
## Warum vorher nachgesehen wird (Befund 29.08.2026)
|
||||
|
||||
Der Commander bekam:
|
||||
|
||||
makemkvcon endete mit Code 11 — letzte Meldung:
|
||||
Das Öffnen der Disk schlug fehl — keine MKV-Datei entstanden
|
||||
|
||||
Auffaellig war, was FEHLTE: kein „Ursache:". Waere der Geraetepfad schuld
|
||||
gewesen, stuende dort MSG 2024. Bleibt: kein Datentraeger im Laufwerk.
|
||||
Nach einem fertigen Rip wirft Rippy die Disc aus — ein zweiter Versuch
|
||||
trifft dann ein leeres Laufwerk, laeuft zwei Minuten in makemkvcon hinein
|
||||
und meldet einen Satz, aus dem niemand das schliessen kann.
|
||||
|
||||
Nachsehen kostet Millisekunden und erspart genau diesen Satz.
|
||||
|
||||
⚠️ Ein FEHLGESCHLAGENER Blick ist kein Grund, den Rip zu verweigern. Wer
|
||||
das Laufwerk gerade nicht lesen kann, weiss nicht, dass es leer ist — und
|
||||
„ich weiss es nicht" darf nie zu „es geht nicht" werden.
|
||||
"""
|
||||
if zustand is None:
|
||||
try:
|
||||
from rippy import drives as _schicht
|
||||
|
||||
zustand = _schicht.treiber().drive_status
|
||||
except Exception: # noqa: BLE001
|
||||
return ""
|
||||
try:
|
||||
stand = zustand(device_path)
|
||||
except Exception: # noqa: BLE001
|
||||
return ""
|
||||
if stand == CDS_NO_DISC:
|
||||
return ("Kein Datentraeger im Laufwerk %s. Nach einem fertigen Rip "
|
||||
"wirft Rippy die Disc aus — fuer einen neuen Rip muss sie "
|
||||
"wieder hinein." % device_path)
|
||||
if stand == CDS_TRAY_OPEN:
|
||||
return "Die Schublade von %s ist offen." % device_path
|
||||
return ""
|
||||
|
||||
|
||||
def run_makemkv(device_path: str, output_dir: str, progress_cb=None, titel: str = "all",
|
||||
log_cb=None) -> dict:
|
||||
"""Rippt eine DVD/Blu-ray verlustfrei mit makemkvcon; meldet Fortschritt.
|
||||
@@ -794,6 +836,10 @@ def run_makemkv(device_path: str, output_dir: str, progress_cb=None, titel: str
|
||||
if not check_makemkv_installed():
|
||||
return {"status": "error", "error": "makemkvcon ist nicht installiert"}
|
||||
|
||||
fehlt = disc_fehlt(device_path)
|
||||
if fehlt:
|
||||
return {"status": "error", "error": fehlt}
|
||||
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
try:
|
||||
|
||||
@@ -519,3 +519,70 @@ def test_handbrake_kommando_mit_sprachauswahl():
|
||||
assert cmd[cmd.index("--audio-lang-list") + 1] == "deu,jpn"
|
||||
assert cmd[cmd.index("--subtitle-lang-list") + 1] == "deu"
|
||||
assert "--first-audio" in cmd and "--all-subtitles" in cmd
|
||||
|
||||
|
||||
# ── Erst nachsehen, dann rippen (Befund 29.08.2026) ─────────────────────
|
||||
#
|
||||
# Commander: „makemkvcon endete mit Code 11 — letzte Meldung: Das Öffnen der
|
||||
# Disk schlug fehl — keine MKV-Datei entstanden"
|
||||
#
|
||||
# Auffaellig war, was FEHLTE: kein „Ursache:". Waere der Geraetepfad schuld
|
||||
# gewesen, stuende dort MSG 2024. Bleibt: kein Datentraeger. Nach einem
|
||||
# fertigen Rip wirft Rippy die Disc aus — ein zweiter Versuch trifft dann ein
|
||||
# leeres Laufwerk, laeuft zwei Minuten in makemkvcon hinein und meldet einen
|
||||
# Satz, aus dem niemand das schliessen kann.
|
||||
|
||||
|
||||
def test_ein_leeres_laufwerk_wird_vorher_erkannt():
|
||||
import ripping
|
||||
from rippy.drives.linux import CDS_NO_DISC
|
||||
|
||||
grund = ripping.disc_fehlt("G:", zustand=lambda p: CDS_NO_DISC)
|
||||
assert "Kein Datentraeger" in grund
|
||||
assert "wirft Rippy die Disc aus" in grund, "der Grund muss erklaert sein"
|
||||
|
||||
|
||||
def test_offene_schublade_auch():
|
||||
import ripping
|
||||
from rippy.drives.linux import CDS_TRAY_OPEN
|
||||
|
||||
assert "Schublade" in ripping.disc_fehlt("G:", zustand=lambda p: CDS_TRAY_OPEN)
|
||||
|
||||
|
||||
def test_mit_disc_wird_nicht_gemeckert():
|
||||
import ripping
|
||||
from rippy.drives.linux import CDS_DISC_OK
|
||||
|
||||
assert ripping.disc_fehlt("G:", zustand=lambda p: CDS_DISC_OK) == ""
|
||||
|
||||
|
||||
def test_ein_fehlgeschlagener_blick_verweigert_den_rip_NICHT():
|
||||
"""„Ich weiss es nicht" darf nie zu „es geht nicht" werden. Wer das
|
||||
Laufwerk gerade nicht lesen kann, weiss nicht, dass es leer ist."""
|
||||
import ripping
|
||||
|
||||
def wirft(p):
|
||||
raise OSError(5, "Zugriff verweigert")
|
||||
|
||||
assert ripping.disc_fehlt("G:", zustand=wirft) == ""
|
||||
|
||||
|
||||
def test_run_makemkv_sieht_vorher_nach():
|
||||
"""Waechter: Die Pruefung muss VOR dem Prozessstart stehen, sonst laeuft
|
||||
man weiterhin zwei Minuten ins Leere."""
|
||||
import inspect
|
||||
|
||||
import ripping
|
||||
|
||||
quelle = inspect.getsource(ripping.run_makemkv)
|
||||
vor_popen = quelle.index("subprocess.Popen")
|
||||
assert "disc_fehlt(" in quelle[:vor_popen], \
|
||||
"die Disc-Pruefung gehoert vor den makemkvcon-Start"
|
||||
|
||||
|
||||
def test_die_sammelmeldung_5010_wird_erklaert():
|
||||
"""5010 ist MakeMKVs „ging nicht" und sagt fuer sich nichts."""
|
||||
from rippy.rip.makemkv_aufruf import KRITISCHE_CODES
|
||||
|
||||
assert 5010 in KRITISCHE_CODES
|
||||
assert "Disc" in KRITISCHE_CODES[5010]
|
||||
|
||||
Reference in New Issue
Block a user