Songtext aus Datei-Tags, Warteschlangen-Aktionen, Kategorie-Cover im
Sperrbildschirm und ReplayGain - DB-Schema 6: lyrics + gain_db - Songtext bevorzugt lokalen Tag, Server nur als Rueckfall; Song-ID-Bug beim Lyrics-Aufruf behoben - "Als Naechstes spielen" / "Zur Warteschlange hinzufuegen" ohne Eingriff in Favoriten oder Wiedergabelisten - songToMediaItem nimmt eine Cover-Vorgabe: Sperrbildschirm zeigt das Kategorie-Cover - ReplayGain: Tags werden gelesen, laute Titel abgesenkt, abschaltbar Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011snPXPafPC5i87o68H14W7
This commit is contained in:
@@ -2,6 +2,18 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:melo/library/database.dart';
|
||||
import 'package:melo/library/song_media.dart';
|
||||
|
||||
Song _song({String? coverPath}) => Song(
|
||||
id: 'song-1',
|
||||
path: '/a.mp3',
|
||||
title: 'A',
|
||||
coverPath: coverPath,
|
||||
dateAddedMs: 0,
|
||||
updatedAtMs: 0,
|
||||
deleted: false,
|
||||
playCount: 0,
|
||||
categoriesEdited: false,
|
||||
);
|
||||
|
||||
void main() {
|
||||
test('songToMediaItem trägt die Song-UUID in extras', () {
|
||||
final song = Song(
|
||||
@@ -23,4 +35,22 @@ void main() {
|
||||
|
||||
expect(item.extras?['songId'], song.id);
|
||||
});
|
||||
|
||||
test('ohne Cover-Vorgabe gilt das eigene Cover des Songs', () {
|
||||
final item = songToMediaItem(_song(coverPath: '/eigen.img'));
|
||||
|
||||
expect(item.artUri, Uri.file('/eigen.img'));
|
||||
});
|
||||
|
||||
test('Cover-Vorgabe (z. B. aus der Kategorie) gewinnt — auch auf dem '
|
||||
'Sperrbildschirm', () {
|
||||
final item =
|
||||
songToMediaItem(_song(coverPath: '/eigen.img'), cover: '/kategorie.img');
|
||||
|
||||
expect(item.artUri, Uri.file('/kategorie.img'));
|
||||
});
|
||||
|
||||
test('ohne jedes Cover bleibt artUri leer', () {
|
||||
expect(songToMediaItem(_song()).artUri, isNull);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:melo/player/audio_handler.dart';
|
||||
|
||||
void main() {
|
||||
group('playNextIndex', () {
|
||||
test('fügt direkt hinter dem laufenden Titel ein', () {
|
||||
expect(playNextIndex(currentIndex: 0, queueLength: 3), 1);
|
||||
expect(playNextIndex(currentIndex: 2, queueLength: 5), 3);
|
||||
});
|
||||
|
||||
test('hängt ans Ende, wenn der letzte Titel läuft', () {
|
||||
expect(playNextIndex(currentIndex: 2, queueLength: 3), 3);
|
||||
});
|
||||
|
||||
test('hängt ans Ende, wenn nichts läuft', () {
|
||||
expect(playNextIndex(currentIndex: null, queueLength: 4), 4);
|
||||
expect(playNextIndex(currentIndex: null, queueLength: 0), 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:melo/player/replay_gain.dart';
|
||||
|
||||
void main() {
|
||||
group('parseReplayGain', () {
|
||||
test('liest das übliche Tag-Format', () {
|
||||
expect(parseReplayGain('-6.54 dB'), closeTo(-6.54, 0.001));
|
||||
expect(parseReplayGain('+2.30 dB'), closeTo(2.30, 0.001));
|
||||
expect(parseReplayGain('-8.120000 dB'), closeTo(-8.12, 0.001));
|
||||
});
|
||||
|
||||
test('kommt auch ohne Einheit zurecht', () {
|
||||
expect(parseReplayGain('-3.2'), closeTo(-3.2, 0.001));
|
||||
});
|
||||
|
||||
test('ignoriert unbrauchbare Werte', () {
|
||||
expect(parseReplayGain(null), isNull);
|
||||
expect(parseReplayGain(''), isNull);
|
||||
expect(parseReplayGain('keine Ahnung'), isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('volumeForGain', () {
|
||||
test('ohne Wert bleibt die Lautstärke unverändert', () {
|
||||
expect(volumeForGain(null), 1.0);
|
||||
});
|
||||
|
||||
test('negative Verstärkung senkt die Lautstärke ab', () {
|
||||
// -6 dB entspricht ungefähr der halben Amplitude.
|
||||
expect(volumeForGain(-6), closeTo(0.501, 0.005));
|
||||
expect(volumeForGain(-20), closeTo(0.1, 0.005));
|
||||
});
|
||||
|
||||
test('positive Verstärkung bleibt bei voller Lautstärke', () {
|
||||
// Lauter als 100 % geht nicht — angeglichen wird nach unten.
|
||||
expect(volumeForGain(6), 1.0);
|
||||
});
|
||||
|
||||
test('sehr starke Absenkung bleibt hörbar', () {
|
||||
expect(volumeForGain(-60), greaterThan(0.0));
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user