Compare commits

..

8 Commits
1.3.0 ... 2.1.1

16 changed files with 317 additions and 139 deletions

View File

@@ -4,6 +4,27 @@ 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.
- Several versions have been bumped to fix vulnerabilities
## 2.0.0
### Breaking changes
- Changed settings hotkey from "ctrl+/" to "ctrl+=" to avoid a conflict with the default Tidal hotkeys
## Other changes
- Added a setting to disable custom hotkeys
- Fixed the bug that the previous song hotkey would register 3 times. (Twice due to a duplicate block of code + once from the default tidal hotkey)
## 1.3.0
-- re-enabled mpris-service wit the electron downloader fixes

View File

@@ -14,12 +14,18 @@ The web version of [listen.tidal.com](listen.tidal.com) running in electron with
- [Installation](#installation)
- [Using releases](#using-releases)
- [Snap install](#snap-install)
- [Arch Linux](#arch-linux)
- [Using source](#using-source)
- [features](#features)
- [Integrations](#integrations)
- [Known bugs](#known-bugs)
- [Why](#why)
- [Why not extend existing projects?](#why-not-extend-existing-projects)
- [Special thanks to..](#special-thanks-to)
- [Special thanks to...](#special-thanks-to)
- [Buy me a coffee? Please don't](#buy-me-a-coffee-please-dont)
- [Images](#images)
- [settings window](#settings-window)
- [user setups](#user-setups)
<!-- tocstop -->
@@ -66,9 +72,9 @@ To install and work with the code on this project follow these steps:
- HiFi playback
- Notifications
- Shortcuts ([source](https://defkey.com/tidal-desktop-shortcuts))
- Custom hotkeys ([source](https://defkey.com/tidal-desktop-shortcuts))
- API for status and playback
- [Settings feature](./docs/settings.png) to disable certain functionality. (`ctrl+/`)
- [Settings feature](./docs/settings.png) to disable certain functionality. (`ctrl+=`)
## Integrations
@@ -104,3 +110,14 @@ Sometimes it's just easier to start over, cover my own needs and then making it
Instead spend some money on a charity I care for: [kwf.nl](secure.kwf.nl/donation).
Inspired by [haydenjames' issue](https://github.com/Mastermindzh/tidal-hifi/issues/27#issuecomment-704198429)
## Images
### settings window
![settings window](./docs/settings-preview.png)
### user setups
Some of our users are kind enough to share their usage pictures.
If you want to see them or possibly even add one please do so in the following issue: [#3 - image thread](https://github.com/Mastermindzh/tidal-hifi/issues/3).

View File

@@ -1,6 +1,6 @@
pkgbase = tidal-hifi-git
pkgdesc = The web version of listen.tidal.com running in electron with hifi support thanks to widevine.
pkgver = 1.2.0
pkgver = 2.1.0
pkgrel = 1
url = https://github.com/Mastermindzh/tidal-hifi
arch = x86_64
@@ -11,9 +11,9 @@ pkgbase = tidal-hifi-git
depends = nss
depends = gtk3
provides = tidal-hifi
source = https://github.com/Mastermindzh/tidal-hifi/archive/1.2.0.zip
source = https://github.com/Mastermindzh/tidal-hifi/archive/2.1.0.zip
source = tidal-hifi.desktop
sha512sums = e1c0e47257cebe6b2609131964f0971c3eb70fc28c86f3d7177cb3cea09a3311236f4147bafa91347210fe2c96e6bd9d2e4ac7ca5b105e0c899657645705913d
sha512sums = 30b50243e7033219351f7d7f318757e4590e5c78a7031762cf846ae3652b424ab3f54388cba44209e49434d8534edb198e1c65d0b53450b4367636ef0f4653e0
sha512sums = 35f38ac308b871c1822d7f6f760f2fb54c3748cf769822cb0f0dfb90f0f5754ba9316da5e903a0d2e9839de3a43ec76f238f3f2e44021956fa1da19142081349
pkgname = tidal-hifi-git

View File

@@ -2,7 +2,7 @@
_pkgname=tidal-hifi
pkgname="$_pkgname-git"
pkgver=1.2.0
pkgver=2.1.0
pkgrel=1
pkgdesc="The web version of listen.tidal.com running in electron with hifi support thanks to widevine."
arch=("x86_64")
@@ -15,7 +15,7 @@ provides=("$_pkgname")
source=("https://github.com/Mastermindzh/tidal-hifi/archive/$pkgver.zip"
"${_pkgname}.desktop")
sha512sums=('e1c0e47257cebe6b2609131964f0971c3eb70fc28c86f3d7177cb3cea09a3311236f4147bafa91347210fe2c96e6bd9d2e4ac7ca5b105e0c899657645705913d'
sha512sums=('30b50243e7033219351f7d7f318757e4590e5c78a7031762cf846ae3652b424ab3f54388cba44209e49434d8534edb198e1c65d0b53450b4367636ef0f4653e0'
'35f38ac308b871c1822d7f6f760f2fb54c3748cf769822cb0f0dfb90f0f5754ba9316da5e903a0d2e9839de3a43ec76f238f3f2e44021956fa1da19142081349')
cdToPkg(){

BIN
docs/settings-preview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 KiB

96
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "tidal-hifi",
"version": "1.3.0",
"version": "2.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -972,6 +972,15 @@
"dev": true,
"optional": true
},
"discord-rpc": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/discord-rpc/-/discord-rpc-3.2.0.tgz",
"integrity": "sha512-KJv0EVbGMlr04HoG6f5b3wD7X9kSHzQ2Ed2qfHSDvYJ1MkE8RbCQmMcQQrSvAxpfsqZgUjB/bsfi/mjyicCH+A==",
"requires": {
"node-fetch": "^2.6.1",
"ws": "^7.3.1"
}
},
"dmg-builder": {
"version": "21.2.0",
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-21.2.0.tgz",
@@ -1732,9 +1741,9 @@
"dev": true
},
"ini": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
"ipaddr.js": {
@@ -1775,6 +1784,11 @@
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
"integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
},
"is-docker": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -1855,9 +1869,12 @@
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"is-wsl": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz",
"integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog=="
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"requires": {
"is-docker": "^2.0.0"
}
},
"is-yarn-global": {
"version": "0.3.0",
@@ -2160,22 +2177,57 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"node-notifier": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-6.0.0.tgz",
"integrity": "sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw==",
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-9.0.1.tgz",
"integrity": "sha512-fPNFIp2hF/Dq7qLDzSg4vZ0J4e9v60gJR+Qx7RbjbWqzPDdEqeVpEx5CFeDAELIl+A/woaaNn1fQ5nEVerMxJg==",
"requires": {
"growly": "^1.3.0",
"is-wsl": "^2.1.1",
"semver": "^6.3.0",
"is-wsl": "^2.2.0",
"semver": "^7.3.2",
"shellwords": "^0.1.1",
"which": "^1.3.1"
"uuid": "^8.3.0",
"which": "^2.0.2"
},
"dependencies": {
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"requires": {
"yallist": "^4.0.0"
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"requires": {
"lru-cache": "^6.0.0"
}
},
"uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"requires": {
"isexe": "^2.0.0"
}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
}
},
@@ -3251,6 +3303,7 @@
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
@@ -3365,6 +3418,11 @@
"signal-exit": "^3.0.2"
}
},
"ws": {
"version": "7.4.5",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz",
"integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g=="
},
"xdg-basedir": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
@@ -3386,9 +3444,9 @@
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
},
"y18n": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
"dev": true
},
"yallist": {

View File

@@ -1,6 +1,6 @@
{
"name": "tidal-hifi",
"version": "1.3.0",
"version": "2.1.1",
"description": "Tidal on Electron with widevine(hifi) support",
"main": "src/main.js",
"scripts": {
@@ -23,11 +23,12 @@
"homepage": "https://github.com/Mastermindzh/tidal-hifi",
"license": "MIT",
"dependencies": {
"discord-rpc": "^3.2.0",
"electron-store": "^5.1.1",
"express": "^4.17.1",
"hotkeys-js": "^3.7.6",
"mpris-service": "^2.1.0",
"node-notifier": "^6.0.0",
"node-notifier": "^9.0.1",
"request": "^2.88.2"
},
"devDependencies": {

View File

@@ -7,7 +7,6 @@ const globalEvents = {
updateInfo: "update-info",
hideSettings: "hideSettings",
showSettings: "showSettings",
updateStatus: "update-status",
storeChanged: "storeChanged",
error: "error",
};

View File

@@ -18,7 +18,9 @@ const settings = {
port: "apiSettings.port",
},
mpris: "mpris",
enableCustomHotkeys: "enableCustomHotkeys",
trayIcon: "trayIcon",
enableDiscord: "enableDiscord",
windowBounds: {
root: "windowBounds",
width: "windowBounds.width",

View File

@@ -9,12 +9,12 @@ const {
} = require("./scripts/settings");
const { addTray, refreshTray } = require("./scripts/tray");
const { addMenu } = require("./scripts/menu");
const path = require("path");
const tidalUrl = "https://listen.tidal.com";
const expressModule = require("./scripts/express");
const mediaKeys = require("./constants/mediaKeys");
const mediaInfoModule = require("./scripts/mediaInfo");
const discordModule = require("./scripts/discord");
const globalEvents = require("./constants/globalEvents");
let mainWindow;
@@ -85,6 +85,7 @@ app.on("ready", () => {
addGlobalShortcuts();
store.get(settings.trayIcon) && addTray({ icon }) && refreshTray();
store.get(settings.api) && expressModule.run(mainWindow);
store.get(settings.enableDiscord) && discordModule.initRPC();
});
app.on("activate", function () {
@@ -96,7 +97,6 @@ app.on("activate", function () {
});
// IPC
ipcMain.on(globalEvents.updateInfo, (event, arg) => {
mediaInfoModule.update(arg);
});
@@ -108,11 +108,14 @@ 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) {
discordModule.initRPC();
} else if (!store.get(settings.enableDiscord) && discordModule.rpc) {
discordModule.unRPC();
}
});
ipcMain.on(globalEvents.error, (event, arg) => {

View File

@@ -19,6 +19,8 @@ function refreshSettings() {
menuBar.checked = store.get(settings.menuBar);
trayIcon.checked = store.get(settings.trayIcon);
mpris.checked = store.get(settings.mpris);
enableCustomHotkeys.checked = store.get(settings.enableCustomHotkeys);
enableDiscord.checked = store.get(settings.enableDiscord);
}
/**
@@ -79,6 +81,8 @@ window.addEventListener("DOMContentLoaded", () => {
menuBar = get("menuBar");
trayIcon = get("trayIcon");
mpris = get("mprisCheckbox");
enableCustomHotkeys = get("enableCustomHotkeys");
enableDiscord = get("enableDiscord");
refreshSettings();
@@ -89,4 +93,6 @@ window.addEventListener("DOMContentLoaded", () => {
addInputListener(menuBar, settings.menuBar);
addInputListener(trayIcon, settings.trayIcon);
addInputListener(mpris, settings.mpris);
addInputListener(enableCustomHotkeys, settings.enableCustomHotkeys);
addInputListener(enableDiscord, settings.enableDiscord);
});

View File

@@ -80,6 +80,16 @@
<span class="slider round"></span>
</label>
</div>
<div class="option">
<h4>Hotkeys</h4>
<p>
Enables extra hotkeys to achieve feature parity with the <a href = "javascript:openExternal('https://defkey.com/tidal-desktop-shortcuts')">desktop apps</a><br />
</p>
<label class="switch">
<input id="enableCustomHotkeys" type="checkbox">
<span class="slider round"></span>
</label>
</div>
</div>
</section>
<section id="api" class="tab-panel">
@@ -131,6 +141,16 @@
<span class="slider round"></span>
</label>
</div>
<div class="option">
<h4>Discord RPC</h4>
<p>
Show what you're listening to on Discord
</p>
<label class="switch">
<input id="enableDiscord" type="checkbox">
<span class="slider round"></span>
</label>
</div>
</div>
</section>
<section id="about" class="tab-panel">

View File

@@ -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^="mediaArtists"]',
artists: '*[data-test^="grid-item-detail-text-title-artist"]',
home: '*[data-test="menu--home"]',
back: '[class^="backwardButton"]',
forward: '[class^="forwardButton"]',
@@ -29,7 +30,8 @@ const elements = {
account: '*[data-test^="profile-image-button"]',
settings: '*[data-test^="open-settings"]',
media: '*[data-test="current-media-imagery"]',
image: '*[class^="image--"]',
image: "img",
url: 'a[href*="/track/"]',
/**
* Get an element from the dom
@@ -101,6 +103,7 @@ function playPause() {
* https://defkey.com/tidal-desktop-shortcuts
*/
function addHotKeys() {
if (store.get(settings.enableCustomHotkeys)) {
hotkeys.add("Control+p", function () {
elements.click("account").click("settings");
});
@@ -120,36 +123,18 @@ function addHotKeys() {
elements.click("forward");
});
hotkeys.add("control+f", function () {
elements.focus("search");
});
hotkeys.add("control+u", function () {
// reloading window without cache should show the update bar if applicable
window.location.reload(true);
});
hotkeys.add("control+left", function () {
elements.click("previous");
});
hotkeys.add("control+right", function () {
elements.click("next");
});
hotkeys.add("control+right", function () {
elements.click("next");
});
hotkeys.add("control+s", function () {
elements.click("shuffle");
});
hotkeys.add("control+r", function () {
elements.click("repeat");
});
}
hotkeys.add("control+/", function () {
// always add the hotkey for the settings window
hotkeys.add("control+=", function () {
ipcRenderer.send(globalEvents.showSettings);
});
}
@@ -172,8 +157,8 @@ function handleLogout() {
},
function (response) {
if (logoutOptions.indexOf("Yes, please") == response) {
for (i = 0; i < window.localStorage.length; i++) {
key = window.localStorage.key(i);
for (let i = 0; i < window.localStorage.length; i++) {
const key = window.localStorage.key(i);
if (key.startsWith("_TIDAL_activeSession")) {
window.localStorage.removeItem(key);
i = window.localStorage.length + 1;
@@ -216,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) {
@@ -226,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";
}
}
}
@@ -240,23 +243,29 @@ function updateStatus() {
*/
setInterval(function () {
const title = elements.getText("title");
const url = elements.get("url").href.replace(/[^0-9]/g, "");
const artists = elements.getText("artists");
const songDashArtistTitle = `${title} - ${artists}`;
updateStatus();
if (getTitle() !== songDashArtistTitle) {
setTitle(songDashArtistTitle);
if (currentSong !== songDashArtistTitle) {
currentSong = songDashArtistTitle;
const image = elements.getSongIcon();
const currentStatus = getCurrentlyPlayingStatus();
const options = {
title,
message: artists,
status: currentStatus,
url: `https://tidal.com/browse/track/${url}`,
};
new Promise((resolve, reject) => {
const playStatusChanged = currentStatus !== currentPlayStatus;
const titleOrArtistChanged = currentSong !== songDashArtistTitle;
if (titleOrArtistChanged || playStatusChanged) {
// update title and play info with new info
setTitle(songDashArtistTitle);
currentSong = songDashArtistTitle;
currentPlayStatus = currentStatus;
const image = elements.getSongIcon();
new Promise((resolve) => {
if (image.startsWith("http")) {
downloadFile(image, notificationPath).then(
() => {
@@ -264,32 +273,21 @@ setInterval(function () {
resolve();
},
() => {
reject();
// if the image can't be downloaded then continue without it
resolve();
}
);
} else {
reject();
// 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,
},
};
}
updateMediaInfo(options, titleOrArtistChanged);
},
() => {}
);
}
}
}, 200);
if (process.platform === "linux" && store.get(settings.mpris)) {

57
src/scripts/discord.js Normal file
View File

@@ -0,0 +1,57 @@
const discordrpc = require("discord-rpc");
const { ipcMain } = require("electron");
const electron = require("electron");
const globalEvents = require("../constants/globalEvents");
const clientId = "833617820704440341";
const mediaInfoModule = require("./mediaInfo");
const discordModule = [];
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 ${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.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 () {
rpc.clearActivity();
rpc.destroy();
rpc = false;
discordModule.rpc = rpc;
ipcMain.removeListener(globalEvents.updateInfo, observer);
};
module.exports = discordModule;

View File

@@ -5,6 +5,7 @@ const mediaInfo = {
artist: "",
icon: "",
status: statuses.paused,
url: "",
};
const mediaInfoModule = {
mediaInfo,
@@ -13,19 +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);
};
/**
* Update tidal's status in the mediaInfo constant
*/
mediaInfoModule.updateStatus = function(status) {
if (Object.values(statuses).includes(status)) {
mediaInfo.status = status;
}
mediaInfo.url = propOrDefault(arg.url);
mediaInfo.status = propOrDefault(arg.status);
};
/**

View File

@@ -16,6 +16,8 @@ const store = new Store({
},
trayIcon: true,
mpris: false,
enableCustomHotkeys: false,
enableDiscord: false,
windowBounds: { width: 800, height: 600 },
},
});