diff --git a/publish/changeLog.md b/publish/changeLog.md index db1fecf1..814bca77 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -12,6 +12,7 @@ - 若自定义源初始化失败,将会出现弹窗提示初始化失败的详情 - 添加win7_x64架构的安装版安装包构建 +- 新增播放歌曲时阻止电脑休眠,默认启用,可到设置-播放设置关闭(#1563) ### 优化 @@ -34,6 +35,10 @@ - 修复临时列表变更会意外触发同步的问题 - 修复最小化后再隐藏窗口时,托盘菜单的显示主界面功能异常的问题 +### 变更 + +- 播放歌曲时默认会阻止系统进入休眠状态,若你不行软件阻止系统休眠,可以到设置-播放设置取消勾选“播放歌曲时阻止电脑休眠”设置 + ### 其他 - 移除所有内置源,由于收到腾讯投诉要求停止提供软件内置的连接到他们平台的在线播放及下载服务,所以从即日(2023年10月18日)起LX本身不再提供上述服务 diff --git a/src/common/defaultSetting.ts b/src/common/defaultSetting.ts index a841f46f..26f32eb5 100644 --- a/src/common/defaultSetting.ts +++ b/src/common/defaultSetting.ts @@ -27,6 +27,7 @@ const defaultSetting: LX.AppSetting = { 'player.highQuality': false, 'player.isShowTaskProgess': true, 'player.volume': 1, + 'player.powerSaveBlocker': true, 'player.isMute': false, 'player.playbackRate': 1, 'player.preservesPitch': true, diff --git a/src/common/ipcNames.ts b/src/common/ipcNames.ts index 0a23c158..95adb1e1 100644 --- a/src/common/ipcNames.ts +++ b/src/common/ipcNames.ts @@ -57,6 +57,7 @@ const modules = { show_dialog: 'show_dialog', open_dir_in_explorer: 'open_dir_in_explorer', open_dev_tools: 'open_dev_tools', + set_power_save_blocker: 'set_power_save_blocker', progress: 'progress', change_tray: 'change_tray', diff --git a/src/common/types/app_setting.d.ts b/src/common/types/app_setting.d.ts index aa54338f..7cf5cf3e 100644 --- a/src/common/types/app_setting.d.ts +++ b/src/common/types/app_setting.d.ts @@ -103,6 +103,11 @@ declare global { */ 'player.volume': number + /** + * 播放歌曲时是否阻止电脑休眠 + */ + 'player.powerSaveBlocker': boolean + /** * 是否静音 */ diff --git a/src/lang/en-us.json b/src/lang/en-us.json index b3dfb928..b855de3d 100644 --- a/src/lang/en-us.json +++ b/src/lang/en-us.json @@ -508,6 +508,7 @@ "setting__play_mediaDevice_title": "Select a media device for audio output", "setting__play_media_device_error_tip": "This function conflicts with advanced audio functions (audio visualization, sound effect settings). These functions have been enabled when you start the software this time. This setting is not available for now. Please close these functions and restart the software before modifying this setting.", "setting__play_media_device_tip": "This feature conflicts with Audio Visualization, both cannot be enabled at the same time, would you like to turn Audio Visualization off and apply the selected audio output settings?", + "setting__play_power_save_blocker": "Prevent computer from sleeping while playing songs", "setting__play_quality": "Priority playback of 320K quality songs (if available)", "setting__play_save_play_time": "Remember playback progress", "setting__play_startup_auto_play": "Play music automatically after launching the software", diff --git a/src/lang/zh-cn.json b/src/lang/zh-cn.json index bd78a104..473af09e 100644 --- a/src/lang/zh-cn.json +++ b/src/lang/zh-cn.json @@ -508,6 +508,7 @@ "setting__play_mediaDevice_title": "选择声音输出的媒体设备", "setting__play_media_device_error_tip": "此功能与高级音频功能(音频可视化、音效设置)冲突,你本次启动软件时已启用这些功能,此设置暂不可用,请 关闭这些功能 并 重启 软件后,再来修改此设置。", "setting__play_media_device_tip": "此功能与音频可视化功能冲突,两者无法同时启用,是否将音频可视化关闭 并 应用所选音频输出设置?", + "setting__play_power_save_blocker": "播放歌曲时阻止电脑休眠", "setting__play_quality": "优先播放320K品质的歌曲(如果可用)", "setting__play_save_play_time": "记住播放进度", "setting__play_startup_auto_play": "启动软件后自动播放音乐", diff --git a/src/lang/zh-tw.json b/src/lang/zh-tw.json index 96bdac0b..6c24a174 100644 --- a/src/lang/zh-tw.json +++ b/src/lang/zh-tw.json @@ -508,6 +508,7 @@ "setting__play_mediaDevice_title": "選擇聲音輸出的媒體設備", "setting__play_media_device_error_tip": "此功能與進階音訊功能(音訊視覺化、音效設定)衝突,你本次啟動軟體時已啟用這些功能,此設定暫不可用,請 關閉這些功能 並 重新啟動 軟體後,再來修改此設定。", "setting__play_media_device_tip": "此功能與音訊視覺化功能衝突,兩者無法同時啟用,是否將音訊視覺化關閉 並 應用所選音訊輸出設定?", + "setting__play_power_save_blocker": "播放歌曲時阻止電腦休眠", "setting__play_quality": "優先播放320K品質的歌曲(如果可用)", "setting__play_save_play_time": "記住播放進度", "setting__play_startup_auto_play": "啟動軟體後自動播放音樂", diff --git a/src/main/modules/winMain/rendererEvent/app.ts b/src/main/modules/winMain/rendererEvent/app.ts index bcf13882..55702e3b 100644 --- a/src/main/modules/winMain/rendererEvent/app.ts +++ b/src/main/modules/winMain/rendererEvent/app.ts @@ -25,7 +25,7 @@ import { showSaveDialog, } from '@main/modules/winMain' import { quitApp } from '@main/app' -import { getAllThemes, removeTheme, saveTheme } from '@main/utils' +import { getAllThemes, removeTheme, saveTheme, setPowerSaveBlocker } from '@main/utils' import { openDirInExplorer } from '@common/utils/electron' export default () => { @@ -55,6 +55,9 @@ export default () => { mainOn(WIN_MAIN_RENDERER_EVENT_NAME.focus, () => { showWindow() }) + mainOn(WIN_MAIN_RENDERER_EVENT_NAME.set_power_save_blocker, ({ params: enabled }) => { + setPowerSaveBlocker(enabled) + }) mainOn(WIN_MAIN_RENDERER_EVENT_NAME.close, ({ params: isForce }) => { if (isForce) { app.exit(0) diff --git a/src/main/utils/index.ts b/src/main/utils/index.ts index a5ba5630..8e399750 100644 --- a/src/main/utils/index.ts +++ b/src/main/utils/index.ts @@ -5,7 +5,7 @@ import { STORE_NAMES, URL_SCHEME_RXP } from '@common/constants' import defaultSetting from '@common/defaultSetting' import defaultHotKey from '@common/defaultHotKey' import { migrateDataJson, migrateHotKey, migrateUserApi, parseDataFile } from './migrate' -import { nativeTheme } from 'electron' +import { nativeTheme, powerSaveBlocker } from 'electron' import { joinPath } from '@common/utils/nodejs' import themes from '@common/theme/index.json' @@ -280,3 +280,15 @@ export const getTheme = () => { }, } } + +let powerSaveBlockerId: number | null = null +export const setPowerSaveBlocker = (enabled: boolean) => { + let isEnabled = powerSaveBlockerId != null && powerSaveBlocker.isStarted(powerSaveBlockerId) + if (enabled) { + if (isEnabled) return + powerSaveBlockerId = powerSaveBlocker.start('prevent-app-suspension') + } else { + if (!isEnabled) return + if (powerSaveBlocker.stop(powerSaveBlockerId!)) powerSaveBlockerId = null + } +} diff --git a/src/renderer/core/player/utils.ts b/src/renderer/core/player/utils.ts index ef32a889..f5cab285 100644 --- a/src/renderer/core/player/utils.ts +++ b/src/renderer/core/player/utils.ts @@ -3,6 +3,7 @@ import { qualityList } from '@renderer/store' import { clearPlayedList } from '@renderer/store/player/action' import { appSetting } from '@renderer/store/setting' import { dislikeInfo } from '@renderer/store/dislikeList' +import { setPowerSaveBlocker as setPowerSaveBlockerRemote } from '@renderer/utils/ipc' export const getPlayType = (highQuality: boolean, musicInfo: LX.Music.MusicInfo | LX.Download.ListItem): LX.Quality | null => { if ('progress' in musicInfo || musicInfo.source == 'local') return null @@ -41,3 +42,24 @@ export const filterList = async({ playedList, listId, list, playerMusicInfo, isN return { filteredList: markRawList(filteredList), playerIndex } } +let timeout: NodeJS.Timer | null = null +const clearTimer = () => { + if (!timeout) return + clearTimeout(timeout) + timeout = null +} +export const setPowerSaveBlocker = (enabled: boolean, force = false) => { + if (enabled) { + clearTimer() + if (!force && !appSetting['player.powerSaveBlocker']) return + setPowerSaveBlockerRemote(true) + } else if (force) { + clearTimer() + setPowerSaveBlockerRemote(false) + } else { + if (timeout) return + timeout = setTimeout(() => { + setPowerSaveBlockerRemote(false) + }, 60_000 * 1.5) + } +} diff --git a/src/renderer/core/useApp/usePlayer/usePlayer.ts b/src/renderer/core/useApp/usePlayer/usePlayer.ts index fa29136b..d3a69d42 100644 --- a/src/renderer/core/useApp/usePlayer/usePlayer.ts +++ b/src/renderer/core/useApp/usePlayer/usePlayer.ts @@ -32,6 +32,7 @@ import { HOTKEY_PLAYER } from '@common/hotKey' import { playNext, pause, playPrev, togglePlay, collectMusic, uncollectMusic, dislikeMusic } from '@renderer/core/player' import usePlaybackRate from './usePlaybackRate' import useSoundEffect from './useSoundEffect' +import { setPowerSaveBlocker } from '@renderer/core/player/utils' export default () => { @@ -53,12 +54,20 @@ export default () => { void playPrev() } + const addPowerSaveBlocker = () => { + setPowerSaveBlocker(true) + } + const removePowerSaveBlocker = () => { + setPowerSaveBlocker(false) + } + const setPlayStatus = () => { setPlay(true) } const setPauseStatus = () => { setPlay(false) if (window.lx.isPlayedStop) pause() + removePowerSaveBlocker() } const handleUpdatePlayInfo = () => { @@ -88,6 +97,7 @@ export default () => { setTitle(null) setAllStatus('') setStop() + removePowerSaveBlocker() } watch(() => appSetting['player.togglePlayMethod'], newValue => { @@ -112,6 +122,8 @@ export default () => { window.app_event.on('stop', setStopStatus) window.app_event.on('musicToggled', handleUpdatePlayInfo) window.app_event.on('playerCanplay', handleCanplay) + window.app_event.on('playerPlaying', addPowerSaveBlocker) + window.app_event.on('playerEmptied', removePowerSaveBlocker) window.app_event.on('playerEnded', handleEnded) @@ -132,7 +144,9 @@ export default () => { window.app_event.off('error', setPauseStatus) window.app_event.off('stop', setStopStatus) window.app_event.off('musicToggled', handleUpdatePlayInfo) - window.app_event.on('playerCanplay', handleCanplay) + window.app_event.off('playerPlaying', addPowerSaveBlocker) + window.app_event.off('playerEmptied', removePowerSaveBlocker) + window.app_event.off('playerCanplay', handleCanplay) window.app_event.off('playerEnded', handleEnded) }) diff --git a/src/renderer/utils/ipc.ts b/src/renderer/utils/ipc.ts index a7b1b40a..77d9a632 100644 --- a/src/renderer/utils/ipc.ts +++ b/src/renderer/utils/ipc.ts @@ -687,6 +687,12 @@ export const showHideWindowToggle = () => { export const focusWindow = () => { rendererSend(WIN_MAIN_RENDERER_EVENT_NAME.focus) } +/** + * 是否启用电源锁 + */ +export const setPowerSaveBlocker = (enabled: boolean) => { + rendererSend(WIN_MAIN_RENDERER_EVENT_NAME.set_power_save_blocker, enabled) +} /** * 窗口获取焦点事件 diff --git a/src/renderer/views/Setting/components/SettingPlay.vue b/src/renderer/views/Setting/components/SettingPlay.vue index 048d2dfe..0eb39f95 100644 --- a/src/renderer/views/Setting/components/SettingPlay.vue +++ b/src/renderer/views/Setting/components/SettingPlay.vue @@ -3,6 +3,8 @@ dt#play {{ $t('setting__play') }} dd .gap-top base-checkbox(id="setting_player_startup_auto_play" :model-value="appSetting['player.startupAutoPlay']" :label="$t('setting__play_startup_auto_play')" @update:model-value="updateSetting({'player.startupAutoPlay': $event})") + .gap-top + base-checkbox(id="setting_player_power_save_blocker" :model-value="appSetting['player.powerSaveBlocker']" :label="$t('setting__play_power_save_blocker')" @update:model-value="handleUpdatePowerSaveBlocker") .gap-top base-checkbox(id="setting_player_save_play_time" :model-value="appSetting['player.isSavePlayTime']" :label="$t('setting__play_save_play_time')" @update:model-value="updateSetting({'player.isSavePlayTime': $event})") .gap-top @@ -35,6 +37,8 @@ import { hasInitedAdvancedAudioFeatures } from '@renderer/plugins/player' import { dialog } from '@renderer/plugins/Dialog' import { useI18n } from '@renderer/plugins/i18n' import { appSetting, updateSetting } from '@renderer/store/setting' +import { setPowerSaveBlocker } from '@renderer/core/player/utils' +import { isPlay } from '@renderer/store/player/state' export default { @@ -84,6 +88,15 @@ export default { mediaDeviceId.value = val }) + const handleUpdatePowerSaveBlocker = (enabled) => { + if (enabled) { + if (isPlay.value) setPowerSaveBlocker(true, true) + } else { + setPowerSaveBlocker(false, true) + } + updateSetting({ 'player.powerSaveBlocker': enabled }) + } + return { appSetting, @@ -91,6 +104,7 @@ export default { mediaDevices, mediaDeviceId, handleMediaDeviceIdChnage, + handleUpdatePowerSaveBlocker, } }, }