import 'package:audio_service/audio_service.dart'; import '../player/audio_handler.dart'; import '../services/navidrome_service.dart'; import 'database.dart'; /// [cover] überschreibt das Coverbild des Songs — damit auf Sperrbildschirm /// und in der Benachrichtigung dasselbe Bild erscheint wie in der App /// (Einstellung "Gleiche Kategorie = gleiches Coverbild"). MediaItem songToMediaItem(Song s, {String? cover}) { final art = cover ?? s.coverPath; return MediaItem( id: Uri.file(s.path).toString(), title: s.title, artist: s.artist, album: s.album, duration: s.durationMs != null ? Duration(milliseconds: s.durationMs!) : null, artUri: art != null ? Uri.file(art) : null, extras: {'songId': s.id, 'gainDb': s.gainDb}, ); } /// Meldung für Titel, die der Offline-Modus aus der Warteschlange genommen /// hat. Der Nutzer soll den Unterschied zwischen "nicht da" und "nicht /// heruntergeladen" sehen, statt eine stillschweigend kürzere Liste zu hören. String offlineHinweis(int uebersprungen) => uebersprungen == 1 ? 'Offline-Modus: 1 Titel übersprungen — nicht heruntergeladen' : 'Offline-Modus: $uebersprungen Titel übersprungen — nicht heruntergeladen'; /// Meldung für einen einzelnen Titel, den der Offline-Modus ablehnt. const nichtOfflineHinweis = 'Offline-Modus: dieser Titel ist nicht heruntergeladen'; /// Ein Titel vom Navidrome-Server als [MediaItem]. /// /// Eine Stelle für beide Aufrufer (Album und Künstler im Server-Browser) — /// vorher war der Aufbau doppelt von Hand geschrieben, und beide Kopien /// vergaßen das Coverbild. MediaItem subsonicToMediaItem(SubsonicSong s, NavidromeService nav) { final coverId = s.coverId; return MediaItem( id: nav.streamUrl(s.id).toString(), title: s.titel, artist: s.kuenstler, album: s.album, duration: Duration(seconds: s.dauerSekunden), // Das Cover liegt am Server, nicht als Datei auf dem Gerät. artUri: coverId == null ? null : nav.coverUrl(coverId), // Die Server-ID getrennt von der Abspiel-URI mitgeben: nur damit erkennt // der Player einen Server-Titel (Cache, Scrobble, Bookmark). extras: {'navidromeId': s.id}, ); } /// Spielt [songs] ab [startIndex] ab. [coverOf] liefert je Song das /// anzuzeigende Cover (siehe [songToMediaItem]). Gibt zurück, wie viele Titel /// der Offline-Modus übersprungen hat. Future playSongs( MeloAudioHandler handler, List songs, int startIndex, { String? Function(Song)? coverOf, }) { return handler.loadPlaylist( [for (final s in songs) songToMediaItem(s, cover: coverOf?.call(s))], startIndex: startIndex, ); }