Skip to content

Commit

Permalink
feat: add playback speed button
Browse files Browse the repository at this point in the history
  • Loading branch information
nini22P committed Feb 23, 2025
1 parent 34457db commit 324ba10
Show file tree
Hide file tree
Showing 14 changed files with 224 additions and 27 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## v1.3.4

### Changelog

* The Android version allows you to set the screen orientation.
* Add playback speed button.
* Add hotkeys: Step forward `+`, Step backward `-`.

### 更新日志

* 安卓版本可以设置屏幕方向。
* 添加播放速度按钮。
* 添加快捷键:帧进 `+`,帧退 `-`


## v1.3.3

### Changelog
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ English | [中文](./README_CN.md)
| `Ctrl + C` | Close currently media file |
| `Ctrl + H` | Play history |
| `Ctrl + P` | Settings |
| `+` | Step forward |
| `-` | Step backward |
| `Enter` | Enter full screen / Exit full screen / Select file |
| `F11` | Enter full screen / Exit full screen |
| `Esc` | Exit current Menu / Go back / Exit full screen |
Expand Down
2 changes: 2 additions & 0 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
| `Ctrl + C` | 关闭当前媒体文件 |
| `Ctrl + H` | 播放历史 |
| `Ctrl + P` | 设置 |
| `+` | 帧进 |
| `-` | 帧退 |
| `Enter` | 进入全屏 / 退出全屏 / 选择文件 |
| `F11` | 进入全屏 / 退出全屏 |
| `Esc` | 退出当前菜单 / 返回上一级 / 关闭全屏 |
Expand Down
13 changes: 9 additions & 4 deletions lib/hooks/use_fvp_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import 'package:wakelock_plus/wakelock_plus.dart';

