feat: osdlyrics desktop lyrics support

This commit is contained in:
Revincx 2022-10-05 16:20:04 +08:00
parent ce778afff6
commit 022f740c3f
No known key found for this signature in database
GPG Key ID: 6E79B88F79CA3126
9 changed files with 99 additions and 2 deletions

View File

@ -32,6 +32,7 @@ import express from 'express';
import expressProxy from 'express-http-proxy';
import Store from 'electron-store';
import { createMpris } from '@/electron/mpris';
import { spawn } from 'child_process';
const clc = require('cli-color');
const log = text => {
console.log(`${clc.blueBright('[background.js]')} ${text}`);
@ -420,6 +421,20 @@ class Background {
registerGlobalShortcut(this.window, this.store);
}
// try to start osdlyrics process on start
if (this.store.get('settings.enableOsdlyricsSupport')) {
log('try to start osdlyrics process');
const osdlyricsProcess = spawn('osdlyrics');
osdlyricsProcess.on('error', err => {
log(`failed to start osdlyrics: ${err.message}`);
});
osdlyricsProcess.on('exit', (code, signal) => {
log(`osdlyrics process exited with code ${code}, signal ${signal}`);
});
}
// create mpris
if (isCreateMpris) {
createMpris(this.window);

View File

@ -5,6 +5,8 @@ import cloneDeep from 'lodash/cloneDeep';
import shortcuts from '@/utils/shortcuts';
import { createMenu } from './menu';
import { isCreateTray, isMac } from '@/utils/platform';
import { resolve } from 'path';
import { existsSync, mkdirSync, writeFileSync } from 'fs';
const clc = require('cli-color');
const log = text => {
@ -309,6 +311,15 @@ export function initIpcMain(win, store, trayEventEmitter) {
registerGlobalShortcut(win, store);
});
ipcMain.on('saveLyric', (event, { name, lyric }) => {
let lyricsDirPath = resolve(process.env.HOME, '.lyrics');
if (!existsSync(lyricsDirPath)) mkdirSync(lyricsDirPath);
if (!existsSync(resolve(lyricsDirPath, name + '.lrc'))) {
writeFileSync(resolve(lyricsDirPath, name + '.lrc'), lyric);
}
win.webContents.send('saveLyricFinished');
});
if (isCreateTray) {
ipcMain.on('updateTrayTooltip', (_, title) => {
trayEventEmitter.emit('updateTooltip', title);

View File

@ -28,6 +28,8 @@ export function createMpris(window) {
});
ipcMain.on('metadata', (e, metadata) => {
// 更新 Mpris 状态前将位置设为0, 否则 OSDLyrics 获取到的进度是上首音乐切换时的进度
player.getPosition = () => 0;
player.metadata = {
'mpris:trackid': player.objectPath('track/' + metadata.trackId),
'mpris:artUrl': metadata.artwork[0].src,

View File

@ -180,6 +180,10 @@ export default {
exit: 'Exit',
minimizeToTray: 'Minimize to tray',
},
enableOsdlyricsSupport: {
title: 'desktop lyrics support',
desc: 'Only takes effect under Linux. After enable, I will download the lyrics file to the local, and try to launch OSDLyrics at startup',
},
unm: {
enable: 'Enable',
audioSource: {

View File

@ -181,6 +181,10 @@ export default {
exit: '退出',
minimizeToTray: '最小化到托盘',
},
enableOsdlyricsSupport: {
title: '桌面歌词支持',
desc: '仅 Linux 下生效,开启后将会下载歌词文件到本地,并会尝试在启动时拉起 OSDLyrics。',
},
unm: {
enable: '启用',
audioSource: {

View File

@ -178,6 +178,10 @@ export default {
exit: '退出',
minimizeToTray: '最小化到工作列角落',
},
enableOsdlyricsSupport: {
title: '桌面歌詞支持',
desc: '僅 Linux 下生效,開啟後將會下載歌詞文件到本地,並會嘗試在啟動時拉起 OSDLyrics',
},
unm: {
enable: '啟用',
audioSource: {

View File

@ -23,6 +23,7 @@ let localStorage = {
nyancatStyle: false,
showLyricsTranslation: true,
lyricsBackground: true,
enableOsdlyricsSupport: false,
closeAppOption: 'ask',
enableDiscordRichPresence: false,
enableGlobalShortcut: true,

View File

@ -3,7 +3,7 @@ import { getArtist } from '@/api/artist';
import { trackScrobble, trackUpdateNowPlaying } from '@/api/lastfm';
import { fmTrash, personalFM } from '@/api/others';
import { getPlaylistDetail, intelligencePlaylist } from '@/api/playlist';
import { getMP3, getTrackDetail, scrobble } from '@/api/track';
import { getLyric, getMP3, getTrackDetail, scrobble } from '@/api/track';
import store from '@/store';
import { isAccountLoggedIn } from '@/utils/auth';
import { cacheTrackSource, getTrackSource } from '@/utils/db';
@ -616,9 +616,29 @@ export default class {
navigator.mediaSession.metadata = new window.MediaMetadata(metadata);
if (isCreateMpris) {
ipcRenderer?.send('metadata', metadata);
this._updateMprisState(track, metadata);
}
}
// OSDLyrics 会检测 Mpris 状态并寻找对应歌词文件,所以要在更新 Mpris 状态之前保证歌词下载完成
async _updateMprisState(track, metadata) {
if (!store.state.settings.enableOsdlyricsSupport) {
return ipcRenderer?.send('metadata', metadata);
}
let lyricName = track.ar.map(ar => ar.name).join(', ') + '-' + track.name;
let lyricContent = await getLyric(track.id);
if (!lyricContent.lrc.lyric) {
return ipcRenderer?.send('metadata', metadata);
}
ipcRenderer.send('saveLyric', {
name: lyricName,
lyric: lyricContent.lrc.lyric,
});
ipcRenderer.on('saveLyricFinished', () => {
ipcRenderer?.send('metadata', metadata);
});
}
_updateMediaSessionPositionState() {
if ('mediaSession' in navigator === false) {
return;

View File

@ -239,6 +239,31 @@
</select>
</div>
</div>
<div v-if="isElectron && isLinux" class="item">
<div class="left">
<div class="title">
{{ $t('settings.unm.enable') }}
<a target="_blank" href="https://github.com/osdlyrics/osdlyrics"
>OSDLyrics</a
>
{{ $t('settings.enableOsdlyricsSupport.title') }}
</div>
<div class="description">
{{ $t('settings.enableOsdlyricsSupport.desc') }}
</div>
</div>
<div class="right">
<div class="toggle">
<input
id="enable-osdlyrics-support"
v-model="enableOsdlyricsSupport"
type="checkbox"
name="enable-osdlyrics-support"
/>
<label for="enable-osdlyrics-support"></label>
</div>
</div>
</div>
<section v-if="isElectron" class="unm-configuration">
<h3>UnblockNeteaseMusic</h3>
@ -963,6 +988,17 @@ export default {
});
},
},
enableOsdlyricsSupport: {
get() {
return this.settings.enableOsdlyricsSupport;
},
set(value) {
this.$store.commit('updateSettings', {
key: 'enableOsdlyricsSupport',
value,
});
},
},
closeAppOption: {
get() {
return this.settings.closeAppOption;