xref: /MusicFree/src/core/lyricManager.ts (revision 41ddce918e1138d8f16e522cc7c19ac86ceca698)
157277364S猫头猫/**
257277364S猫头猫 * 管理当前歌曲的歌词
357277364S猫头猫 */
457277364S猫头猫
5*41ddce91Smaotoumaoimport { isSameMediaItem } from "@/utils/mediaItem";
6*41ddce91Smaotoumaoimport PluginManager from "./pluginManager";
7*41ddce91Smaotoumaoimport LyricParser, { IParsedLrcItem } from "@/utils/lrcParser";
8*41ddce91Smaotoumaoimport { GlobalState } from "@/utils/stateMapper";
9*41ddce91Smaotoumaoimport { EDeviceEvents } from "@/constants/commonConst";
10*41ddce91Smaotoumaoimport { DeviceEventEmitter } from "react-native";
11*41ddce91Smaotoumaoimport Config from "./config.ts";
12*41ddce91Smaotoumaoimport LyricUtil from "@/native/lyricUtil";
13*41ddce91Smaotoumaoimport TrackPlayer from "./trackPlayer";
14*41ddce91Smaotoumaoimport MediaExtra from "./mediaExtra";
15*41ddce91Smaotoumaoimport minDistance from "@/utils/minDistance";
1657277364S猫头猫
1743733013S猫头猫interface ILyricState {
1857277364S猫头猫  loading: boolean;
1957277364S猫头猫  lyricParser?: LyricParser;
2043733013S猫头猫  lyrics: IParsedLrcItem[];
2157277364S猫头猫  meta?: Record<string, string>;
227e883dbbS猫头猫  hasTranslation: boolean;
2343733013S猫头猫}
2457277364S猫头猫
2543733013S猫头猫const defaultLyricState = {
261057be29S猫头猫  loading: true,
271057be29S猫头猫  lyrics: [],
28*41ddce91Smaotoumao  hasTranslation: false
291057be29S猫头猫};
301057be29S猫头猫
3143733013S猫头猫const lyricStateStore = new GlobalState<ILyricState>(defaultLyricState);
3243733013S猫头猫const currentLyricStore = new GlobalState<IParsedLrcItem | null>(null);
3343733013S猫头猫
3443733013S猫头猫function resetLyricState() {
3543733013S猫头猫  lyricStateStore.setValue(defaultLyricState);
361057be29S猫头猫}
3757277364S猫头猫
3857277364S猫头猫// 重新获取歌词
39bae3deccS猫头猫async function refreshLyric(fromStart?: boolean, forceRequest = false) {
405500cea7S猫头猫  const musicItem = TrackPlayer.getCurrentMusic();
4157277364S猫头猫  try {
425500cea7S猫头猫    if (!musicItem) {
435500cea7S猫头猫      lyricStateStore.setValue({
445500cea7S猫头猫        loading: false,
455500cea7S猫头猫        lyrics: [],
46*41ddce91Smaotoumao        hasTranslation: false
475500cea7S猫头猫      });
485500cea7S猫头猫
495500cea7S猫头猫      currentLyricStore.setValue({
5043733013S猫头猫        index: 0,
51*41ddce91Smaotoumao        lrc: "MusicFree",
52*41ddce91Smaotoumao        time: 0
535500cea7S猫头猫      });
545500cea7S猫头猫
555500cea7S猫头猫      return;
565500cea7S猫头猫    }
575500cea7S猫头猫
5843733013S猫头猫    const currentParserMusicItem =
5943733013S猫头猫      lyricStateStore.getValue()?.lyricParser?.musicItem;
6072dabe5bS猫头猫
617e883dbbS猫头猫    let lrcSource: ILyric.ILyricSource | null | undefined;
62bae3deccS猫头猫    if (
63bae3deccS猫头猫      forceRequest ||
64bae3deccS猫头猫      !isSameMediaItem(currentParserMusicItem, musicItem)
65bae3deccS猫头猫    ) {
6643733013S猫头猫      resetLyricState();
6757277364S猫头猫      currentLyricStore.setValue(null);
6857277364S猫头猫
697e883dbbS猫头猫      lrcSource = await PluginManager.getByMedia(
70*41ddce91Smaotoumao        musicItem
717e883dbbS猫头猫      )?.methods?.getLyric(musicItem);
7272dabe5bS猫头猫    } else {
7343733013S猫头猫      lrcSource = lyricStateStore.getValue().lyricParser?.lyricSource;
7472dabe5bS猫头猫    }
7572dabe5bS猫头猫
76*41ddce91Smaotoumao    if (!lrcSource && Config.getConfig("lyric.autoSearchLyric")) {
771057be29S猫头猫      const keyword = musicItem.alias || musicItem.title;
78*41ddce91Smaotoumao      const plugins = PluginManager.getSearchablePlugins("lyric");
791057be29S猫头猫
80b8c85eecS猫头猫      let distance = Infinity;
81b8c85eecS猫头猫      let minDistanceMusicItem;
82b8c85eecS猫头猫      let targetPlugin;
83b8c85eecS猫头猫
841057be29S猫头猫      for (let plugin of plugins) {
851057be29S猫头猫        const realtimeMusicItem = TrackPlayer.getCurrentMusic();
86b8c85eecS猫头猫        if (
87b8c85eecS猫头猫          !isSameMediaItem(musicItem, realtimeMusicItem) ||
88b8c85eecS猫头猫          plugin.name === musicItem.platform
89b8c85eecS猫头猫        ) {
901057be29S猫头猫          return;
911057be29S猫头猫        }
921057be29S猫头猫        const results = await plugin.methods
93*41ddce91Smaotoumao          .search(keyword, 1, "lyric")
941057be29S猫头猫          .catch(() => null);
95b8c85eecS猫头猫
96b8c85eecS猫头猫        // 取前两个
97b8c85eecS猫头猫        const firstTwo = results?.data?.slice(0, 2) || [];
98b8c85eecS猫头猫
99b8c85eecS猫头猫        for (let item of firstTwo) {
100b8c85eecS猫头猫          if (
101b8c85eecS猫头猫            item.title === keyword &&
102b8c85eecS猫头猫            item.artist === musicItem.artist
103b8c85eecS猫头猫          ) {
104b8c85eecS猫头猫            distance = 0;
105b8c85eecS猫头猫            minDistanceMusicItem = item;
106b8c85eecS猫头猫            targetPlugin = plugin;
107b8c85eecS猫头猫            break;
108b8c85eecS猫头猫          } else {
109b8c85eecS猫头猫            const dist =
110b8c85eecS猫头猫              minDistance(keyword, musicItem.title) +
111b8c85eecS猫头猫              minDistance(item.artist, musicItem.artist);
112b8c85eecS猫头猫            if (dist < distance) {
113b8c85eecS猫头猫              distance = dist;
114b8c85eecS猫头猫              minDistanceMusicItem = item;
115b8c85eecS猫头猫              targetPlugin = plugin;
116b8c85eecS猫头猫            }
117b8c85eecS猫头猫          }
118b8c85eecS猫头猫        }
119b8c85eecS猫头猫
120b8c85eecS猫头猫        if (distance === 0) {
1211057be29S猫头猫          break;
1221057be29S猫头猫        }
1231057be29S猫头猫      }
124b8c85eecS猫头猫      if (minDistanceMusicItem && targetPlugin) {
125b8c85eecS猫头猫        lrcSource = await targetPlugin.methods
126b8c85eecS猫头猫          .getLyric(minDistanceMusicItem)
127b8c85eecS猫头猫          .catch(() => null);
1281057be29S猫头猫      }
1291057be29S猫头猫    }
1301057be29S猫头猫
1315500cea7S猫头猫    const realtimeMusicItem = TrackPlayer.getCurrentMusic();
13257277364S猫头猫    if (isSameMediaItem(musicItem, realtimeMusicItem)) {
1337e883dbbS猫头猫      if (lrcSource) {
13472dabe5bS猫头猫        const mediaExtra = MediaExtra.get(musicItem);
13543733013S猫头猫        const parser = new LyricParser(lrcSource.rawLrc!, {
13643733013S猫头猫          extra: {
137*41ddce91Smaotoumao            offset: (mediaExtra?.lyricOffset || 0) * -1
13843733013S猫头猫          },
13943733013S猫头猫          musicItem: musicItem,
14043733013S猫头猫          lyricSource: lrcSource,
141*41ddce91Smaotoumao          translation: lrcSource.translation
14272dabe5bS猫头猫        });
1437e883dbbS猫头猫
14457277364S猫头猫        lyricStateStore.setValue({
14557277364S猫头猫          loading: false,
14657277364S猫头猫          lyricParser: parser,
14743733013S猫头猫          lyrics: parser.getLyricItems(),
14843733013S猫头猫          hasTranslation: parser.hasTranslation,
149*41ddce91Smaotoumao          meta: parser.getMeta()
15057277364S猫头猫        });
15157277364S猫头猫        // 更新当前状态的歌词
15257277364S猫头猫        const currentLyric = fromStart
15343733013S猫头猫          ? parser.getLyricItems()[0]
1545500cea7S猫头猫          : parser.getPosition(
155*41ddce91Smaotoumao            (await TrackPlayer.getProgress()).position
15643733013S猫头猫          );
15757277364S猫头猫        currentLyricStore.setValue(currentLyric || null);
15857277364S猫头猫      } else {
15957277364S猫头猫        // 没有歌词
16057277364S猫头猫        lyricStateStore.setValue({
16157277364S猫头猫          loading: false,
16257277364S猫头猫          lyrics: [],
163*41ddce91Smaotoumao          hasTranslation: false
16457277364S猫头猫        });
16557277364S猫头猫      }
16657277364S猫头猫    }
1677e883dbbS猫头猫  } catch (e) {
168*41ddce91Smaotoumao    console.log(e, "LRC");
1695500cea7S猫头猫    const realtimeMusicItem = TrackPlayer.getCurrentMusic();
17057277364S猫头猫    if (isSameMediaItem(musicItem, realtimeMusicItem)) {
17157277364S猫头猫      // 异常情况
17257277364S猫头猫      lyricStateStore.setValue({
17357277364S猫头猫        loading: false,
17457277364S猫头猫        lyrics: [],
175*41ddce91Smaotoumao        hasTranslation: false
17657277364S猫头猫      });
17757277364S猫头猫    }
17857277364S猫头猫  }
17957277364S猫头猫}
18057277364S猫头猫
18157277364S猫头猫// 获取歌词
18257277364S猫头猫async function setup() {
18357277364S猫头猫  DeviceEventEmitter.addListener(EDeviceEvents.REFRESH_LYRIC, refreshLyric);
18457277364S猫头猫
185*41ddce91Smaotoumao  if (Config.getConfig("lyric.showStatusBarLyric")) {
186*41ddce91Smaotoumao
187*41ddce91Smaotoumao    const statusBarLyricConfig = {
188*41ddce91Smaotoumao      topPercent: Config.getConfig("lyric.topPercent"),
189*41ddce91Smaotoumao      leftPercent: Config.getConfig("lyric.leftPercent"),
190*41ddce91Smaotoumao      align: Config.getConfig("lyric.align"),
191*41ddce91Smaotoumao      color: Config.getConfig("lyric.color"),
192*41ddce91Smaotoumao      backgroundColor: Config.getConfig("lyric.backgroundColor"),
193*41ddce91Smaotoumao      widthPercent: Config.getConfig("lyric.widthPercent"),
194*41ddce91Smaotoumao      fontSize: Config.getConfig("lyric.fontSize")
195*41ddce91Smaotoumao    };
1960be848bcS猫头猫    LyricUtil.showStatusBarLyric(
197*41ddce91Smaotoumao      "MusicFree",
198*41ddce91Smaotoumao      statusBarLyricConfig ?? {}
1990be848bcS猫头猫    );
2000be848bcS猫头猫  }
2010be848bcS猫头猫
20257277364S猫头猫  refreshLyric();
20357277364S猫头猫}
20457277364S猫头猫
20557277364S猫头猫const LyricManager = {
20657277364S猫头猫  setup,
20757277364S猫头猫  useLyricState: lyricStateStore.useValue,
20857277364S猫头猫  getLyricState: lyricStateStore.getValue,
20957277364S猫头猫  useCurrentLyric: currentLyricStore.useValue,
21057277364S猫头猫  getCurrentLyric: currentLyricStore.getValue,
21157277364S猫头猫  setCurrentLyric: currentLyricStore.setValue,
21272dabe5bS猫头猫  refreshLyric,
213*41ddce91Smaotoumao  setLyricLoading: refreshLyric
21457277364S猫头猫};
21557277364S猫头猫
21657277364S猫头猫export default LyricManager;
217