feat(v5): Etappe W-7 — Audio-CD, ISO-Backup, MakeMKV-Schluesselkette
Ampel / ampel (push) Successful in 1m20s
Ampel / ampel (push) Successful in 1m20s
rip/audiocd.ts: die Rechnungen PUR (MSF→LBA mit den 150 Vorlauf-Frames, TOC-Zerlegung mit Lead-Out-Pflicht und Daten-Track-Bit, 27-Sektoren- Bloecke unter der 64-KB-Treibergrenze, RAW_READ_INFO mit DiskOffset in 2048ern OBWOHL der Sektor 2352 hat, WAV-Kopf, AC/DC-sichere Namen). metadaten/musicbrainz.ts: DiscID nach musicbrainz.org-Rechnung — gegen die ECHTE AC/DC-Kennung getestet (3KVSIWn_…), Vorlauf wird beim Melden wieder HINZUgerechnet; Tags je Spur mit Bindewort-Kuenstlern. laufwerk/disc.ts: audioToc + audioSpurLesen ueber die LaufwerkApi. rip/iso.ts (§ 6.4): 1:1-Abbild fuer unbekannte Discs — async (ein 33-GB-Abbild darf den Kern nicht blockieren), sektor-ausgerichtet, unvollstaendig heisst FEHLER mit Byte-Zahlen, nie Schoenfaerberei. werkzeuge/schluessel.ts (§ 9.1): Dauerlizenz schlaegt Forum-Beta-Key (t=1053, T-Muster aus makemkv_key.py), Ablage in HKCU ueber reg.exe (kein zweiter koffi-Ort), GEFRAGT statt gerechnet (makemkvcon info disc:9999, MSG 5020/5021/5051), abgelehnter Key wird ZURUECKGENOMMEN (schlimmer als keiner: 0 Titel, kein Laufwerk), app_UpdateEnable nur- wenn-fehlt (der 4K-Schluesselkanal). Kern prueft beim Start und taeglich; Dashboard-Kachel zeigt Stand + letzten Pruefzeitpunkt; Dauerlizenz-Feld in den Einstellungen. Pipeline verzweigt nach Disc-Typ: cd → Sektoren→WAV→FLAC mit MusicBrainz-Tags (Ordner 'Kuenstler - Album', ohne Treffer ehrlich 'Track NN'), unknown → ISO. Bibliothek-Eintraege fuer beide. 181 Tests gruen, Smoke gruen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
c78ff22ab7
commit
2d9cef22b3
@@ -322,6 +322,13 @@ function Einstellungen({ verbindung }: { verbindung: Verbindung }) {
|
||||
<Feld name="TMDb-API-Key" geheim wert={werte['tmdbApiKey'] ?? ''} aufAendern={(w) => setzen('tmdbApiKey', w)} />
|
||||
<Feld name="OMDb-API-Key" geheim wert={werte['omdbApiKey'] ?? ''} aufAendern={(w) => setzen('omdbApiKey', w)} />
|
||||
</div>
|
||||
<Feld
|
||||
name="MakeMKV-Schlüssel (Dauerlizenz)"
|
||||
hinweis="schlägt den automatischen Beta-Key — leer lassen, wenn keiner gekauft ist"
|
||||
geheim
|
||||
wert={werte['makemkvAppKey'] ?? ''}
|
||||
aufAendern={(w) => setzen('makemkvAppKey', w)}
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section className="space-y-3">
|
||||
@@ -426,6 +433,7 @@ export default function App() {
|
||||
einstellungen: {},
|
||||
werkzeuge: null,
|
||||
bibliothek: [],
|
||||
schluessel: null,
|
||||
meldungen: [],
|
||||
})
|
||||
|
||||
@@ -535,6 +543,24 @@ export default function App() {
|
||||
: ['Ping unterwegs …']
|
||||
}
|
||||
/>
|
||||
<Kachel
|
||||
titel="MakeMKV-Schlüssel (§ 9.1)"
|
||||
zustand={
|
||||
verbindung.schluessel === null
|
||||
? 'wartet'
|
||||
: verbindung.schluessel.angenommen === true
|
||||
? 'ok'
|
||||
: 'fehler'
|
||||
}
|
||||
zeilen={
|
||||
verbindung.schluessel === null
|
||||
? ['wird geprüft …']
|
||||
: [
|
||||
verbindung.schluessel.text,
|
||||
`zuletzt geprüft: ${verbindung.schluessel.geholtAm.slice(0, 16).replace('T', ' ')}`,
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface Verbindung {
|
||||
einstellungen: Record<string, string>
|
||||
werkzeuge: WerkzeugAuskunft | null
|
||||
bibliothek: BibliothekEintrag[]
|
||||
schluessel: { quelle: string; angenommen: boolean | null; gueltigBis: string; geholtAm: string; text: string } | null
|
||||
/** Kurze Ereigniszeilen (neueste zuerst): Disc rein/raus, Auswurf, Fehler. */
|
||||
meldungen: string[]
|
||||
}
|
||||
@@ -47,6 +48,7 @@ const stand: Verbindung = {
|
||||
einstellungen: {},
|
||||
werkzeuge: null,
|
||||
bibliothek: [],
|
||||
schluessel: null,
|
||||
meldungen: [],
|
||||
}
|
||||
const horcher = new Set<Horcher>()
|
||||
@@ -122,6 +124,10 @@ function kernNachricht(nachricht: KernNachricht): void {
|
||||
case 'bibliothek':
|
||||
stand.bibliothek = nachricht.eintraege
|
||||
break
|
||||
case 'schluessel-status':
|
||||
stand.schluessel = nachricht.stand
|
||||
if (nachricht.stand.angenommen === false) meldung(`⚠ MakeMKV-Schlüssel: ${nachricht.stand.text}`)
|
||||
break
|
||||
case 'rip-status': {
|
||||
stand.rips = { ...stand.rips, [nachricht.status.id]: nachricht.status }
|
||||
if (nachricht.status.phase === 'fertig') {
|
||||
|
||||
Reference in New Issue
Block a user