v2.32 — Defekte Musik erkennen (Magic Bytes, ffprobe, DB-Flag, UI)
This commit is contained in:
@@ -3,6 +3,7 @@ import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:just_audio/just_audio.dart';
|
||||
import '../models/song.dart';
|
||||
import '../database/db_helper.dart';
|
||||
import 'melo_logger.dart';
|
||||
|
||||
class PlayerService {
|
||||
@@ -14,6 +15,7 @@ class PlayerService {
|
||||
final List<Song> _warteschlange = [];
|
||||
int _aktuellerIndex = -1;
|
||||
StreamSubscription<PlayerState>? _autoNextSub;
|
||||
StreamSubscription<PlayerState>? _fehlerSub;
|
||||
|
||||
AudioPlayer get _p {
|
||||
if (_player == null) {
|
||||
@@ -23,6 +25,21 @@ class PlayerService {
|
||||
naechstes();
|
||||
}
|
||||
});
|
||||
// ── Playback-Fehler abfangen → Song als korrupt markieren ──
|
||||
_fehlerSub = _player!.playerStateStream.listen((state) {
|
||||
if (state.processingState == ProcessingState.completed) return; // bereits behandelt
|
||||
// PlayerState hat kein explizites "failure"-Feld, aber wir prüfen ob
|
||||
// die Quelle nicht geladen werden konnte (idle nach Fehlversuch)
|
||||
if (state.processingState == ProcessingState.idle &&
|
||||
_aktuellerIndex >= 0 &&
|
||||
_aktuellerIndex < _warteschlange.length) {
|
||||
final song = _warteschlange[_aktuellerIndex];
|
||||
// Nur markieren wenn kein Stream (Stream-Fehler sind oft temporär)
|
||||
if (song.streamUrl == null || song.streamUrl!.isEmpty) {
|
||||
_markiereAlsKorrupt(song);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return _player!;
|
||||
}
|
||||
@@ -60,6 +77,11 @@ class PlayerService {
|
||||
_songWechsel.add(song);
|
||||
} catch (e) {
|
||||
debugPrint('Fehler beim Abspielen: $e');
|
||||
MeloLogger().fehler('player_abspiel_fehler', e);
|
||||
// Song als korrupt markieren wenn lokale Datei
|
||||
if (song.streamUrl == null || song.streamUrl!.isEmpty) {
|
||||
_markiereAlsKorrupt(song);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,8 +122,25 @@ class PlayerService {
|
||||
|
||||
void dispose() {
|
||||
_autoNextSub?.cancel();
|
||||
_fehlerSub?.cancel();
|
||||
_player?.dispose();
|
||||
_player = null;
|
||||
_songWechsel.close();
|
||||
}
|
||||
|
||||
/// Markiert den aktuellen Song in der DB als korrupt
|
||||
Future<void> _markiereAlsKorrupt(Song song) async {
|
||||
if (song.id == null) return;
|
||||
try {
|
||||
final db = DbHelper();
|
||||
final s = await db.songNachId(song.id!);
|
||||
if (s != null && !s.istKorrupt) {
|
||||
await db.alsKorruptMarkieren(song.id!);
|
||||
debugPrint('⚠️ Song als korrupt markiert: ${song.titel}');
|
||||
MeloLogger().fehler('korrupt_markiert', 'Playback-Fehler: ${song.titel} (${song.dateiPfad})');
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Korrupt-Markierung fehlgeschlagen: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user