Kaynağa Gözat

修复自动播放下一首

chendeben 1 yıl önce
ebeveyn
işleme
f5d240cb8a

+ 1 - 1
entry/src/main/ets/common/service/PlaylistModel.ets

@@ -248,7 +248,7 @@ export class PlaylistModel {
       case PlayMode.SINGLE_REPEAT:
         return true; // 单曲循环总是有下一首(自己)
       case PlayMode.SEQUENCE:
-        return this.currentIndex < this.songs.length - 1;
+        return true; // 顺序播放支持循环,总是有下一首
       case PlayMode.NORMAL:
         return this.currentIndex < this.songs.length - 1;
       case PlayMode.RANDOM:

+ 105 - 5
entry/src/main/ets/common/service/UnifiedPlayerService.ets

@@ -261,6 +261,8 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
   private lastUpdateTime: number=0;
   private favList: VideoItem[]=[];
   table: undefined;
+  private lastAutoPlayTime: number = 0; // 新增:上次自动播放时间,用于防抖
+  private autoPlayDebounceMs: number = 1000; // 自动播放防抖间隔(毫秒)
 
   private constructor() {
     this.playerManager = PlayerManager.getInstance();
@@ -684,11 +686,11 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
       // 首先检查服务是否已准备就绪
       if (!this.isAllServicesReady()) {
         LogUtils.getInstance().LOGI('UnifiedPlayerService: playNext - 服务未就绪,等待服务初始化完成');
-        const isReady = await this.waitForAllServicesReady(2000, false);
+        // 在自动播放场景下,减少等待时间避免阻塞
+        const isReady = await this.waitForAllServicesReady(500, false);
         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()) {
         LogUtils.getInstance().LOGI('UnifiedPlayerService: playPrevious - 服务未就绪,等待服务初始化完成');
-        const isReady = await this.waitForAllServicesReady(2000, false);
+        const isReady = await this.waitForAllServicesReady(500, false);
         if (!isReady) {
           const error = new Error('Services not ready for playPrevious');
           await this.handlePlaybackError(error, PlayerErrorType.INITIALIZATION_ERROR);
@@ -2177,6 +2179,104 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
     // 更新卡片显示播放完成状态
     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 {