fix(replaygain): write and verify native Opus gain tags

Preserve audio and artwork while replacing conflicting Opus gain tags with R128 comments. Verify manual, download, and album writes, handle SAF failures, and refresh playback normalization after saving.
This commit is contained in:
zarzet
2026-09-06 21:03:57 +07:00
parent 0acdd6d0b0
commit bfffb8da11
14 changed files with 745 additions and 138 deletions
+35
View File
@@ -1,7 +1,42 @@
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:spotiflac_android/services/playback_normalization.dart';
void main() {
test('updated gain replaces the cached volume for the same URI', () async {
var gain = '-4.00 dB';
final cache = PlaybackNormalizationCache(
readMetadata: (_, {displayName}) async => {'replaygain_track_gain': gain},
);
const source = 'content://music/song';
expect(await cache.volumeFor(source), closeTo(0.630957, 0.000001));
gain = '-12.20 dB';
cache.invalidate(source);
expect(await cache.volumeFor(source), closeTo(0.245471, 0.000001));
});
test(
'a read started before an edit cannot restore stale cache data',
() async {
final staleRead = Completer<Map<String, dynamic>>();
var reads = 0;
final cache = PlaybackNormalizationCache(
readMetadata: (_, {displayName}) async {
if (++reads == 1) return staleRead.future;
return {'replaygain_track_gain': '-12.20 dB'};
},
);
final pending = cache.volumeFor('song');
cache.invalidate('song');
await cache.volumeFor('song');
staleRead.complete({'replaygain_track_gain': '-4.00 dB'});
await pending;
expect(await cache.volumeFor('song'), closeTo(0.245471, 0.000001));
expect(reads, 2);
},
);
test(
'descriptor normalization uses hint and caches by original URI',
() async {