feat(player): handle stop/skip/speed media-session commands
The platforms advertise stop, skip forward/backward, and playback-rate commands by default, but both the music and video handlers silently dropped them (Android Auto/Bluetooth stop and FF/rewind did nothing; iOS/macOS showed a dead rate control). setControlsEnabled now manages those controls: music handles Stop and in-track skips and stops advertising a speed control; video handles Stop (exit, matching the companion remote), skips via a shared relative-seek helper, and rate changes through player.setRate. Skip commands stay off on iOS/macOS where they would displace the next/previous lock-screen buttons. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
73be8ab1c8
commit
28bc4a5df8
@@ -1,5 +1,9 @@
|
||||
part of '../../video_player_screen.dart';
|
||||
|
||||
/// Fallback for OS skip commands that arrive without an interval (the
|
||||
/// platforms normally send one — Android hardcodes 15s).
|
||||
const _defaultMediaControlSkip = Duration(seconds: 15);
|
||||
|
||||
extension _VideoPlayerPlaybackServiceMethods on VideoPlayerScreenState {
|
||||
void _queueScrubPreviewLoad({
|
||||
required MediaItem metadata,
|
||||
@@ -331,6 +335,21 @@ extension _VideoPlayerPlaybackServiceMethods on VideoPlayerScreenState {
|
||||
} else if (event is PreviousTrackEvent) {
|
||||
appLogger.d('Media control: Previous track event received');
|
||||
unawaited(_restartOrPlayPrevious());
|
||||
} else if (event is StopEvent) {
|
||||
// Same semantics as the companion remote's stop: exit the player.
|
||||
appLogger.d('Media control: Stop event received');
|
||||
unawaited(_handleBackButton());
|
||||
} else if (event is SkipForwardEvent) {
|
||||
appLogger.d('Media control: Skip forward event received (${event.interval})');
|
||||
unawaited(_seekRelative(event.interval ?? _defaultMediaControlSkip));
|
||||
} else if (event is SkipBackwardEvent) {
|
||||
appLogger.d('Media control: Skip backward event received (${event.interval})');
|
||||
unawaited(_seekRelative(-(event.interval ?? _defaultMediaControlSkip)));
|
||||
} else if (event is SetSpeedEvent) {
|
||||
// UI, Discord, and the media-session state all follow reactively
|
||||
// via streams.rate — same unguarded path as keyboard shortcuts.
|
||||
appLogger.d('Media control: Set speed event received (${event.speed}x)');
|
||||
unawaited(activePlayer!.setRate(event.speed));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user