Compare commits

..

2 Commits

17 changed files with 65 additions and 150 deletions

View File

@@ -4,11 +4,16 @@ 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).
## [5.7.0]
- Renamed app to TIDAL Hi-Fi.
- Made sure all windows run with the same web preferences set (compared to main app).
- Fixes the last.fm bug.
## [5.6.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)
- Made it clear in the readme that this TIDAL Hi-Fi client supports High & Max audio settings. fixes [#261](https://github.com/Mastermindzh/tidal-hifi/issues/261)
- 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]:
@@ -89,7 +94,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New settings window by BlueManCZ
- Fixed the desktop files in electron-builder
- icon is set to new static path based on Arch/Debian
- Name has changed to Tidal-Hifi
- Name has changed to TIDAL Hi-Fi
## 4.1.2
@@ -137,7 +142,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated to Electron 15
- Fixed the develop "build-unpacked" command
- Added setting to disable multiple tidal-hifi windows (defaults to true)
- Added setting to disable multiple TIDAL Hi-Fi windows (defaults to true)
- Added setting to disable HardwareMediaKeyHandling (defaults to false)
## 2.8.2
@@ -175,7 +180,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## 2.5.0
- Notify-send now correctly shows "Tidal HiFi" as the program name
- Notify-send now correctly shows "Tidal Hi-Fi" as the program name
- Updated dependencies (including electron itself)
### known issues

View File

