From 71a170deb595bf9d97cba9a21e160de8ec9c9b9c Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Sun, 19 Oct 2025 11:24:14 +0800 Subject: [PATCH] audio notification Closes #1635 Signed-off-by: bggRGjQaUbCoE --- lib/pages/audio/controller.dart | 38 +++++++++++++++++++++++++++++++++ lib/plugin/pl_player/view.dart | 7 ++++-- lib/services/audio_handler.dart | 20 ++++++++++++++--- 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/lib/pages/audio/controller.dart b/lib/pages/audio/controller.dart index 272dd9df..259b14fc 100644 --- a/lib/pages/audio/controller.dart +++ b/lib/pages/audio/controller.dart @@ -20,6 +20,8 @@ import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/pages/video/introduction/ugc/widgets/triple_mixin.dart'; import 'package:PiliPlus/pages/video/pay_coins/view.dart'; import 'package:PiliPlus/plugin/pl_player/models/play_repeat.dart'; +import 'package:PiliPlus/plugin/pl_player/models/play_status.dart'; +import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/global_data.dart'; @@ -114,6 +116,22 @@ class AudioController extends GetxController _queryPlayUrl(); } }); + videoPlayerServiceHandler + ?..onPlay = onPlay + ..onPause = onPause + ..onSeek = onSeek; + } + + Future onPlay() async { + await player?.play(); + } + + Future onPause() async { + await player?.pause(); + } + + Future onSeek(Duration duration) async { + await player?.seek(duration); } void _updateCurrItem(DetailItem item) { @@ -121,6 +139,11 @@ class AudioController extends GetxController hasLike.value = item.stat.hasLike_7; coinNum.value = item.stat.hasCoin_8 ? 2 : 0; hasFav.value = item.stat.hasFav; + videoPlayerServiceHandler?.onVideoDetailChange( + item, + (subId.firstOrNull ?? oid).toInt(), + hashCode.toString(), + ); } Future _queryPlayList({ @@ -240,20 +263,30 @@ class AudioController extends GetxController if (position.inSeconds != this.position.value.inSeconds) { this.position.value = position; _videoDetailController?.playedTime = position; + videoPlayerServiceHandler?.onPositionChange(position); } }), player!.stream.duration.listen((duration) { this.duration.value = duration; }), player!.stream.playing.listen((playing) { + PlayerStatus playerStatus; if (playing) { animController.forward(); + playerStatus = PlayerStatus.playing; } else { animController.reverse(); + playerStatus = PlayerStatus.paused; } + videoPlayerServiceHandler?.onStatusChange(playerStatus, false, false); }), player!.stream.completed.listen((completed) { _videoDetailController?.playedTime = duration.value; + videoPlayerServiceHandler?.onStatusChange( + PlayerStatus.completed, + false, + false, + ); if (completed) { switch (playMode.value) { case PlayRepeat.pause: @@ -614,6 +647,11 @@ class AudioController extends GetxController @override void onClose() { // _cancelTimer(); + videoPlayerServiceHandler + ?..onPlay = null + ..onPause = null + ..onSeek = null + ..onVideoDetailDispose(hashCode.toString()); _subscriptions?.forEach((e) => e.cancel()); _subscriptions = null; player?.dispose(); diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 71161075..68599420 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -1171,7 +1171,11 @@ class _PLVideoPlayerState extends State LongPressGestureRecognizer? _longPressRecognizer; LongPressGestureRecognizer get longPressRecognizer => _longPressRecognizer ??= - LongPressGestureRecognizer(duration: const Duration(milliseconds: 300)) + LongPressGestureRecognizer( + duration: plPlayerController.enableTapDm + ? const Duration(milliseconds: 300) + : null, + ) ..onLongPressStart = ((_) => plPlayerController.setLongPressStatus(true)) ..onLongPressEnd = (_) => plPlayerController.setLongPressStatus(false); @@ -1318,7 +1322,6 @@ class _PLVideoPlayerState extends State if (!isLive) Positioned.fill( - top: 4, child: IgnorePointer( ignoring: !plPlayerController.enableDragSubtitle, child: Obx( diff --git a/lib/services/audio_handler.dart b/lib/services/audio_handler.dart index 2bd17d35..32258add 100644 --- a/lib/services/audio_handler.dart +++ b/lib/services/audio_handler.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/grpc/bilibili/app/listener/v1.pb.dart' show DetailItem; import 'package:PiliPlus/models_new/live/live_room_info_h5/data.dart'; import 'package:PiliPlus/models_new/pgc/pgc_info_model/episode.dart'; import 'package:PiliPlus/models_new/video/video_detail/data.dart'; @@ -29,15 +30,19 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { static final List _item = []; bool enableBackgroundPlay = Pref.enableBackgroundPlay; + Function? onPlay; + Function? onPause; + Function(Duration position)? onSeek; + @override Future play() async { - PlPlayerController.playIfExists(); + onPlay?.call() ?? PlPlayerController.playIfExists(); // player.play(); } @override Future pause() async { - await PlPlayerController.pauseIfExists(); + await (onPause?.call() ?? PlPlayerController.pauseIfExists()); // player.pause(); } @@ -48,7 +53,8 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { updatePosition: position, ), ); - await PlPlayerController.seekToIfExists(position, isSeek: false); + await (onSeek?.call(position) ?? + PlPlayerController.seekToIfExists(position, isSeek: false)); // await player.seekTo(position); } @@ -179,6 +185,14 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { duration: Duration(seconds: data.duration ?? 0), artUri: Uri.parse(cover ?? ''), ); + } else if (data is DetailItem) { + mediaItem = MediaItem( + id: id, + title: data.arc.title, + artist: data.owner.name, + duration: Duration(seconds: data.arc.duration.toInt()), + artUri: Uri.parse(data.arc.cover), + ); } if (mediaItem == null) return; // if (kDebugMode) debugPrint("exist: ${PlPlayerController.instanceExists()}");