2023-07-23 23:11:04 +02:00
import { app , dialog , Notification } from "@electron/remote" ;
import { clipboard , ipcRenderer } from "electron" ;
2023-05-10 22:07:11 +02:00
import fs from "fs" ;
2023-05-07 15:45:45 +02:00
import Player from "mpris-service" ;
2023-05-07 16:13:30 +02:00
import { globalEvents } from "./constants/globalEvents" ;
2023-05-07 15:45:45 +02:00
import { settings } from "./constants/settings" ;
2023-07-31 13:43:32 +02:00
import {
ListenBrainz ,
ListenBrainzConstants ,
ListenBrainzStore ,
} from "./features/listenbrainz/listenbrainz" ;
2023-08-07 20:28:14 +02:00
import { StoreData } from "./features/listenbrainz/models/storeData" ;
import { Logger } from "./features/logger" ;
import { Songwhip } from "./features/songwhip/songwhip" ;
import { MediaStatus } from "./models/mediaStatus" ;
2023-05-01 23:23:43 +02:00
import { Options } from "./models/options" ;
import { downloadFile } from "./scripts/download" ;
import { addHotkey } from "./scripts/hotkeys" ;
2023-05-07 15:45:45 +02:00
import { settingsStore } from "./scripts/settings" ;
2023-05-07 16:13:30 +02:00
import { setTitle } from "./scripts/window-functions" ;
2023-07-23 23:11:04 +02:00
2019-10-22 21:25:57 +02:00
const notificationPath = ` ${ app . getPath ( "userData" ) } /notification.jpg ` ;
2023-08-14 21:20:53 +02:00
const appName = "TIDAL Hi-Fi" ;
2019-11-03 18:52:15 +01:00
let currentSong = "" ;
2023-05-13 22:45:15 +02:00
let player : Player ;
2023-07-31 13:43:32 +02:00
let currentPlayStatus = MediaStatus . paused ;
2019-10-20 22:47:01 +02:00
const elements = {
play : '*[data-test="play"]' ,
pause : '*[data-test="pause"]' ,
next : '*[data-test="next"]' ,
previous : 'button[data-test="previous"]' ,
title : '*[data-test^="footer-track-title"]' ,
2021-05-30 15:40:27 +02:00
artists : '*[data-test^="grid-item-detail-text-title-artist"]' ,
2019-10-20 22:47:01 +02:00
home : '*[data-test="menu--home"]' ,
2023-07-23 23:13:37 +02:00
back : '[title^="Back"]' ,
forward : '[title^="Next"]' ,
2019-10-20 22:47:01 +02:00
search : '[class^="searchField"]' ,
shuffle : '*[data-test="shuffle"]' ,
repeat : '*[data-test="repeat"]' ,
2023-07-23 23:13:37 +02:00
account : '*[class^="profileOptions"]' ,
2019-10-20 22:47:01 +02:00
settings : '*[data-test^="open-settings"]' ,
2019-10-22 21:25:57 +02:00
media : '*[data-test="current-media-imagery"]' ,
2021-01-10 13:52:22 +01:00
image : "img" ,
2021-04-20 21:56:02 +02:00
current : '*[data-test="current-time"]' ,
2022-06-18 10:26:21 +02:00
duration : '*[data-test="duration"]' ,
2021-04-20 21:56:02 +02:00
bar : '*[data-test="progress-bar"]' ,
2021-05-30 15:40:27 +02:00
footer : "#footerPlayer" ,
2023-07-23 23:13:37 +02:00
mediaItem : "[data-type='mediaItem']" ,
2021-12-28 17:31:10 +01:00
album_header_title : '.header-details [data-test="title"]' ,
2023-07-23 23:13:37 +02:00
currentlyPlaying : "[class^='isPlayingIcon'], [data-test-is-playing='true']" ,
album_name_cell : '[class^="album"]' ,
2021-12-28 17:31:10 +01:00
tracklist_row : '[data-test="tracklist-row"]' ,
2022-03-31 17:37:12 +02:00
volume : '*[data-test="volume"]' ,
2019-10-22 21:25:57 +02:00
/ * *
* Get an element from the dom
* @param { * } key key in elements object to fetch
* /
2023-05-01 23:23:43 +02:00
get : function ( key : string ) {
2019-10-20 22:47:01 +02:00
return window . document . querySelector ( this [ key . toLowerCase ( ) ] ) ;
} ,
2019-10-22 21:25:57 +02:00
/ * *
* Get the icon of the current song
* /
2020-10-04 11:52:08 +02:00
getSongIcon : function ( ) {
2019-10-22 21:25:57 +02:00
const figure = this . get ( "media" ) ;
if ( figure ) {
const mediaElement = figure . querySelector ( this [ "image" ] ) ;
if ( mediaElement ) {
2021-12-19 13:18:39 +01:00
return mediaElement . src . replace ( "80x80" , "640x640" ) ;
2019-10-22 21:25:57 +02:00
}
}
return "" ;
} ,
2023-04-23 21:24:04 +02:00
/ * *
* returns an array of all artists in the current song
* @returns { Array } artists
2023-04-27 11:35:00 +02:00
* /
2023-04-23 21:24:04 +02:00
getArtistsArray : function ( ) {
2021-05-30 15:40:27 +02:00
const footer = this . get ( "footer" ) ;
if ( footer ) {
2023-04-23 21:24:04 +02:00
const artists = footer . querySelectorAll ( this . artists ) ;
2023-05-01 23:23:43 +02:00
if ( artists ) return Array . from ( artists ) . map ( ( artist ) = > ( artist as HTMLElement ) . textContent ) ;
2021-05-30 15:40:27 +02:00
}
2023-04-23 21:24:04 +02:00
return [ ] ;
} ,
2021-05-30 15:40:27 +02:00
2023-04-23 21:24:04 +02:00
/ * *
* unify the artists array into a string separated by commas
* @param { Array } artistsArray
* @returns { String } artists
2023-04-27 11:35:00 +02:00
* /
2023-05-01 23:23:43 +02:00
getArtistsString : function ( artistsArray : string [ ] ) {
2023-04-27 11:35:00 +02:00
if ( artistsArray . length > 0 ) return artistsArray . join ( ", " ) ;
2021-05-30 15:40:27 +02:00
return "unknown artist(s)" ;
} ,
2021-12-28 17:31:10 +01:00
getAlbumName : function ( ) {
//If listening to an album, get its name from the header title
2022-01-23 10:55:50 +01:00
if ( window . location . href . includes ( "/album/" ) ) {
2021-12-28 17:31:10 +01:00
const albumName = window . document . querySelector ( this . album_header_title ) ;
2022-01-23 10:55:50 +01:00
if ( albumName ) {
2021-12-28 17:31:10 +01:00
return albumName . textContent ;
}
//If listening to a playlist or a mix, get album name from the list
2022-01-23 10:55:50 +01:00
} else if (
window . location . href . includes ( "/playlist/" ) ||
window . location . href . includes ( "/mix/" )
) {
2023-07-31 13:43:32 +02:00
if ( currentPlayStatus === MediaStatus . playing ) {
2023-07-23 23:13:37 +02:00
// find the currently playing element from the list (which might be in an album icon), traverse back up to the mediaItem (row) and select the album cell.
// document.querySelector("[class^='isPlayingIcon'], [data-test-is-playing='true']").closest('[data-type="mediaItem"]').querySelector('[class^="album"]').textContent
const row = window . document . querySelector ( this . currentlyPlaying ) . closest ( this . mediaItem ) ;
2022-01-23 10:55:50 +01:00
if ( row ) {
return row . querySelector ( this . album_name_cell ) . textContent ;
2021-12-28 17:31:10 +01:00
}
}
}
return "" ;
} ,
2022-03-31 17:37:12 +02:00
isMuted : function ( ) {
return this . get ( "volume" ) . getAttribute ( "aria-checked" ) === "false" ; // it's muted if aria-checked is false
} ,
2019-10-22 21:25:57 +02:00
/ * *
* Shorthand function to get the text of a dom element
* @param { * } key key in elements object to fetch
* /
2023-05-01 23:23:43 +02:00
getText : function ( key : string ) {
2019-10-22 21:25:57 +02:00
const element = this . get ( key ) ;
return element ? element . textContent : "" ;
2019-10-20 22:47:01 +02:00
} ,
2019-10-22 21:25:57 +02:00
/ * *
* Shorthand function to click a dom element
* @param { * } key key in elements object to fetch
* /
2023-05-01 23:23:43 +02:00
click : function ( key : string ) {
2019-10-20 22:47:01 +02:00
this . get ( key ) . click ( ) ;
return this ;
} ,
2019-10-22 21:25:57 +02:00
/ * *
* Shorthand function to focus a dom element
* @param { * } key key in elements object to fetch
* /
2023-05-01 23:23:43 +02:00
focus : function ( key : string ) {
2019-10-20 22:47:01 +02:00
return this . get ( key ) . focus ( ) ;
} ,
} ;
2023-04-27 14:13:32 +02:00
function addCustomCss() {
window . addEventListener ( "DOMContentLoaded" , ( ) = > {
2023-08-07 20:04:06 +02:00
const selectedTheme = settingsStore . get < string , string > ( settings . theme ) ;
2023-05-10 22:07:11 +02:00
if ( selectedTheme !== "none" ) {
2023-08-07 20:04:06 +02:00
const userThemePath = ` ${ app . getPath ( "userData" ) } /themes/ ${ selectedTheme } ` ;
const resourcesThemePath = ` ${ process . resourcesPath } / ${ selectedTheme } ` ;
const themeFile = fs . existsSync ( userThemePath ) ? userThemePath : resourcesThemePath ;
2023-05-10 22:07:11 +02:00
fs . readFile ( themeFile , "utf-8" , ( err , data ) = > {
if ( err ) {
2023-08-07 20:04:06 +02:00
Logger . alert ( "An error ocurred reading the theme file." , err , alert ) ;
2023-05-10 22:07:11 +02:00
return ;
}
const themeStyle = document . createElement ( "style" ) ;
themeStyle . innerHTML = data ;
document . head . appendChild ( themeStyle ) ;
} ) ;
}
// read customCSS (it will override the theme)
2023-04-27 14:13:32 +02:00
const style = document . createElement ( "style" ) ;
2023-05-10 22:07:11 +02:00
style . innerHTML = settingsStore . get < string , string [ ] > ( settings . customCSS ) . join ( "\n" ) ;
2023-04-27 14:13:32 +02:00
document . head . appendChild ( style ) ;
} ) ;
}
2023-04-27 11:35:00 +02:00
/ * *
* Get the update frequency from the store
* make sure it returns a number , if not use the default
* /
function getUpdateFrequency() {
2023-07-31 13:43:32 +02:00
const storeValue = settingsStore . get < string , number > ( settings . updateFrequency ) ;
2023-04-27 11:35:00 +02:00
const defaultValue = 500 ;
if ( ! isNaN ( storeValue ) ) {
return storeValue ;
} else {
return defaultValue ;
}
}
2019-10-20 22:47:01 +02:00
/ * *
* Play or pause the current song
* /
function playPause() {
const play = elements . get ( "play" ) ;
if ( play ) {
elements . click ( "play" ) ;
} else {
elements . click ( "pause" ) ;
}
}
2023-07-31 12:06:31 +02:00
/ * *
* Clears the old listenbrainz data on launch
* /
ListenBrainzStore . clear ( ) ;
2019-10-20 22:47:01 +02:00
/ * *
* Add hotkeys for when tidal is focused
* Reflects the desktop hotkeys found on :
* https : //defkey.com/tidal-desktop-shortcuts
* /
function addHotKeys() {
2023-05-07 15:45:45 +02:00
if ( settingsStore . get ( settings . enableCustomHotkeys ) ) {
2023-05-01 23:23:43 +02:00
addHotkey ( "Control+p" , function ( ) {
2023-07-23 23:13:37 +02:00
elements . click ( "account" ) ;
setTimeout ( ( ) = > {
elements . click ( "settings" ) ;
} , 100 ) ;
2021-01-10 13:52:22 +01:00
} ) ;
2023-05-01 23:23:43 +02:00
addHotkey ( "Control+l" , function ( ) {
2021-01-10 13:52:22 +01:00
handleLogout ( ) ;
} ) ;
2019-10-20 22:47:01 +02:00
2023-05-01 23:23:43 +02:00
addHotkey ( "Control+h" , function ( ) {
2021-01-10 13:52:22 +01:00
elements . click ( "home" ) ;
} ) ;
2019-10-20 22:47:01 +02:00
2023-05-01 23:23:43 +02:00
addHotkey ( "backspace" , function ( ) {
2021-01-10 13:52:22 +01:00
elements . click ( "back" ) ;
} ) ;
2019-10-20 22:47:01 +02:00
2023-05-01 23:23:43 +02:00
addHotkey ( "shift+backspace" , function ( ) {
2021-01-10 13:52:22 +01:00
elements . click ( "forward" ) ;
} ) ;
2019-10-20 22:47:01 +02:00
2023-05-01 23:23:43 +02:00
addHotkey ( "control+u" , function ( ) {
2021-01-10 13:52:22 +01:00
// reloading window without cache should show the update bar if applicable
2023-05-01 23:23:43 +02:00
window . location . reload ( ) ;
2021-01-10 13:52:22 +01:00
} ) ;
2019-10-20 22:47:01 +02:00
2023-05-01 23:23:43 +02:00
addHotkey ( "control+r" , function ( ) {
2021-01-10 13:52:22 +01:00
elements . click ( "repeat" ) ;
} ) ;
2023-07-23 23:11:04 +02:00
addHotkey ( "control+w" , async function ( ) {
const result = await ipcRenderer . invoke ( globalEvents . whip , getTrackURL ( ) ) ;
const url = Songwhip . getWhipUrl ( result ) ;
clipboard . writeText ( url ) ;
new Notification ( {
title : ` Successfully whipped: ` ,
body : ` URL copied to clipboard: ${ url } ` ,
} ) . show ( ) ;
} ) ;
2021-01-10 13:52:22 +01:00
}
2019-11-03 18:52:15 +01:00
2021-01-10 13:52:22 +01:00
// always add the hotkey for the settings window
2023-05-01 23:23:43 +02:00
addHotkey ( "control+=" , function ( ) {
2019-11-03 18:52:15 +01:00
ipcRenderer . send ( globalEvents . showSettings ) ;
} ) ;
2023-05-01 23:23:43 +02:00
addHotkey ( "control+0" , function ( ) {
2022-01-23 11:02:28 +01:00
ipcRenderer . send ( globalEvents . showSettings ) ;
} ) ;
2019-10-20 22:47:01 +02:00
}
/ * *
* This function will ask the user whether he / she wants to log out .
* It will log the user out if he / she selects "yes"
* /
function handleLogout() {
const logoutOptions = [ "Cancel" , "Yes, please" , "No, thanks" ] ;
2023-05-01 23:23:43 +02:00
dialog
. showMessageBox ( null , {
2019-10-20 22:47:01 +02:00
type : "question" ,
title : "Logging out" ,
message : "Are you sure you want to log out?" ,
buttons : logoutOptions ,
defaultId : 2 ,
2023-05-01 23:23:43 +02:00
} )
. then ( ( result : { response : number } ) = > {
2023-07-31 13:43:32 +02:00
if ( logoutOptions . indexOf ( "Yes, please" ) === result . response ) {
2021-04-19 20:59:37 +02:00
for ( let i = 0 ; i < window . localStorage . length ; i ++ ) {
const key = window . localStorage . key ( i ) ;
2019-10-20 22:47:01 +02:00
if ( key . startsWith ( "_TIDAL_activeSession" ) ) {
window . localStorage . removeItem ( key ) ;
2023-05-01 23:23:43 +02:00
break ;
2019-10-20 22:47:01 +02:00
}
}
window . location . reload ( ) ;
}
2023-05-01 23:23:43 +02:00
} ) ;
2019-10-20 22:47:01 +02:00
}
2022-01-23 10:55:50 +01:00
function addFullScreenListeners() {
2022-04-21 17:49:11 +02:00
window . document . addEventListener ( "fullscreenchange" , ( ) = > {
2022-01-23 10:55:50 +01:00
ipcRenderer . send ( globalEvents . refreshMenuBar ) ;
} ) ;
}
2019-10-20 22:47:01 +02:00
/ * *
* Add ipc event listeners .
* Some actions triggered outside of the site need info from the site .
* /
function addIPCEventListeners() {
window . addEventListener ( "DOMContentLoaded" , ( ) = > {
2022-04-21 17:49:11 +02:00
ipcRenderer . on ( "globalEvent" , ( _event , args ) = > {
2019-10-22 21:25:57 +02:00
switch ( args ) {
2019-10-30 22:49:04 +01:00
case globalEvents . playPause :
2019-10-22 21:25:57 +02:00
playPause ( ) ;
break ;
2019-10-30 22:49:04 +01:00
case globalEvents . next :
2019-10-22 21:25:57 +02:00
elements . click ( "next" ) ;
break ;
2019-10-30 22:49:04 +01:00
case globalEvents . previous :
2019-10-22 21:25:57 +02:00
elements . click ( "previous" ) ;
break ;
2019-10-30 22:49:04 +01:00
case globalEvents . play :
elements . click ( "play" ) ;
break ;
case globalEvents . pause :
elements . click ( "pause" ) ;
break ;
2023-07-31 13:43:32 +02:00
default :
break ;
2019-10-22 21:25:57 +02:00
}
} ) ;
2019-10-20 22:47:01 +02:00
} ) ;
}
2019-10-30 23:42:08 +01:00
/ * *
* Update the current status of tidal ( e . g playing or paused )
* /
2021-04-19 23:08:19 +02:00
function getCurrentlyPlayingStatus() {
2023-05-07 15:45:45 +02:00
const pause = elements . get ( "pause" ) ;
2021-04-19 23:08:19 +02:00
let status = undefined ;
2020-10-04 11:52:08 +02:00
// if pause button is visible tidal is playing
if ( pause ) {
2023-07-31 13:43:32 +02:00
status = MediaStatus . playing ;
2020-10-04 11:52:08 +02:00
} else {
2023-07-31 13:43:32 +02:00
status = MediaStatus . paused ;
2020-10-04 11:52:08 +02:00
}
2021-04-19 23:08:19 +02:00
return status ;
}
2021-11-29 22:43:51 +01:00
/ * *
* Convert the duration from MM :SS to seconds
* @param { * } duration
* /
2023-05-01 23:23:43 +02:00
function convertDuration ( duration : string ) {
2021-11-29 22:43:51 +01:00
const parts = duration . split ( ":" ) ;
return parseInt ( parts [ 1 ] ) + 60 * parseInt ( parts [ 0 ] ) ;
}
2021-04-19 23:08:19 +02:00
/ * *
* Update Tidal - hifi ' s media info
*
* @param { * } options
* /
2023-05-01 23:23:43 +02:00
function updateMediaInfo ( options : Options , notify : boolean ) {
2021-04-19 23:08:19 +02:00
if ( options ) {
ipcRenderer . send ( globalEvents . updateInfo , options ) ;
2023-05-07 15:45:45 +02:00
if ( settingsStore . get ( settings . notifications ) && notify ) {
2023-04-27 14:29:28 +02:00
new Notification ( { title : options.title , body : options.artists , icon : options.icon } ) . show ( ) ;
2021-12-28 17:31:10 +01:00
}
2023-07-31 13:43:32 +02:00
updateMpris ( options ) ;
updateListenBrainz ( options ) ;
}
}
function updateMpris ( options : Options ) {
if ( player ) {
player . metadata = {
. . . player . metadata ,
. . . {
"xesam:title" : options . title ,
"xesam:artist" : [ options . artists ] ,
"xesam:album" : options . album ,
"mpris:artUrl" : options . image ,
"mpris:length" : convertDuration ( options . duration ) * 1000 * 1000 ,
"mpris:trackid" : "/org/mpris/MediaPlayer2/track/" + getTrackID ( ) ,
} ,
} ;
player . playbackStatus = options . status === MediaStatus . paused ? "Paused" : "Playing" ;
}
}
function updateListenBrainz ( options : Options ) {
if ( settingsStore . get ( settings . ListenBrainz . enabled ) ) {
const oldData = ListenBrainzStore . get ( ListenBrainzConstants . oldData ) as StoreData ;
if (
( ! oldData && options . status === MediaStatus . playing ) ||
( oldData && oldData . title !== options . title )
) {
ListenBrainz . scrobble (
options . title ,
options . artists ,
options . status ,
convertDuration ( options . duration )
) ;
2023-07-31 12:06:31 +02:00
}
2019-10-30 23:42:08 +01:00
}
}
2021-04-22 11:33:57 +02:00
/ * *
* Checks if Tidal is playing a video or song by grabbing the "a" element from the title .
2022-08-07 16:05:48 +02:00
* If it ' s a song it returns the track URL , if not it will return undefined
2021-04-22 11:33:57 +02:00
* /
2022-08-07 16:05:48 +02:00
function getTrackURL() {
2023-04-21 11:26:10 +02:00
const id = getTrackID ( ) ;
return ` https://tidal.com/browse/track/ ${ id } ` ;
2021-04-22 11:33:57 +02:00
}
2023-04-20 19:11:22 +02:00
function getTrackID() {
2021-04-22 11:33:57 +02:00
const URLelement = elements . get ( "title" ) . querySelector ( "a" ) ;
2022-08-07 16:05:48 +02:00
if ( URLelement !== null ) {
2023-04-21 11:26:10 +02:00
const id = URLelement . href . replace ( /\D/g , "" ) ;
2023-04-20 19:11:22 +02:00
return id ;
2021-04-22 11:33:57 +02:00
}
2022-08-07 16:05:48 +02:00
return window . location ;
2021-04-22 11:33:57 +02:00
}
2023-05-01 23:23:43 +02:00
function updateMediaSession ( options : Options ) {
2023-04-27 14:29:28 +02:00
if ( "mediaSession" in navigator ) {
navigator . mediaSession . metadata = new MediaMetadata ( {
title : options.title ,
artist : options.artists ,
album : options.album ,
artwork : [
{
src : options.icon ,
sizes : "640x640" ,
type : "image/png" ,
} ,
] ,
} ) ;
}
}
2019-10-20 22:47:01 +02:00
/ * *
2019-10-22 21:25:57 +02:00
* Watch for song changes and update title + notify
2019-10-20 22:47:01 +02:00
* /
2020-10-04 11:52:08 +02:00
setInterval ( function ( ) {
2019-10-20 22:47:01 +02:00
const title = elements . getText ( "title" ) ;
2023-04-23 21:24:04 +02:00
const artistsArray = elements . getArtistsArray ( ) ;
const artistsString = elements . getArtistsString ( artistsArray ) ;
skipArtistsIfFoundInSkippedArtistsList ( artistsArray ) ;
2023-01-20 22:15:36 +01:00
2021-12-28 17:31:10 +01:00
const album = elements . getAlbumName ( ) ;
2021-04-20 21:56:02 +02:00
const current = elements . getText ( "current" ) ;
const duration = elements . getText ( "duration" ) ;
2023-04-23 21:24:04 +02:00
const songDashArtistTitle = ` ${ title } - ${ artistsString } ` ;
2021-04-19 23:08:19 +02:00
const currentStatus = getCurrentlyPlayingStatus ( ) ;
const options = {
title ,
2023-04-27 14:29:28 +02:00
artists : artistsString ,
2021-12-28 17:31:10 +01:00
album : album ,
2021-04-19 23:08:19 +02:00
status : currentStatus ,
2022-08-07 16:05:48 +02:00
url : getTrackURL ( ) ,
current ,
duration ,
2022-01-23 10:55:50 +01:00
"app-name" : appName ,
2023-05-01 23:23:43 +02:00
image : "" ,
icon : "" ,
2021-04-19 23:08:19 +02:00
} ;
2019-10-22 21:25:57 +02:00
2023-04-27 14:29:28 +02:00
const titleOrArtistsChanged = currentSong !== songDashArtistTitle ;
2019-10-30 23:42:08 +01:00
2022-08-07 16:05:48 +02:00
// update title, url and play info with new info
setTitle ( songDashArtistTitle ) ;
getTrackURL ( ) ;
currentSong = songDashArtistTitle ;
currentPlayStatus = currentStatus ;
const image = elements . getSongIcon ( ) ;
2023-05-01 23:23:43 +02:00
new Promise < void > ( ( resolve ) = > {
2022-08-07 16:05:48 +02:00
if ( image . startsWith ( "http" ) ) {
options . image = image ;
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 ( ) ;
2021-04-20 22:15:34 +02:00
}
2023-05-07 15:45:45 +02:00
} ) . then ( ( ) = > {
updateMediaInfo ( options , titleOrArtistsChanged ) ;
if ( titleOrArtistsChanged ) {
updateMediaSession ( options ) ;
2022-03-31 17:37:12 +02:00
}
2023-05-07 15:45:45 +02:00
} ) ;
2023-01-22 21:18:20 +01:00
/ * *
* automatically skip a song if the artists are found in the list of artists to skip
2023-04-23 21:24:04 +02:00
* @param { * } artists array of artists
2023-01-22 21:18:20 +01:00
* /
2023-05-01 23:23:43 +02:00
function skipArtistsIfFoundInSkippedArtistsList ( artists : string [ ] ) {
2023-05-07 15:45:45 +02:00
if ( settingsStore . get ( settings . skipArtists ) ) {
const skippedArtists = settingsStore . get < string , string [ ] > ( settings . skippedArtists ) ;
2023-04-23 21:24:04 +02:00
if ( skippedArtists . length > 0 ) {
const artistsToSkip = skippedArtists . map ( ( artist ) = > artist ) ;
const artistNames = Object . values ( artists ) . map ( ( artist ) = > artist ) ;
const foundArtist = artistNames . some ( ( artist ) = > artistsToSkip . includes ( artist ) ) ;
if ( foundArtist ) {
elements . click ( "next" ) ;
}
2023-01-22 21:18:20 +01:00
}
}
}
2023-04-27 11:35:00 +02:00
} , getUpdateFrequency ( ) ) ;
2019-10-20 22:47:01 +02:00
2023-05-07 15:45:45 +02:00
if ( process . platform === "linux" && settingsStore . get ( settings . mpris ) ) {
2020-11-29 10:55:01 +01:00
try {
player = Player ( {
2023-08-14 21:20:53 +02:00
name : "TIDAL Hi-Fi" ,
identity : "TIDAL Hi-Fi" ,
2020-11-29 10:55:01 +01:00
supportedUriSchemes : [ "file" ] ,
supportedMimeTypes : [
"audio/mpeg" ,
"audio/flac" ,
"audio/x-flac" ,
"application/ogg" ,
"audio/wav" ,
] ,
supportedInterfaces : [ "player" ] ,
desktopEntry : "tidal-hifi" ,
} ) ;
// Events
2023-05-01 23:23:43 +02:00
const events = {
2020-11-29 10:55:01 +01:00
next : "next" ,
previous : "previous" ,
pause : "pause" ,
playpause : "playpause" ,
stop : "stop" ,
play : "play" ,
loopStatus : "repeat" ,
shuffle : "shuffle" ,
seek : "seek" ,
2023-05-01 23:23:43 +02:00
} as { [ key : string ] : string } ;
2020-11-29 10:55:01 +01:00
Object . keys ( events ) . forEach ( function ( eventName ) {
player . on ( eventName , function ( ) {
const eventValue = events [ eventName ] ;
switch ( events [ eventValue ] ) {
case events . playpause :
playPause ( ) ;
break ;
default :
elements . click ( eventValue ) ;
}
} ) ;
} ) ;
2021-11-29 22:43:51 +01:00
// Override get position function
player . getPosition = function ( ) {
return convertDuration ( elements . getText ( "current" ) ) * 1000 * 1000 ;
} ;
2020-11-29 10:55:01 +01:00
player . on ( "quit" , function ( ) {
app . quit ( ) ;
} ) ;
} catch ( exception ) {
console . log ( "player api not working" ) ;
}
}
2023-04-27 14:13:32 +02:00
addCustomCss ( ) ;
2019-10-20 22:47:01 +02:00
addHotKeys ( ) ;
addIPCEventListeners ( ) ;
2022-01-23 10:55:50 +01:00
addFullScreenListeners ( ) ;