From c7b3921514c805fb73f16acd342947157936aa68 Mon Sep 17 00:00:00 2001 From: Mastermindzh Date: Sat, 12 Aug 2023 15:02:23 +0200 Subject: [PATCH] Added app suspension inhibitors when music is playing. fixes #257 --- CHANGELOG.md | 1 + package.json | 2 +- src/features/idleInhibitor/idleInhibitor.ts | 65 +++++++++++++++++++++ src/features/logger.ts | 14 +++-- src/main.ts | 15 ++++- 5 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 src/features/idleInhibitor/idleInhibitor.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bed8a5..655ce66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for Wayland (on by default) fixes [#262](https://github.com/Mastermindzh/tidal-hifi/issues/262) and [#157](https://github.com/Mastermindzh/tidal-hifi/issues/157) - Made it clear in the readme that this tidal-hifi client supports High & Max audio settings. fixes [#261](https://github.com/Mastermindzh/tidal-hifi/issues/261) +- Added app suspension inhibitors when music is playing. fixes [#257](https://github.com/Mastermindzh/tidal-hifi/issues/257) - Fixed bug with theme files from user directory trying to load: "an error occurred reading the theme file" - Fixed: config flags not being set correctly - [DEV]: diff --git a/package.json b/package.json index 08b6fc1..e587566 100644 --- a/package.json +++ b/package.json @@ -72,4 +72,4 @@ "typescript": "^5.1.6" }, "prettier": "@mastermindzh/prettier-config" -} \ No newline at end of file +} diff --git a/src/features/idleInhibitor/idleInhibitor.ts b/src/features/idleInhibitor/idleInhibitor.ts new file mode 100644 index 0000000..10b43c0 --- /dev/null +++ b/src/features/idleInhibitor/idleInhibitor.ts @@ -0,0 +1,65 @@ +import { PowerSaveBlocker, powerSaveBlocker } from "electron"; +import { Logger } from "../logger"; + +/** + * Start blocking idle/screen timeouts + * @param blocker optional instance of the powerSaveBlocker to use + * @returns id of current block + */ +export const acquireInhibitor = (blocker?: PowerSaveBlocker): number => { + const currentBlocker = blocker ?? powerSaveBlocker; + const blockId = currentBlocker.start("prevent-app-suspension"); + Logger.log(`Started preventing app suspension with id: ${blockId}`); + return blockId; +}; + +/** + * Check whether there is a blocker active for the current id, if not start it. + * @param id id of inhibitor you want to check activity against + * @param blocker optional instance of the powerSaveBlocker to use + */ +export const acquireInhibitorIfInactive = (id: number, blocker?: PowerSaveBlocker): number => { + const currentBlocker = blocker ?? powerSaveBlocker; + if (!isInhibitorActive(id, currentBlocker)) { + return acquireInhibitor(); + } + + return id; +}; + +/** + * stop blocking idle/screen timeouts + * @param id id of inhibitor you want to check activity against + * @param blocker optional instance of the powerSaveBlocker to use + */ +export const releaseInhibitor = (id: number, blocker?: PowerSaveBlocker) => { + try { + const currentBlocker = blocker ?? powerSaveBlocker; + currentBlocker.stop(id); + Logger.log(`Released inhibitor with id: ${id}`); + } catch (error) { + Logger.log("Releasing inhibitor failed"); + } +}; + +/** + * stop blocking idle/screen timeouts if a inhibitor is active + * @param id id of inhibitor you want to check activity against + * @param blocker optional instance of the powerSaveBlocker to use + */ +export const releaseInhibitorIfActive = (id: number, blocker?: PowerSaveBlocker) => { + const currentBlocker = blocker ?? powerSaveBlocker; + if (isInhibitorActive(id, currentBlocker)) { + releaseInhibitor(id, currentBlocker); + } +}; + +/** + * check whether the inhibitor is active + * @param id id of inhibitor you want to check activity against + * @param blocker optional instance of the powerSaveBlocker to use + */ +export const isInhibitorActive = (id: number, blocker?: PowerSaveBlocker) => { + const currentBlocker = blocker ?? powerSaveBlocker; + return currentBlocker.isStarted(id); +}; diff --git a/src/features/logger.ts b/src/features/logger.ts index 2aa184e..b233f8c 100644 --- a/src/features/logger.ts +++ b/src/features/logger.ts @@ -1,4 +1,4 @@ -import { IpcMain, ipcRenderer, ipcMain } from "electron"; +import { IpcMain, ipcMain, IpcMainEvent, ipcRenderer } from "electron"; import { globalEvents } from "../constants/globalEvents"; export class Logger { @@ -7,10 +7,13 @@ export class Logger { * @param ipcMain main thread IPC client so we can subscribe to events */ public static watch(ipcMain: IpcMain) { - ipcMain.on(globalEvents.log, (event, message) => { - const { content, object } = message; - this.logToSTDOut(content, object); - }); + ipcMain.on( + globalEvents.log, + (event: IpcMainEvent | { content: string; message: string }, message) => { + const { content, object } = message ?? event; + this.logToSTDOut(content, object); + } + ); } /** * Log content to STDOut @@ -23,7 +26,6 @@ export class Logger { } else { ipcMain.emit(globalEvents.log, { content, object }); } - this.logToSTDOut(content, object); } /** diff --git a/src/main.ts b/src/main.ts index 24ea755..216bd07 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,7 +1,7 @@ import { enable, initialize } from "@electron/remote/main"; import { - BrowserWindow, app, + BrowserWindow, components, globalShortcut, ipcMain, @@ -13,9 +13,14 @@ import { globalEvents } from "./constants/globalEvents"; import { mediaKeys } from "./constants/mediaKeys"; import { settings } from "./constants/settings"; import { setDefaultFlags, setManagedFlagsFromSettings } from "./features/flags/flags"; +import { + acquireInhibitorIfInactive, + releaseInhibitorIfActive, +} from "./features/idleInhibitor/idleInhibitor"; import { Logger } from "./features/logger"; import { Songwhip } from "./features/songwhip/songwhip"; import { MediaInfo } from "./models/mediaInfo"; +import { MediaStatus } from "./models/mediaStatus"; import { initRPC, rpc, unRPC } from "./scripts/discord"; import { startExpress } from "./scripts/express"; import { updateMediaInfo } from "./scripts/mediaInfo"; @@ -29,6 +34,7 @@ import { } from "./scripts/settings"; import { addTray, refreshTray } from "./scripts/tray"; const tidalUrl = "https://listen.tidal.com"; +let mainInhibitorId = -1; initialize(); @@ -106,6 +112,7 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) { }); // Emitted when the window is closed. mainWindow.on("closed", function () { + releaseInhibitorIfActive(mainInhibitorId); closeSettingsWindow(); app.quit(); }); @@ -178,6 +185,12 @@ app.on("browser-window-created", (_, window) => { // IPC ipcMain.on(globalEvents.updateInfo, (_event, arg: MediaInfo) => { updateMediaInfo(arg); + if (arg.status === MediaStatus.playing) { + mainInhibitorId = acquireInhibitorIfInactive(mainInhibitorId); + } else { + releaseInhibitorIfActive(mainInhibitorId); + mainInhibitorId = -1; + } }); ipcMain.on(globalEvents.hideSettings, () => {