diff --git a/lib/models/common/audio_normalization.dart b/lib/models/common/audio_normalization.dart index 43534f33a..5c21932d8 100644 --- a/lib/models/common/audio_normalization.dart +++ b/lib/models/common/audio_normalization.dart @@ -2,9 +2,24 @@ enum AudioNormalization { disable('禁用'), // ref https://github.com/KRTirtho/spotube/commit/da10ab2e291d4ba4d3082b9a6ae535639fb8f1b7 dynaudnorm('预设 dynaudnorm', 'dynaudnorm=g=5:f=250:r=0.9:p=0.5'), + loudnorm('预设 loudnorm', 'loudnorm=I=-16:LRA=11:TP=-1.5'), custom('自定义参数'); final String title; final String param; const AudioNormalization(this.title, [this.param = '']); + + static String getTitleFromConfig(String config) => switch (config) { + '0' => disable.title, + '1' => dynaudnorm.title, + '2' => loudnorm.title, + _ => config, + }; + + static String getParamFromConfig(String config) => switch (config) { + '0' => disable.param, + '1' => dynaudnorm.param, + '2' => loudnorm.param, + _ => config, + }; } diff --git a/lib/models/video/play/url.dart b/lib/models/video/play/url.dart index be56be9b8..fc078f7f1 100644 --- a/lib/models/video/play/url.dart +++ b/lib/models/video/play/url.dart @@ -37,6 +37,7 @@ class PlayUrlModel { Dash? dash; List? durl; List? supportFormats; + Volume? volume; int? lastPlayTime; int? lastPlayCid; String? curLanguage; @@ -62,6 +63,7 @@ class PlayUrlModel { supportFormats = (json['support_formats'] as List?) ?.map((e) => FormatItem.fromJson(e)) .toList(); + volume = json['volume'] == null ? null : Volume.fromJson(json['volume']); lastPlayTime = json['last_play_time']; lastPlayCid = json['last_play_cid']; curLanguage = json['cur_language']; @@ -304,3 +306,48 @@ class FormatItem { codecs = (json['codecs'] as List?)?.fromCast(); } } + +class Volume { + Volume({ + required this.measuredI, + required this.measuredLra, + required this.measuredTp, + required this.measuredThreshold, + required this.targetOffset, + required this.targetI, + required this.targetTp, + // required this.multiSceneArgs, + }); + + final num measuredI; + final num measuredLra; + final num measuredTp; + final num measuredThreshold; + final num targetOffset; + final num targetI; + final num targetTp; + // final MultiSceneArgs? multiSceneArgs; + + factory Volume.fromJson(Map json) { + return Volume( + measuredI: json["measured_i"] ?? 0, + measuredLra: json["measured_lra"] ?? 0, + measuredTp: json["measured_tp"] ?? 0, + measuredThreshold: json["measured_threshold"] ?? 0, + targetOffset: json["target_offset"] ?? 0, + targetI: json["target_i"] ?? 0, + targetTp: json["target_tp"] ?? 0, + // multiSceneArgs: json["multi_scene_args"] == null ? null : MultiSceneArgs.fromJson(json["multi_scene_args"]), + ); + } + + @override + String toString() => + 'measured_I=$measuredI:measured_LRA=$measuredLra:measured_TP=$measuredTp:measured_thresh=$measuredThreshold'; + + bool get isNotEmpty => + measuredI != 0 || + measuredLra != 0 || + measuredTp != 0 || + measuredThreshold != 0; +} diff --git a/lib/pages/setting/models/extra_settings.dart b/lib/pages/setting/models/extra_settings.dart index 7ed06e5fc..c3d2ad624 100644 --- a/lib/pages/setting/models/extra_settings.dart +++ b/lib/pages/setting/models/extra_settings.dart @@ -23,6 +23,7 @@ import 'package:PiliPlus/pages/setting/models/model.dart'; import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart'; import 'package:PiliPlus/pages/setting/widgets/slide_dialog.dart'; import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart'; +import 'package:PiliPlus/plugin/pl_player/controller.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/cache_manage.dart'; import 'package:PiliPlus/utils/feed_back.dart'; @@ -32,6 +33,7 @@ import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/update.dart'; import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/foundation.dart' show kDebugMode; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -453,94 +455,27 @@ List get extraSettings => [ } catch (_) {} }, ), - SettingsModel( - settingsType: SettingsType.normal, - title: '音量均衡', - setKey: SettingBoxKey.audioNormalization, - leading: const Icon(Icons.multitrack_audio), - getSubtitle: () { - String audioNormalization = Pref.audioNormalization; - // TODO: remove next version - if (audioNormalization == '2') { - GStorage.setting.put(SettingBoxKey.audioNormalization, '1'); - audioNormalization = '1'; - } - audioNormalization = switch (audioNormalization) { - '0' => AudioNormalization.disable.title, - '1' => AudioNormalization.dynaudnorm.title, - _ => audioNormalization, - }; - return '当前:「$audioNormalization」'; - }, - onTap: (setState) async { - String? result = await showDialog( - context: Get.context!, - builder: (context) { - String audioNormalization = Pref.audioNormalization; - final values = {'0', '1', audioNormalization, '2'}; - return SelectDialog( - title: '音量均衡', - value: audioNormalization, - values: values - .map( - (e) => ( - e, - switch (e) { - '0' => AudioNormalization.disable.title, - '1' => AudioNormalization.dynaudnorm.title, - '2' => AudioNormalization.custom.title, - _ => e, - }, - ), - ) - .toList(), - ); - }, - ); - if (result != null) { - if (result == '2') { - String param = ''; - showDialog( - context: Get.context!, - builder: (context) { - return AlertDialog( - title: const Text('自定义参数'), - content: TextField( - autofocus: true, - onChanged: (value) => param = value, - ), - actions: [ - TextButton( - onPressed: Get.back, - child: Text( - '取消', - style: TextStyle( - color: Theme.of(context).colorScheme.outline, - ), - ), - ), - TextButton( - onPressed: () async { - Get.back(); - await GStorage.setting.put( - SettingBoxKey.audioNormalization, - param, - ); - setState(); - }, - child: const Text('确定'), - ), - ], - ); - }, - ); + if (kDebugMode || Platform.isAndroid) + SettingsModel( + settingsType: SettingsType.normal, + title: '音量均衡', + setKey: SettingBoxKey.audioNormalization, + leading: const Icon(Icons.multitrack_audio), + getSubtitle: () { + final audioNormalization = AudioNormalization.getTitleFromConfig( + Pref.audioNormalization, + ); + String fallback = Pref.fallbackNormalization; + if (fallback == '0') { + fallback = ''; } else { - await GStorage.setting.put(SettingBoxKey.audioNormalization, result); - setState(); + fallback = + ',无参数时:「${AudioNormalization.getTitleFromConfig(fallback)}」'; } - } - }, - ), + return '当前:「$audioNormalization」$fallback'; + }, + onTap: audioNormalization, + ), SettingsModel( settingsType: SettingsType.normal, title: '超分辨率', @@ -1188,3 +1123,99 @@ List get extraSettings => [ }, ), ]; + +Future audioNormalization( + VoidCallback setState, { + bool fallback = false, +}) async { + final key = fallback + ? SettingBoxKey.fallbackNormalization + : SettingBoxKey.audioNormalization; + final result = await showDialog( + context: Get.context!, + builder: (context) { + String audioNormalization = fallback + ? Pref.fallbackNormalization + : Pref.audioNormalization; + Set values = { + '0', + '1', + if (!fallback) '2', + audioNormalization, + '3', + }; + return SelectDialog( + title: fallback ? '服务器无loudnorm配置时使用' : '音量均衡', + toggleable: true, + value: audioNormalization, + values: values + .map( + (e) => ( + e, + switch (e) { + '0' => AudioNormalization.disable.title, + '1' => AudioNormalization.dynaudnorm.title, + '2' => AudioNormalization.loudnorm.title, + '3' => AudioNormalization.custom.title, + _ => e, + }, + ), + ) + .toList(), + ); + }, + ); + if (result != null) { + if (result == '3') { + String param = ''; + await showDialog( + context: Get.context!, + builder: (context) { + return AlertDialog( + title: const Text('自定义参数'), + content: Column( + mainAxisSize: MainAxisSize.min, + spacing: 16, + children: [ + const Text('等同于 --lavfi-complex="[aid1] 参数 [ao]"'), + TextField( + autofocus: true, + onChanged: (value) => param = value, + ), + ], + ), + actions: [ + TextButton( + onPressed: Get.back, + child: Text( + '取消', + style: TextStyle( + color: ColorScheme.of(context).outline, + ), + ), + ), + TextButton( + onPressed: () async { + Get.back(); + await GStorage.setting.put(key, param); + if (!fallback && + PlPlayerController.loudnormRegExp.hasMatch(param)) { + audioNormalization(setState, fallback: true); + } + setState(); + }, + child: const Text('确定'), + ), + ], + ); + }, + ); + } else { + await GStorage.setting.put(key, result); + if (result == '2') { + audioNormalization(setState, fallback: true); + } + setState(); + } + } +} diff --git a/lib/pages/setting/models/model.dart b/lib/pages/setting/models/model.dart index 0079b3b20..e9e4b320b 100644 --- a/lib/pages/setting/models/model.dart +++ b/lib/pages/setting/models/model.dart @@ -58,7 +58,7 @@ class SettingsModel { SettingsType.sw1tch => SetSwitchItem( title: title, subtitle: subtitle, - setKey: setKey, + setKey: setKey!, defaultVal: defaultVal, onChanged: onChanged, needReboot: needReboot, diff --git a/lib/pages/setting/widgets/select_dialog.dart b/lib/pages/setting/widgets/select_dialog.dart index bfd9ff3fd..c23495ab5 100644 --- a/lib/pages/setting/widgets/select_dialog.dart +++ b/lib/pages/setting/widgets/select_dialog.dart @@ -16,6 +16,7 @@ class SelectDialog extends StatelessWidget { final String title; final List<(T, String)> values; final Widget Function(BuildContext, int)? subtitleBuilder; + final bool toggleable; const SelectDialog({ super.key, @@ -23,11 +24,12 @@ class SelectDialog extends StatelessWidget { required this.values, required this.title, this.subtitleBuilder, + this.toggleable = false, }); @override Widget build(BuildContext context) { - final titleMedium = Theme.of(context).textTheme.titleMedium!; + final titleMedium = TextTheme.of(context).titleMedium!; return AlertDialog( clipBehavior: Clip.hardEdge, title: Text(title), @@ -37,7 +39,7 @@ class SelectDialog extends StatelessWidget { contentPadding: const EdgeInsets.symmetric(vertical: 12), content: SingleChildScrollView( child: RadioGroup( - onChanged: Navigator.of(context).pop, + onChanged: (v) => Navigator.of(context).pop(v ?? value), groupValue: value, child: Column( mainAxisSize: MainAxisSize.min, @@ -46,6 +48,7 @@ class SelectDialog extends StatelessWidget { (index) { final item = values[index]; return RadioListTile( + toggleable: toggleable, dense: true, value: item.$1, title: Text( diff --git a/lib/pages/setting/widgets/switch_item.dart b/lib/pages/setting/widgets/switch_item.dart index a15a4fc5d..8040d98d9 100644 --- a/lib/pages/setting/widgets/switch_item.dart +++ b/lib/pages/setting/widgets/switch_item.dart @@ -9,7 +9,7 @@ import 'package:get/get.dart'; class SetSwitchItem extends StatefulWidget { final String? title; final String? subtitle; - final String? setKey; + final String setKey; final bool defaultVal; final ValueChanged? onChanged; final bool needReboot; @@ -21,7 +21,7 @@ class SetSwitchItem extends StatefulWidget { const SetSwitchItem({ this.title, this.subtitle, - this.setKey, + required this.setKey, this.defaultVal = false, this.onChanged, this.needReboot = false, diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index cf82cbae7..7e010a5b0 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -1056,6 +1056,7 @@ class VideoDetailController extends GetxController Duration? seekToTime, Duration? duration, bool? autoplay, + Volume? volume, }) async { await plPlayerController.setDataSource( DataSource( @@ -1095,6 +1096,7 @@ class VideoDetailController extends GetxController }, width: firstVideo.width, height: firstVideo.height, + volume: volume ?? this.volume, ); if (plPlayerController.enableSponsorBlock) { @@ -1125,6 +1127,8 @@ class VideoDetailController extends GetxController queryVideoUrl(defaultST: playedTime); } + Volume? volume; + // 视频链接 Future queryVideoUrl({ Duration? defaultST, @@ -1164,6 +1168,8 @@ class VideoDetailController extends GetxController languages.value = data.language?.items; currLang.value = data.curLanguage; + volume = data.volume; + if (data.acceptDesc?.contains('试看') == true) { SmartDialog.showToast( '该视频为专属视频,仅提供试看', diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index bf5fbf97d..e8bfd5455 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -43,7 +43,6 @@ import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:intl/intl.dart' show DateFormat; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; -import 'package:media_kit/media_kit.dart'; class HeaderControl extends StatefulWidget { const HeaderControl({ @@ -446,8 +445,9 @@ class HeaderControlState extends State { SmartDialog.showToast('播放器未初始化'); return; } - final hwdec = await (player.platform as NativePlayer) - .getProperty('hwdec-current'); + final hwdec = await player.platform!.getProperty( + 'hwdec-current', + ); if (!context.mounted) return; showDialog( context: context, diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 76331f170..acb722ff3 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -15,6 +15,7 @@ import 'package:PiliPlus/models/common/sponsor_block/skip_type.dart'; import 'package:PiliPlus/models/common/super_resolution_type.dart'; import 'package:PiliPlus/models/common/video/video_type.dart'; import 'package:PiliPlus/models/user/danmaku_rule.dart'; +import 'package:PiliPlus/models/video/play/url.dart'; import 'package:PiliPlus/models_new/video/video_shot/data.dart'; import 'package:PiliPlus/pages/mine/controller.dart'; import 'package:PiliPlus/plugin/pl_player/models/bottom_progress_behavior.dart'; @@ -54,7 +55,6 @@ import 'package:media_kit/media_kit.dart'; import 'package:media_kit_video/media_kit_video.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; -import 'package:universal_platform/universal_platform.dart'; import 'package:window_manager/window_manager.dart'; class PlPlayerController { @@ -598,6 +598,7 @@ class PlPlayerController { int? pgcType, VideoType? videoType, VoidCallback? callback, + Volume? volume, }) async { try { _isLive = isLive; @@ -637,6 +638,7 @@ class PlPlayerController { dataSource, _looping, seekTo, + volume, ); callback?.call(); // 获取视频时长 00:00 @@ -716,7 +718,7 @@ class PlPlayerController { setting.put(SettingBoxKey.superResolutionType, type.index); } } - pp ??= _videoPlayerController?.platform as NativePlayer; + pp ??= _videoPlayerController!.platform!; await pp.waitForPlayerInitialization; await pp.waitForVideoControllerInitializationIfAttached; switch (type) { @@ -745,11 +747,14 @@ class PlPlayerController { } } + static final loudnormRegExp = RegExp('loudnorm=[^,]+'); + // 配置播放器 Future _createVideoController( DataSource dataSource, PlaylistMode looping, Duration? seekTo, + Volume? volume, ) async { // 每次配置时先移除监听 removeListeners(); @@ -759,6 +764,7 @@ class PlPlayerController { _position.value = Duration.zero; // 初始化时清空弹幕,防止上次重叠 danmakuController?.clear(); + Player player = _videoPlayerController ?? Player( @@ -769,20 +775,14 @@ class PlPlayerController { : (isLive ? 16 * 1024 * 1024 : 4 * 1024 * 1024), ), ); - var pp = player.platform as NativePlayer; + final pp = player.platform!; if (_videoPlayerController == null) { if (isAnim) { setShader(superResolutionType.value, pp); } - String audioNormalization = Pref.audioNormalization; - audioNormalization = switch (audioNormalization) { - '0' => '', - '1' => ',${AudioNormalization.dynaudnorm.param}', - _ => ',$audioNormalization', - }; await pp.setProperty( "af", - "scaletempo2=max-speed=8$audioNormalization", + "scaletempo2=max-speed=8", ); if (Platform.isAndroid) { await pp.setProperty("volume-max", "100"); @@ -804,7 +804,7 @@ class PlPlayerController { if (dataSource.audioSource?.isNotEmpty == true) { await pp.setProperty( 'audio-files', - UniversalPlatform.isWindows + Platform.isWindows ? dataSource.audioSource!.replaceAll(';', '\\;') : dataSource.audioSource!.replaceAll(':', '\\:'), ); @@ -816,7 +816,7 @@ class PlPlayerController { if (dataSource.subFiles?.isNotEmpty == true) { await pp.setProperty( 'sub-files', - UniversalPlatform.isWindows + Platform.isWindows ? dataSource.subFiles!.replaceAll(';', '\\;') : dataSource.subFiles!.replaceAll(':', '\\:'), ); @@ -835,12 +835,44 @@ class PlPlayerController { ); player.setPlaylistMode(looping); + + final Map? filters; + if (kDebugMode || Platform.isAndroid) { + String audioNormalization = ''; + audioNormalization = AudioNormalization.getParamFromConfig( + Pref.audioNormalization, + ); + if (volume != null && volume.isNotEmpty) { + audioNormalization = audioNormalization.replaceFirstMapped( + loudnormRegExp, + (i) => '${i[0]}:$volume', + ); + } else { + audioNormalization = audioNormalization.replaceFirst( + loudnormRegExp, + AudioNormalization.getParamFromConfig(Pref.fallbackNormalization), + ); + } + filters = audioNormalization.isEmpty + ? null + : {'lavfi-complex': '"[aid1] $audioNormalization [ao]"'}; + } else { + filters = null; + } + + if (kDebugMode) debugPrint(filters.toString()); + if (dataSource.type == DataSourceType.asset) { final assetUrl = dataSource.videoSource!.startsWith("asset://") ? dataSource.videoSource! : "asset://${dataSource.videoSource!}"; await player.open( - Media(assetUrl, httpHeaders: dataSource.httpHeaders, start: seekTo), + Media( + assetUrl, + httpHeaders: dataSource.httpHeaders, + start: seekTo, + extras: filters, + ), play: false, ); } else { @@ -849,6 +881,7 @@ class PlPlayerController { dataSource.videoSource!, httpHeaders: dataSource.httpHeaders, start: seekTo, + extras: filters, ), play: false, ); @@ -874,9 +907,9 @@ class PlPlayerController { if (dataSource.audioSource.isNullOrEmpty) { SmartDialog.showToast('音频源为空'); } else { - await (_videoPlayerController!.platform as NativePlayer).setProperty( + await (_videoPlayerController!.platform!).setProperty( 'audio-files', - UniversalPlatform.isWindows + Platform.isWindows ? dataSource.audioSource!.replaceAll(';', '\\;') : dataSource.audioSource!.replaceAll(':', '\\:'), ); @@ -1658,7 +1691,7 @@ class PlPlayerController { // dataStatus.status.close(); if (_videoPlayerController != null) { - var pp = _videoPlayerController!.platform as NativePlayer; + var pp = _videoPlayerController!.platform!; await pp.setProperty('audio-files', ''); removeListeners(); await _videoPlayerController!.dispose(); diff --git a/lib/plugin/pl_player/widgets/mpv_convert_webp.dart b/lib/plugin/pl_player/widgets/mpv_convert_webp.dart index dcf07a1f2..10d15132e 100644 --- a/lib/plugin/pl_player/widgets/mpv_convert_webp.dart +++ b/lib/plugin/pl_player/widgets/mpv_convert_webp.dart @@ -9,6 +9,7 @@ import 'package:get/get_rx/get_rx.dart'; import 'package:media_kit/ffi/src/allocation.dart'; import 'package:media_kit/ffi/src/utf8.dart'; import 'package:media_kit/generated/libmpv/bindings.dart' as generated; +import 'package:media_kit/media_kit.dart'; import 'package:media_kit/src/player/native/core/initializer.dart'; import 'package:media_kit/src/player/native/core/native_library.dart'; @@ -54,7 +55,15 @@ class MpvConvertWebp { '${Pref.hardwareDecoding},auto-copy', // transcode only support copy }, ); - _setHeader(); + NativePlayer.setHeader( + const { + 'user-agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', + 'referer': HttpString.baseUrl, + }, + _mpv, + _ctx, + ); if (progress != null) { _observeProperty('time-pos'); } @@ -79,7 +88,7 @@ class MpvConvertWebp { switch (event.ref.event_id) { case generated.mpv_event_id.MPV_EVENT_PROPERTY_CHANGE: final prop = event.ref.data.cast().ref; - if (prop.name.cast().toDartString() == 'time-pos' && + if (prop.name.toDartString() == 'time-pos' && prop.format == generated.mpv_format.MPV_FORMAT_DOUBLE) { progress!.value = (prop.data.cast().value - start) / duration; } @@ -89,9 +98,9 @@ class MpvConvertWebp { break; case generated.mpv_event_id.MPV_EVENT_LOG_MESSAGE: final log = event.ref.data.cast().ref; - final prefix = log.prefix.cast().toDartString().trim(); - final level = log.level.cast().toDartString().trim(); - final text = log.text.cast().toDartString().trim(); + final prefix = log.prefix.toDartString().trim(); + final level = log.level.toDartString().trim(); + final text = log.text.toDartString().trim(); debugPrint('WebpConvert: $level $prefix : $text'); if (kDebugMode) { _success = level != 'error' && level != 'fatal'; @@ -108,18 +117,8 @@ class MpvConvertWebp { } } - void _command(List args) { - final pointers = args.map((e) => e.toNativeUtf8()).toList(); - final arr = calloc>(128); - for (int i = 0; i < args.length; i++) { - arr[i] = pointers[i]; - } - - _mpv.mpv_command(_ctx, arr.cast()); - - calloc.free(arr); - pointers.forEach(calloc.free); - } + void _command(List args) => + NativePlayer.statiCommand(args, _mpv, _ctx); void _observeProperty(String property) { final name = property.toNativeUtf8(); @@ -132,47 +131,6 @@ class MpvConvertWebp { calloc.free(name); } - - void _setHeader() { - final property = 'http-header-fields'.toNativeUtf8(); - // Allocate & fill the [mpv_node] with the headers. - final value = calloc(); - final valRef = value.ref - ..format = generated.mpv_format.MPV_FORMAT_NODE_ARRAY; - valRef.u.list = calloc(); - final valList = valRef.u.list.ref - ..num = 2 - ..values = calloc(2); - - const entries = [ - ( - 'user-agent', - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', - ), - ('referer', HttpString.baseUrl), - ]; - for (int i = 0; i < 2; i++) { - final (k, v) = entries[i]; - valList.values[i] - ..format = generated.mpv_format.MPV_FORMAT_STRING - ..u.string = '$k: $v'.toNativeUtf8().cast(); - } - _mpv.mpv_set_property( - _ctx, - property.cast(), - generated.mpv_format.MPV_FORMAT_NODE, - value.cast(), - ); - // Free the allocated memory. - calloc.free(property); - for (int i = 0; i < valList.num; i++) { - calloc.free(valList.values[i].u.string); - } - calloc - ..free(valList.values) - ..free(valRef.u.list) - ..free(value); - } } enum WebpPreset { diff --git a/lib/utils/storage_key.dart b/lib/utils/storage_key.dart index 41697fc8c..46b6ea5c1 100644 --- a/lib/utils/storage_key.dart +++ b/lib/utils/storage_key.dart @@ -93,6 +93,7 @@ abstract class SettingBoxKey { refreshDisplacement = 'refreshDisplacement', showHotRcmd = 'showHotRcmd', audioNormalization = 'audioNormalization', + fallbackNormalization = 'fallbackNormalization', superResolutionType = 'superResolutionType', preInitPlayer = 'preInitPlayer', mainTabBarView = 'mainTabBarView', diff --git a/lib/utils/storage_pref.dart b/lib/utils/storage_pref.dart index 75ed5d63a..f5fc77cd6 100644 --- a/lib/utils/storage_pref.dart +++ b/lib/utils/storage_pref.dart @@ -414,6 +414,9 @@ abstract class Pref { static String get audioNormalization => _setting.get(SettingBoxKey.audioNormalization, defaultValue: '0'); + static String get fallbackNormalization => + _setting.get(SettingBoxKey.fallbackNormalization, defaultValue: '0'); + static SuperResolutionType get superResolutionType { SuperResolutionType? superResolutionType; final index = _setting.get(SettingBoxKey.superResolutionType); diff --git a/pubspec.lock b/pubspec.lock index b985aa276..d7593cf5e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1143,10 +1143,11 @@ packages: media_kit: dependency: "direct main" description: - name: media_kit - sha256: "1f1deee148533d75129a6f38251ff8388e33ee05fc2d20a6a80e57d6051b7b62" - url: "https://pub.dev" - source: hosted + path: media_kit + ref: "version_1.2.5" + resolved-ref: "4d68e69281b44f2c8e3c444cca3d8d8dc6dcff88" + url: "https://github.com/My-Responsitories/media-kit.git" + source: git version: "1.1.11" media_kit_libs_android_video: dependency: "direct overridden" @@ -1184,10 +1185,11 @@ packages: media_kit_libs_video: dependency: "direct main" description: - name: media_kit_libs_video - sha256: "20bb4aefa8fece282b59580e1cd8528117297083a6640c98c2e98cfc96b93288" - url: "https://pub.dev" - source: hosted + path: "libs/universal/media_kit_libs_video" + ref: "version_1.2.5" + resolved-ref: "4d68e69281b44f2c8e3c444cca3d8d8dc6dcff88" + url: "https://github.com/My-Responsitories/media-kit.git" + source: git version: "1.0.5" media_kit_libs_windows_video: dependency: transitive @@ -1200,18 +1202,19 @@ packages: media_kit_native_event_loop: dependency: "direct overridden" description: - name: media_kit_native_event_loop - sha256: "7d82e3b3e9ded5c35c3146c5ba1da3118d1dd8ac3435bac7f29f458181471b40" - url: "https://pub.dev" - source: hosted + path: media_kit_native_event_loop + ref: "version_1.2.5" + resolved-ref: "4d68e69281b44f2c8e3c444cca3d8d8dc6dcff88" + url: "https://github.com/My-Responsitories/media-kit.git" + source: git version: "1.0.9" media_kit_video: dependency: "direct main" description: path: media_kit_video ref: "version_1.2.5" - resolved-ref: "902e962556c0bde4d384cd8f72b814598e5dfcf2" - url: "https://github.com/bggRGjQaUbCoE/media-kit.git" + resolved-ref: "4d68e69281b44f2c8e3c444cca3d8d8dc6dcff88" + url: "https://github.com/My-Responsitories/media-kit.git" source: git version: "1.2.5" menu_base: @@ -1474,10 +1477,10 @@ packages: dependency: transitive description: name: safe_local_storage - sha256: ede4eb6cb7d88a116b3d3bf1df70790b9e2038bc37cb19112e381217c74d9440 + sha256: e9a21b6fec7a8aa62cc2585ff4c1b127df42f3185adbd2aca66b47abe2e80236 url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "2.0.1" saver_gallery: dependency: "direct main" description: @@ -1836,22 +1839,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" - universal_platform: - dependency: "direct main" - description: - name: universal_platform - sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec" - url: "https://pub.dev" - source: hosted - version: "1.1.0" uri_parser: dependency: transitive description: name: uri_parser - sha256: "6543c9fd86d2862fac55d800a43e67c0dcd1a41677cb69c2f8edfe73bbcf1835" + sha256: ff4d2c720aca3f4f7d5445e23b11b2d15ef8af5ddce5164643f38ff962dcb270 url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "3.0.0" url_launcher: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 384210dd3..3c6b60040 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -219,7 +219,6 @@ dependencies: stream_transform: any screen_brightness_platform_interface: any mime: any - universal_platform: any path: any collection: any material_color_utilities: any @@ -234,15 +233,32 @@ dependency_overrides: path: ^1.9.1 mime: ^2.0.0 rxdart: ^0.28.0 - media_kit: 1.1.11 - media_kit_libs_video: 1.0.5 - media_kit_native_event_loop: ^1.0.9 - font_awesome_flutter: 10.9.0 + media_kit: + git: + url: https://github.com/My-Responsitories/media-kit.git + path: media_kit + ref: version_1.2.5 + media_kit_video: + git: + url: https://github.com/My-Responsitories/media-kit.git + path: media_kit_video + ref: version_1.2.5 + media_kit_libs_video: + git: + url: https://github.com/My-Responsitories/media-kit.git + path: libs/universal/media_kit_libs_video + ref: version_1.2.5 + media_kit_native_event_loop: + git: + url: https://github.com/My-Responsitories/media-kit.git + path: media_kit_native_event_loop + ref: version_1.2.5 media_kit_libs_android_video: git: url: https://github.com/bggRGjQaUbCoE/media-kit.git path: libs/android/media_kit_libs_android_video ref: version_1.2.5 + font_awesome_flutter: 10.9.0 dev_dependencies: flutter_test: