فهرست منبع

实现cue点击分轨列表播放分轨列表里面歌曲

onecold 10 ماه پیش
والد
کامیت
ad9f079c6a

+ 7 - 0
entry/src/main/ets/common/util/CueUtils.ets

@@ -41,7 +41,14 @@ export async function parseCueFile(cuePath: string, totalDuration?: number): Pro
     console.log('onecold  CUE文件内容=', content);
     // 解析基础信息
     const result = parseCueContent(content);
+    // 在 parseCueContent 函数末尾,在返回 result 之前添加以下代码
+
     console.log('onecold  cue result =', JSON.stringify(result));
+    if (result.filePath) {
+      const parentPath = cuePath.substring(0, cuePath.lastIndexOf('/'));
+      result.filePath = parentPath + '/' + result.filePath;
+    }
+    console.log('onecold   result.filePath =',  result.filePath);
     // 计算时间信息
     return calculateTrackTimes(result, totalDuration);
   } finally {

+ 20 - 0
entry/src/main/ets/common/util/Utility.ets

@@ -1196,6 +1196,26 @@ export class Utility {
     }
   }
 
+  /**
+   * 根据文件路径从项数组中查找对应的VideoItem
+   * @param list VideoItem数组
+   * @param filePath 文件路径
+   * @returns 对应的VideoItem,如果未找到则返回undefined
+   */
+  static getItemByFilePath(list: Array<VideoItem>, filePath: string): VideoItem | undefined {
+    if (!list || list.length === 0 || !filePath) {
+      return undefined;
+    }
+
+    for (let i = 0; i < list.length; i++) {
+      if (list[i].filePath === filePath) {
+        return list[i];
+      }
+    }
+
+    return undefined;
+  }
+
   //根据filePath获取当前索引index
   static getCurIndexFromGlobalList(localList:Array<VideoItem>,filePath:string){
     let index: number = 0;

+ 16 - 4
entry/src/main/ets/view/CueComptent.ets

@@ -11,8 +11,8 @@ import { CueTrack, millisecondsToTime } from '../common/util/CueUtils';
 export struct CueComptent {
   @Prop title: string = ''
   @Prop isLongNameRoLL: boolean = true
-
-  onDeleteResult = (_result: boolean) => {
+  @State curIndex:number = -1
+  onDoItemClick = (item: CueTrack, index: number) => {
   }
   onCancel = () => {
   }
@@ -36,7 +36,8 @@ export struct CueComptent {
         Button($r('app.string.back'))
           .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.8 })
           .padding(15)
-          .width(120)
+          .fontSize(13)
+          .width(138)
           .onClick(() => {
             this.onCancel()
           })
@@ -64,7 +65,14 @@ export struct CueComptent {
                 Text(item.title || 'Unknown Title')
                   .fontSize(14)
                   .padding({ left: 6 })
-                  .fontColor($r('app.color.text_color'))
+                  .fontColor(this.curIndex==index?this.themeColor:$r('app.color.text_color'))
+                  .maxLines(1)
+                  .textOverflow({ overflow: this.isLongNameRoLL?TextOverflow.MARQUEE:TextOverflow.Ellipsis })//超长滚动
+
+                Text(item.performer || '')
+                  .fontSize(11)
+                  .padding({ left: 8 })
+                  .fontColor(this.curIndex==index?this.themeColor:Color.Gray)
                   .maxLines(1)
                   .textOverflow({ overflow: this.isLongNameRoLL?TextOverflow.MARQUEE:TextOverflow.Ellipsis })//超长滚动
               }
@@ -84,6 +92,10 @@ export struct CueComptent {
           .width('100%')
           .height(50)
           .padding({ left: 15, right: 15 })
+          .onClick(() => {
+            this.curIndex=index
+            this.onDoItemClick(item, index)
+          })
         }
       }) // 使用唯一标识符作为key
     }

+ 40 - 13
entry/src/main/ets/view/LocalMusic.ets

