diff --git a/CHANGELOG.md b/CHANGELOG.md index 30dfac4..1bec63d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 2.1.1 + +- The discord integration now doesn't send an update every 15 seconds it sends an update whenever the media info changes +- consolidated updating the media info changes with the status changes into a single global event + ## 2.1.0 - [Mar0xy](https://github.com/Mar0xy) added Discord integration. diff --git a/package.json b/package.json index 0b8db6e..f4ba291 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tidal-hifi", - "version": "2.1.0", + "version": "2.1.1", "description": "Tidal on Electron with widevine(hifi) support", "main": "src/main.js", "scripts": { diff --git a/src/constants/globalEvents.js b/src/constants/globalEvents.js index 191fd12..22f47d4 100644 --- a/src/constants/globalEvents.js +++ b/src/constants/globalEvents.js @@ -7,7 +7,6 @@ const globalEvents = { updateInfo: "update-info", hideSettings: "hideSettings", showSettings: "showSettings", - updateStatus: "update-status", storeChanged: "storeChanged", error: "error", }; diff --git a/src/main.js b/src/main.js index 28ca3c7..45f61f0 100644 --- a/src/main.js +++ b/src/main.js @@ -17,7 +17,6 @@ const mediaInfoModule = require("./scripts/mediaInfo"); const discordModule = require("./scripts/discord"); const globalEvents = require("./constants/globalEvents"); - let mainWindow; let icon = path.join(__dirname, "../assets/icon.png"); @@ -98,7 +97,6 @@ app.on("activate", function () { }); // IPC - ipcMain.on(globalEvents.updateInfo, (event, arg) => { mediaInfoModule.update(arg); }); @@ -110,15 +108,12 @@ ipcMain.on(globalEvents.showSettings, (event, arg) => { showSettingsWindow(); }); -ipcMain.on(globalEvents.updateStatus, (event, arg) => { - mediaInfoModule.updateStatus(arg); -}); ipcMain.on(globalEvents.storeChanged, (event, arg) => { mainWindow.setMenuBarVisibility(store.get(settings.menuBar)); - if(store.get(settings.enableDiscord) && !discordModule.rpc) { + if (store.get(settings.enableDiscord) && !discordModule.rpc) { discordModule.initRPC(); - } else if(!store.get(settings.enableDiscord) && discordModule.rpc) { + } else if (!store.get(settings.enableDiscord) && discordModule.rpc) { discordModule.unRPC(); } }); diff --git a/src/preload.js b/src/preload.js index d2a5c8c..10ad1be 100644 --- a/src/preload.js +++ b/src/preload.js @@ -1,4 +1,4 @@ -const { setTitle, getTitle } = require("./scripts/window-functions"); +const { setTitle } = require("./scripts/window-functions"); const { dialog, process } = require("electron").remote; const { store, settings } = require("./scripts/settings"); const { ipcRenderer } = require("electron"); @@ -11,6 +11,7 @@ const notifier = require("node-notifier"); const notificationPath = `${app.getPath("userData")}/notification.jpg`; let currentSong = ""; let player; +let currentPlayStatus = statuses.paused; const elements = { play: '*[data-test="play"]', @@ -18,7 +19,7 @@ const elements = { next: '*[data-test="next"]', previous: 'button[data-test="previous"]', title: '*[data-test^="footer-track-title"]', - artists: '*[class^="css-14o5h2y"]', + artists: '*[data-test^="grid-item-detail-text-title-artist"]', home: '*[data-test="menu--home"]', back: '[class^="backwardButton"]', forward: '[class^="forwardButton"]', @@ -200,9 +201,9 @@ function addIPCEventListeners() { /** * Update the current status of tidal (e.g playing or paused) */ -function updateStatus() { +function getCurrentlyPlayingStatus() { let pause = elements.get("pause"); - let status; + let status = undefined; // if pause button is visible tidal is playing if (pause) { @@ -210,11 +211,29 @@ function updateStatus() { } else { status = statuses.paused; } + return status; +} + +/** + * Update Tidal-hifi's media info + * + * @param {*} options + */ +function updateMediaInfo(options, notify) { + if (options) { + ipcRenderer.send(globalEvents.updateInfo, options); + store.get(settings.notifications) && notify && notifier.notify(options); - if (status) { - ipcRenderer.send(globalEvents.updateStatus, status); if (player) { - player.playbackStatus = status == statuses.paused ? "Paused" : "Playing"; + player.metadata = { + ...player.metadata, + ...{ + "xesam:title": options.title, + "xesam:artist": [options.artists], + "mpris:artUrl": options.image, + }, + }; + player.playbackStatus = options.status == statuses.paused ? "Paused" : "Playing"; } } } @@ -227,56 +246,47 @@ setInterval(function () { const url = elements.get("url").href.replace(/[^0-9]/g, ""); const artists = elements.getText("artists"); const songDashArtistTitle = `${title} - ${artists}`; + const currentStatus = getCurrentlyPlayingStatus(); + const options = { + title, + message: artists, + status: currentStatus, + url: `https://tidal.com/browse/track/${url}`, + }; - updateStatus(); + const playStatusChanged = currentStatus !== currentPlayStatus; + const titleOrArtistChanged = currentSong !== songDashArtistTitle; - if (getTitle() !== songDashArtistTitle) { + if (titleOrArtistChanged || playStatusChanged) { + // update title and play info with new info setTitle(songDashArtistTitle); + currentSong = songDashArtistTitle; + currentPlayStatus = currentStatus; - if (currentSong !== songDashArtistTitle) { - currentSong = songDashArtistTitle; - const image = elements.getSongIcon(); + const image = elements.getSongIcon(); - const options = { - title, - message: artists, - url: `https://tidal.com/browse/track/${url}`, - }; - new Promise((resolve, reject) => { - if (image.startsWith("http")) { - downloadFile(image, notificationPath).then( - () => { - options.icon = notificationPath; - resolve(); - }, - () => { - // if the image can't be downloaded then continue without it - resolve(); - } - ); - } else { - // if the image can't be found on the page continue without it - resolve(); - } - }).then( - () => { - ipcRenderer.send(globalEvents.updateInfo, options); - store.get(settings.notifications) && notifier.notify(options); - - if (player) { - player.metadata = { - ...player.metadata, - ...{ - "xesam:title": title, - "xesam:artist": [artists], - "mpris:artUrl": image, - }, - }; + new Promise((resolve) => { + if (image.startsWith("http")) { + downloadFile(image, notificationPath).then( + () => { + options.icon = notificationPath; + resolve(); + }, + () => { + // if the image can't be downloaded then continue without it + resolve(); } - }, - () => {} - ); - } + ); + } else { + // if the image can't be found on the page continue without it + resolve(); + } + }).then( + () => { + updateMediaInfo(options, titleOrArtistChanged); + }, + () => {} + ); } }, 200); diff --git a/src/scripts/discord.js b/src/scripts/discord.js index cee1485..628d821 100644 --- a/src/scripts/discord.js +++ b/src/scripts/discord.js @@ -1,52 +1,57 @@ const discordrpc = require("discord-rpc"); -const clientId = '833617820704440341'; +const { ipcMain } = require("electron"); +const electron = require("electron"); +const globalEvents = require("../constants/globalEvents"); +const clientId = "833617820704440341"; const mediaInfoModule = require("./mediaInfo"); - const discordModule = []; -let discord; let rpc; +const observer = (event, arg) => { + if (mediaInfoModule.mediaInfo.status == "paused" && rpc) { + rpc.setActivity(idleStatus); + } else if (rpc) { + rpc.setActivity({ + ...idleStatus, + ...{ + details: `Listening to ${mediaInfoModule.mediaInfo.title}`, + state: mediaInfoModule.mediaInfo.artist, + buttons: [{ label: "Play on Tidal", url: mediaInfoModule.mediaInfo.url }], + }, + }); + } +}; const idleStatus = { - details: `Browsing Tidal`, - largeImageKey: 'tidal-hifi-icon', - largeImageText: 'Tidal HiFi 2.0.0', - instance: false, -} + details: `Browsing Tidal`, + largeImageKey: "tidal-hifi-icon", + largeImageText: `Tidal HiFi ${electron.app.getVersion()}`, + instance: false, +}; +/** + * Set up the discord rpc and listen on globalEvents.updateInfo + */ discordModule.initRPC = function () { - rpc = new discordrpc.Client({ transport: 'ipc' }); - rpc.login({ clientId }).catch(console.error); - discordModule.rpc = rpc; + rpc = new discordrpc.Client({ transport: "ipc" }); + rpc.login({ clientId }).catch(console.error); + discordModule.rpc = rpc; - rpc.on('ready', () => { - rpc.setActivity(idleStatus); - }) - - discord = setInterval(() => { - if (mediaInfoModule.mediaInfo.status == 'paused' && rpc) { - rpc.setActivity(idleStatus); - } else if (rpc) { - rpc.setActivity({ - details: `Listening to ${mediaInfoModule.mediaInfo.title}`, - state: mediaInfoModule.mediaInfo.artist, - largeImageKey: 'tidal-hifi-icon', - largeImageText: 'Tidal HiFi 2.0.0', - buttons: [ - { label: "Play on Tidal", url: mediaInfoModule.mediaInfo.url } - ], - instance: false, - }); - } - }, 15e3); -} + rpc.on("ready", () => { + rpc.setActivity(idleStatus); + }); + ipcMain.on(globalEvents.updateInfo, observer); +}; +/** + * Remove any RPC connection with discord and remove the event listener on globalEvents.updateInfo + */ discordModule.unRPC = function () { - clearInterval(discord); - rpc.clearActivity(); - rpc.destroy(); - rpc = false; - discordModule.rpc = rpc; -} + rpc.clearActivity(); + rpc.destroy(); + rpc = false; + discordModule.rpc = rpc; + ipcMain.removeListener(globalEvents.updateInfo, observer); +}; -module.exports = discordModule; \ No newline at end of file +module.exports = discordModule; diff --git a/src/scripts/mediaInfo.js b/src/scripts/mediaInfo.js index 9641e14..e7d7f62 100644 --- a/src/scripts/mediaInfo.js +++ b/src/scripts/mediaInfo.js @@ -5,7 +5,7 @@ const mediaInfo = { artist: "", icon: "", status: statuses.paused, - url: "" + url: "", }; const mediaInfoModule = { mediaInfo, @@ -14,20 +14,12 @@ const mediaInfoModule = { /** * Update artist and song info in the mediaInfo constant */ -mediaInfoModule.update = function(arg) { +mediaInfoModule.update = function (arg) { mediaInfo.title = propOrDefault(arg.title); mediaInfo.artist = propOrDefault(arg.message); mediaInfo.icon = propOrDefault(arg.icon); mediaInfo.url = propOrDefault(arg.url); -}; - -/** - * Update tidal's status in the mediaInfo constant - */ -mediaInfoModule.updateStatus = function(status) { - if (Object.values(statuses).includes(status)) { - mediaInfo.status = status; - } + mediaInfo.status = propOrDefault(arg.status); }; /**