xref: /MusicFree/src/core/lyricManager.ts (revision 4d0d956507a5e90230a0a07fc80821ac4f800408)
1/**
2 * 管理当前歌曲的歌词
3 */
4
5import {isSameMediaItem} from '@/utils/mediaItem';
6import MusicQueue from './musicQueue';
7import PluginManager from './pluginManager';
8import LyricParser from '@/utils/lrcParser';
9import {GlobalState} from '@/utils/stateMapper';
10import {EDeviceEvents} from '@/constants/commonConst';
11import {DeviceEventEmitter} from 'react-native';
12import Config from './config';
13import LyricUtil from '@/native/lyricUtil';
14
15const lyricStateStore = new GlobalState<{
16    loading: boolean;
17    lyricParser?: LyricParser;
18    lyrics: ILyric.IParsedLrc;
19    meta?: Record<string, string>;
20}>({
21    loading: true,
22    lyrics: [],
23});
24
25const currentLyricStore = new GlobalState<ILyric.IParsedLrcItem | null>(null);
26
27// 重新获取歌词
28async function refreshLyric(fromStart?: boolean) {
29    const musicItem = MusicQueue.getCurrentMusicItem();
30    try {
31        lyricStateStore.setValue({
32            loading: true,
33            lyrics: [],
34        });
35        currentLyricStore.setValue(null);
36
37        const lrc = await PluginManager.getByMedia(
38            musicItem,
39        )?.methods?.getLyricText(musicItem);
40        const realtimeMusicItem = MusicQueue.getCurrentMusicItem();
41        if (isSameMediaItem(musicItem, realtimeMusicItem)) {
42            if (lrc) {
43                const parser = new LyricParser(lrc, musicItem);
44                lyricStateStore.setValue({
45                    loading: false,
46                    lyricParser: parser,
47                    lyrics: parser.getLyric(),
48                    meta: parser.getMeta(),
49                });
50                // 更新当前状态的歌词
51                const currentLyric = fromStart
52                    ? parser.getLyric()[0]
53                    : parser.getPosition(await MusicQueue.getPosition()).lrc;
54                currentLyricStore.setValue(currentLyric || null);
55            } else {
56                // 没有歌词
57                lyricStateStore.setValue({
58                    loading: false,
59                    lyrics: [],
60                });
61            }
62        }
63    } catch {
64        const realtimeMusicItem = MusicQueue.getCurrentMusicItem();
65        if (isSameMediaItem(musicItem, realtimeMusicItem)) {
66            // 异常情况
67            lyricStateStore.setValue({
68                loading: false,
69                lyrics: [],
70            });
71        }
72    }
73}
74
75// 获取歌词
76async function setup() {
77    DeviceEventEmitter.addListener(EDeviceEvents.REFRESH_LYRIC, refreshLyric);
78
79    if (Config.get('setting.lyric.showStatusBarLyric')) {
80        LyricUtil.showStatusBarLyric(
81            'MusicFree',
82            Config.get('setting.lyric') ?? {},
83        );
84    }
85
86    refreshLyric();
87}
88
89const LyricManager = {
90    setup,
91    useLyricState: lyricStateStore.useValue,
92    getLyricState: lyricStateStore.getValue,
93    useCurrentLyric: currentLyricStore.useValue,
94    getCurrentLyric: currentLyricStore.getValue,
95    setCurrentLyric: currentLyricStore.setValue,
96};
97
98export default LyricManager;
99