diff --git a/.circleci/config.yml b/.circleci/config.yml index b15cbeb7..7a2b6ebd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,6 +15,11 @@ jobs: executor: cider-ci steps: - checkout + - run: + name: Install buildtools + command: | + sudo apt-get update + sudo apt-get install -y autoconf automake g++ libtool || true - run: name: Update Version Number of App command: sudo chmod +x resources/version.sh && ./resources/version.sh || true diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index f47f1d37..1297437f 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -90,7 +90,8 @@ jobs: DEVELOPER_DIR: /Applications/Xcode_12.4.app/Contents/Developer run: | rm cider-yarn.lock || true - xcodebuild -version + xcodebuild -version + brew install autoconf automake libtool yarn install cp resources/verror-types node_modules/@types/verror/index.d.ts cp resources/macPackager.js node_modules/app-builder-lib/out/macPackager.js diff --git a/package.json b/package.json index 7b37c78a..0c6a92f3 100644 --- a/package.json +++ b/package.json @@ -227,7 +227,10 @@ "darkModeSupport": true, "target": [ "dmg" - ] + ], + "extendInfo": { + "NSUserNotificationAlertStyle": "alert" + } } } } diff --git a/resources/version.sh b/resources/version.sh index deb492ca..8184da46 100755 --- a/resources/version.sh +++ b/resources/version.sh @@ -1,7 +1,8 @@ #!/bin/bash -LATEST_SHA=$(curl -s https://api.github.com/repos/ciderapp/Cider/branches/stable | grep sha | cut -d '"' -f 4 | sed 's/v//' | xargs) -COMMITSINCESTABLE=$(git rev-list $LATEST_SHA..HEAD --count) +LATEST_SHA=$(curl -s https://api.github.com/repos/ciderapp/Cider/branches/stable | grep '"sha"' | head -1 | cut -d '"' -f 4) +SHA_DATE=$(git show -s --format=%ci $LATEST_SHA) +COMMITSINCESTABLE=$(git rev-list $LATEST_SHA..HEAD --count --since="$SHA_DATE") CURRENT_VERSION=$(node -p -e "require('./package.json').version") if [[ $CIRCLE_BRANCH == "main" && $COMMITSINCESTABLE -gt 0 ]]; then NEW_VERSION="${CURRENT_VERSION}-beta.${COMMITSINCESTABLE}" diff --git a/src/i18n/en_US.json b/src/i18n/en_US.json index 71ef359a..b996e50a 100644 --- a/src/i18n/en_US.json +++ b/src/i18n/en_US.json @@ -108,7 +108,7 @@ "term.showMore": "Show more", "term.showLess": "Show less", "term.topSongs": "Top Songs", - "term.latestReleases": "Latest Releases", + "term.latestReleases": "Latest Release", "term.time.added": "Added", "term.time.released": "Released", "term.time.updated": "Updated", diff --git a/src/i18n/source/en_US.json b/src/i18n/source/en_US.json index ba797af7..122de9ad 100644 --- a/src/i18n/source/en_US.json +++ b/src/i18n/source/en_US.json @@ -108,7 +108,7 @@ "term.showMore": "Show more", "term.showLess": "Show less", "term.topSongs": "Top Songs", - "term.latestReleases": "Latest Releases", + "term.latestReleases": "Latest Release", "term.time.added": "Added", "term.time.released": "Released", "term.time.updated": "Updated", diff --git a/src/main/base/app.ts b/src/main/base/app.ts index fe54b158..4443c5b1 100644 --- a/src/main/base/app.ts +++ b/src/main/base/app.ts @@ -168,6 +168,14 @@ export class AppEvents { utils.getWindow().webContents.executeJavaScript(`ipcRenderer.send('lastfm:auth', "${authURI.split('lastfm?token=')[1]}")`).catch(console.error) } } + else if (arg.includes('playpause')) { + //language=JS + utils.getWindow().webContents.executeJavaScript('MusicKitInterop.playPause()') + } + else if (arg.includes('nextitem')) { + //language=JS + utils.getWindow().webContents.executeJavaScript('app.mk.skipToNextItem()') + } // Play else if (arg.includes('/play/')) { //Steer away from protocol:// specific conditionals const playParam = arg.split('/play/')[1] diff --git a/src/main/base/browserwindow.ts b/src/main/base/browserwindow.ts index a63dec93..e8ca660f 100644 --- a/src/main/base/browserwindow.ts +++ b/src/main/base/browserwindow.ts @@ -1183,11 +1183,6 @@ export class BrowserWindow { app.quit(); }) - app.on('before-quit', () => { - - }) - - ipcMain.on('play', (_event, type, id) => { BrowserWindow.win.webContents.executeJavaScript(` MusicKit.getInstance().setQueue({ ${type}: '${id}', parameters : {l : app.mklang}}).then(function(queue) { @@ -1442,70 +1437,63 @@ export class BrowserWindow { FULL_SCREEN: 3, }; let wndState = WND_STATE.NORMAL; + const win = BrowserWindow.win; + let isQuitting = false; - BrowserWindow.win.on("resize", (_: any) => { - const isMaximized = BrowserWindow.win.isMaximized(); - const isMinimized = BrowserWindow.win.isMinimized(); - const isFullScreen = BrowserWindow.win.isFullScreen(); + win.on("resize", (_: any) => { + const isMaximized = win.isMaximized(); + const isMinimized = win.isMinimized(); + const isFullScreen = win.isFullScreen(); const state = wndState; if (isMinimized && state !== WND_STATE.MINIMIZED) { wndState = WND_STATE.MINIMIZED; - BrowserWindow.win.webContents.send('window-state-changed', 'minimized'); + win.webContents.send('window-state-changed', 'minimized'); } else if (isFullScreen && state !== WND_STATE.FULL_SCREEN) { wndState = WND_STATE.FULL_SCREEN; - BrowserWindow.win.webContents.send('window-state-changed', 'fullscreen') + win.webContents.send('window-state-changed', 'fullscreen') } else if (isMaximized && state !== WND_STATE.MAXIMIZED) { wndState = WND_STATE.MAXIMIZED; - BrowserWindow.win.webContents.send('window-state-changed', 'maximized') - BrowserWindow.win.webContents.executeJavaScript(`app.chrome.maximized = true`); + win.webContents.send('window-state-changed', 'maximized') + win.webContents.executeJavaScript(`app.chrome.maximized = true`); } else if (state !== WND_STATE.NORMAL) { wndState = WND_STATE.NORMAL; - BrowserWindow.win.webContents.send('window-state-changed', 'normal') - BrowserWindow.win.webContents.executeJavaScript( + win.webContents.send('window-state-changed', 'normal') + win.webContents.executeJavaScript( `app.chrome.maximized = false` ); } }); - - let isQuiting = false - - BrowserWindow.win.on("close", (event: Event) => { - if ((utils.getStoreValue('general.close_button_hide') || process.platform === "darwin") && !isQuiting) { - event.preventDefault(); - BrowserWindow.win.hide(); - } else { - BrowserWindow.win.webContents.executeJavaScript(` - window.localStorage.setItem("currentTrack", JSON.stringify(app.mk.nowPlayingItem)); - window.localStorage.setItem("currentTime", JSON.stringify(app.mk.currentPlaybackTime)); - window.localStorage.setItem("currentQueue", JSON.stringify(app.mk.queue._unplayedQueueItems)); - ipcRenderer.send('stopGCast','');`) - BrowserWindow.win.destroy(); + win.on("close", (e: any) => { + if ((process.platform === "darwin" || utils.getStoreValue("general.close_button_hide")) && !isQuitting) { + e.preventDefault() + win.hide() } }) + win.on("closed", (_: any) => { + win.webContents.executeJavaScript(` + window.localStorage.setItem("currentTrack", JSON.stringify(app.mk.nowPlayingItem)); + window.localStorage.setItem("currentTime", JSON.stringify(app.mk.currentPlaybackTime)); + window.localStorage.setItem("currentQueue", JSON.stringify(app.mk.queue._unplayedQueueItems)); + ipcRenderer.send('stopGCast','');`) + }) + app.on('before-quit', () => { - isQuiting = true + isQuitting = true; }); app.on('activate', function () { - BrowserWindow.win.show() - BrowserWindow.win.focus() + win.show() }); // Quit when all windows are closed. app.on('window-all-closed', () => { - // On macOS it is common for applications and their menu bar - // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== 'darwin') { app.quit() } }) - BrowserWindow.win.on("closed", () => { - BrowserWindow.win = null; - }); - // Set window Handler BrowserWindow.win.webContents.setWindowOpenHandler((x: any) => { if (x.url.includes("apple") || x.url.includes("localhost")) { diff --git a/src/main/base/store.ts b/src/main/base/store.ts index d7881352..f20f9a14 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -65,6 +65,7 @@ export class Store { ], "albums": [ "CommandOrControl", + process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift" : "Alt"), "A" ], "artists": [ @@ -134,6 +135,7 @@ export class Store { "scrobble_after": 50, "filter_loop": false, "filter_types": {}, + "remove_featured": false, "secrets": { "username": "", "key": "" diff --git a/src/main/base/utils.ts b/src/main/base/utils.ts index da47e917..58e7bdd5 100644 --- a/src/main/base/utils.ts +++ b/src/main/base/utils.ts @@ -90,7 +90,8 @@ export class utils { if (language !== "en_US" && fs.existsSync(path.join(this.paths.i18nPath, `${language}.json`))) { i18n = Object.assign(i18n, JSON.parse(fs.readFileSync(path.join(this.paths.i18nPath, `${language}.json`), "utf8"))); - } else if (!fs.existsSync(path.join(this.paths.i18nPath, `${language}.json`))) { + } + /* else if (!fs.existsSync(path.join(this.paths.i18nPath, `${language}.json`))) { fetch(`https://raw.githubusercontent.com/ciderapp/Cider/main/src/i18n/${language}.json`) .then(res => res.json()) .then(res => { @@ -101,7 +102,8 @@ export class utils { i18n = Object.assign(i18n, JSON.parse(fs.readFileSync(path.join(this.paths.i18nPath, `en_US.json`), "utf8"))); } }) - } + } */ + if (key) { return i18n[key] } else { diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts index 027f997c..ea4d071e 100644 --- a/src/main/plugins/lastfm.ts +++ b/src/main/plugins/lastfm.ts @@ -131,7 +131,7 @@ export default class lastfm { if (!attributes.lfmAlbum) { this._lfm.album.getInfo({ - "artist": attributes.artistName, + "artist": attributes.primaryArtist, "album": attributes.albumName }, (err: any, data: any) => { if (err) { @@ -144,7 +144,7 @@ export default class lastfm { } }) } else { - this._lfm.track.getCorrection(attributes.artistName, attributes.name, (err: any, data: any) => { + this._lfm.track.getCorrection(attributes.primaryArtist, attributes.name, (err: any, data: any) => { if (err) { console.error(`[${lastfm.name}] [track.getCorrection] Error: ${typeof err === "string" ? err : err.message}`) return {}; diff --git a/src/main/plugins/playbackNotifications.ts b/src/main/plugins/playbackNotifications.ts new file mode 100644 index 00000000..b9807d53 --- /dev/null +++ b/src/main/plugins/playbackNotifications.ts @@ -0,0 +1,118 @@ +import fetch from "electron-fetch"; +import {nativeImage, Notification} from "electron"; +import NativeImage = Electron.NativeImage; + +export default class playbackNotifications { + + + /** + * Base Plugin Details (Eventually implemented into a GUI in settings) + */ + public name: string = 'Playback Notifications'; + public description: string = 'Creates notifications on playback.'; + public version: string = '1.0.0'; + public author: string = 'Core'; + public contributors: string[] = ['Core', 'Monochromish']; + + private _utils: any; + private _notification: Notification | undefined; + private _artworkImage: { [key: string]: NativeImage } = {}; + private _artworkNums: Array = []; + + /** + * Creates playback notification + * @param a: Music Attributes + */ + createNotification(a: any): void { + if (this._notification) { + this._notification.close(); + } + + this._notification = new Notification({ + title: a.name, + body: `${a.artistName} — ${a.albumName}`, + silent: true, + icon: this._artworkImage[a.artwork.url], + urgency: 'low', + actions: [ + { + 'type': 'button', + 'text': 'Play/Pause' + }, + { + 'type': 'button', + 'text': 'Next' + } + ], + toastXml: ` + + + + ${a?.name.replace(/&/g, '&')} + ${a?.artistName.replace(/&/g, '&')} — ${a?.albumName.replace(/&/g, '&')} + + + + + + + ` + }); + + // image implementation in windows toasts + //img + + this._notification.on('click', (_: any) => { + this._utils.getWindow().show() + this._utils.getWindow().focus() + }) + + this._notification.on('close', (_: any) => { + this._notification = undefined; + }) + + this._notification.on('action', (event: any, action: any) => { + if (action === 0) { + this._utils.playback.playPause() + } else if (action === 1) { + this._utils.playback.next() + } + }) + + this._notification.show(); + + } + + + /******************************************************************************************* + * Public Methods + * ****************************************************************************************/ + + /** + * Runs on plugin load (Currently run on application start) + */ + constructor(utils: any) { + this._utils = utils; + console.debug(`[Plugin][${this.name}] Loading Complete.`); + + utils.getIPCMain().on('playbackNotifications:create', (event: any, a: any) => { + a.artwork.url = a.artwork.url.replace('/{w}x{h}bb', '/512x512bb').replace('/2000x2000bb', '/35x35bb'); + + if (this._artworkNums.length > 20) { + delete this._artworkImage[this._artworkNums[0]]; + this._artworkNums.shift(); + } + + if (this._artworkImage[a.artwork.url]) { + this.createNotification(a); + } else { + fetch(a.artwork.url).then(async blob => { + this._artworkImage[a.artwork.url] = nativeImage.createFromBuffer(Buffer.from(await blob.arrayBuffer())); + this._artworkNums[this._artworkNums.length] = a.artwork.url; + this.createNotification(a); + }); + } + }) + } + +} diff --git a/src/main/plugins/raop.ts b/src/main/plugins/raop.ts index e99c3de7..0116746d 100644 --- a/src/main/plugins/raop.ts +++ b/src/main/plugins/raop.ts @@ -88,14 +88,16 @@ export default class RAOP { `; - private ondeviceup(name: any, host: any, port: any, addresses: any, text: any) { - if (this.castDevices.findIndex((item: any) => item.name == host.replace(".local","") && item.port == port && item.addresses == addresses) === -1) { + private ondeviceup(name: any, host: any, port: any, addresses: any, text: any, airplay2: any = null) { + console.log(this.castDevices.findIndex((item: any) => {return (item.name == host.replace(".local","") && item.port == port )})) + if (this.castDevices.findIndex((item: any) => {return (item.name == host.replace(".local","") && item.port == port )}) == -1) { this.castDevices.push({ name: host.replace(".local",""), host: addresses ? addresses[0] : '', port: port, addresses: addresses, - txt: text + txt: text, + airplay2: airplay2 }); if (this.devices.indexOf(host) === -1) { this.devices.push(host); @@ -147,7 +149,7 @@ export default class RAOP { browser.on('ready', browser.discover); browser.on('update', (service: any) => { - if (service.addresses && service.fullname && (service.fullname.includes('_raop._tcp') || service.fullname.includes('_airplay._tcp'))) { + if (service.addresses && service.fullname && (service.fullname.includes('_raop._tcp'))) { // console.log(service.txt) this._win.webContents.executeJavaScript(`console.log( "${service.name} ${service.host}:${service.port} ${service.addresses}" @@ -155,6 +157,19 @@ export default class RAOP { this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt); } }); + + const browser2 = this.mdns.createBrowser(this.mdns.tcp('airplay')); + browser2.on('ready', browser2.discover); + + browser2.on('update', (service: any) => { + if (service.addresses && service.fullname && (service.fullname.includes('_airplay._tcp'))) { + // console.log(service.txt) + this._win.webContents.executeJavaScript(`console.log( + "${service.name} ${service.host}:${service.port} ${service.addresses}" + )`); + this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt, true); + } + }); // const browser2 = this.mdns.createBrowser(this.mdns.tcp('airplay')); // browser2.on('ready', browser2.discover); @@ -173,7 +188,7 @@ export default class RAOP { - electron.ipcMain.on("performAirplayPCM", (event, ipv4, ipport, sepassword, title, artist, album, artworkURL,txt) => { + electron.ipcMain.on("performAirplayPCM", (event, ipv4, ipport, sepassword, title, artist, album, artworkURL,txt,airplay2dv) => { if (ipv4 != this.ipairplay || ipport != this.portairplay) { if (this.airtunes == null) { this.airtunes = new this.u()} @@ -183,7 +198,9 @@ export default class RAOP { port: ipport, volume: 50, password: sepassword, - txt: txt + txt: txt, + airplay2: airplay2dv, + debug: true }); // console.log('lol',txt) this.device.on('status', (status: any) => { diff --git a/src/preload/cider-preload.js b/src/preload/cider-preload.js index 8afae876..33fc5a91 100644 --- a/src/preload/cider-preload.js +++ b/src/preload/cider-preload.js @@ -6,6 +6,7 @@ let cache = {playParams: {id: 0}, status: null, remainingTime: 0}, const MusicKitInterop = { init: function () { + /* MusicKit.Events.playbackStateDidChange */ MusicKit.getInstance().addEventListener(MusicKit.Events.playbackStateDidChange, () => { const attributes = MusicKitInterop.getAttributes() if (MusicKitInterop.filterTrack(attributes, true, false)) { @@ -14,19 +15,28 @@ const MusicKitInterop = { } }); - /** wsapi */ - MusicKit.getInstance().addEventListener(MusicKit.Events.playbackProgressDidChange, () => { - ipcRenderer.send('wsapi-updatePlaybackState', MusicKitInterop.getAttributes()); + /* MusicKit.Events.playbackProgressDidChange */ + MusicKit.getInstance().addEventListener(MusicKit.Events.playbackProgressDidChange, async () => { + const attributes = MusicKitInterop.getAttributes() + // wsapi call + ipcRenderer.send('wsapi-updatePlaybackState', attributes); + // lastfm call + if (app.mk.currentPlaybackProgress === (app.cfg.connectivity.lastfm.scrobble_after / 100)) { + attributes.primaryArtist = (app.cfg.connectivity.lastfm.enabled && app.cfg.connectivity.lastfm.remove_featured) ? await this.fetchPrimaryArtist(attributes.artistName) : attributes.artistName; + ipcRenderer.send('lastfm:scrobbleTrack', attributes); + } }); - /** wsapi */ + /* MusicKit.Events.playbackTimeDidChange */ MusicKit.getInstance().addEventListener(MusicKit.Events.playbackTimeDidChange, () => { - ipcRenderer.send('mpris:playbackTimeDidChange', (MusicKit.getInstance()?.currentPlaybackTime * 1000 * 1000 ) ?? 0); - }) + ipcRenderer.send('mpris:playbackTimeDidChange', (MusicKit.getInstance()?.currentPlaybackTime * 1000 * 1000) ?? 0); + }); + /* MusicKit.Events.nowPlayingItemDidChange */ MusicKit.getInstance().addEventListener(MusicKit.Events.nowPlayingItemDidChange, async () => { console.debug('[cider:preload] nowPlayingItemDidChange') const attributes = MusicKitInterop.getAttributes() + attributes.primaryArtist = (app.cfg.connectivity.lastfm.enabled && app.cfg.connectivity.lastfm.remove_featured) ? await this.fetchPrimaryArtist(attributes.artistName) : attributes.artistName; if (MusicKitInterop.filterTrack(attributes, false, true)) { global.ipcRenderer.send('nowPlayingItemDidChange', attributes); @@ -34,24 +44,32 @@ const MusicKitInterop = { global.ipcRenderer.send('lastfm:nowPlayingChange', attributes); } + if (app.cfg.general.playbackNotifications && !document.hasFocus() && attributes.artistName && attributes.artwork && attributes.name) { + global.ipcRenderer.send('playbackNotifications:create', attributes); + } + if (MusicKit.getInstance().nowPlayingItem) { await this.sleep(750); MusicKit.getInstance().playbackRate = app.cfg.audio.playbackRate; } }); + /* MusicKit.Events.authorizationStatusDidChange */ MusicKit.getInstance().addEventListener(MusicKit.Events.authorizationStatusDidChange, () => { global.ipcRenderer.send('authorizationStatusDidChange', MusicKit.getInstance().authorizationStatus) }); + /* MusicKit.Events.mediaPlaybackError */ MusicKit.getInstance().addEventListener(MusicKit.Events.mediaPlaybackError, (e) => { console.warn(`[cider:preload] mediaPlaybackError] ${e}`); }); + /* MusicKit.Events.shuffleModeDidChange */ MusicKit.getInstance().addEventListener(MusicKit.Events.shuffleModeDidChange, () => { global.ipcRenderer.send('shuffleModeDidChange', MusicKit.getInstance().shuffleMode) }); + /* MusicKit.Events.repeatModeDidChange */ MusicKit.getInstance().addEventListener(MusicKit.Events.repeatModeDidChange, () => { global.ipcRenderer.send('repeatModeDidChange', MusicKit.getInstance().repeatMode) }); @@ -63,6 +81,15 @@ const MusicKitInterop = { }); }, + async fetchPrimaryArtist(artist) { + if (app.mk.nowPlayingItem?.relationships?.artists) { + const artist = await app.mk.api.artist(app.mk.nowPlayingItem.relationships.artists.data[0].id) + return artist.attributes.name + } else { + return artist + } + }, + getAttributes: function () { const mk = MusicKit.getInstance() const nowPlayingItem = mk.nowPlayingItem; @@ -71,6 +98,7 @@ const MusicKitInterop = { const currentPlaybackProgress = mk.currentPlaybackProgress; const attributes = (nowPlayingItem != null ? nowPlayingItem.attributes : {}); + attributes.songId = attributes.songId ?? attributes.playParams?.catalogId ?? attributes.playParams?.id attributes.status = isPlayingExport ?? null; attributes.name = attributes?.name ?? 'no-title-found'; attributes.artwork = attributes?.artwork ?? {url: ''}; diff --git a/src/renderer/less/fullscreen.less b/src/renderer/less/fullscreen.less index 82c3bdd9..7b48bfc3 100644 --- a/src/renderer/less/fullscreen.less +++ b/src/renderer/less/fullscreen.less @@ -480,6 +480,7 @@ display: inline-flex; width: 100%; justify-content: center; + align-items: center; } } diff --git a/src/renderer/main/app.js b/src/renderer/main/app.js index 5698d739..d5a809f7 100644 --- a/src/renderer/main/app.js +++ b/src/renderer/main/app.js @@ -33,11 +33,14 @@ if (app.cfg.advanced.disableLogging === true) { // Mount Vue to #app app.$mount("#app") -// Init CiderAudio -if (app.cfg.advanced.AudioContext === true) { - CiderAudio.init() +// Init CiderAudio and force audiocontext +if (app.cfg.advanced.AudioContext != true) { + app.cfg.advanced.AudioContext = true; + window.location.reload(); } +CiderAudio.init() + // Import gamepad support app.simulateGamepad = simulateGamepad app.spawnMica = spawnMica diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index bc5b03ff..5e59e9be 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -949,12 +949,6 @@ const app = new Vue({ } }); - this.mk.addEventListener(MusicKit.Events.playbackProgressDidChange, () => { - if (self.mk.currentPlaybackProgress === (app.cfg.connectivity.lastfm.scrobble_after / 100)) { - ipcRenderer.send('lastfm:scrobbleTrack', MusicKitInterop.getAttributes()); - } - }) - this.mk.addEventListener(MusicKit.Events.playbackStateDidChange, (event) => { ipcRenderer.send('wsapi-updatePlaybackState', wsapi.getAttributes()); document.body.setAttribute("playback-state", event.state == 2 ? "playing" : "paused") @@ -1013,8 +1007,8 @@ const app = new Vue({ try {localStorage.setItem("playingBitrate", app.mk.nowPlayingItem.flavor)} catch(e) {} } - if (!app.cfg.audio.normalization && app.cfg.advanced.AudioContext === false) { CiderAudio.hierarchical_loading(); } - + + if (app.cfg.audio.normalization === false) { CiderAudio.hierarchical_loading(); } // Just Reload for Adaptive CAP if norm is off else { // get unencrypted audio previews to get SoundCheck's normalization tag try { @@ -1080,17 +1074,6 @@ const app = new Vue({ app.getNowPlayingArtworkBG(32); app.loadLyrics(); - // Playback Notifications - if (this.cfg.general.playbackNotifications && !document.hasFocus() && a.artistName && a.artwork && a.name) { - if (this.notification) { - this.notification.close() - } - this.notification = new Notification(a.name, { - body: `${a.artistName} — ${a.albumName}`, - icon: a.artwork.url.replace('/{w}x{h}bb', '/512x512bb').replace('/2000x2000bb', '/35x35bb'), - silent: true, - }); - } setTimeout(() => { let i = (document.querySelector('#apple-music-player')?.src ?? "") if (i.endsWith(".m3u8") || i.endsWith(".m3u")) { @@ -1887,27 +1870,7 @@ const app = new Vue({ return dDisplay + (dDisplay && hDisplay ? ", " : "") + hDisplay + (hDisplay && mDisplay ? ", " : "") + mDisplay; } else { - let returnTime = datetime.toISOString().substring(11, 19); - - const timeGates = { - 600: 15, // 10 Minutes - 3600: 14, // Hour - 36000: 12, // 10 Hours - } - - for (let key in timeGates) { - if (seconds < key) { - returnTime = datetime.toISOString().substring(timeGates[key], 19) - break - } - } - - // Add the days on the front - if (seconds >= 86400) { - returnTime = parseInt(datetime.toISOString().substring(8, 10)) - 1 + ":" + returnTime - } - - return returnTime + return MusicKit.formatMediaTime(seconds); } }, hashCode(str) { @@ -4391,7 +4354,7 @@ const app = new Vue({ "id": "equalizer", "icon": "../views/svg/speaker.svg", "name": app.getLz('term.equalizer'), - "hidden": true, + "hidden": false, "action": function () { app.modals.equalizer = true app.modals.audioSettings = false @@ -4401,7 +4364,7 @@ const app = new Vue({ "id": "audioLab", "icon": "../views/svg/speaker.svg", "name": app.getLz('settings.option.audio.audioLab'), - "hidden": true, + "hidden": false, "action": function () { app.openSettingsPage('audiolabs') } @@ -4409,10 +4372,12 @@ const app = new Vue({ ] } } + /* if (this.cfg.advanced.AudioContext) { menus.normal.items.find(i => i.id === 'audioLab').hidden = false menus.normal.items.find(i => i.id === 'equalizer').hidden = false } + */ if (this.contextExt) { if (this.contextExt.normal) { menus.normal.items = menus.normal.items.concat(this.contextExt.normal) diff --git a/src/renderer/views/app/app-navigation.ejs b/src/renderer/views/app/app-navigation.ejs index 2f072641..7efad7f4 100644 --- a/src/renderer/views/app/app-navigation.ejs +++ b/src/renderer/views/app/app-navigation.ejs @@ -65,7 +65,7 @@ + @click="modals.castMenu = true">
diff --git a/src/renderer/views/components/airplay-modal.ejs b/src/renderer/views/components/airplay-modal.ejs index 994d3a9d..690105c8 100644 --- a/src/renderer/views/components/airplay-modal.ejs +++ b/src/renderer/views/components/airplay-modal.ejs @@ -3,7 +3,7 @@