@@ -5107,11 +5107,8 @@ export struct LocalMusic {
         return
         break;
       case CommonConstants.TYPE_LOCAL:
-        if (this.CONTROL_PlayStatus !== PlayStatus.INIT) {
-          this.stop();
-        }
         if(item&&item.filePath.toLowerCase().endsWith('.cue')){
-         const cueinfo:CueInfo = await parseCueFile(item.filePath,Number(item.duration))
+          const cueinfo:CueInfo = await parseCueFile(item.filePath,Number(item.duration))
           const cueTracks:CueTrack[] = cueinfo.tracks
           console.log('onecold  cue cueTracks =', JSON.stringify(cueTracks));
           if(ArrayUtil.isNotEmpty(cueTracks)){
@@ -5120,6 +5117,9 @@ export struct LocalMusic {
           // this.showCueSheet = !this.showCueSheet
           return
         }
+        if (this.CONTROL_PlayStatus !== PlayStatus.INIT) {
+          this.stop();
+        }
 
         if (isOpen) {
           this.currentSong = item
@@ -5193,7 +5193,28 @@ export struct LocalMusic {
       onCancel:()=>{
         this.getUIContext().getPromptAction().closeCustomDialog(this.cueComponentId)
       },
-      onDeleteResult:(result: boolean)=>{
+      onDoItemClick:(item: CueTrack, index: number)=>{
+        //获取cueinfo对应的filePath
+        let globalVideoList = Utility.getGlobalList(this.videoLocalList, CommonConstants.TYPE_LOCAL) as VideoItem[];
+        this.curIndex = Utility.getCurIndexFromGlobalList(globalVideoList, cueinfo.filePath)
+        this.currentSong = Utility.getItemByFilePath(globalVideoList, cueinfo.filePath)
+        console.info('onecold  cueinfo.filePath=',  cueinfo.filePath)
+        console.info('onecold this.currentSong =', JSON.stringify(this.currentSong))
+        if (this.currentSong){
+          if (this.CONTROL_PlayStatus !== PlayStatus.INIT) {
+            this.stop();//播放之前先停止之前播放。
+          }
+          this.songList = globalVideoList
+          this.sonDataSource.pushArrayData(this.songList)
+          this.videoUrl = this.currentSong.filePath
+          this.name = item.title||this.currentSong.name
+          this.cover = this.currentSong.pixelMapPath
+          this.artist = item.performer||this.currentSong.artist
+          this.currentSong.name = this.name
+          this.currentSong.artist = this.artist
+          AppStorage.setOrCreate('currentSong',this.currentSong) ;
+          this.startPlayOrResumePlay(item.startOffset)//从cue的某个位置开始播放
+        }
 
 
       }
@@ -11058,7 +11079,8 @@ export struct LocalMusic {
     }
   }
 
-  private startPlayOrResumePlay() {
+  //startOffset 从cue分轨时间开始播
+  private startPlayOrResumePlay(startOffset?:number) {
     //针对dsf文件高采样率sampleRate>441000,统一转wav播放
     const sampleRate = this.currentSong?.sampleRate||0
     if(this.videoUrl.toLowerCase().endsWith('.dsf')&&sampleRate>=441000){
@@ -11069,23 +11091,23 @@ export struct LocalMusic {
         const task = new taskpool.Task(convertDsfToWav,this.videoUrl,newDsfPath);
         taskpool.execute(task, taskpool.Priority.HIGH).then((data)=>{
           this.videoUrl = newDsfPath
-          this.startPlay()
+          this.startPlay(startOffset)
         }).catch((e:object)=>{
           console.info("task1 catch e: " + e);
         })
       }else{
         this.videoUrl = newDsfPath
-        this.startPlay()
+        this.startPlay(startOffset)
       }
 
     }else{
-      this.startPlay()
+      this.startPlay(startOffset)
     }
 
 
   }
 
-  startPlay() {
+  startPlay(startOffset?:number) {
     this.startPipLyric()
     this.mDestroyPage = false;
     this.animationState = AnimationStatus.Running
@@ -11093,7 +11115,7 @@ export struct LocalMusic {
     if (this.CONTROL_PlayStatus == PlayStatus.INIT) {
       this.stopProgressTask();
       this.startProgressTask();
-      this.play(this.videoUrl.toString());
+      this.play(this.videoUrl.toString(),startOffset);
 
 
     }
@@ -11254,7 +11276,7 @@ export struct LocalMusic {
     this.replayVisible = Visibility.Visible;
   }
 
-  private async play(url: string) {
+  private async play(url: string,startOffset?:number) {
     let that = this;
     that.showLoadIng();
     this.isOpenAB = false
@@ -11397,8 +11419,13 @@ export struct LocalMusic {
             this.updateSessionPlayState(true)
             this.setCurrentPlayMode()
           }, 500)
-          //rmvb和flac格式马上记忆播放会报错,会延迟1s在读取记忆播放。
 
+          if(startOffset&&startOffset>0){//cue分轨播放
+            this.seekTo(startOffset  + "");
+            this.saveLastPlayList()
+            return
+          }
+          //rmvb和flac格式马上记忆播放会报错,会延迟1s在读取记忆播放。
           let timeoutPlay = 0
           if (StrUtil.isNotEmpty(this.videoUrl) &&
             (this.videoUrl.toLowerCase().endsWith('.rmvb') || this.videoUrl.toLowerCase().endsWith('.flac'))) {