diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index abee46cf8..c14008d59 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -282,6 +282,41 @@ class PlPlayerController { } } + static bool instanceExists() { + return _instance != null; + } + + static Future playIfExists( + {bool repeat = false, bool hideControls = true, dynamic duration}) async { + await _instance?.play( + repeat: repeat, hideControls: hideControls, duration: duration); + } + + // try to get PlayerStatus + static PlayerStatus? getPlayerStatusIfExists() { + return _instance?.playerStatus.status.value; + } + + static Future pauseIfExists( + {bool notify = true, bool isInterrupt = false}) async { + if (_instance?.playerStatus.status.value == PlayerStatus.playing) { + await _instance?.pause(notify: notify, isInterrupt: isInterrupt); + } + } + + static Future seekToIfExists(Duration position, {type = 'seek'}) async { + await _instance?.seekTo(position, type: type); + } + + static double? getVolumeIfExists() { + return _instance?.volume.value; + } + + static Future setVolumeIfExists(double volumeNew, + {bool videoPlayerVolume = false}) async { + await _instance?.setVolume(volumeNew, videoPlayerVolume: videoPlayerVolume); + } + // 添加一个私有构造函数 PlPlayerController._() { _videoType = videoType; @@ -439,8 +474,9 @@ class PlPlayerController { } }); } - } catch (err) { + } catch (err, stackTrace) { dataStatus.status.value = DataStatus.error; + debugPrint(stackTrace.toString()); print('plPlayer err: $err'); } } @@ -564,6 +600,7 @@ class PlPlayerController { Duration seekTo = Duration.zero, Duration? duration, }) async { + if (_instance == null) return; // 设置倍速 if (videoType.value == 'live') { await setPlaybackSpeed(1.0); @@ -586,7 +623,8 @@ class PlPlayerController { // 自动播放 if (_autoPlay) { - await play(duration: duration); + await playIfExists(duration: duration); + // await play(duration: duration); } } @@ -781,6 +819,7 @@ class PlPlayerController { /// TODO _duration.value丢失 Future play( {bool repeat = false, bool hideControls = true, dynamic duration}) async { + if (_playerCount.value == 0) return; // 播放时自动隐藏控制条 controls = !hideControls; // repeat为true,将从头播放 @@ -1237,10 +1276,12 @@ class PlPlayerController { return; } Map s = _vttSubtitles[index]; + debugPrint(s['text']); _videoPlayerController?.setSubtitleTrack(SubtitleTrack.data( s['text']!, title: s['title']!, language: s['language']!, )); + _vttSubtitlesIndex.value = index; } } diff --git a/lib/services/audio_handler.dart b/lib/services/audio_handler.dart index 3a7e69fba..66ee0fb3f 100644 --- a/lib/services/audio_handler.dart +++ b/lib/services/audio_handler.dart @@ -1,4 +1,6 @@ +import 'package:PiliPalaX/models/danmaku/dm.pb.dart'; import 'package:audio_service/audio_service.dart'; +import 'package:flutter/cupertino.dart'; import 'package:hive/hive.dart'; import 'package:PiliPalaX/models/bangumi/info.dart'; import 'package:PiliPalaX/models/video_detail_res.dart'; @@ -26,7 +28,7 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { static final List _item = []; Box setting = GStrorage.setting; bool enableBackgroundPlay = true; - PlPlayerController player = PlPlayerController.getInstance(); + // PlPlayerController player = PlPlayerController.getInstance(); VideoPlayerServiceHandler() { revalidateSetting(); @@ -39,12 +41,14 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { @override Future play() async { - player.play(); + await PlPlayerController.playIfExists(); + // player.play(); } @override Future pause() async { - player.pause(); + await PlPlayerController.pauseIfExists(); + // player.pause(); } @override @@ -52,12 +56,17 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { playbackState.add(playbackState.value.copyWith( updatePosition: position, )); - await player.seekTo(position); + await PlPlayerController.seekToIfExists(position); + // await player.seekTo(position); } Future setMediaItem(MediaItem newMediaItem) async { if (!enableBackgroundPlay) return; - mediaItem.add(newMediaItem); + // print("此时调用栈为:"); + // print(newMediaItem); + // print(newMediaItem.title); + // debugPrint(StackTrace.current.toString()); + if(!mediaItem.isClosed) mediaItem.add(newMediaItem); } Future setPlaybackState(PlayerStatus status, bool isBuffering) async { @@ -99,9 +108,11 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { onVideoDetailChange(dynamic data, int cid) { if (!enableBackgroundPlay) return; - + // print('当前调用栈为:'); + // print(StackTrace.current); + if (!PlPlayerController.instanceExists()) return; if (data == null) return; - if (Get.arguments == null) return; + if (Get.arguments == null || Get.arguments['heroTag'] == null) return; final heroTag = Get.arguments['heroTag']; late MediaItem? mediaItem; @@ -137,6 +148,8 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { ); } if (mediaItem == null) return; + print("exist: ${PlPlayerController.instanceExists()}"); + if (!PlPlayerController.instanceExists()) return; setMediaItem(mediaItem); _item.add(mediaItem); } @@ -153,10 +166,8 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { } if (_item.isNotEmpty) { setMediaItem(_item.last); - } - if (_item.isEmpty) { - playbackState - .add(playbackState.value.copyWith(updatePosition: Duration.zero)); + } else { + mediaItem?.close(); } stop(); } diff --git a/lib/services/audio_session.dart b/lib/services/audio_session.dart index 3f83d3202..5a362026f 100644 --- a/lib/services/audio_session.dart +++ b/lib/services/audio_session.dart @@ -18,29 +18,38 @@ class AudioSessionHandler { session.configure(const AudioSessionConfiguration.music()); session.interruptionEventStream.listen((event) { - final player = PlPlayerController.getInstance(); + final playerStatus = PlPlayerController.getPlayerStatusIfExists(); + // final player = PlPlayerController.getInstance(); if (event.begin) { - if (!player.playerStatus.playing) return; + if (playerStatus != PlayerStatus.playing) return; + // if (!player.playerStatus.playing) return; switch (event.type) { case AudioInterruptionType.duck: - player.setVolume(player.volume.value * 0.5); + PlPlayerController.setVolumeIfExists( + (PlPlayerController.getVolumeIfExists() ?? 0) * 0.5); + // player.setVolume(player.volume.value * 0.5); break; case AudioInterruptionType.pause: - player.pause(isInterrupt: true); + PlPlayerController.pauseIfExists(isInterrupt: true); + // player.pause(isInterrupt: true); _playInterrupted = true; break; case AudioInterruptionType.unknown: - player.pause(isInterrupt: true); + PlPlayerController.pauseIfExists(isInterrupt: true); + // player.pause(isInterrupt: true); _playInterrupted = true; break; } } else { switch (event.type) { case AudioInterruptionType.duck: - player.setVolume(player.volume.value * 2); + PlPlayerController.setVolumeIfExists( + (PlPlayerController.getVolumeIfExists() ?? 0) * 2); + // player.setVolume(player.volume.value * 2); break; case AudioInterruptionType.pause: - if (_playInterrupted) player.play(); + if (_playInterrupted) PlPlayerController.playIfExists(); + //player.play(); break; case AudioInterruptionType.unknown: break; @@ -51,10 +60,11 @@ class AudioSessionHandler { // 耳机拔出暂停 session.becomingNoisyEventStream.listen((_) { - final player = PlPlayerController.getInstance(); - if (player.playerStatus.playing) { - player.pause(); - } + PlPlayerController.pauseIfExists(); + // final player = PlPlayerController.getInstance(); + // if (player.playerStatus.playing) { + // player.pause(); + // } }); } } diff --git a/lib/services/shutdown_timer_service.dart b/lib/services/shutdown_timer_service.dart index aa9c5ceb2..825ad232b 100644 --- a/lib/services/shutdown_timer_service.dart +++ b/lib/services/shutdown_timer_service.dart @@ -1,6 +1,7 @@ // 定时关闭服务 import 'dart:async'; import 'dart:io'; +import 'package:PiliPalaX/plugin/pl_player/index.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -29,8 +30,8 @@ class ShutdownTimerService { return; } SmartDialog.showToast("设置 $scheduledExitInMinutes 分钟后定时关闭"); - _shutdownTimer = Timer(Duration(minutes: scheduledExitInMinutes), - () => _shutdownDecider()); + _shutdownTimer = Timer( + Duration(minutes: scheduledExitInMinutes), () => _shutdownDecider()); } void _showTimeUpButPauseDialog() { @@ -59,7 +60,7 @@ class ShutdownTimerService { // Start the 10-second timer to auto close the dialog _autoCloseDialogTimer?.cancel(); _autoCloseDialogTimer = Timer(const Duration(seconds: 10), () { - SmartDialog.dismiss();// Close the dialog + SmartDialog.dismiss(); // Close the dialog _executeShutdown(); }); return AlertDialog( @@ -88,9 +89,12 @@ class ShutdownTimerService { _showShutdownDialog(); return; } - PlPlayerController plPlayerController = PlPlayerController.getInstance(); + // PlPlayerController plPlayerController = PlPlayerController.getInstance(); + PlayerStatus? playerStatus = PlPlayerController.getPlayerStatusIfExists(); if (!exitApp && !waitForPlayingCompleted) { - if (!plPlayerController.playerStatus.playing) { + // if (!plPlayerController.playerStatus.playing) { + if (playerStatus == PlayerStatus.paused || + playerStatus == PlayerStatus.completed) { //仅提示用户 _showTimeUpButPauseDialog(); } else { @@ -99,7 +103,9 @@ class ShutdownTimerService { return; } //waitForPlayingCompleted - if (!plPlayerController.playerStatus.playing) { + if (playerStatus == PlayerStatus.paused || + playerStatus == PlayerStatus.completed) { + // if (!plPlayerController.playerStatus.playing) { _showShutdownDialog(); return; } @@ -108,26 +114,36 @@ class ShutdownTimerService { //该方法依赖耦合实现,不够优雅 isWaiting = true; } - void handleWaitingFinished(){ - if(isWaiting){ + + void handleWaitingFinished() { + if (isWaiting) { _showShutdownDialog(); isWaiting = false; } } + void _executeShutdown() { if (exitApp) { //退出app exit(0); } else { //暂停播放 - PlPlayerController plPlayerController = PlPlayerController.getInstance(); - if (plPlayerController.playerStatus.playing) { - plPlayerController.pause(); + PlayerStatus? playerStatus = PlPlayerController.getPlayerStatusIfExists(); + if (playerStatus == PlayerStatus.playing) { + PlPlayerController.pauseIfExists(); waitForPlayingCompleted = true; SmartDialog.showToast("已暂停播放"); } else { SmartDialog.showToast("当前未播放"); } + // PlPlayerController plPlayerController = PlPlayerController.getInstance(); + // if (plPlayerController.playerStatus.playing) { + // plPlayerController.pause(); + // waitForPlayingCompleted = true; + // SmartDialog.showToast("已暂停播放"); + // } else { + // SmartDialog.showToast("当前未播放"); + // } } }