mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-08-05 18:20:10 +08:00
opt: ao (#1811)
* opt: ao * multi select --------- Co-authored-by: dom <githubaccount56556@proton.me>
This commit is contained in:
committed by
GitHub
parent
038f03a4e7
commit
bfb2becb2d
@@ -1,4 +1,6 @@
|
|||||||
enum SkipType {
|
import 'package:PiliPlus/models/common/enum_with_label.dart';
|
||||||
|
|
||||||
|
enum SkipType implements EnumWithLabel {
|
||||||
alwaysSkip('总是跳过'),
|
alwaysSkip('总是跳过'),
|
||||||
skipOnce('跳过一次'),
|
skipOnce('跳过一次'),
|
||||||
skipManually('手动跳过'),
|
skipManually('手动跳过'),
|
||||||
@@ -6,6 +8,7 @@ enum SkipType {
|
|||||||
disable('禁用')
|
disable('禁用')
|
||||||
;
|
;
|
||||||
|
|
||||||
final String title;
|
@override
|
||||||
const SkipType(this.title);
|
final String label;
|
||||||
|
const SkipType(this.label);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,54 +134,12 @@ List<SettingsModel> get extraSettings => [
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
NormalModel(
|
getPopupMenuModel(
|
||||||
leading: const Icon(MdiIcons.debugStepOver),
|
|
||||||
title: '番剧片头/片尾跳过类型',
|
title: '番剧片头/片尾跳过类型',
|
||||||
getTrailing: () => Builder(
|
leading: const Icon(MdiIcons.debugStepOver),
|
||||||
builder: (context) {
|
key: SettingBoxKey.pgcSkipType,
|
||||||
final pgcSkipType = Pref.pgcSkipType;
|
values: SkipType.values,
|
||||||
final colorScheme = ColorScheme.of(context);
|
defaultIndex: SkipType.skipOnce.index,
|
||||||
final color = pgcSkipType == SkipType.disable
|
|
||||||
? colorScheme.outline
|
|
||||||
: colorScheme.secondary;
|
|
||||||
return PopupMenuButton<SkipType>(
|
|
||||||
initialValue: pgcSkipType,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
||||||
child: Text.rich(
|
|
||||||
style: TextStyle(fontSize: 14, height: 1, color: color),
|
|
||||||
strutStyle: const StrutStyle(
|
|
||||||
leading: 0,
|
|
||||||
height: 1,
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
TextSpan(text: pgcSkipType.title),
|
|
||||||
WidgetSpan(
|
|
||||||
alignment: .middle,
|
|
||||||
child: Icon(
|
|
||||||
MdiIcons.unfoldMoreHorizontal,
|
|
||||||
size: 14,
|
|
||||||
color: color,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onSelected: (value) async {
|
|
||||||
await GStorage.setting.put(SettingBoxKey.pgcSkipType, value.index);
|
|
||||||
if (context.mounted) {
|
|
||||||
(context as Element).markNeedsBuild();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemBuilder: (context) => SkipType.values
|
|
||||||
.map((e) => PopupMenuItem(value: e, child: Text(e.title)))
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SwitchModel(
|
SwitchModel(
|
||||||
title: '检查未读动态',
|
title: '检查未读动态',
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:PiliPlus/common/constants.dart';
|
import 'package:PiliPlus/common/constants.dart';
|
||||||
|
import 'package:PiliPlus/models/common/enum_with_label.dart';
|
||||||
import 'package:PiliPlus/pages/setting/widgets/normal_item.dart';
|
import 'package:PiliPlus/pages/setting/widgets/normal_item.dart';
|
||||||
import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart';
|
import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart';
|
||||||
import 'package:PiliPlus/pages/setting/widgets/switch_item.dart';
|
import 'package:PiliPlus/pages/setting/widgets/switch_item.dart';
|
||||||
@@ -7,6 +8,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/services.dart' show FilteringTextInputFormatter;
|
import 'package:flutter/services.dart' show FilteringTextInputFormatter;
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
sealed class SettingsModel {
|
sealed class SettingsModel {
|
||||||
@@ -258,3 +260,61 @@ SettingsModel getVideoFilterSelectModel({
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsModel getPopupMenuModel({
|
||||||
|
required String title,
|
||||||
|
Widget? leading,
|
||||||
|
String? subtitle,
|
||||||
|
required String key,
|
||||||
|
required List<EnumWithLabel> values,
|
||||||
|
int defaultIndex = 0,
|
||||||
|
}) {
|
||||||
|
// final globalKey = GlobalKey<PopupMenuButtonState<EnumWithLabel>>();
|
||||||
|
return NormalModel(
|
||||||
|
title: title,
|
||||||
|
subtitle: subtitle,
|
||||||
|
leading: leading,
|
||||||
|
// onTap: (context, setState) => globalKey.currentState?.showButtonMenu(),
|
||||||
|
getTrailing: () => Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final color = ColorScheme.of(context).secondary;
|
||||||
|
final v = values[GStorage.setting.get(key, defaultValue: defaultIndex)];
|
||||||
|
return PopupMenuButton(
|
||||||
|
// key: globalKey,
|
||||||
|
padding: .zero,
|
||||||
|
initialValue: v,
|
||||||
|
onSelected: (value) async {
|
||||||
|
await GStorage.setting.put(key, value.index);
|
||||||
|
if (context.mounted) {
|
||||||
|
(context as Element).markNeedsBuild();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemBuilder: (context) => values
|
||||||
|
.map((i) => PopupMenuItem(value: i, child: Text(i.label)))
|
||||||
|
.toList(),
|
||||||
|
child: Padding(
|
||||||
|
padding: const .symmetric(vertical: 8),
|
||||||
|
child: Text.rich(
|
||||||
|
style: TextStyle(fontSize: 14, height: 1, color: color),
|
||||||
|
strutStyle: const StrutStyle(leading: 0, height: 1, fontSize: 14),
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(text: v.label),
|
||||||
|
WidgetSpan(
|
||||||
|
alignment: .middle,
|
||||||
|
child: Icon(
|
||||||
|
size: 14,
|
||||||
|
MdiIcons.unfoldMoreHorizontal,
|
||||||
|
color: color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
style: TextStyle(color: color),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ import 'package:PiliPlus/models/common/video/video_quality.dart';
|
|||||||
import 'package:PiliPlus/pages/setting/models/model.dart';
|
import 'package:PiliPlus/pages/setting/models/model.dart';
|
||||||
import 'package:PiliPlus/pages/setting/widgets/ordered_multi_select_dialog.dart';
|
import 'package:PiliPlus/pages/setting/widgets/ordered_multi_select_dialog.dart';
|
||||||
import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart';
|
import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart';
|
||||||
|
import 'package:PiliPlus/plugin/pl_player/models/audio_output_type.dart';
|
||||||
import 'package:PiliPlus/plugin/pl_player/models/hwdec_type.dart';
|
import 'package:PiliPlus/plugin/pl_player/models/hwdec_type.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
import 'package:PiliPlus/utils/storage_key.dart';
|
import 'package:PiliPlus/utils/storage_key.dart';
|
||||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||||
import 'package:PiliPlus/utils/video_utils.dart';
|
import 'package:PiliPlus/utils/video_utils.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||||
@@ -317,13 +319,32 @@ List<SettingsModel> get videoSettings => [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (Platform.isAndroid)
|
if (kDebugMode || Platform.isAndroid)
|
||||||
const SwitchModel(
|
NormalModel(
|
||||||
title: '优先使用 OpenSL ES 输出音频',
|
title: '音频输出设备',
|
||||||
leading: Icon(Icons.speaker_outlined),
|
leading: const Icon(Icons.speaker_outlined),
|
||||||
subtitle: '关闭则优先使用AAudio输出音频(此项即mpv的--ao),若遇系统音效丢失、无声、音画不同步等问题请尝试打开。',
|
getSubtitle: () => '当前:${Pref.audioOutput}',
|
||||||
setKey: SettingBoxKey.useOpenSLES,
|
onTap: (context, setState) async {
|
||||||
defaultVal: false,
|
final result = await showDialog<List<String>>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return OrderedMultiSelectDialog<String>(
|
||||||
|
title: '音频输出设备',
|
||||||
|
initValues: Pref.audioOutput.split(','),
|
||||||
|
values: {
|
||||||
|
for (final e in AudioOutput.values) e.name: e.label,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result != null && result.isNotEmpty) {
|
||||||
|
await GStorage.setting.put(
|
||||||
|
SettingBoxKey.audioOutput,
|
||||||
|
result.join(','),
|
||||||
|
);
|
||||||
|
setState();
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const SwitchModel(
|
const SwitchModel(
|
||||||
title: '扩大缓冲区',
|
title: '扩大缓冲区',
|
||||||
|
|||||||
@@ -594,7 +594,7 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
|||||||
.map(
|
.map(
|
||||||
(item) => PopupMenuItem<SkipType>(
|
(item) => PopupMenuItem<SkipType>(
|
||||||
value: item,
|
value: item,
|
||||||
child: Text(item.title),
|
child: Text(item.label),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
@@ -617,7 +617,7 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
|||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: item.second.title),
|
TextSpan(text: item.second.label),
|
||||||
WidgetSpan(
|
WidgetSpan(
|
||||||
alignment: .middle,
|
alignment: .middle,
|
||||||
child: Icon(
|
child: Icon(
|
||||||
|
|||||||
@@ -659,7 +659,7 @@ class VideoDetailController extends GetxController
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
item.skipType.title,
|
item.skipType.label,
|
||||||
style: const TextStyle(fontSize: 13),
|
style: const TextStyle(fontSize: 13),
|
||||||
),
|
),
|
||||||
if (item.segment.second != 0)
|
if (item.segment.second != 0)
|
||||||
|
|||||||
@@ -796,8 +796,7 @@ class PlPlayerController {
|
|||||||
await pp.setProperty("af", "scaletempo2=max-speed=8");
|
await pp.setProperty("af", "scaletempo2=max-speed=8");
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
await pp.setProperty("volume-max", "100");
|
await pp.setProperty("volume-max", "100");
|
||||||
final ao = Pref.useOpenSLES ? "opensles,aaudio" : "aaudio,opensles";
|
await pp.setProperty("ao", Pref.audioOutput);
|
||||||
await pp.setProperty("ao", ao);
|
|
||||||
}
|
}
|
||||||
// video-sync=display-resample
|
// video-sync=display-resample
|
||||||
await pp.setProperty("video-sync", Pref.videoSync);
|
await pp.setProperty("video-sync", Pref.videoSync);
|
||||||
|
|||||||
14
lib/plugin/pl_player/models/audio_output_type.dart
Normal file
14
lib/plugin/pl_player/models/audio_output_type.dart
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import 'package:PiliPlus/models/common/enum_with_label.dart';
|
||||||
|
|
||||||
|
enum AudioOutput implements EnumWithLabel {
|
||||||
|
aaudio('AAudio'),
|
||||||
|
opensles('OpenSL ES'),
|
||||||
|
audiotrack('AudioTrack')
|
||||||
|
;
|
||||||
|
|
||||||
|
static final defaultValue = values.map((e) => e.name).join(',');
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String label;
|
||||||
|
const AudioOutput(this.label);
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ abstract final class SettingBoxKey {
|
|||||||
defaultToastOp = 'defaultToastOp',
|
defaultToastOp = 'defaultToastOp',
|
||||||
defaultPicQa = 'defaultPicQa',
|
defaultPicQa = 'defaultPicQa',
|
||||||
enableHA = 'enableHA',
|
enableHA = 'enableHA',
|
||||||
useOpenSLES = 'useOpenSLES',
|
audioOutput = 'audioOutput',
|
||||||
expandBuffer = 'expandBuffer',
|
expandBuffer = 'expandBuffer',
|
||||||
hardwareDecoding = 'hardwareDecoding',
|
hardwareDecoding = 'hardwareDecoding',
|
||||||
videoSync = 'videoSync',
|
videoSync = 'videoSync',
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import 'package:PiliPlus/models/common/video/video_decode_type.dart';
|
|||||||
import 'package:PiliPlus/models/common/video/video_quality.dart';
|
import 'package:PiliPlus/models/common/video/video_quality.dart';
|
||||||
import 'package:PiliPlus/models/user/danmaku_rule.dart';
|
import 'package:PiliPlus/models/user/danmaku_rule.dart';
|
||||||
import 'package:PiliPlus/models/user/info.dart';
|
import 'package:PiliPlus/models/user/info.dart';
|
||||||
|
import 'package:PiliPlus/plugin/pl_player/models/audio_output_type.dart';
|
||||||
import 'package:PiliPlus/plugin/pl_player/models/bottom_progress_behavior.dart';
|
import 'package:PiliPlus/plugin/pl_player/models/bottom_progress_behavior.dart';
|
||||||
import 'package:PiliPlus/plugin/pl_player/models/fullscreen_mode.dart';
|
import 'package:PiliPlus/plugin/pl_player/models/fullscreen_mode.dart';
|
||||||
import 'package:PiliPlus/plugin/pl_player/models/hwdec_type.dart';
|
import 'package:PiliPlus/plugin/pl_player/models/hwdec_type.dart';
|
||||||
@@ -786,8 +787,10 @@ abstract final class Pref {
|
|||||||
static bool get expandBuffer =>
|
static bool get expandBuffer =>
|
||||||
_setting.get(SettingBoxKey.expandBuffer, defaultValue: false);
|
_setting.get(SettingBoxKey.expandBuffer, defaultValue: false);
|
||||||
|
|
||||||
static bool get useOpenSLES =>
|
static String get audioOutput => _setting.get(
|
||||||
_setting.get(SettingBoxKey.useOpenSLES, defaultValue: false);
|
SettingBoxKey.audioOutput,
|
||||||
|
defaultValue: AudioOutput.defaultValue,
|
||||||
|
);
|
||||||
|
|
||||||
static bool get enableAi =>
|
static bool get enableAi =>
|
||||||
_setting.get(SettingBoxKey.enableAi, defaultValue: false);
|
_setting.get(SettingBoxKey.enableAi, defaultValue: false);
|
||||||
|
|||||||
Reference in New Issue
Block a user