@@ -1,20 +1,20 @@
# Tidal-hifi<img src = "./build/icon.png" height="40" align="right"/>
# TIDAL Hi-Fi (Max quality) <img src = "./build/icon.png" height="40" align="right"/>
![GitHub release](https://img.shields.io/github/release/Mastermindzh/tidal-hifi.svg) [![github builds](https://github.com/mastermindzh/tidal-hifi/actions/workflows/build.yml/badge.svg)](https://github.com/Mastermindzh/tidal-hifi/actions) [![Build Status](https://ci.mastermindzh.tech/api/badges/Mastermindzh/tidal-hifi/status.svg)](https://ci.mastermindzh.tech/Mastermindzh/tidal-hifi) [![Discord logo](./docs/images/discord.png)](https://discord.gg/yhNwf4v4He)
The web version of [listen.tidal.com](https://listen.tidal.com) running in electron with hifi (High & Max) support thanks to widevine.
![tidal-hifi preview](./docs/images/preview.png)
![TIDAL Hi-Fi preview](./docs/images/preview.png)
## Table of Contents
<!-- toc -->
- [Tidal-hifi](#tidal-hifi)
- [TIDAL Hi-Fi (Max quality)](#tidal-hi-fi-max-quality-)
- [Table of Contents](#table-of-contents)
- [Features](#features)
- [Contributions](#contributions)
- [Why did I create tidal-hifi?](#why-did-i-create-tidal-hifi)
- [Why did I create TIDAL Hi-Fi?](#why-did-i-create-tidal-hi-fi)
- [Why not extend existing projects?](#why-not-extend-existing-projects)
- [Installation](#installation)
- [Dependencies](#dependencies)
@@ -26,7 +26,6 @@ The web version of [listen.tidal.com](https://listen.tidal.com) running in elect
- [Using source](#using-source)
- [Integrations](#integrations)
- [Known bugs](#known-bugs)
- [last.fm doesn't work out of the box. Use rescrobbler as a workaround](#lastfm-doesnt-work-out-of-the-box-use-rescrobbler-as-a-workaround)
- [DRM not working on Windows](#drm-not-working-on-windows)
- [Special thanks to](#special-thanks-to)
- [Donations](#donations)
@@ -58,7 +57,7 @@ To contribute you can use the standard GitHub features (issues, prs, etc) or joi
- ![Discord logo](./docs/images/discord.png) [Join the Discord server](https://discord.gg/yhNwf4v4He)
## Why did I create tidal-hifi?
## Why did I create TIDAL Hi-Fi?
I moved from Spotify over to Tidal and found Linux support to be lacking.
When I started this project there weren't any Linux apps that offered Tidal's "hifi" options nor any scripts to control it.
@@ -103,10 +102,10 @@ To install with `snap` you need to download the pre-packaged snap-package from t
### Arch Linux
Arch Linux users can use the AUR to install tidal-hifi:
Arch Linux users can use the AUR to install TIDAL Hi-Fi:
```sh
trizen tidal-hifi-bin
trizen tidal-hifi-git
```
### Flatpak
@@ -130,13 +129,13 @@ nix-env -iA nixpkgs.tidal-hifi
To install and work with the code on this project follow these steps:
- git clone [https://github.com/Mastermindzh/tidal-hifi.git](https://github.com/Mastermindzh/tidal-hifi.git)
- cd tidal-hifi
- cd TIDAL Hi-Fi
- npm install
- npm start
## Integrations
tidal-hifi comes with several integrations out of the box.
TIDAL Hi-Fi comes with several integrations out of the box.
You can find these in the settings menu (`ctrl + =` by default) under the "integrations" tab.
![integrations menu, showing a list of integrations](./docs/images/integrations.png)
@@ -148,15 +147,9 @@ Integrations with other projects that are not included natively:
## Known bugs
### last.fm doesn't work out of the box. Use rescrobbler as a workaround
The last.fm login doesn't work, as is evident from the following issue: [Last.fm login doesn't work](https://github.com/Mastermindzh/tidal-hifi/issues/4).
However, in that same issue you can read about a workaround using [rescrobbler](https://github.com/InputUsername/rescrobbled).
For now, that will be the default workaround.
### DRM not working on Windows
Most Windows users run into DRM issues when trying to use tidal-hifi.
Most Windows users run into DRM issues when trying to use TIDAL Hi-Fi.
Nothing I can do about that I'm afraid... Tidal is working on removing/changing DRM so when they finish with that we can give it another shot.
## Special thanks to

View File

@@ -1,11 +0,0 @@
# Security Policy
## Supported Versions
Only the very latest 😄.
## Reporting a Vulnerability
If you find a vulnerability just add it as an issue.
If there's an especially bad vulnerability that you don't want to make public just send me a private message (email, discord, wherever).

View File

@@ -1,10 +1,10 @@
# Theming tidal-hifi
# Theming TIDAL Hi-Fi
## Table of contents
<!-- toc -->
- [Theming tidal-hifi](#theming-tidal-hifi)
- [Theming TIDAL Hi-Fi](#theming-TIDAL Hi-Fi)
- [Table of contents](#table-of-contents)
- [Custom CSS](#custom-css)
- [config](#config)
@@ -12,7 +12,7 @@
<!-- tocstop -->
By default tidal-hifi comes with a few themes.
By default TIDAL Hi-Fi comes with a few themes.
You can select these in the settings window under the theming tab as shown below.
![Settings window with the theming tab opened](./images/theming.png)

4
package-lock.json generated
View File

@@ -1,11 +1,11 @@
{
"name": "tidal-hifi",
"name": "TIDAL Hi-Fi",
"version": "5.6.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "tidal-hifi",
"name": "TIDAL Hi-Fi",
"version": "5.6.0",
"license": "MIT",
"dependencies": {

View File

@@ -35,7 +35,7 @@
"castlabs"
],
"author": "Rick van Lieshout <info@rickvanlieshout.com> (http://rickvanlieshout.com)",
"homepage": "https://github.com/Mastermindzh/tidal-hifi",
"homepage": "https://github.com/Mastermindzh/TIDAL Hi-Fi",
"license": "MIT",
"dependencies": {
"@electron/remote": "^2.0.10",
@@ -72,4 +72,4 @@
"typescript": "^5.1.6"
},
"prettier": "@mastermindzh/prettier-config"
}
}

View File

@@ -1,3 +1,3 @@
export default {
name: "tidal-hifi",
name: "TIDAL Hi-Fi",
};

View File

@@ -21,7 +21,6 @@ export function setManagedFlagsFromSettings(app: App) {
for (const [key, value] of Object.entries(flagsFromSettings)) {
if (value) {
flags[key].forEach((flag) => {
Logger.log(`enabling command line option ${flag.flag} with value ${flag.value}`);
setFlag(app, flag.flag, flag.value);
});
}
@@ -37,5 +36,6 @@ export function setManagedFlagsFromSettings(app: App) {
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function setFlag(app: App, flag: string, value?: any) {
Logger.log(`enabling command line option ${flag} with value ${value}`);
app.commandLine.appendSwitch(flag, value);
}

View File

@@ -1,65 +0,0 @@
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);
};

View File

@@ -1,4 +1,4 @@
import { IpcMain, ipcMain, IpcMainEvent, ipcRenderer } from "electron";
import { IpcMain, ipcRenderer, ipcMain } from "electron";
import { globalEvents } from "../constants/globalEvents";
export class Logger {
@@ -7,13 +7,10 @@ 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: IpcMainEvent | { content: string; message: string }, message) => {
const { content, object } = message ?? event;
this.logToSTDOut(content, object);
}
);
ipcMain.on(globalEvents.log, (event, message) => {
const { content, object } = message;
this.logToSTDOut(content, object);
});
}
/**
* Log content to STDOut
@@ -26,6 +23,7 @@ export class Logger {
} else {
ipcMain.emit(globalEvents.log, { content, object });
}
this.logToSTDOut(content, object);
}
/**

View File

@@ -1,7 +1,7 @@
import { enable, initialize } from "@electron/remote/main";
import {
app,
BrowserWindow,
app,
components,
globalShortcut,
ipcMain,
@@ -13,14 +13,9 @@ 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";
@@ -34,13 +29,16 @@ import {
} from "./scripts/settings";
import { addTray, refreshTray } from "./scripts/tray";
const tidalUrl = "https://listen.tidal.com";
let mainInhibitorId = -1;
initialize();
let mainWindow: BrowserWindow;
const icon = path.join(__dirname, "../assets/icon.png");
const PROTOCOL_PREFIX = "tidal";
const windowPreferences = {
sandbox: false,
plugins: true,
devTools: true, // I like tinkering, others might too
};
setDefaultFlags(app);
setManagedFlagsFromSettings(app);
@@ -84,10 +82,10 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) {
backgroundColor: options.backgroundColor,
autoHideMenuBar: true,
webPreferences: {
sandbox: false,
preload: path.join(__dirname, "preload.js"),
plugins: true,
devTools: true, // I like tinkering, others might too
...windowPreferences,
...{
preload: path.join(__dirname, "preload.js"),
},
},
});
enable(mainWindow.webContents);
@@ -112,7 +110,6 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) {
});
// Emitted when the window is closed.
mainWindow.on("closed", function () {
releaseInhibitorIfActive(mainInhibitorId);
closeSettingsWindow();
app.quit();
});
@@ -120,6 +117,18 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) {
const { width, height } = mainWindow.getBounds();
settingsStore.set(settings.windowBounds.root, { width, height });
});
mainWindow.webContents.setWindowOpenHandler(() => {
return {
action: "allow",
overrideBrowserWindowOptions: {
webPreferences: {
sandbox: false,
plugins: true,
devTools: true, // I like tinkering, others might too
},
},
};
});
}
function registerHttpProtocols() {
@@ -185,12 +194,6 @@ 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, () => {

View File

@@ -118,7 +118,7 @@ function hide() {
}
/**
* Restart tidal-hifi after changes
* Restart TIDAL Hi-Fi after changes
*/
function restart() {
app.relaunch();

View File

@@ -250,7 +250,7 @@
<div class="group__description">
<h4>Update frequency</h4>
<p>
The amount of time, in milliseconds, that tidal-hifi will refresh its playback info by scraping the
The amount of time, in milliseconds, that TIDAL Hi-Fi will refresh its playback info by scraping the
website.
The default of 500 seems to work in more cases but if you are fine with a bit more resource usage you
can decrease it as well.
@@ -300,7 +300,7 @@
<div class="group__description">
<h4>Wayland support</h4>
<p>
Adds a couple of Electron flags to help Tidal-hifi run smoothly on the Wayland window system.
Adds a couple of Electron flags to help TIDAL Hi-Fi run smoothly on the Wayland window system.
</p>
</div>
<label class="switch">

View File

@@ -20,7 +20,7 @@ import { settingsStore } from "./scripts/settings";
import { setTitle } from "./scripts/window-functions";
const notificationPath = `${app.getPath("userData")}/notification.jpg`;
const appName = "Tidal Hifi";
const appName = "TIDAL Hi-Fi";
let currentSong = "";
let player: Player;
let currentPlayStatus = MediaStatus.paused;
@@ -531,8 +531,8 @@ setInterval(function () {
if (process.platform === "linux" && settingsStore.get(settings.mpris)) {
try {
player = Player({
name: "tidal-hifi",
identity: "tidal-hifi",
name: "TIDAL Hi-Fi",
identity: "TIDAL Hi-Fi",
supportedUriSchemes: ["file"],
supportedMimeTypes: [
"audio/mpeg",
@@ -544,7 +544,6 @@ if (process.platform === "linux" && settingsStore.get(settings.mpris)) {
supportedInterfaces: ["player"],
desktopEntry: "tidal-hifi",
});
// Events
const events = {
next: "next",

View File

@@ -53,7 +53,7 @@ const observer = () => {
const idleStatus = {
details: `Browsing Tidal`,
largeImageKey: "tidal-hifi-icon",
largeImageText: `Tidal HiFi ${app.getVersion()}`,
largeImageText: `TIDAL Hi-Fi ${app.getVersion()}`,
instance: false,
};

View File

@@ -8,7 +8,7 @@ import { mediaInfo } from "./mediaInfo";
import { settingsStore } from "./settings";
/**
* Function to enable tidal-hifi's express api
* Function to enable TIDAL Hi-Fi's express api
*/
// expressModule.run = function (mainWindow)

View File

@@ -33,7 +33,6 @@ export const getMenu = function (mainWindow: BrowserWindow) {
{
label: name,
submenu: [
{ role: "about" },
settingsMenuEntry,
{ type: "separator" },
{ role: "services" },
@@ -101,12 +100,6 @@ export const getMenu = function (mainWindow: BrowserWindow) {
],
},
settingsMenuEntry,
{
label: "About",
click() {
showSettingsWindow("about");
},
},
toggleWindow,
quitMenuEntry,
];