feat(library): filter tracks missing verified ReplayGain tags

This commit is contained in:
zarzet committed 2026-10-02 01:24:26 +07:00
1 parent fbf479c102
commit 718e13f24e
20 files changed
+568 -20

No files matched your search

@@ -35,6 +35,11 @@ class DownloadHistoryItem {
final bool explicit;
final bool hasLyrics;
final int lyricsMetadataScanVersion;
final bool hasReplayGain;
/// 0 until the finished file's tags were read; only then is a false
/// [hasReplayGain] a confirmed absence.
final int replayGainMetadataScanVersion;
const DownloadHistoryItem({
required this.id,
@@ -71,6 +76,8 @@ class DownloadHistoryItem {
this.explicit = false,
this.hasLyrics = false,
this.lyricsMetadataScanVersion = 0,
this.hasReplayGain = false,
this.replayGainMetadataScanVersion = 0,
});
Map<String, dynamic> toJson() => {
@@ -108,6 +115,8 @@ class DownloadHistoryItem {
'explicit': explicit,
'hasLyrics': hasLyrics,
'lyricsMetadataScanVersion': lyricsMetadataScanVersion,
'hasReplayGain': hasReplayGain,
'replayGainMetadataScanVersion': replayGainMetadataScanVersion,
};
factory DownloadHistoryItem.fromJson(Map<String, dynamic> json) =>
@@ -147,6 +156,10 @@ class DownloadHistoryItem {
hasLyrics: json['hasLyrics'] == true || json['hasLyrics'] == 1,
lyricsMetadataScanVersion:
(json['lyricsMetadataScanVersion'] as num?)?.toInt() ?? 0,
hasReplayGain:
json['hasReplayGain'] == true || json['hasReplayGain'] == 1,
replayGainMetadataScanVersion:
(json['replayGainMetadataScanVersion'] as num?)?.toInt() ?? 0,
);
DownloadHistoryItem copyWith({
@@ -181,6 +194,8 @@ class DownloadHistoryItem {
bool? explicit,
bool? hasLyrics,
int? lyricsMetadataScanVersion,
bool? hasReplayGain,
int? replayGainMetadataScanVersion,
}) {
return DownloadHistoryItem(
id: id,
@@ -218,6 +233,9 @@ class DownloadHistoryItem {
hasLyrics: hasLyrics ?? this.hasLyrics,
lyricsMetadataScanVersion:
lyricsMetadataScanVersion ?? this.lyricsMetadataScanVersion,
hasReplayGain: hasReplayGain ?? this.hasReplayGain,
replayGainMetadataScanVersion:
replayGainMetadataScanVersion ?? this.replayGainMetadataScanVersion,
);
}
}
+17 -1
View File
@@ -214,6 +214,15 @@ class DownloadHistoryNotifier extends Notifier<DownloadHistoryState> {
item.lyricsMetadataScanVersion,
existing.lyricsMetadataScanVersion,
),
hasReplayGain:
item.replayGainMetadataScanVersion >=
existing.replayGainMetadataScanVersion
? item.hasReplayGain
: existing.hasReplayGain,
replayGainMetadataScanVersion: max(
item.replayGainMetadataScanVersion,
existing.replayGainMetadataScanVersion,
),
);
return (item: mergedItem, existingId: existing?.id);
}
@@ -493,6 +502,8 @@ class DownloadHistoryNotifier extends Notifier<DownloadHistoryState> {
bool? explicit,
bool? hasLyrics,
int? lyricsMetadataScanVersion,
bool? hasReplayGain,
int? replayGainMetadataScanVersion,
}) async {
final target = await _historyItemForUpdate(id);
if (target == null) {
@@ -518,6 +529,8 @@ class DownloadHistoryNotifier extends Notifier<DownloadHistoryState> {
explicit: explicit,
hasLyrics: hasLyrics,
lyricsMetadataScanVersion: lyricsMetadataScanVersion,
hasReplayGain: hasReplayGain,
replayGainMetadataScanVersion: replayGainMetadataScanVersion,
);
if (updated.quality == current.quality &&
@@ -534,7 +547,10 @@ class DownloadHistoryNotifier extends Notifier<DownloadHistoryState> {
updated.explicit == current.explicit &&
updated.hasLyrics == current.hasLyrics &&
updated.lyricsMetadataScanVersion ==
current.lyricsMetadataScanVersion) {
current.lyricsMetadataScanVersion &&
updated.hasReplayGain == current.hasReplayGain &&
updated.replayGainMetadataScanVersion ==
current.replayGainMetadataScanVersion) {
return;
}
@@ -272,6 +272,7 @@ extension _HistoryStartupMaintenance on DownloadHistoryNotifier {
bool _shouldBackfillAudioMetadata(DownloadHistoryItem item) {
return item.lyricsMetadataScanVersion < 1 ||
item.replayGainMetadataScanVersion < 1 ||
_needsAverageBitrateBackfill(item) ||
_shouldBackfillAudioMetadataIgnoringBitrate(item);
}
@@ -506,6 +507,10 @@ extension _HistoryStartupMaintenance on DownloadHistoryNotifier {
'totalDiscs': totalDiscs,
'hasLyrics': hasLyrics,
'lyricsMetadataScanVersion': lyricsMetadataScanVersion,
if (replayGainMetadataWasRead(result)) ...{
'hasReplayGain': metadataHasReplayGain(result),
'replayGainMetadataScanVersion': 1,
},
};
} catch (e) {
_historyLog.d('Audio metadata probe failed for $filePath: $e');
@@ -562,6 +567,7 @@ extension _HistoryStartupMaintenance on DownloadHistoryNotifier {
Map<String, dynamic>? probed;
if (item.lyricsMetadataScanVersion < 1 ||
item.replayGainMetadataScanVersion < 1 ||
_shouldBackfillAudioMetadataIgnoringBitrate(item)) {
probed = await _probeAudioMetadata(
item,
@@ -609,6 +615,9 @@ extension _HistoryStartupMaintenance on DownloadHistoryNotifier {
final resolvedHasLyrics = probed['hasLyrics'] as bool?;
final resolvedLyricsScanVersion =
probed['lyricsMetadataScanVersion'] as int?;
final resolvedHasReplayGain = probed['hasReplayGain'] as bool?;
final resolvedReplayGainScanVersion =
probed['replayGainMetadataScanVersion'] as int?;
final qualityChanged =
resolvedQuality != null && resolvedQuality != item.quality;
@@ -639,6 +648,12 @@ extension _HistoryStartupMaintenance on DownloadHistoryNotifier {
final lyricsScanVersionChanged =
resolvedLyricsScanVersion != null &&
resolvedLyricsScanVersion != item.lyricsMetadataScanVersion;
final replayGainChanged =
resolvedHasReplayGain != null &&
resolvedHasReplayGain != item.hasReplayGain;
final replayGainScanVersionChanged =
resolvedReplayGainScanVersion != null &&
resolvedReplayGainScanVersion != item.replayGainMetadataScanVersion;
if (!qualityChanged &&
!bitDepthChanged &&
@@ -652,7 +667,9 @@ extension _HistoryStartupMaintenance on DownloadHistoryNotifier {
!discNumberChanged &&
!totalDiscsChanged &&
!hasLyricsChanged &&
!lyricsScanVersionChanged) {
!lyricsScanVersionChanged &&
!replayGainChanged &&
!replayGainScanVersionChanged) {
continue;
}
@@ -670,6 +687,8 @@ extension _HistoryStartupMaintenance on DownloadHistoryNotifier {
totalDiscs: resolvedTotalDiscs,
hasLyrics: resolvedHasLyrics,
lyricsMetadataScanVersion: resolvedLyricsScanVersion,
hasReplayGain: resolvedHasReplayGain,
replayGainMetadataScanVersion: resolvedReplayGainScanVersion,
);
updatedItems ??= [...items];
updatedItems[index] = updated;
@@ -308,6 +308,8 @@ extension _DownloadQueueFinalization on DownloadQueueNotifier {
String? copyright,
required bool hasLyrics,
required int lyricsMetadataScanVersion,
required bool hasReplayGain,
required int replayGainMetadataScanVersion,
}) {
final backendTitle = result['title'] as String?;
final backendArtist = result['artist'] as String?;
@@ -394,19 +396,35 @@ extension _DownloadQueueFinalization on DownloadQueueNotifier {
parseExplicitFlag(result['explicit']) == true,
hasLyrics: hasLyrics,
lyricsMetadataScanVersion: lyricsMetadataScanVersion,
hasReplayGain: hasReplayGain,
replayGainMetadataScanVersion: replayGainMetadataScanVersion,
);
}
Future<({bool hasLyrics, int scanVersion})> _resolveFinalLyricsAvailability({
Future<
({
bool hasLyrics,
int scanVersion,
bool hasReplayGain,
int replayGainScanVersion,
})
>
_resolveFinalLyricsAvailability({
required String filePath,
Map<String, dynamic>? probedMetadata,
bool externalLrcWritten = false,
}) async {
var metadataScanned = false;
var hasEmbeddedLyrics = false;
var hasReplayGain = false;
var replayGainScanVersion = 0;
try {
final metadata =
probedMetadata ?? await PlatformBridge.readFileMetadata(filePath);
if (replayGainMetadataWasRead(metadata)) {
hasReplayGain = metadataHasReplayGain(metadata);
replayGainScanVersion = 1;
}
if (metadata['error'] == null &&
(metadata.containsKey('lyrics') ||
metadata.containsKey('hasLyrics'))) {
@@ -439,6 +457,8 @@ extension _DownloadQueueFinalization on DownloadQueueNotifier {
return (
hasLyrics: hasLyrics,
scanVersion: hasLyrics || metadataScanned ? 1 : 0,
hasReplayGain: hasReplayGain,
replayGainScanVersion: replayGainScanVersion,
);
}
@@ -194,6 +194,9 @@ extension _DownloadQueueNativeWorker on DownloadQueueNotifier {
copyright: normalizeOptionalString(result['copyright']?.toString()),
hasLyrics: lyricsAvailability.hasLyrics,
lyricsMetadataScanVersion: lyricsAvailability.scanVersion,
hasReplayGain: lyricsAvailability.hasReplayGain,
replayGainMetadataScanVersion:
lyricsAvailability.replayGainScanVersion,
),
preserveTrackVariant: context.item.preserveQualityVariant,
);
@@ -1555,6 +1558,9 @@ extension _DownloadQueueNativeWorker on DownloadQueueNotifier {
),
hasLyrics: lyricsAvailability.hasLyrics,
lyricsMetadataScanVersion: lyricsAvailability.scanVersion,
hasReplayGain: lyricsAvailability.hasReplayGain,
replayGainMetadataScanVersion:
lyricsAvailability.replayGainScanVersion,
),
preserveTrackVariant: item.preserveQualityVariant,
);
@@ -1673,6 +1673,9 @@ class _DownloadRun {
copyright: effectiveCopyright,
hasLyrics: lyricsAvailability.hasLyrics,
lyricsMetadataScanVersion: lyricsAvailability.scanVersion,
hasReplayGain: lyricsAvailability.hasReplayGain,
replayGainMetadataScanVersion:
lyricsAvailability.replayGainScanVersion,
),
preserveTrackVariant: item.preserveQualityVariant,
);