diff --git a/publish/changeLog.md b/publish/changeLog.md index 64643a7b..fc90efcd 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -1,4 +1,3 @@ ### 新增 -- 新增「设置 → 其他设置 → 主窗口使用软件内置的圆角及阴影」设置(#2360) - *默认启用,关闭后将使用系统原生的窗口样式,该设置重启软件后生效* +- 开放API新增播放器声音大小、静音、播放进度控制,详情看接入文档(#2386) diff --git a/src/common/types/player.d.ts b/src/common/types/player.d.ts index 4a67248f..754f1bbe 100644 --- a/src/common/types/player.d.ts +++ b/src/common/types/player.d.ts @@ -11,6 +11,9 @@ declare namespace LX { | 'pause' | 'play' | 'next' + | 'seek' + | 'volume' + | 'mute' interface LyricInfo extends LX.Music.LyricInfo { rawlrcInfo: LX.Music.LyricInfo @@ -29,6 +32,8 @@ declare namespace LX { lyricLineAllText: string lyric: string collect: boolean + volume: number + mute: boolean } } } diff --git a/src/main/app.ts b/src/main/app.ts index ee59de4c..fc04b381 100644 --- a/src/main/app.ts +++ b/src/main/app.ts @@ -65,6 +65,8 @@ export const initGlobalData = () => { lyricLineAllText: '', lyric: '', collect: false, + volume: 0, + mute: false, }, } @@ -230,6 +232,15 @@ export const listenerAppEvent = (startApp: () => void) => { global.lx.theme.shouldUseDarkColors = shouldUseDarkColors global.lx?.event_app.system_theme_change(shouldUseDarkColors) }) + + global.lx.event_app.on('updated_config', (config, setting) => { + if (config.includes('player.volume')) { + global.lx.event_app.player_status({ volume: Math.trunc(setting['player.volume']! * 100) }) + } + if (config.includes('player.isMute')) { + global.lx.event_app.player_status({ mute: setting['player.isMute'] }) + } + }) } const initTheme = () => { diff --git a/src/main/modules/openApi/index.ts b/src/main/modules/openApi/index.ts index ce2c59d3..5475c0bb 100644 --- a/src/main/modules/openApi/index.ts +++ b/src/main/modules/openApi/index.ts @@ -142,12 +142,44 @@ const handleStartServer = async(port: number, ip: string) => new Promise(( case '/skip-prev': sendTaskbarButtonClick('prev') break + case '/seek': { + const offset = parseFloat(querystring.parse(query ?? '').offset as string) + if (Number.isNaN(offset) || offset < 0 || offset > global.lx.player_status.duration) { + code = 400 + msg = 'Invalid offset' + } else { + sendTaskbarButtonClick('seek', parseFloat(offset.toFixed(3))) + } + break + } case '/collect': sendTaskbarButtonClick('collect') break case '/uncollect': sendTaskbarButtonClick('unCollect') break + case '/volume': { + const volume = parseInt(querystring.parse(query ?? '').volume as string) + if (Number.isNaN(volume) || volume < 0 || volume > 100) { + code = 400 + msg = 'Invalid volume' + } else { + sendTaskbarButtonClick('volume', volume / 100) + } + break + } + case '/mute': { + const mute = querystring.parse(query ?? '').mute + if (mute == 'true') { + sendTaskbarButtonClick('mute', true) + } else if (mute == 'false') { + sendTaskbarButtonClick('mute', false) + } else { + code = 400 + msg = 'Invalid mute value' + } + break + } case '/subscribe-player-status': try { handleSubscribePlayerStatus(req, res, query) diff --git a/src/main/modules/winMain/rendererEvent/app.ts b/src/main/modules/winMain/rendererEvent/app.ts index 677f5a11..a4d09102 100644 --- a/src/main/modules/winMain/rendererEvent/app.ts +++ b/src/main/modules/winMain/rendererEvent/app.ts @@ -137,8 +137,8 @@ export const sendFocus = () => { sendEvent(WIN_MAIN_RENDERER_EVENT_NAME.focus) } -export const sendTaskbarButtonClick = (action: LX.Player.StatusButtonActions) => { - sendEvent(WIN_MAIN_RENDERER_EVENT_NAME.player_action_on_button_click, action) +export const sendTaskbarButtonClick = (action: LX.Player.StatusButtonActions, data?: unknown) => { + sendEvent(WIN_MAIN_RENDERER_EVENT_NAME.player_action_on_button_click, { action, data }) } export const sendConfigChange = (setting: Partial) => { sendEvent(WIN_MAIN_RENDERER_EVENT_NAME.on_config_change, setting) diff --git a/src/renderer/core/useApp/usePlayer/usePlayStatus.ts b/src/renderer/core/useApp/usePlayer/usePlayStatus.ts index f6b185dc..e40a408c 100644 --- a/src/renderer/core/useApp/usePlayer/usePlayStatus.ts +++ b/src/renderer/core/useApp/usePlayer/usePlayStatus.ts @@ -81,7 +81,7 @@ export default () => { // buttons.lockLrc = setting.desktopLyric.isLock // setButtons() // } - const rTaskbarThumbarClick = onPlayerAction(async({ params: action }) => { + const rTaskbarThumbarClick = onPlayerAction(async({ params: { action, data } }) => { switch (action) { case 'play': play() @@ -105,6 +105,19 @@ export default () => { void removeListMusics({ listId: loveList.id, ids: ['progress' in playMusicInfo.musicInfo ? playMusicInfo.musicInfo.metadata.musicInfo.id : playMusicInfo.musicInfo.id] }) if (await updateCollectStatus()) sendPlayerStatus({ collect }) break + case 'seek': { + let progress = data as number + if (progress < 0) progress = 0 + else if (progress > playProgress.maxPlayTime) progress = playProgress.maxPlayTime + window.app_event.setProgress(progress) + break + } + case 'mute': + window.app_event.setVolumeIsMute(data as boolean) + break + case 'volume': + window.app_event.setVolume(data as number) + break // case 'lrc': // setVisibleDesktopLyric(true) // updateSetting() diff --git a/src/renderer/utils/ipc.ts b/src/renderer/utils/ipc.ts index 643ef16f..ca4b8a70 100644 --- a/src/renderer/utils/ipc.ts +++ b/src/renderer/utils/ipc.ts @@ -476,7 +476,10 @@ export const hotKeyGetStatus = async() => { } // 主进程操作播放器状态 -export const onPlayerAction = (listener: LX.IpcRendererEventListenerParams): RemoveListener => { +export const onPlayerAction = (listener: LX.IpcRendererEventListenerParams<{ + action: LX.Player.StatusButtonActions + data?: unknown +}>): RemoveListener => { rendererOn(WIN_MAIN_RENDERER_EVENT_NAME.player_action_on_button_click, listener) return () => { rendererOff(WIN_MAIN_RENDERER_EVENT_NAME.player_action_on_button_click, listener)