118 lines
3.3 KiB
Dart
118 lines
3.3 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../core/contracts/library.dart';
|
|
import '../core/media/media_range_detector.dart';
|
|
import 'shared/settings_persistence.dart';
|
|
|
|
enum VersionPriority {
|
|
dolbyVision('杜比视界优先'),
|
|
hdr('HDR 优先'),
|
|
sdr('SDR 优先'),
|
|
highBitrate('高码率优先'),
|
|
lowBitrate('低码率优先'),
|
|
highFramerate('高帧率优先'),
|
|
largeFile('大文件优先');
|
|
|
|
final String label;
|
|
const VersionPriority(this.label);
|
|
}
|
|
|
|
class VersionPriorityState {
|
|
final List<VersionPriority> activePriorities;
|
|
const VersionPriorityState({this.activePriorities = const []});
|
|
}
|
|
|
|
class VersionPriorityNotifier extends AsyncNotifier<VersionPriorityState>
|
|
with SettingsPersistence {
|
|
static const _key = 'smplayer.version_priorities';
|
|
|
|
@override
|
|
Future<VersionPriorityState> build() async {
|
|
final prefs = await getPrefs();
|
|
final raw = prefs.getStringList(_key);
|
|
if (raw == null) return const VersionPriorityState();
|
|
final priorities = raw
|
|
.map((name) {
|
|
try {
|
|
return VersionPriority.values.byName(name);
|
|
} catch (_) {
|
|
return null;
|
|
}
|
|
})
|
|
.whereType<VersionPriority>()
|
|
.toList();
|
|
return VersionPriorityState(activePriorities: priorities);
|
|
}
|
|
|
|
Future<void> _save(List<VersionPriority> list) async {
|
|
state = AsyncValue.data(VersionPriorityState(activePriorities: list));
|
|
await persistField(_key, list.map((p) => p.name).toList());
|
|
}
|
|
|
|
Future<void> toggle(VersionPriority p) async {
|
|
final current = List<VersionPriority>.from(
|
|
state.value?.activePriorities ?? [],
|
|
);
|
|
current.contains(p) ? current.remove(p) : current.add(p);
|
|
await _save(current);
|
|
}
|
|
|
|
Future<void> setPriorities(List<VersionPriority> list) => _save(list);
|
|
}
|
|
|
|
final versionPriorityProvider =
|
|
AsyncNotifierProvider<VersionPriorityNotifier, VersionPriorityState>(
|
|
VersionPriorityNotifier.new,
|
|
);
|
|
|
|
List<EmbyRawMediaSource> sortMediaSources(
|
|
List<EmbyRawMediaSource> sources,
|
|
List<VersionPriority> priorities,
|
|
) {
|
|
if (priorities.isEmpty || sources.length <= 1) return sources;
|
|
final sorted = List<EmbyRawMediaSource>.from(sources);
|
|
sorted.sort((a, b) => compareMediaSourcesByPriority(a, b, priorities));
|
|
return sorted;
|
|
}
|
|
|
|
|
|
int compareMediaSourcesByPriority(
|
|
EmbyRawMediaSource a,
|
|
EmbyRawMediaSource b,
|
|
List<VersionPriority> priorities,
|
|
) {
|
|
for (final p in priorities) {
|
|
final cmp = _compareByRule(a, b, p);
|
|
if (cmp != 0) return cmp;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int _compareByRule(
|
|
EmbyRawMediaSource a,
|
|
EmbyRawMediaSource b,
|
|
VersionPriority rule,
|
|
) {
|
|
switch (rule) {
|
|
case VersionPriority.dolbyVision:
|
|
return _boolDesc(isDolbyVision(a), isDolbyVision(b));
|
|
case VersionPriority.hdr:
|
|
return _boolDesc(isHdr(a), isHdr(b));
|
|
case VersionPriority.sdr:
|
|
return _boolDesc(!isHdr(a), !isHdr(b));
|
|
case VersionPriority.highBitrate:
|
|
return (b.Bitrate ?? 0).compareTo(a.Bitrate ?? 0);
|
|
case VersionPriority.lowBitrate:
|
|
return (a.Bitrate ?? 0).compareTo(b.Bitrate ?? 0);
|
|
case VersionPriority.highFramerate:
|
|
return getFrameRate(b).compareTo(getFrameRate(a));
|
|
case VersionPriority.largeFile:
|
|
return (b.Size ?? 0).compareTo(a.Size ?? 0);
|
|
}
|
|
}
|
|
|
|
int _boolDesc(bool a, bool b) {
|
|
if (a == b) return 0;
|
|
return a ? -1 : 1;
|
|
}
|