FvpPlayer useFvpPlayer(BuildContext context) {
final autoPlay = useAppStore().select(context, (state) => state.autoPlay);
final rate = useAppStore().select(context, (state) => state.rate);
final volume = useAppStore().select(context, (state) => state.volume);
final isMuted = useAppStore().select(context, (state) => state.isMuted);
final repeat = useAppStore().select(context, (state) => state.repeat);
Expand Down Expand Up @@ -91,6 +92,7 @@ FvpPlayer useFvpPlayer(BuildContext context) {
try {
await controller.initialize();
await controller.setLooping(repeat == Repeat.one ? true : false);
await controller.setPlaybackSpeed(rate);
await controller.setVolume(isMuted ? 0 : volume / 100);
} catch (e) {
logger('Error initializing player: $e');
Expand All @@ -115,8 +117,6 @@ FvpPlayer useFvpPlayer(BuildContext context) {
useListenableSelector(controller, () => controller.value.position);
final buffered =
useListenableSelector(controller, () => controller.value.buffered);
final playbackSpeed =
useListenableSelector(controller, () => controller.value.playbackSpeed);
final size = useListenableSelector(controller, () => controller.value.size);
final isCompleted =
useListenableSelector(controller, () => controller.value.isCompleted);
Expand Down Expand Up @@ -187,6 +187,13 @@ FvpPlayer useFvpPlayer(BuildContext context) {
return;
}, [isCompleted]);

useEffect(() {
if (controller.value.isInitialized) {
controller.setPlaybackSpeed(rate);
}
return;
}, [rate]);

useEffect(() {
if (controller.value.isInitialized) {
controller.setVolume(isMuted ? 0 : volume / 100);
Expand Down Expand Up @@ -299,7 +306,6 @@ FvpPlayer useFvpPlayer(BuildContext context) {
aspect: aspect,
width: size.width,
height: size.height,
rate: playbackSpeed,
play: play,
pause: pause,
backward: (seconds) =>
Expand All @@ -308,7 +314,6 @@ FvpPlayer useFvpPlayer(BuildContext context) {
seekTo(Duration(seconds: position.inSeconds + seconds)),
stepBackward: stepBackward,
stepForward: stepForward,
updateRate: (value) => controller.setPlaybackSpeed(value),
seekTo: seekTo,
saveProgress: saveProgress,
seeking: seeking.value,
Expand Down
14 changes: 8 additions & 6 deletions lib/hooks/use_media_kit_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ MediaKitPlayer useMediaKitPlayer(BuildContext context) {

final controller = useMemoized(() => VideoController(player));

final rate = useAppStore().select(context, (state) => state.rate);
final volume = useAppStore().select(context, (state) => state.volume);
final isMuted = useAppStore().select(context, (state) => state.isMuted);

useEffect(() {
() async {
player.setSubtitleTrack(SubtitleTrack.no());
player.setRate(rate);
player.setVolume(isMuted ? 0 : volume.toDouble());

if (Platform.isAndroid) {
Expand Down Expand Up @@ -95,7 +97,7 @@ MediaKitPlayer useMediaKitPlayer(BuildContext context) {
Duration duration = useStream(player.stream.duration).data ?? Duration.zero;
Duration buffer = useStream(player.stream.buffer).data ?? Duration.zero;
bool completed = useStream(player.stream.completed).data ?? false;
double rate = useStream(player.stream.rate).data ?? 1.0;
// double rate = useStream(player.stream.rate).data ?? 1.0;

Track? track = useStream(player.stream.track).data;
AudioTrack audio =
Expand Down Expand Up @@ -227,6 +229,11 @@ MediaKitPlayer useMediaKitPlayer(BuildContext context) {
return null;
}, [completed, repeat]);

useEffect(() {
player.setRate(rate);
return;
}, [rate]);

useEffect(() {
player.setVolume(isMuted ? 0 : volume.toDouble());
return;
Expand Down Expand Up @@ -309,9 +316,6 @@ MediaKitPlayer useMediaKitPlayer(BuildContext context) {
}
}

Future<void> updateRate(double value) async =>
player.state.rate == value ? null : await player.setRate(value);

return MediaKitPlayer(
player: player,
controller: controller,
Expand All @@ -326,7 +330,6 @@ MediaKitPlayer useMediaKitPlayer(BuildContext context) {
duration: duration,
buffer: duration == Duration.zero ? Duration.zero : buffer,
seeking: seeking.value,
rate: rate,
aspect: videoParams?.aspect,
width: videoParams?.w?.toDouble(),
height: videoParams?.h?.toDouble(),
Expand All @@ -339,7 +342,6 @@ MediaKitPlayer useMediaKitPlayer(BuildContext context) {
forward: forward,
stepBackward: stepBackward,
stepForward: stepForward,
updateRate: updateRate,
seekTo: seekTo,
);
}
1 change: 1 addition & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"pause": "Pause",
"play": "Play",
"play_queue": "Play queue",
"playback_speed": "Playback speed",
"player_backend": "Player backend",
"port": "Port",
"portrait": "Portrait",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_zh.arb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"pause": "暂停",
"play": "播放",
"play_queue": "播放队列",
"playback_speed": "播放速度",
"player_backend": "播放器后端",
"port": "端口",
"portrait": "纵向",
Expand Down
8 changes: 0 additions & 8 deletions lib/models/player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class MediaPlayer {
final Duration duration;
final Duration buffer;
final bool seeking;
final double rate;
final double? aspect;
final double? width;
final double? height;
Expand All @@ -25,7 +24,6 @@ class MediaPlayer {
final Future<void> Function(int) forward;
final Future<void> Function() stepBackward;
final Future<void> Function() stepForward;
final Future<void> Function(double) updateRate;
final Future<void> Function(Duration) seekTo;

MediaPlayer({
Expand All @@ -36,7 +34,6 @@ class MediaPlayer {
required this.duration,
required this.buffer,
required this.seeking,
required this.rate,
required this.aspect,
required this.width,
required this.height,
Expand All @@ -49,7 +46,6 @@ class MediaPlayer {
required this.forward,
required this.stepBackward,
required this.stepForward,
required this.updateRate,
required this.seekTo,
});
}
Expand All @@ -76,7 +72,6 @@ class MediaKitPlayer extends MediaPlayer {
required super.duration,
required super.buffer,
required super.seeking,
required super.rate,
required super.aspect,
required super.width,
required super.height,
Expand All @@ -89,7 +84,6 @@ class MediaKitPlayer extends MediaPlayer {
required super.forward,
required super.stepBackward,
required super.stepForward,
required super.updateRate,
required super.seekTo,
});
}
Expand All @@ -108,7 +102,6 @@ class FvpPlayer extends MediaPlayer {
required super.duration,
required super.buffer,
required super.seeking,
required super.rate,
required super.aspect,
required super.width,
required super.height,
Expand All @@ -121,7 +114,6 @@ class FvpPlayer extends MediaPlayer {
required super.forward,
required super.stepBackward,
required super.stepForward,
required super.updateRate,
required super.seekTo,
});
}
1 change: 1 addition & 0 deletions lib/models/store/app_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class AppState with _$AppState {
@Default(false) bool shuffle,
@Default(Repeat.none) Repeat repeat,
@Default(BoxFit.contain) BoxFit fit,
@Default(1) double rate,
@Default(80) int volume,
@Default(false) bool isMuted,
@Default(ThemeMode.system) ThemeMode themeMode,
Expand Down
65 changes: 65 additions & 0 deletions lib/pages/dialog/show_rate_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_zustand/flutter_zustand.dart';
import 'package:iris/store/use_app_store.dart';
import 'package:iris/utils/get_localizations.dart';

Future<void> showRateDialog(BuildContext context) async =>
await showDialog<void>(
context: context,
builder: (context) => const RateDialog(),
);

class RateDialog extends HookWidget {
const RateDialog({super.key});

@override
Widget build(BuildContext context) {
final t = getLocalizations(context);
final rate = useAppStore().select(context, (state) => state.rate);

void updateRate(double rate) {
useAppStore().updateRate(rate);
Navigator.pop(context);
}

return AlertDialog(
title: Text(t.playback_speed),
content: SingleChildScrollView(
child: Column(
children: [
0.25,
0.5,
0.75,
1.0,
1.25,
1.5,
1.75,
2.0,
3.0,
4.0,
5.0,
]
.map(
(item) => ListTile(
title: Text('${item}X'),
leading: Radio(
value: item,
groupValue: rate,
onChanged: (_) => updateRate(item),
),
onTap: () => updateRate(item),
),
)
.toList(),
),
),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'Cancel'),
child: Text(t.cancel),
),
],
);
}
}
Loading

0 comments on commit 324ba10

Please sign in to comment.