Skip to content

Commit 3f15767

Browse files
committed
feat(player): configurable play/pause fade duration
The play/pause volume fade was hardcoded to 175ms, which delays the actual mpv pause until the fade completes and makes toggling playback feel sluggish compared to native players like mpc/mpv. Expose the fade length as a 'Play/pause fade duration' setting (0-1000ms) shown beneath the existing fade toggle. A value of 0 (or any duration shorter than one fade step) now skips the fade entirely and hits mpv immediately for an instant, snappy response. Default stays at 175ms to preserve current behaviour.
1 parent 50867e2 commit 3f15767

7 files changed

Lines changed: 87 additions & 6 deletions

File tree

lib/l10n/app_en.arb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,10 @@
984984
"@settingsPlayerPlayPauseFadeTitle": {},
985985
"settingsPlayerPlayPauseFadeDesc": "Fade volume in and out when playing or pausing",
986986
"@settingsPlayerPlayPauseFadeDesc": {},
987+
"settingsPlayerPlayPauseFadeDurationTitle": "Play/pause fade duration",
988+
"@settingsPlayerPlayPauseFadeDurationTitle": {},
989+
"settingsPlayerPlayPauseFadeDurationDesc": "How long the volume fade takes when playing or pausing. Lower values feel snappier; set to 0 for an instant response.",
990+
"@settingsPlayerPlayPauseFadeDurationDesc": {},
987991
"settingsPlayerBufferSizeDesc": "Configure the buffer size for video playback, determining how much data is loaded into the cache.",
988992
"@settingsPlayerBufferSizeDesc": {},
989993
"settingsPlayerTitle": "Player",

lib/models/settings/video_player_settings.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ abstract class VideoPlayerSettingsModel with _$VideoPlayerSettingsModel {
108108
@Default(true) bool enableReplayGain,
109109
@Default(ReplayGainVolumeLevel.quiet) ReplayGainVolumeLevel replayGainVolumeLevel,
110110
@Default(true) bool enablePlayPauseFade,
111+
@Default(175) int playPauseFadeDurationMs,
111112
@Default(true) bool enableCrossfade,
112113
@Default(400) int crossfadeDurationMs,
113114
}) = _VideoPlayerSettingsModel;

lib/models/settings/video_player_settings.freezed.dart

Lines changed: 29 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/models/settings/video_player_settings.g.dart

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/providers/settings/video_player_settings_provider.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ class VideoPlayerSettingsProviderNotifier extends StateNotifier<VideoPlayerSetti
187187

188188
void setEnablePlayPauseFade(bool value) => state = state.copyWith(enablePlayPauseFade: value);
189189

190+
void setPlayPauseFadeDurationMs(int value) =>
191+
state = state.copyWith(playPauseFadeDurationMs: value.clamp(0, 1000));
192+
190193
void setReplayGainVolumeLevel(ReplayGainVolumeLevel value) => state = state.copyWith(replayGainVolumeLevel: value);
191194

192195
void setEnableCrossfade(bool value) {

lib/screens/settings/player_settings_page.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,44 @@ class _PlayerSettingsPageState extends ConsumerState<PlayerSettingsPage> {
437437
onChanged: (value) => provider.setEnablePlayPauseFade(value),
438438
),
439439
),
440+
if (currentPlayer == PlayerOptions.libMPV && videoSettings.enablePlayPauseFade)
441+
Padding(
442+
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
443+
child: Column(
444+
crossAxisAlignment: CrossAxisAlignment.start,
445+
children: [
446+
Text(
447+
context.localized.settingsPlayerPlayPauseFadeDurationTitle,
448+
style: Theme.of(context).textTheme.titleLarge,
449+
),
450+
Padding(
451+
padding: const EdgeInsets.only(bottom: 8),
452+
child: Text(
453+
context.localized.settingsPlayerPlayPauseFadeDurationDesc,
454+
style: Theme.of(context).textTheme.bodyMedium,
455+
),
456+
),
457+
Row(
458+
children: [
459+
Expanded(
460+
child: FladderSlider(
461+
min: 0,
462+
max: 1000,
463+
value: videoSettings.playPauseFadeDurationMs.toDouble(),
464+
divisions: 40,
465+
onChanged: (value) => provider.setPlayPauseFadeDurationMs(value.round()),
466+
),
467+
),
468+
const SizedBox(width: 12),
469+
Text(
470+
'${videoSettings.playPauseFadeDurationMs} ms',
471+
style: Theme.of(context).textTheme.bodyLarge,
472+
),
473+
],
474+
),
475+
],
476+
),
477+
),
440478
if (currentPlayer == PlayerOptions.libMPV)
441479
SettingsListTile(
442480
label: Text(context.localized.settingsPlayerBufferSizeTitle),

lib/wrappers/players/lib_mpv.dart

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class LibMPV extends BasePlayer {
4646
double _preferredVolume = 100;
4747
int _crossfadeGeneration = 0;
4848
Timer? _fadeTimer;
49-
Duration get playPauseFadeDuration => const Duration(milliseconds: 175);
49+
Duration get playPauseFadeDuration => Duration(milliseconds: _settings.playPauseFadeDurationMs);
5050

5151
@override
5252
Future<void> init(VideoPlayerSettingsModel settings) async {
@@ -372,17 +372,22 @@ class LibMPV extends BasePlayer {
372372

373373
_fadeTimer?.cancel();
374374

375-
if (!_settings.enablePlayPauseFade) {
375+
const stepMs = 16;
376+
final steps = playPauseFadeDuration.inMilliseconds ~/ stepMs;
377+
378+
// Skip the fade entirely when disabled or the configured duration is too
379+
// short to produce at least one step. This makes play/pause hit mpv
380+
// immediately for a snappy, mpc-like response.
381+
if (!_settings.enablePlayPauseFade || steps <= 0) {
376382
if (fadingIn) {
383+
player.setVolume(_preferredVolume);
377384
player.play();
378385
} else {
379386
player.pause();
380387
}
381388
return;
382389
}
383390

384-
const stepMs = 16;
385-
final steps = playPauseFadeDuration.inMilliseconds ~/ stepMs;
386391
final stepSize = _preferredVolume / steps;
387392

388393
if (fadingIn) player.play();

0 commit comments

Comments
 (0)