diff options
Diffstat (limited to 'app/index.php')
-rw-r--r-- | app/index.php | 538 |
1 files changed, 442 insertions, 96 deletions
diff --git a/app/index.php b/app/index.php index 3dc4b44..6989866 100644 --- a/app/index.php +++ b/app/index.php @@ -15,6 +15,9 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI <!--<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>--> <script src="/assets/localforage.min.js"></script> <script src="/assets/js/shortcuts.js"></script> + <script src="/assets/js/normalizer.js"></script> + <script src="/assets/js/pako.js"></script> + <script src="/assets/js/stella.js"></script> <link rel="shortcut icon" href="/assets/logo-display.svg" type="image/svg+xml"> <link rel="manifest" href="/manifest.json" /> <meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)"> @@ -30,10 +33,16 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI } </style> </head> -<body <?php if (!str_contains($_SERVER['HTTP_USER_AGENT'], "MistNative/")): ?>class="web"<?php endif; ?>> +<body <?php if (!str_contains($_SERVER['HTTP_USER_AGENT'], "MistNative/")): ?>class="web"<?php else: ?>class="native"<?php endif; ?>> <script src="/assets/js/common.js"></script> <script> - if (location.hash.trim() === "") location.hash = "#/albums"; + if (location.hash.trim() === "") { + if (window.innerWidth < 863) { + location.hash = "#/library"; + } else { + location.hash = "#/albums"; + } + } if (window.MistNative) { MistNative.version("<?= explode("|", trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/version")))[0] ?>", "<?= trim(file_exists("/opt/spotify/build.txt") ? file_get_contents("/opt/spotify/build.txt") : "trunk") ?>"); @@ -41,7 +50,15 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI } </script> <div id="loading" style="z-index: 999999; position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; background-color: white;"> - <span id="loading-text">Initializing...</span> + <img src="/assets/logo-transparent.svg" style="width: 256px; height: 256px;" alt="Mist"> + <span id="loading-text" style="display: none;">Initializing...</span> + </div> + + <div id="mobile-navbar" style="padding: 0 10px; border-bottom: 1px solid rgba(0, 0, 0, .1); height: 48px; top: var(--android-status-bar); left: 0; right: 0; position: fixed; display: none; grid-template-columns: max-content 1fr;"> + <div style="display: flex; align-items: center;" onclick="document.getElementById('ui').contentWindow.history.back();"> + <img alt="Back" src="/assets/icons/back-mobile.svg" style="height: 32px; width: 32px;"> + </div> + <div style="display: flex; align-items: center; margin-left: 10px;" id="mobile-navbar-title"></div> </div> <iframe title="Player" id="player" src="ui/player.php" style="position: fixed; top: var(--android-status-bar); left: 320px; right: 0; width: calc(100vw - 320px); height: 64px; border-bottom: 1px solid rgba(0, 0, 0, .25); z-index: 9999;"></iframe> @@ -52,12 +69,42 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI <iframe title="Mobile player" style="background: #ddd; width: 100%; height: 100%;" src="ui/player-mobile.php" id="player-mobile"></iframe> </div> + <div id="mouse-logging" style="display: block; inset: 0; position: fixed; z-index: 99999999; pointer-events: none;"></div> + <iframe id="modal" src="ui/modal.php" style="width: 100vw; height: 100vh; border: none; inset: 0; position: fixed; z-index: 99999999; display: none;"></iframe> + <script> + window.modalLoaded = false; + document.getElementById("modal").onload = () => { + window.modalLoaded = true; + + <?php $app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); global $_PROFILE; if (in_array($_PROFILE["id"], $app["dp"])): ?> + openModal("Mist Developer Preview", "welcome-dp.php", false); + <?php else: ?> + if (localStorage.getItem("welcomed") !== "true") { + openModal("Welcome to Mist", "welcome.php", true); + } else { + if (localStorage.getItem("lastUpdate") !== "<?= trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/version")) ?>|<?= trim(file_exists("/opt/spotify/build.txt") ? file_get_contents("/opt/spotify/build.txt") : "trunk") ?>") { + openModal("What's new in Mist?", "update.php", true); + } + } + <?php endif; ?> + } + window.onerror = (_1, _2, _3, _4, err) => { - document.body.innerHTML = ""; - let pre = document.createElement("pre"); - pre.innerText = err.stack; - document.body.append(pre); + let loadWait = setInterval(() => { + if (window.modalLoaded) { + clearInterval(loadWait); + + document.getElementById("modal").style.display = ""; + document.getElementById("modal").contentDocument.getElementById("error-content").innerText = err.stack; + document.getElementById("modal").contentWindow._error.show(); + + setInterval(() => { + document.getElementById("modal").contentWindow._modal.hide(); + window.parent.document.getElementById("modal").style.display = ""; + }); + } + }); } window.playlist = []; @@ -67,7 +114,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI document.getElementById("lyrics-page").style.display = ""; document.getElementById("ui").style.display = "none"; Array.from(document.getElementById("navigation").contentDocument.getElementsByClassName("navigation-item")).map(i => i.classList.remove("active")); - document.getElementById("navigation").contentDocument.getElementById("lyrics").classList.add("active"); + if (document.getElementById("navigation").contentDocument.getElementById("lyrics")) document.getElementById("navigation").contentDocument.getElementById("lyrics").classList.add("active"); } function openUI(name) { @@ -77,20 +124,45 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI document.getElementById("ui").style.display = ""; document.getElementById("ui").src = "ui/" + name + ".php"; Array.from(document.getElementById("navigation").contentDocument.getElementsByClassName("navigation-item")).map(i => i.classList.remove("active")); - document.getElementById("navigation").contentDocument.getElementById(name).classList.add("active"); + if (document.getElementById("navigation").contentDocument.getElementById(name)) document.getElementById("navigation").contentDocument.getElementById(name).classList.add("active"); } - let name = location.hash.split("/")[1]; + window.onhashchange = window.loadHash = () => { + window.name = location.hash.split("/")[1]; - if (name === "lyrics") { - document.getElementById("ui").src = "ui/albums.php"; - } else if (name === "albums" && location.hash.split("/")[2]) { - document.getElementById("ui").src = "ui/listing.php?a=" + location.hash.split("/")[2]; - } else { - document.getElementById("ui").src = "ui/" + name + ".php"; + function setSrcIfDifferent(src) { + if (document.getElementById("ui").contentWindow.location.pathname.substring(5) !== src) { + document.getElementById("ui").src = src; + } + } + + if (name === "lyrics") { + showLyrics(); + } else if (name === "albums" && location.hash.split("/")[2]) { + document.getElementById("lyrics-page").style.display = "none"; + document.getElementById("ui").style.display = ""; + setSrcIfDifferent("ui/listing.php?a=" + location.hash.split("/")[2]); + } else if (name === "search" && location.hash.split("/")[2]) { + document.getElementById("lyrics-page").style.display = "none"; + document.getElementById("ui").style.display = ""; + setSrcIfDifferent("ui/search.php?q=" + location.hash.split("/")[2]); + name = "explore"; + } else { + document.getElementById("lyrics-page").style.display = "none"; + document.getElementById("ui").style.display = ""; + setSrcIfDifferent("ui/" + name + ".php"); + } } - document.getElementById("navigation").onload = () => { + loadHash(); + + document.getElementById("ui").onload = () => { + window.resizeHandler(); + document.getElementById("mobile-navbar-title").innerText = document.getElementById("ui").contentDocument.title; + } + + document.getElementById("navigation").onload = window.redoNavigation = (name) => { + if (!name || typeof name !== "string") name = window.name; if (name === "lyrics") showLyrics(); Array.from(document.getElementById("navigation").contentDocument.getElementsByClassName("navigation-item")).map(i => i.classList.remove("active")); document.getElementById("navigation").contentDocument.getElementById(name).classList.add("active"); @@ -100,35 +172,63 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI document.getElementById("player").onload = document.getElementById("player-mobile").onload = () => { loadedPlayers++; - if (loadedPlayers === 2) continueLoading(); + if (loadedPlayers === 2) { + window.resizeHandler(); + continueLoading(); + } } - window.onresize = window.onload = () => { + window.onresize = window.onload = window.resizeHandler = () => { if (window.innerWidth <= 863) { - document.getElementById("player").contentDocument.getElementById("player").classList.add("mobilified"); + if (document.getElementById("player").contentDocument && document.getElementById("player").contentDocument.getElementById("player")) document.getElementById("player").contentDocument.getElementById("player").classList.add("mobilified"); + if (document.getElementById("ui").contentDocument && document.getElementById("ui").contentDocument.body) document.getElementById("ui").contentDocument.body.classList.add("mobile-ui"); } else { - document.getElementById("player").contentDocument.getElementById("player").classList.remove("mobilified"); + if (document.getElementById("player").contentDocument && document.getElementById("player").contentDocument.getElementById("player")) document.getElementById("player").contentDocument.getElementById("player").classList.remove("mobilified"); + if (document.getElementById("ui").contentDocument && document.getElementById("ui").contentDocument.body) document.getElementById("ui").contentDocument.body.classList.remove("mobile-ui"); } } + window.needInitializeNormalizer = false; + function continueLoading() { window.playerDocument = document.getElementById("player").contentDocument; window.playerDocumentMobile = document.getElementById("player-mobile").contentDocument; + window.needInitializeNormalizer = true; if (!localStorage.getItem("data-saving")) { localStorage.setItem("data-saving", "false"); } + if (!localStorage.getItem("normalize")) { + localStorage.setItem("normalize", "true"); + } + if (!localStorage.getItem("desktop-notification")) { localStorage.setItem("desktop-notification", "true"); } playerDocument.getElementById("seekbar-container").onclick = (e) => { playerDocument.getElementById("player-audio").currentTime = (e.offsetX / playerDocument.getElementById("seekbar-container").clientWidth) * playerDocument.getElementById("player-audio").duration; + + if (playingStella) { + playerDocument.getElementById("player-audio-stella-side1").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side2").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side3").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side4").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side5").currentTime = playerDocument.getElementById("player-audio").currentTime; + } } playerDocumentMobile.getElementById("seekbar-container").onclick = (e) => { playerDocument.getElementById("player-audio").currentTime = (e.offsetX / playerDocumentMobile.getElementById("seekbar-container").clientWidth) * playerDocument.getElementById("player-audio").duration; + + if (playingStella) { + playerDocument.getElementById("player-audio-stella-side1").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side2").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side3").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side4").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side5").currentTime = playerDocument.getElementById("player-audio").currentTime; + } } function parseTime(subject, max) { @@ -147,6 +247,18 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI next(); } + window.seekTo = (time) => { + document.getElementById("player").contentDocument.getElementById("player-audio").currentTime = time; + + if (playingStella) { + playerDocument.getElementById("player-audio-stella-side1").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side2").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side3").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side4").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side5").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + } + window.stop = () => { if (window.MistAndroid) { window.MistAndroid.removeNotification(); @@ -166,16 +278,10 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI document.getElementById("player").contentWindow.location.reload(); document.getElementById("player").onload = () => { window.playerDocument = document.getElementById("player").contentDocument; + window.needInitializeNormalizer = true; - if (window.innerWidth <= 863) { - document.getElementById("player").contentDocument.getElementById("player").classList.add("mobilified"); - } else { - document.getElementById("player").contentDocument.getElementById("player").classList.remove("mobilified"); - } - - playerDocument.getElementById("player-audio").ontimeupdate = playerDocument.getElementById("player-audio").onchange = playerDocument.getElementById("player-audio").onunload = playerDocument.getElementById("player-audio").onstop = playerDocument.getElementById("player-audio").onplay = playerDocument.getElementById("player-audio").onpause = () => { - updateDisplay(); - } + window.resizeHandler(); + initializePlayerDocument(); } document.getElementById("player-mobile").contentWindow.location.reload(); @@ -192,6 +298,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI if (window.currentSongID !== null) { document.getElementById("player-mobile-container").style.bottom = "0"; document.getElementById("lyrics-page").classList.add("mobile-show"); + document.getElementById("lyrics-page").style.pointerEvents = "none"; } } @@ -200,6 +307,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI document.getElementById("player-mobile-container").style.bottom = "-100vh"; document.getElementById("lyrics-page").classList.remove("mobile-show"); + document.getElementById("lyrics-page").style.pointerEvents = ""; } document.getElementById("player-mobile-container").onclick = (e) => { @@ -210,8 +318,12 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI window.currentPlaylistPosition = 0; window.buffering = false; + window.calledNextRecently = false; window.next = () => { + if (window.calledNextRecently) return; + window.calledNextRecently = true; + if (window.repeat) { playlist.push(playlist[currentPlaylistPosition]); } @@ -225,6 +337,9 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI } window.previous = () => { + if (window.calledNextRecently) return; + window.calledNextRecently = true; + if (playlist[currentPlaylistPosition - 1]) { playSong(playlist[currentPlaylistPosition - 1], "keep"); currentPlaylistPosition--; @@ -233,22 +348,130 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI } } - playerDocument.getElementById("player-audio").ontimeupdate = playerDocument.getElementById("player-audio").onchange = playerDocument.getElementById("player-audio").onunload = playerDocument.getElementById("player-audio").onstop = playerDocument.getElementById("player-audio").onplay = playerDocument.getElementById("player-audio").onpause = () => { - updateDisplay(); + function initializePlayerDocument() { + playerDocument.getElementById("player-audio").ontimeupdate = playerDocument.getElementById("player-audio").onchange = playerDocument.getElementById("player-audio").onunload = playerDocument.getElementById("player-audio").onstop = () => { + updateDisplay(); + + if (playingStella) { + if (playerDocument.getElementById("player-audio").paused) { + if (!playerDocument.getElementById("player-audio-stella-side1").paused) { + playerDocument.getElementById("player-audio-stella-side1").pause(); + playerDocument.getElementById("player-audio-stella-side1").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + if (!playerDocument.getElementById("player-audio-stella-side2").paused) { + playerDocument.getElementById("player-audio-stella-side2").pause(); + playerDocument.getElementById("player-audio-stella-side2").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + if (!playerDocument.getElementById("player-audio-stella-side3").paused) { + playerDocument.getElementById("player-audio-stella-side3").pause(); + playerDocument.getElementById("player-audio-stella-side3").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + if (!playerDocument.getElementById("player-audio-stella-side4").paused) { + playerDocument.getElementById("player-audio-stella-side4").pause(); + playerDocument.getElementById("player-audio-stella-side4").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + if (!playerDocument.getElementById("player-audio-stella-side5").paused) { + playerDocument.getElementById("player-audio-stella-side5").pause(); + playerDocument.getElementById("player-audio-stella-side5").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + } else { + if (playerDocument.getElementById("player-audio-stella-side1").paused) { + playerDocument.getElementById("player-audio-stella-side1").play(); + playerDocument.getElementById("player-audio-stella-side1").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + if (playerDocument.getElementById("player-audio-stella-side2").paused) { + playerDocument.getElementById("player-audio-stella-side2").play(); + playerDocument.getElementById("player-audio-stella-side2").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + if (playerDocument.getElementById("player-audio-stella-side3").paused) { + playerDocument.getElementById("player-audio-stella-side3").play(); + playerDocument.getElementById("player-audio-stella-side3").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + if (playerDocument.getElementById("player-audio-stella-side4").paused) { + playerDocument.getElementById("player-audio-stella-side4").play(); + playerDocument.getElementById("player-audio-stella-side4").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + if (playerDocument.getElementById("player-audio-stella-side5").paused) { + playerDocument.getElementById("player-audio-stella-side5").play(); + playerDocument.getElementById("player-audio-stella-side5").currentTime = playerDocument.getElementById("player-audio").currentTime; + } + } + } + } + + playerDocument.getElementById("player-audio").onplay = () => { + if (window.preloadedGains[window.currentSongID]) { + window.currentNormalizationSource.connect(window.preloadedGains[window.currentSongID]); + window.currentNormalizationSource2.connect(window.preloadedGainsBoosted1[window.currentSongID]); + window.currentNormalizationSource3.connect(window.preloadedGainsBoosted2[window.currentSongID]); + window.preloadedGains[window.currentSongID].connect(window.currentNormalizationContext.destination); + } + + if (playingStella) { + for (let player of [ + window.currentNormalizationSource2, + window.currentNormalizationSource3, + window.currentNormalizationSource4, + window.currentNormalizationSource5 + ]) { + player.connect(window.preloadedGainsBoosted1[window.currentSongID]); + window.preloadedGainsBoosted1[window.currentSongID].connect(window.currentNormalizationContext.destination); + } + + window.currentNormalizationSource1.connect(window.preloadedGainsBoosted2[window.currentSongID]); + window.preloadedGainsBoosted2[window.currentSongID].connect(window.currentNormalizationContext.destination); + } + + updateDisplay(); + } + + playerDocument.getElementById("player-audio").onpause = () => { + if (window.preloadedGains[window.currentSongID]) { + try { + window.currentNormalizationSource.disconnect(window.preloadedGains[window.currentSongID]); + window.preloadedGains[window.currentSongID].disconnect(window.currentNormalizationContext.destination); + } catch (e) { + console.error(e); + } + + if (playingStella) { + for (let player of [ + window.currentNormalizationSource2, + window.currentNormalizationSource3, + window.currentNormalizationSource4, + window.currentNormalizationSource5 + ]) { + try { + player.disconnect(window.preloadedGainsBoosted1[window.currentSongID]); + window.preloadedGainsBoosted1[window.currentSongID].disconnect(window.currentNormalizationContext.destination); + } catch (e) { + console.error(e); + } + } + + try { + window.currentNormalizationSource1.disconnect(window.preloadedGainsBoosted2[window.currentSongID]); + window.preloadedGainsBoosted2[window.currentSongID].disconnect(window.currentNormalizationContext.destination); + } catch (e) { + console.error(e); + } + } + } + + if (playerDocument.getElementById("player-audio").currentTime >= playerDocument.getElementById("player-audio").duration) { + next(); + return; + } + + updateDisplay(); + } } + initializePlayerDocument(); + function updateDisplay() { if (window.MistAndroid && currentSong) { - window.MistAndroid.setNotificationData(currentSong.title, - currentSong.artist, - currentSong.album, - Math.round(playerDocument.getElementById("player-audio").currentTime * 1000), - Math.round(playerDocument.getElementById("player-audio").duration * 1000), - !playerDocument.getElementById("player-audio").paused), - buffering, - shuffle, - repeat - ; + window.MistAndroid.setNotificationData(currentSong.title, currentSong.artist, currentSong.album, Math.round(playerDocument.getElementById("player-audio").currentTime * 1000), Math.round(playerDocument.getElementById("player-audio").duration * 1000), !playerDocument.getElementById("player-audio").paused, buffering); } if (playerDocument.getElementById("player-audio").paused) { @@ -297,12 +520,28 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI } else { playerDocument.getElementById("player-audio").currentTime = 0; } + + if (playingStella) { + playerDocument.getElementById("player-audio-stella-side1").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side2").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side3").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side4").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side5").currentTime = playerDocument.getElementById("player-audio").currentTime; + } }); document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("seekforward", (e) => { let time = e.seekOffset ?? 10; if (playerDocument.getElementById("player-audio").currentTime + time < playerDocument.getElementById("player-audio").duration) { playerDocument.getElementById("player-audio").currentTime += time; + + if (playingStella) { + playerDocument.getElementById("player-audio-stella-side1").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side2").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side3").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side4").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side5").currentTime = playerDocument.getElementById("player-audio").currentTime; + } } else { next(); } @@ -310,6 +549,14 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("seekto", (e) => { if (e.seekTime) { playerDocument.getElementById("player-audio").currentTime = e.seekTime; + + if (playingStella) { + playerDocument.getElementById("player-audio-stella-side1").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side2").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side3").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side4").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side5").currentTime = playerDocument.getElementById("player-audio").currentTime; + } } }); document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("previoustrack", () => { @@ -317,6 +564,14 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI previous(); } else { playerDocument.getElementById("player-audio").currentTime = 0; + + if (playingStella) { + playerDocument.getElementById("player-audio-stella-side1").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side2").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side3").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side4").currentTime = playerDocument.getElementById("player-audio").currentTime; + playerDocument.getElementById("player-audio-stella-side5").currentTime = playerDocument.getElementById("player-audio").currentTime; + } } }); document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("nexttrack", () => { @@ -354,33 +609,6 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI playerDocument.getElementById("btn-play-icon").src = playerDocumentMobile.getElementById("btn-play-icon").src = "/assets/icons/pause.svg"; } - if (localStorage.getItem("data-saving") === "true") { - playerDocument.getElementById("badge-lossy").style.display = "inline"; - playerDocument.getElementById("badge-cd").style.display = "none"; - playerDocument.getElementById("badge-hires").style.display = "none"; - playerDocumentMobile.getElementById("badge-lossy").style.display = "inline"; - playerDocumentMobile.getElementById("badge-cd").style.display = "none"; - playerDocumentMobile.getElementById("badge-hires").style.display = "none"; - } else { - if (window.currentSong && window.currentSong.hiRes) { - playerDocument.getElementById("badge-lossy").style.display = "none"; - playerDocument.getElementById("badge-cd").style.display = "none"; - playerDocument.getElementById("badge-hires").style.display = "inline"; - playerDocument.getElementById("badge-hires").innerHTML = "<span style='display: grid; grid-template-columns: max-content max-content'><span><img src='/assets/icons/lossless.svg' alt='' class='player-badge-icon' style='filter: invert(1);'>Hi-Res Lossless</span><span class='player-badge-desktop'>" + window.currentSong.bitDepth + "-bit " + (window.currentSong.sampleRate / 1000) + " kHz</span>"; - playerDocumentMobile.getElementById("badge-lossy").style.display = "none"; - playerDocumentMobile.getElementById("badge-cd").style.display = "none"; - playerDocumentMobile.getElementById("badge-hires").style.display = "inline"; - } else if (window.currentSong) { - playerDocument.getElementById("badge-lossy").style.display = "none"; - playerDocument.getElementById("badge-cd").style.display = "inline"; - playerDocument.getElementById("badge-hires").style.display = "none"; - playerDocumentMobile.getElementById("badge-lossy").style.display = "none"; - playerDocumentMobile.getElementById("badge-cd").style.display = "inline"; - playerDocumentMobile.getElementById("badge-hires").style.display = "none"; - playerDocument.getElementById("badge-cd").innerHTML = "<span style='display: grid; grid-template-columns: max-content max-content;'><span><img src='/assets/icons/lossless.svg' alt='' class='player-badge-icon' style='filter: invert(1);'>Lossless</span><span class='player-badge-desktop'>" + window.currentSong.bitDepth + "-bit " + (window.currentSong.sampleRate / 1000) + " kHz</span>"; - } - } - if (window.currentSong) { playerDocument.getElementById("title").innerText = playerDocumentMobile.getElementById("title").innerText = window.currentSong.title; playerDocument.getElementById("artist").innerText = playerDocumentMobile.getElementById("artist").innerText = window.currentSong.artist; @@ -441,9 +669,15 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI document.getElementById("loading").style.display = "none"; })(); + window.playingStella = false; window.currentSong = null; window.currentSongID = null; window.preloaded = {}; + window.preloadedURLs = {}; + window.preloadedGains = {}; + window.preloadedGainsBoosted1 = {}; + window.preloadedGainsBoosted2 = {}; + window.preloadedBlobs = {}; window.shuffle = false; window.repeat = false; @@ -545,8 +779,33 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI window.currentPlaylistID = null; window.playSong = async (id, playlistID, updatePosition) => { + playerDocument.getElementById("badge-cd").style.display = "none"; + playerDocument.getElementById("badge-stella").style.display = "none"; + playerDocument.getElementById("badge-hires").style.display = "none"; + playerDocumentMobile.getElementById("badge-cd").style.display = "none"; + playerDocumentMobile.getElementById("badge-stella").style.display = "none"; + playerDocumentMobile.getElementById("badge-hires").style.display = "none"; + document.getElementById("player").contentWindow.buildTooltips(); + + if (!window.currentNormalizationContext) { + window.currentNormalizationContext = new AudioContext(); + window.currentNormalizationContext2 = new AudioContext(); + window.currentNormalizationContext3 = new AudioContext(); + } + + if (window.needInitializeNormalizer) { + window.currentNormalizationSource = window.currentNormalizationContext.createMediaElementSource(playerDocument.getElementById("player-audio")); + window.currentNormalizationSource1 = window.currentNormalizationContext.createMediaElementSource(playerDocument.getElementById("player-audio-stella-side1")); + window.currentNormalizationSource2 = window.currentNormalizationContext.createMediaElementSource(playerDocument.getElementById("player-audio-stella-side2")); + window.currentNormalizationSource3 = window.currentNormalizationContext.createMediaElementSource(playerDocument.getElementById("player-audio-stella-side3")); + window.currentNormalizationSource4 = window.currentNormalizationContext.createMediaElementSource(playerDocument.getElementById("player-audio-stella-side4")); + window.currentNormalizationSource5 = window.currentNormalizationContext.createMediaElementSource(playerDocument.getElementById("player-audio-stella-side5")); + window.needInitializeNormalizer = false; + } + playerDocument.getElementById("player-audio").pause(); playerDocument.getElementById("player-audio").currentTime = 0; + window.playingStella = false; if (playlistID) { if (playlistID === "favorites") { @@ -560,7 +819,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI } else if (playlistID !== "keep") { window.playlist = [id]; window.currentPlaylistPosition = 0; - } else if (typeof updatePosition !== "boolean" || updatePosition) { + } else if (updatePosition !== false) { window.currentPlaylistPosition = window.playlist.indexOf(id) ?? 0; } } else { @@ -574,22 +833,100 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI updateDisplay(); if (document.getElementById("ui").contentWindow.refreshQueue) document.getElementById("ui").contentWindow.refreshQueue(); - if (!window.preloaded[id]) { - window.buffering = true; + let stellaCompatible = false; - if (localStorage.getItem("data-saving") === "true") { - window.preloaded[id] = URL.createObjectURL(new Blob([await (await fetch("/assets/content/" + id + ".m4a")).arrayBuffer()], { type: "audio/mp4" })); - } else { - window.preloaded[id] = URL.createObjectURL(new Blob([await (await fetch("/assets/content/" + id + ".flac")).arrayBuffer()], { type: "audio/flac" })); + if (localStorage.getItem("enable-stella") === "true" && localStorage.getItem("data-saving") !== "true") { + stellaCompatible = await (await fetch("/api/hasStella.php?id=" + id)).text() === "true"; + } + + if (stellaCompatible) { + window.preloaded[id] = await Stella.build("/assets/content/" + id + ".stella"); + window.preloadedGains[id] = await normalizeAudio(window.preloaded[id].stems.other.buffer, 0); + window.preloadedGainsBoosted1[id] = await normalizeAudio(window.preloaded[id].stems.other.buffer, .05); + window.preloadedGainsBoosted2[id] = await normalizeAudio(window.preloaded[id].stems.other.buffer, .1); + } else { + if (!window.preloaded[id]) { + window.buffering = true; + + if (localStorage.getItem("data-saving") === "true") { + window.preloaded[id] = await (await fetch("/assets/content/" + id + ".m4a")).arrayBuffer(); + window.preloadedBlobs[id] = new Blob([window.preloaded[id]], { type: "audio/mp4" }); + } else { + window.preloaded[id] = await (await fetch("/assets/content/" + id + ".flac")).arrayBuffer(); + window.preloadedBlobs[id] = new Blob([window.preloaded[id]], { type: "audio/flac" }); + } + + window.preloadedGains[id] = await normalizeAudio(window.preloaded[id], 0); + window.preloadedGainsBoosted1[id] = await normalizeAudio(window.preloaded[id], .05); + window.preloadedGainsBoosted2[id] = await normalizeAudio(window.preloaded[id], .1); } } cleanupPreload(); preloadMore(); - playerDocument.getElementById("player-audio").src = window.preloaded[id]; - playerDocument.getElementById("player-audio").play(); - window.buffering = false; + if (!stellaCompatible) { + if (!window.preloadedURLs[id]) { + window.preloadedURLs[id] = localStorage.getItem("data-saving") ? URL.createObjectURL(window.preloadedBlobs[id]) : URL.createObjectURL(window.preloadedBlobs[id]); + } + } else { + window.playingStella = true; + playerDocument.getElementById("player-audio").src = window.preloaded[id].urls.hpf; + playerDocument.getElementById("player-audio-stella-side1").src = window.preloaded[id].urls.bass; + playerDocument.getElementById("player-audio-stella-side2").src = window.preloaded[id].urls.drums; + playerDocument.getElementById("player-audio-stella-side3").src = window.preloaded[id].urls.other; + playerDocument.getElementById("player-audio-stella-side4").src = window.preloaded[id].urls.piano; + playerDocument.getElementById("player-audio-stella-side5").src = window.preloaded[id].urls.vocals; + playerDocument.getElementById("player-audio").play(); + window.buffering = false; + } + + if (!stellaCompatible) { + playerDocument.getElementById("player-audio").src = window.preloadedURLs[id]; + playerDocument.getElementById("player-audio").play(); + window.buffering = false; + } + + window.calledNextRecently = false; + + if (localStorage.getItem("data-saving") === "true") { + playerDocument.getElementById("badge-cd").style.display = "none"; + playerDocument.getElementById("badge-stella").style.display = "none"; + playerDocument.getElementById("badge-hires").style.display = "none"; + playerDocumentMobile.getElementById("badge-cd").style.display = "none"; + playerDocumentMobile.getElementById("badge-stella").style.display = "none"; + playerDocumentMobile.getElementById("badge-hires").style.display = "none"; + document.getElementById("player").contentWindow.buildTooltips(); + } else { + if (window.playingStella) { + playerDocument.getElementById("badge-cd").style.display = "none"; + playerDocument.getElementById("badge-stella").style.display = "inline"; + playerDocument.getElementById("badge-hires").style.display = "none"; + playerDocumentMobile.getElementById("badge-cd").style.display = "none"; + playerDocumentMobile.getElementById("badge-stella").style.display = "inline"; + playerDocumentMobile.getElementById("badge-hires").style.display = "none"; + document.getElementById("player").contentWindow.buildTooltips(); + } else { + if (window.currentSong && window.currentSong.hiRes) { + playerDocument.getElementById("badge-cd").style.display = "none"; + playerDocument.getElementById("badge-stella").style.display = "none"; + playerDocument.getElementById("badge-hires").style.display = "inline"; + playerDocument.getElementById("badge-hires").title = "<b>Hi-Res Lossless</b><br>" + window.currentSong.bitDepth + "-bit " + (window.currentSong.sampleRate / 1000) + " kHz"; + playerDocumentMobile.getElementById("badge-cd").style.display = "none"; + playerDocumentMobile.getElementById("badge-stella").style.display = "none"; + playerDocumentMobile.getElementById("badge-hires").style.display = "inline"; + document.getElementById("player").contentWindow.buildTooltips(); + } else if (window.currentSong) { + playerDocument.getElementById("badge-cd").style.display = "inline"; + playerDocument.getElementById("badge-hires").style.display = "none"; + playerDocumentMobile.getElementById("badge-cd").style.display = "inline"; + playerDocumentMobile.getElementById("badge-stella").style.display = "none"; + playerDocumentMobile.getElementById("badge-hires").style.display = "none"; + playerDocument.getElementById("badge-cd").title = "<b>Lossless</b><br>" + window.currentSong.bitDepth + "-bit " + (window.currentSong.sampleRate / 1000) + " kHz"; + document.getElementById("player").contentWindow.buildTooltips(); + } + } + } if (window.MistNative && localStorage.getItem("desktop-notification") === "true") { window.MistNative.notification(currentSong, await (async function() { @@ -620,6 +957,8 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI if (window.MistAndroid) { window.MistAndroid.updateNotificationAlbumArt("https://" + location.hostname + "/albumart.php?i=" + currentSongID); } + + await fetch("/api/addHistory.php?i=" + currentSongID); } } @@ -627,12 +966,30 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI for (let i = 1; i <= 10; i++) { if (playlist[currentPlaylistPosition + i]) { let id = playlist[currentPlaylistPosition + i]; + let stellaCompatible = false; - if (!window.preloaded[id]) { - if (localStorage.getItem("data-saving") === "true") { - window.preloaded[id] = URL.createObjectURL(new Blob([await (await fetch("/assets/content/" + id + ".m4a")).arrayBuffer()], { type: "audio/mp4" })); - } else { - window.preloaded[id] = URL.createObjectURL(new Blob([await (await fetch("/assets/content/" + id + ".flac")).arrayBuffer()], { type: "audio/flac" })); + if (localStorage.getItem("enable-stella") === "true" && localStorage.getItem("data-saving") !== "true") { + stellaCompatible = await (await fetch("/api/hasStella.php?id=" + id)).text() === "true"; + } + + if (stellaCompatible) { + window.preloaded[id] = await Stella.build("/assets/content/" + id + ".stella"); + window.preloadedGains[id] = await normalizeAudio(window.preloaded[id].stems.other.buffer, 0); + window.preloadedGainsBoosted1[id] = await normalizeAudio(window.preloaded[id].stems.other.buffer, .05); + window.preloadedGainsBoosted2[id] = await normalizeAudio(window.preloaded[id].stems.other.buffer, .1); + } else { + if (!window.preloaded[id]) { + if (localStorage.getItem("data-saving") === "true") { + window.preloaded[id] = await (await fetch("/assets/content/" + id + ".m4a")).arrayBuffer(); + window.preloadedBlobs[id] = new Blob([window.preloaded[id]], { type: "audio/mp4" }); + } else { + window.preloaded[id] = await (await fetch("/assets/content/" + id + ".flac")).arrayBuffer(); + window.preloadedBlobs[id] = new Blob([window.preloaded[id]], { type: "audio/flac" }); + } + + window.preloadedGains[id] = await normalizeAudio(window.preloaded[id], 0); + window.preloadedGainsBoosted1[id] = await normalizeAudio(window.preloaded[id], .05); + window.preloadedGainsBoosted2[id] = await normalizeAudio(window.preloaded[id], .1); } } } @@ -646,14 +1003,13 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI for (let key of Object.keys(window.preloaded)) { if (!keys.includes(key)) { - URL.revokeObjectURL(window.preloaded[key]); + if (window.preloadedURLs[key]) URL.revokeObjectURL(window.preloadedURLs[key]); delete window.preloaded[key]; } } } </script> - <iframe id="modal" src="ui/modal.php" style="width: 100vw; height: 100vh; border: none; inset: 0; position: fixed; z-index: 99999; display: none;"></iframe> <script> function openModal(title, url, hideTitle) { document.getElementById("modal").style.display = ""; @@ -670,16 +1026,6 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFI document.getElementById("modal").contentWindow._modal.show(); } - document.getElementById("modal").onload = () => { - if (localStorage.getItem("welcomed") !== "true") { - openModal("Welcome to Mist", "welcome.php", true); - } else { - if (localStorage.getItem("lastUpdate") !== "<?= trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/version")) ?>|<?= trim(file_exists("/opt/spotify/build.txt") ? file_get_contents("/opt/spotify/build.txt") : "trunk") ?>") { - openModal("What's new in Mist?", "update.php", true); - } - } - } - if (!localStorage.getItem("rich-presence")) { localStorage.setItem("rich-presence", "true"); } |