Ver código fonte

修复编辑内嵌标签的问题

onecold 9 meses atrás
pai
commit
c4f77b685b

+ 1 - 0
entry/src/main/ets/common/util/RdbUtils.ets

@@ -294,6 +294,7 @@ export default class RdbUtils {
           //检查是否存在相同id的记录,存在则不插入,进一步判断pixelMapPath字段,如果旧值为空而新值不为空,则更新该字段。
           //20250924不判断pixelMapPath字段了,如果存在不插入,则返回
           if (resultSet.goToFirstRow()) {
+            callback(resultSet);
             resultSet.close();
             return;
             // const existingPixelMapPath = resultSet.getString(resultSet.getColumnIndex('pixelMapPath'));

+ 2 - 1
entry/src/main/ets/common/util/Utility.ets

@@ -673,7 +673,8 @@ export class Utility {
     await ReqPermissionUtil.persistPermission(uri);
     //这里加个判断,如果文件的大小是0K,这个文件是空的,直接返回
     try {
-      const fileStat = await fs.stat(uri);
+      const file = fs.openSync(uri, fs.OpenMode.READ_ONLY | fs.OpenMode.CREATE)
+      const fileStat = await fs.stat(file.fd);
       if (fileStat.size === 0) {
         console.warn(`File ${uri} is empty (0KB). Returning default VideoItem.`);
         // Return a default or empty VideoItem object

Diferenças do arquivo suprimidas por serem muito extensas
+ 388 - 394
entry/src/main/ets/view/LocalMusic.ets


+ 225 - 1
entry/src/main/ets/workers/Worker.ets

@@ -1,10 +1,12 @@
 import { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope, worker } from '@kit.ArkTS';
-import { FileUtil } from '@pura/harmony-utils';
+import { FileUtil, StrUtil } from '@pura/harmony-utils';
 import { CommonConstants } from '../common/constants/CommonConstants';
 import Logger from '../common/util/Logger';
 import MediaTable from '../common/util/MediaTable';
 import { Utility } from '../common/util/Utility';
 import { VideoItem } from '../viewmodel/VideoItem';
+import { changeMusicCover, repairAudioMetadata } from '../common/util/MusicTagUtils';
+import { FFMpegTags } from '../common/util/Utility';
 
 const workerPort: ThreadWorkerGlobalScope = worker.workerPort;
 
@@ -16,6 +18,28 @@ interface MetadataRequestPayload {
   trackCount?: string;
 }
 
+interface EditMusicRequestPayload {
+  context: Context;
+  item: VideoItem;
+  titleStr: string;
+  artistStr: string;
+  ablumStr: string;
+  yearStr: string;
+  genreStr: string;
+  trackStr: string;
+  albumArtistStr: string;
+  composerStr: string;
+  lyricistStr: string;
+  commentStr: string;
+  discStr: string;
+  lyricConStr: string;
+  imagePathStr: string;
+  currentPath: string;
+  packName: string;
+  modeType: number;
+  autoParseMusicName: boolean;
+}
+
 
 /**
  * Defines the event handler to be called when the worker thread receives a message sent by the host thread.
@@ -52,6 +76,9 @@ workerPort.onmessage = async (e: MessageEvents) => {
         e.data.data4 as MetadataRequestPayload
       );
       break;
+    case 6://编辑内嵌音乐元数据和封面
+      await handleEditMusic(e.data.data as EditMusicRequestPayload);
+      break;
 
   }
 
@@ -344,6 +371,203 @@ async function analyzeCachedMediaMetadata(
   }
 }
 
+async function updateInfoDb(
+  context: Context,
+  filePath: string,
+  titleStr: string,
+  artistStr: string,
+  albumStr: string,
+  lyricConStr: string,
+  yearStr: string,
+  genreStr: string,
+  trackStr: string,
+  albumArtistStr: string,
+  composerStr: string,
+  lyricistStr: string,
+  commentStr: string,
+  discStr: string,
+): Promise<boolean> {
+  const table: MediaTable = new MediaTable(context);
+  await new Promise<void>((resolve, reject) => {
+    table.getRdbStore(context,  (err:Error) => {
+      err ? reject(err) : resolve();
+    });
+  });
+
+  return await new Promise<boolean>((resolve) => {
+    table.updateMediaInfo(filePath, titleStr, artistStr, albumStr, lyricConStr,
+      yearStr, genreStr, trackStr, albumArtistStr, composerStr, lyricistStr, commentStr, discStr,
+      (success: boolean, error?: string) => {
+        if (success) {
+          console.log("heanup 编辑信息成功,数据库已同步");
+        } else {
+          console.error("heanup 编辑信息数据库失败原因: " + error);
+        }
+        resolve(success);
+      });
+  });
+}
+
+async function handleEditMusic(payload: EditMusicRequestPayload): Promise<void> {
+  try {
+    const context = payload.context;
+    const item = payload.item;
+    const titleStr = payload.titleStr;
+    const artistStr = payload.artistStr;
+    const ablumStr = payload.ablumStr;
+    const yearStr = payload.yearStr;
+    const genreStr = payload.genreStr;
+    const trackStr = payload.trackStr;
+    const albumArtistStr = payload.albumArtistStr;
+    const composerStr = payload.composerStr;
+    const lyricistStr = payload.lyricistStr;
+    const commentStr = payload.commentStr;
+    const discStr = payload.discStr;
+    const lyricConStr = payload.lyricConStr;
+    const imagePathStr = payload.imagePathStr;
+    const currentPath = payload.currentPath;
+    const packName = payload.packName;
+    const modeType = payload.modeType;
+    const autoParseMusicName = payload.autoParseMusicName;
+
+    if (!item || StrUtil.isEmpty(titleStr)) {
+      workerPort.postMessage({
+        code: 106,
+        success: false,
+        error: '标题不能为空'
+      });
+      return;
+    }
+
+    let tempOutPath = '';
+    // 如果不是 packName 包下的文件,则直接路径用currentPath
+    if (!item.filePath.toLowerCase().includes(packName)) {
+      tempOutPath = currentPath + '/' + item.fileName;
+    }
+    console.info('heanup tempOutPath =' + tempOutPath);
+
+    let coverResult = false;
+    // 用户更改了封面,那就内嵌下封面
+    if (StrUtil.isNotEmpty(imagePathStr)) {
+      coverResult = await changeMusicCover(
+        context,
+        item.filePath,
+        imagePathStr,
+        true,
+        tempOutPath
+      );
+
+      if (coverResult) {
+        console.log('heanup 内嵌封面成功');
+      } else {
+        console.error('heanup 内嵌封面失败');
+      }
+    }
+
+    const metadata: FFMpegTags = {
+      title: titleStr,
+      artist: artistStr,
+      album: ablumStr,
+      TYER: yearStr,
+      genre: genreStr,
+      track: trackStr,
+      album_artist: albumArtistStr,
+      TPE2: albumArtistStr,
+      COMPOSER: composerStr,
+      lyricist: lyricistStr,
+      TEXT: lyricistStr,
+      comment: commentStr,
+      disc: discStr,
+    };
+
+    let newInput = item.filePath;
+    // 内嵌标签歌路径如果不是包含包名,输入newInput要赋值tempOutPath,然后tempOutPath为空
+    if (!item.filePath.toLowerCase().includes(packName) && FileUtil.accessSync(tempOutPath)) {
+      newInput = tempOutPath;
+      tempOutPath = '';
+    }
+    console.info('heanup repairAudioMetadata newInput =' + newInput);
+    console.info('heanup repairAudioMetadata tempOutPath =' + tempOutPath);
+    // 内嵌下标签的值,设置overwrite为true会直接修改原文件
+    const metadataResult = await repairAudioMetadata(
+      newInput,
+      lyricConStr,
+      metadata,
+      true,
+      tempOutPath
+    );
+
+    if (!metadataResult) {
+      workerPort.postMessage({
+        code: 106,
+        success: false,
+        error: '内嵌音乐标签失败'
+      });
+      return;
+    }
+
+    let needRefreshList = false;
+    if (!item.filePath.includes(packName)) {
+      // 内嵌成功的歌路径如果不是包含包名,则要入库
+      let newItem: VideoItem = await Utility.uriGetMusicAssetsFromFile(
+        context,
+        newInput,
+        CommonConstants.TYPE_LOCAL,
+        autoParseMusicName
+      );
+
+      const table: MediaTable = new MediaTable(context);
+      await new Promise<void>((resolve, reject) => {
+        table.getRdbStore(context, (err: Error) => {
+          err ? reject(err) : resolve();
+        });
+      });
+
+      await new Promise<void>((resolve) => {
+        table.insert(newItem, (id: number) => {
+          needRefreshList = true;
+          resolve();
+        });
+      });
+    }
+
+    // 更新数据库信息
+    const dbResult = await updateInfoDb(
+      context,
+      item.filePath,
+      titleStr,
+      artistStr,
+      ablumStr,
+      lyricConStr,
+      yearStr,
+      genreStr,
+      trackStr,
+      albumArtistStr,
+      composerStr,
+      lyricistStr,
+      commentStr,
+      discStr
+    );
+
+    workerPort.postMessage({
+      code: 106,
+      success: dbResult,
+      coverResult: coverResult,
+      needRefreshList: needRefreshList,
+      metadataResult: metadataResult
+    });
+
+  } catch (error) {
+    const err = error as Error;
+    console.error('heanup doEdit worker error: ' + err.message);
+    workerPort.postMessage({
+      code: 106,
+      success: false,
+      error: err.message
+    });
+  }
+}
+
 
 /**
  * Defines the event handler to be called when the worker receives a message that cannot be deserialized.

BIN
entry/src/main/resources/base/media/hm_music.png


BIN
entry/src/main/resources/base/media/ic_avatar1.png


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff