|
@@ -261,6 +261,8 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
private lastUpdateTime: number=0;
|
|
private lastUpdateTime: number=0;
|
|
|
private favList: VideoItem[]=[];
|
|
private favList: VideoItem[]=[];
|
|
|
table: undefined;
|
|
table: undefined;
|
|
|
|
|
+ private lastAutoPlayTime: number = 0; // 新增:上次自动播放时间,用于防抖
|
|
|
|
|
+ private autoPlayDebounceMs: number = 1000; // 自动播放防抖间隔(毫秒)
|
|
|
|
|
|
|
|
private constructor() {
|
|
private constructor() {
|
|
|
this.playerManager = PlayerManager.getInstance();
|
|
this.playerManager = PlayerManager.getInstance();
|
|
@@ -684,11 +686,11 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
// 首先检查服务是否已准备就绪
|
|
// 首先检查服务是否已准备就绪
|
|
|
if (!this.isAllServicesReady()) {
|
|
if (!this.isAllServicesReady()) {
|
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService: playNext - 服务未就绪,等待服务初始化完成');
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService: playNext - 服务未就绪,等待服务初始化完成');
|
|
|
- const isReady = await this.waitForAllServicesReady(2000, false);
|
|
|
|
|
|
|
+ // 在自动播放场景下,减少等待时间避免阻塞
|
|
|
|
|
+ const isReady = await this.waitForAllServicesReady(500, false);
|
|
|
if (!isReady) {
|
|
if (!isReady) {
|
|
|
- const error = new Error('Services not ready for playNext');
|
|
|
|
|
- await this.handlePlaybackError(error, PlayerErrorType.INITIALIZATION_ERROR);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Services not ready for playNext, skipping');
|
|
|
|
|
+ return; // 直接返回,不抛出错误
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -735,7 +737,7 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
// 首先检查服务是否已准备就绪
|
|
// 首先检查服务是否已准备就绪
|
|
|
if (!this.isAllServicesReady()) {
|
|
if (!this.isAllServicesReady()) {
|
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService: playPrevious - 服务未就绪,等待服务初始化完成');
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService: playPrevious - 服务未就绪,等待服务初始化完成');
|
|
|
- const isReady = await this.waitForAllServicesReady(2000, false);
|
|
|
|
|
|
|
+ const isReady = await this.waitForAllServicesReady(500, false);
|
|
|
if (!isReady) {
|
|
if (!isReady) {
|
|
|
const error = new Error('Services not ready for playPrevious');
|
|
const error = new Error('Services not ready for playPrevious');
|
|
|
await this.handlePlaybackError(error, PlayerErrorType.INITIALIZATION_ERROR);
|
|
await this.handlePlaybackError(error, PlayerErrorType.INITIALIZATION_ERROR);
|
|
@@ -2177,6 +2179,104 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
// 更新卡片显示播放完成状态
|
|
// 更新卡片显示播放完成状态
|
|
|
this.updateWidgetsForPlayStateChange();
|
|
this.updateWidgetsForPlayStateChange();
|
|
|
|
|
|
|
|
|
|
+ // 异步处理自动播放逻辑,避免阻塞主线程
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.handleAutoPlayOnCompletion().catch(() => {
|
|
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Auto-play error`);
|
|
|
|
|
+ });
|
|
|
|
|
+ }, 100); // 延迟100ms执行,确保当前回调完成
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 处理歌曲播放完成后的自动播放逻辑
|
|
|
|
|
+ */
|
|
|
|
|
+ private async handleAutoPlayOnCompletion(): Promise<void> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 防抖检查:避免快速连续的自动播放调用
|
|
|
|
|
+ const currentTime = Date.now();
|
|
|
|
|
+ if (currentTime - this.lastAutoPlayTime < this.autoPlayDebounceMs) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Auto-play debounced, skipping');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.lastAutoPlayTime = currentTime;
|
|
|
|
|
+
|
|
|
|
|
+ // 检查服务状态,避免在服务未就绪时执行自动播放
|
|
|
|
|
+ if (!this.isAllServicesReady()) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Services not ready for auto-play, skipping');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const currentState = this.stateModel.getState();
|
|
|
|
|
+ const playMode = currentState.playMode;
|
|
|
|
|
+
|
|
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Handling auto-play, mode: ${playMode}`);
|
|
|
|
|
+
|
|
|
|
|
+ switch (playMode) {
|
|
|
|
|
+ case PlayMode.SEQUENCE: // 0: 顺序播放/列表循环
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Auto-playing next song in sequence mode');
|
|
|
|
|
+ // 检查是否有下一首歌曲
|
|
|
|
|
+ if (this.playlistModel.hasNext(playMode)) {
|
|
|
|
|
+ await this.playNext();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: No next song available in sequence mode');
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case PlayMode.SINGLE_REPEAT: // 1: 单曲循环
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Repeating current song');
|
|
|
|
|
+ // 重新播放当前歌曲
|
|
|
|
|
+ await this.startPlayOrResumePlay();
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case PlayMode.NORMAL: // 2: 正常播放,播完停止
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Normal mode - stopping after completion');
|
|
|
|
|
+ // 不做任何操作,保持停止状态
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case PlayMode.RANDOM: // 3: 随机播放
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Auto-playing random next song');
|
|
|
|
|
+ await this.playRandomNext();
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Unknown play mode: ${playMode}`);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Error in auto-play handling: ${error}`);
|
|
|
|
|
+ // 在自动播放失败时,简单记录错误但不触发复杂的错误处理流程
|
|
|
|
|
+ // 这样可以避免错误处理过程中的潜在阻塞
|
|
|
|
|
+ this.stateModel.updatePlayingState(false);
|
|
|
|
|
+ this.stateModel.updateLoadingState(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 随机播放下一首歌曲
|
|
|
|
|
+ */
|
|
|
|
|
+ private async playRandomNext(): Promise<void> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const playlist = this.playlistModel.getSongs();
|
|
|
|
|
+ if (playlist.length <= 1) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Not enough songs for random play');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const currentIndex = this.playlistModel.getCurrentIndex();
|
|
|
|
|
+ let randomIndex: number;
|
|
|
|
|
+
|
|
|
|
|
+ // 确保随机选择的不是当前歌曲
|
|
|
|
|
+ do {
|
|
|
|
|
+ randomIndex = Math.floor(Math.random() * playlist.length);
|
|
|
|
|
+ } while (randomIndex === currentIndex);
|
|
|
|
|
+
|
|
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Playing random song at index ${randomIndex}`);
|
|
|
|
|
+ await this.playSongAtIndex(randomIndex);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Error in random play: ${error}`);
|
|
|
|
|
+ // 不再抛出异常,而是通过错误处理机制处理
|
|
|
|
|
+ await this.handlePlaybackError(error as Error, PlayerErrorType.PLAYBACK_ERROR);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
onPlaybackError(what: number, extra: number): void {
|
|
onPlaybackError(what: number, extra: number): void {
|