diff options
| -rw-r--r-- | fonts/VCR_OSD_MONO_1.001.ttf | bin | 0 -> 75864 bytes | |||
| -rw-r--r-- | hg.css | 59 | ||||
| -rw-r--r-- | index.html | 156 | ||||
| -rw-r--r-- | player.js | 589 | 
4 files changed, 500 insertions, 304 deletions
| diff --git a/fonts/VCR_OSD_MONO_1.001.ttf b/fonts/VCR_OSD_MONO_1.001.ttfBinary files differ new file mode 100644 index 0000000..dcca687 --- /dev/null +++ b/fonts/VCR_OSD_MONO_1.001.ttf @@ -2,6 +2,10 @@    font-family: "StreamSter";    src: url(./fonts/Streamster.ttf);  } +@font-face { +  font-family: "VCR"; +  src: url(./fonts/VCR_OSD_MONO_1.001.ttf); +}  #app,  body,  html { @@ -15,7 +19,7 @@ body {    padding: 0;    margin: 0;    background: #fafafa; -  font-family: "Helvetica Neue", arial, sans-serif; +  font-family: "VCR", arial, sans-serif;    font-weight: 400;    color: #444;    -webkit-font-smoothing: antialiased; @@ -131,7 +135,8 @@ h3#track-name {    font-weight: 500;    letter-spacing: 2px;    color: #e91e63; -  font-family: "StreamSter", sans-serif; +  /* font-family: "StreamSter", sans-serif; */ +  font-family: "VCR", sans-serif;    margin-bottom: 0;    background: rgb(0 0 0 / 71%);    padding: 10px; @@ -149,7 +154,7 @@ hr {    width: 170px;    margin: 0 auto;    color: #dce3e7; -  font-family: "Droid Serif", serif; +  font-family: "VCR", serif;    font-size: 13px;    font-style: italic;    line-height: 18px; @@ -247,19 +252,23 @@ dialog::backdrop {  .controls {    font-style: italic;    font-size: larger; +  color: #ff0095;  }  .footer {    position: absolute;    bottom: 0px; -  width: 350px; +  width: 342px;    display: flex;    color: #ffffff;    z-index: 999;    justify-content: center; +  height: 17px;  }  .footer .footer-items { +  font-size: 13px; +  font-family: "VCR", serif;    text-decoration: none;    cursor: pointer;    padding-left: 10px; @@ -267,15 +276,53 @@ dialog::backdrop {    justify-content: center;  } +.footer-items#history { +  margin-top: 3px; +} +  canvas {    position: absolute;    top: 0;  } -.refresh { +.buttons {    z-index: 999;    cursor: pointer;    position: relative; -  float: right;    user-select: none;  } + +.refresh { +  float: right; +} + +.fullscreen { +  float: left; +  float: left; +  margin-left: 5px; +  margin-top: 3px; +  color: #565656; +} + +.fullscreen svg { +  height: 10px; +  width: 10px; +  color: #ffffffff; +} + +.fullscreen:hover * { +  color: #ffffff; +} + +.hidden { +  display: none; +} + +.OVR { +  position: absolute; +  bottom: 0; +  z-index: 999; +  color: #ffff; +  right: 0; +  margin-right: 5px; +} @@ -1,62 +1,128 @@  <!DOCTYPE html>  <html lang="en"> - -<head> -    <meta charset="UTF-8"> -    <meta http-equiv="X-UA-Compatible" content="IE=edge"> -    <meta name="viewport" content="width=device-width, initial-scale=1.0"> +  <head> +    <meta charset="UTF-8" /> +    <meta http-equiv="X-UA-Compatible" content="IE=edge" /> +    <meta name="viewport" content="width=device-width, initial-scale=1.0" />      <title>Retrowave Player</title>      <script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.3/howler.min.js"></script>      <script src="https://unpkg.com/hydra-synth"></script> -    <link rel="stylesheet" href="hg.css"> -    <link rel="icon" href="/favicon.ico"> -    <link rel="icon" type="image/svg+xml" href="/favicon.svg"> -</head> +    <link rel="stylesheet" href="hg.css" /> +    <link rel="icon" href="/favicon.ico" /> +    <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> +  </head> -<body> +  <body>      <div class="modal" id="intro-modal"> -        <div class="modal-bg modal-exit"></div> -        <div class="modal-container"> -            <h3 class="text-center">Welcome to Retrowave Player</h3> -            <p class="mt-5">Here are the controls:</p> -            <h4 class="mt-5">Play/Pause <span class="controls">SPACE or Click or Touch</span></h4> -            <h4 class="mt-5">Volume Up <span class="controls">w or Swipe Up</span></h4> -            <h4 class="mt-5">Volume Down <span class="controls">s or Swipe Down</span></h4> -            <h4 class="mt-5">Next Track<span class="controls"> n or Press the Refresh Button</span></h4> -            <p class="mt-5">(You can download the music history of your current browser by clicking the history link on -                the player)</p> -                <p class="mt-5">All the music is fetched from retrowave.ru</p> -            <button class="modal-close modal-exit" id="initButton">X</button> -        </div> +      <div class="modal-bg modal-exit"></div> +      <div class="modal-container"> +        <h3 class="text-center">Welcome to Retrowave Player</h3> +        <p class="mt-5">Here are the controls:</p> +        <h4 class="mt-5"> +          Play/Pause <span class="controls">SPACE or Click or Touch</span> +        </h4> +        <h4 class="mt-5"> +          Volume Up <span class="controls">w or Swipe Up</span> +        </h4> +        <h4 class="mt-5"> +          Volume Down <span class="controls">s or Swipe Down</span> +        </h4> +        <h4 class="mt-5"> +          Next Track<span class="controls"> n or Press the Refresh Button</span> +        </h4> +        <h4 class="mt-5"> +          Toggle Controls<span class="controls"> h</span> +        </h4> +        <p class="mt-5"> +          (You can download the music history of your current browser by +          clicking the history link on the player) +        </p> +        <p class="mt-5">All the music is fetched from retrowave.ru</p> +        <button class="modal-close modal-exit" id="initButton">X</button> +      </div>      </div>      <div id="app"> -        <div class="music-player"> -            <div class="no-pause refresh">🔃</div> -            <div class="title-content"> -                <div class="intro">Now Playing</div> -                <hr> -                <h3 id="track-name">Retrowave Player</h3> -            </div> -            <div class="gradient-overlay"></div> -            <div class="color-overlay"></div> -            <div class="footer"> -                <div id="history" class="no-pause footer-items">history</div> -                <div id="source"><a class="no-pause footer-items" href="https://git.indrajith.dev/retrowave-player/" -                        target="_blank">source code</a></div> -                <div id="retrowaveru" class="no-pause"><a class="no-pause footer-items" href="http://retrowave.ru/" -                        target="_blank">retrowave.ru</a></div> -                <div id="guestbook" class="no-pause"><a class="no-pause footer-items" href="https://indrajith.atabook.org/" -                        target="_blank">guestbook</a></div> -            </div> -            <!-- <div id="upload-info" class="no-pause" title="Upload a playlist (downloaded from history)">Upload</div> --> +      <div class="music-player"> +        <div title="FULLSCREEN" class="no-pause buttons fullscreen toggleable"> +          <svg +            class="no-pause" +            width="800px" +            height="800px" +            fill="#000000" +            version="1.1" +            viewBox="0 0 384.97 384.97" +            xml:space="preserve" +            xmlns="http://www.w3.org/2000/svg" +          > +            <g style="fill: #f9f9f9"> +              <g id="Fullscreen" style="fill: #f9f9f9"> +                <path +                  d="m384.97 12.03c0-6.713-5.317-12.03-12.03-12.03h-108.09c-6.833 0-11.922 5.39-11.934 12.223 0 6.821 5.101 11.838 11.934 11.838h96.062l-0.193 96.519c0 6.833 5.197 12.03 12.03 12.03 6.833-0.012 12.03-5.197 12.03-12.03l0.193-108.37c0-0.036-0.012-0.06-0.012-0.084 1e-3 -0.037 0.013-0.061 0.013-0.097z" +                  style="fill: #f9f9f9" +                /> +                <path +                  d="M120.496,0H12.403c-0.036,0-0.06,0.012-0.096,0.012C12.283,0.012,12.247,0,12.223,0C5.51,0,0.192,5.317,0.192,12.03    L0,120.399c0,6.833,5.39,11.934,12.223,11.934c6.821,0,11.838-5.101,11.838-11.934l0.192-96.339h96.242    c6.833,0,12.03-5.197,12.03-12.03C132.514,5.197,127.317,0,120.496,0z" +                  style="fill: #f9f9f9" +                /> +                <path +                  d="m120.12 360.91h-96.062v-96.242c0-6.833-5.197-12.03-12.03-12.03s-12.031 5.196-12.031 12.03v108.09c0 0.036 0.012 0.06 0.012 0.084 0 0.036-0.012 0.06-0.012 0.096 0 6.713 5.317 12.03 12.03 12.03h108.09c6.833 0 11.922-5.39 11.934-12.223 1e-3 -6.82-5.1-11.837-11.933-11.837z" +                  style="fill: #f9f9f9" +                /> +                <path +                  d="m372.75 252.91c-6.833 0-11.85 5.101-11.838 11.934v96.062h-96.242c-6.833 0-12.03 5.197-12.03 12.03s5.197 12.03 12.03 12.03h108.09c0.036 0 0.06-0.012 0.084-0.012 0.036-0.012 0.06 0.012 0.096 0.012 6.713 0 12.03-5.317 12.03-12.03v-108.09c1e-3 -6.833-5.389-11.934-12.222-11.934z" +                  style="fill: #f9f9f9" +                /> +              </g> +            </g> +          </svg> +        </div> +        <div class="no-pause buttons refresh toggleable" title="NEXT TRACK">🔃</div> +        <div class="title-content"> +          <div class="intro">Now Playing</div> +          <hr /> +          <h3 id="track-name">Retrowave Player</h3>          </div> +        <div class="gradient-overlay"></div> +        <div class="color-overlay"></div> +        <div class="footer toggleable"> +          <div title="DOWNLOAD YOUR PLAYLIST HISTORY" id="history" class="no-pause footer-items">history</div> +          <div id="source"> +            <a +              title="SOURCE CODE" +              class="no-pause footer-items" +              href="https://git.indrajith.dev/retrowave-player/" +              target="_blank" +              >source code</a +            > +          </div> +          <div id="retrowaveru" class="no-pause"> +            <a +              title="RETROWAVE.RU" +              class="no-pause footer-items" +              href="http://retrowave.ru/" +              target="_blank" +              >retrowave.ru</a +            > +          </div> +          <div id="guestbook" class="no-pause"> +            <a +              title="SIGN MY GUESTBOOK" +              class="no-pause footer-items" +              href="https://indrajith.atabook.org/" +              target="_blank" +              >guestbook</a +            > +          </div> +        </div> +        <!-- <div id="upload-info" class="no-pause" title="Upload a playlist (downloaded from history)">Upload</div> --> +      </div>      </div>      <div id="codef-canvas"></div> +    <div class="OVR hidden"></div>      <input id="file-upload" type="file" accept="application/json" />      <!-- <script src="libs/codef_core.js"></script>      <script src="libs/codef_starfield.js"></script>      <script src="libs/codef_3d.js"></script> -->      <script src="player.js"></script> -</body> - -</html>
\ No newline at end of file +  </body> +</html> @@ -1,293 +1,376 @@  (function () { -    let isPlaying = false; -    let currentTracks = []; -    let cursor = 0; -    let howlerInstance; -    const retroWaveRu = "https://retrowave.ru"; -    let titleEl = document.getElementById("track-name"); -    let coverArtEl = document.getElementsByClassName("music-player")[0]; -    let refreshBtn = document.querySelector(".refresh"); -    const modalEl = document.getElementById("intro-modal"); -    // const uploadInfoEl = document.getElementById("upload-info"); -    const fileUploadEl = document.getElementById("file-upload"); -    let volume = 1; -    let effectCanvas; -    let starField; -    let line3D; -    const synthwaveColor = 0xff2975; - -    openDialog(); -    getMusic(); -    listenUploadFileChange(); - -    coverArtEl.addEventListener("click", (event) => { -        const isNoPause = event.target.classList.contains("no-pause"); -        if (howlerInstance && !isNoPause) { -            togglePlay(); +  let isPlaying = false; +  let currentTracks = []; +  let cursor = 0; +  let howlerInstance; +  const retroWaveRu = "https://retrowave.ru"; +  let titleEl = document.getElementById("track-name"); +  let coverArtEl = document.getElementsByClassName("music-player")[0]; +  let refreshBtn = document.querySelector(".refresh"); +  let ovr = document.querySelector(".OVR"); +  let fullScreenBtn = document.querySelector(".fullscreen"); +  const modalEl = document.getElementById("intro-modal"); +  // const uploadInfoEl = document.getElementById("upload-info"); +  const fileUploadEl = document.getElementById("file-upload"); +  let volume = 1; +  let effectCanvas; +  let starField; +  let line3D; +  const synthwaveColor = 0xff2975; + +  openDialog(); +  getMusic(); +  listenUploadFileChange(); + +  function initDynamicTooltips() { +    document.querySelectorAll("[title]").forEach((element) => { +      const title = element.getAttribute("title"); +      element.removeAttribute("title"); +      element.setAttribute("data-title", title); + +      element.addEventListener("mouseenter", function (e) { +        const tooltip = document.createElement("div"); +        tooltip.textContent = this.getAttribute("data-title"); +        tooltip.style.cssText = ` +                font-family: "VCR", sans-serif; +                position: fixed; +                background:rgb(255, 255, 255); +                color: #000000; +                border: 1px solidrgb(0, 0, 0); +                padding: 4px 8px; +                font-size: 12px; +                border-radius: 3px; +                z-index: 10000; +                pointer-events: none; +                white-space: nowrap; +            `; + +        document.body.appendChild(tooltip); +        this.tooltipEl = tooltip; + +        const rect = this.getBoundingClientRect(); +        tooltip.style.left = +          rect.left + rect.width / 2 - tooltip.offsetWidth / 2 + "px"; +        tooltip.style.top = rect.top - tooltip.offsetHeight - 8 + "px"; +      }); + +      element.addEventListener("mouseleave", function () { +        if (this.tooltipEl) { +          document.body.removeChild(this.tooltipEl); +          this.tooltipEl = null;          } +      });      }); +  } -    // uploadInfoEl.addEventListener("click", () => { -    //     const confirmText = `Do you really want to change your playlist?\nThis will replace all your retrowave music history.\nIf you are sure about this, make sure to upload a valid json file probably downloaded using history link.`; - -    //     if (confirm(confirmText)) { -    //         fileUploadEl.click(); -    //     } -    // }); - -    function listenUploadFileChange() { -        fileUploadEl.onchange = function () { -            const selectedFile = fileUploadEl.files[0]; -            const reader = new FileReader(); -            reader.readAsText(selectedFile, "UTF-8"); -            reader.onload = function (event) { -                try { -                    const uploadedPlaylist = JSON.parse(event.target.result); -                    localStorage.setItem("retrowave-history", event.target.result); - -                } catch (error) { -                    alert("malformed/invalid json file"); -                } -            }; -        }; -    } - -    document.getElementById("initButton")?.addEventListener("click", () => { -        var hydra = new Hydra({ detectAudio: false }) -        modalEl.classList.remove("open"); -        playMusic(); -        initHydra(); -        initControls(); -    }); - -    document.getElementById("history").addEventListener("click", () => { -        downloadHistory(); -    }); - -    document.addEventListener("keyup", (event) => { -        const { key } = event; -        console.log("key pressed", key); -        switch (key) { -            case " ": -                togglePlay(); -                break; -            case "a": -                break; -            case "d": -                break; -            case "w": -                volumeUp(); -                break; -            case "s": -                volumeDown(); -                break; -            case "n": -                playNextTrack(); -                break; - -        } -    }); +  document.addEventListener("DOMContentLoaded", initDynamicTooltips); -    let touchstartX = 0; -    let touchendX = 0; -    let touchstartY = 0; -    let touchendY = 0; -    const musixPlayerEl = document.getElementsByClassName("music-player")[0]; -    if (musixPlayerEl) { -        musixPlayerEl.addEventListener("touchstart", (e) => { -            touchstartX = e.changedTouches[0].screenX; -            touchstartY = e.changedTouches[0].screenY; -        }); - -        musixPlayerEl.addEventListener("touchend", (e) => { -            touchendX = e.changedTouches[0].screenX; -            touchendY = e.changedTouches[0].screenY; -            checkDirection(); -        }); +  coverArtEl.addEventListener("click", (event) => { +    const isNoPause = event.target.classList.contains("no-pause"); +    if (howlerInstance && !isNoPause) { +      togglePlay();      } - -    function checkDirection() { -        if (touchendX < touchstartX) { -            // Swipe Left -        } -        if (touchendX > touchstartX) { -            // Swipe Right -        } - -        if (touchendY < touchstartY) { -            volumeUp(); -        } -        if (touchendY > touchstartY) { -            volumeDown(); +  }); + +  // uploadInfoEl.addEventListener("click", () => { +  //     const confirmText = `Do you really want to change your playlist?\nThis will replace all your retrowave music history.\nIf you are sure about this, make sure to upload a valid json file probably downloaded using history link.`; + +  //     if (confirm(confirmText)) { +  //         fileUploadEl.click(); +  //     } +  // }); + +  function listenUploadFileChange() { +    fileUploadEl.onchange = function () { +      const selectedFile = fileUploadEl.files[0]; +      const reader = new FileReader(); +      reader.readAsText(selectedFile, "UTF-8"); +      reader.onload = function (event) { +        try { +          const uploadedPlaylist = JSON.parse(event.target.result); +          localStorage.setItem("retrowave-history", event.target.result); +        } catch (error) { +          alert("malformed/invalid json file");          } +      }; +    }; +  } + +  document.getElementById("initButton")?.addEventListener("click", () => { +    var hydra = new Hydra({ detectAudio: false }); +    modalEl.classList.remove("open"); +    playMusic(); +    initHydra(); +    initControls(); +  }); + +  document.getElementById("history").addEventListener("click", () => { +    downloadHistory(); +  }); + +  document.addEventListener("keyup", (event) => { +    const { key } = event; +    switch (key) { +      case " ": +        togglePlay(); +        break; +      case "a": +        break; +      case "d": +        break; +      case "w": +        volumeUp(); +        break; +      case "s": +        volumeDown(); +        break; +      case "n": +        playNextTrack(); +        break; +      case "f": +        toggleFullScreen(); +        break; +     case "h": +        toggleControls(); +        break; +     case 'x': +        toggleEverything();      } +  }); + +  let touchstartX = 0; +  let touchendX = 0; +  let touchstartY = 0; +  let touchendY = 0; +  const musixPlayerEl = document.getElementsByClassName("music-player")[0]; +  if (musixPlayerEl) { +    musixPlayerEl.addEventListener("touchstart", (e) => { +      touchstartX = e.changedTouches[0].screenX; +      touchstartY = e.changedTouches[0].screenY; +    }); -    function openDialog() { -        modalEl.classList.add("open"); -    } +    musixPlayerEl.addEventListener("touchend", (e) => { +      touchendX = e.changedTouches[0].screenX; +      touchendY = e.changedTouches[0].screenY; +      checkDirection(); +    }); +  } -    async function getMusic() { -        const res = await fetch( -          `https://retrowave.ru/api/v1/tracks?limit=10&cursor=${cursor}` -        ).then((res) => res.json()); -        const { -          body: { tracks, cursor: currentCursor }, -        } = res; -        cursor = currentCursor; -        currentTracks = tracks; +  function checkDirection() { +    if (touchendX < touchstartX) { +      // Swipe Left      } - -    function initPlayer() { } - -    function playMusic() { -        const currentTrack = currentTracks[0]; -        const singleTrack = currentTrack.streamUrl; -        const fullTrack = `${retroWaveRu}${singleTrack}`; -        howlerInstance = new Howl({ -            src: [fullTrack], -            html5: true, -            onend: function () { -                playNextTrack(); -            }, -        }); -        setVolume(); -        isPlaying = true; -        window.hw = howlerInstance - -        updateInfo(currentTrack); - -        addToHistory(currentTrack); -        howlerInstance.play(); +    if (touchendX > touchstartX) { +      // Swipe Right      } -    function volumeDown() { -        console.log(volume); -        if (volume > 0.1) { -            volume -= 0.1; -        } -        setVolume(); +    if (touchendY < touchstartY) { +      volumeUp();      } - -    function volumeUp() { -        if (volume < 1) { -            volume += 0.1; -        } -        setVolume(); +    if (touchendY > touchstartY) { +      volumeDown();      } +  } + +  function openDialog() { +    modalEl.classList.add("open"); +  } + +  async function getMusic() { +    const res = await fetch( +      `https://retrowave.ru/api/v1/tracks?limit=10&cursor=${cursor}` +    ).then((res) => res.json()); +    const { +      body: { tracks, cursor: currentCursor }, +    } = res; +    cursor = currentCursor; +    currentTracks = tracks; +  } + +  function initPlayer() {} + +  function playMusic() { +    const currentTrack = currentTracks[0]; +    const singleTrack = currentTrack.streamUrl; +    const fullTrack = `${retroWaveRu}${singleTrack}`; +    howlerInstance = new Howl({ +      src: [fullTrack], +      html5: true, +      onend: function () { +        playNextTrack(); +      }, +    }); +    setVolume(); +    isPlaying = true; +    window.hw = howlerInstance; -    function setVolume() { -        howlerInstance.volume(volume); -    } +    updateInfo(currentTrack); -    function togglePlay() { -        isPlaying = !isPlaying; +    addToHistory(currentTrack); +    howlerInstance.play(); +  } -        if (isPlaying) { -            howlerInstance.play(); -        } else { -            howlerInstance.pause(); -        } +  function volumeDown() { +    if (volume > 0.1) { +      volume -= 0.1;      } +    setVolume(); +  } -    function updateInfo(trackDetails) { -        titleEl.innerText = trackDetails.title; -        document.title = `Now Playing... ${trackDetails.title}`; -        coverArtEl.style.backgroundImage = `url("${retroWaveRu}${trackDetails.artworkUrl}")`; +  function volumeUp() { +    if (volume < 1) { +      volume += 0.1;      } +    setVolume(); +  } -    function getHistory() { -        let localHistoryStore = localStorage.getItem("retrowave-history") || "[]"; -        let historyArray = JSON.parse(localHistoryStore); -        return historyArray; -    } +  function setVolume() { +    howlerInstance.volume(volume); +  } -    function addToHistory(trackDetails) { -        let historyArray = getHistory(); -        historyArray.push(trackDetails); -        localStorage.setItem("retrowave-history", JSON.stringify(historyArray)); -    } +  function togglePlay() { +    isPlaying = !isPlaying; -    function downloadHistory() { -        const historyArray = getHistory(); -        let element = document.createElement("a"); -        let playListData = '#EXTM3U'; -        historyArray.forEach((musicData) => { -            playListData = `${playListData} +    if (isPlaying) { +      howlerInstance.play(); +    } else { +      howlerInstance.pause(); +    } +  } + +  function updateInfo(trackDetails) { +    titleEl.innerText = trackDetails.title; +    document.title = `Now Playing... ${trackDetails.title}`; +    coverArtEl.style.backgroundImage = `url("${retroWaveRu}${trackDetails.artworkUrl}")`; +    ovr.innerHTML = `${trackDetails.title}` +  } + +  function getHistory() { +    let localHistoryStore = localStorage.getItem("retrowave-history") || "[]"; +    let historyArray = JSON.parse(localHistoryStore); +    return historyArray; +  } + +  function addToHistory(trackDetails) { +    let historyArray = getHistory(); +    historyArray.push(trackDetails); +    localStorage.setItem("retrowave-history", JSON.stringify(historyArray)); +  } + +  function downloadHistory() { +    const historyArray = getHistory(); +    let element = document.createElement("a"); +    let playListData = "#EXTM3U"; +    historyArray.forEach((musicData) => { +      playListData = `${playListData}  #EXTINF:${Math.ceil(musicData.duration / 1000)}, ${musicData.title}  https://retrowave.ru/${musicData.streamUrl}  `; -        }); +    }); -        element.setAttribute( -            "href", -            "data:audio/x-mpegurl;;charset=utf-8," + -            encodeURIComponent(playListData) -        ); -        element.setAttribute("download", "retrowave_playlist.m3u"); +    element.setAttribute( +      "href", +      "data:audio/x-mpegurl;;charset=utf-8," + encodeURIComponent(playListData) +    ); +    element.setAttribute("download", "retrowave_playlist.m3u"); -        element.style.display = "none"; -        document.body.appendChild(element); +    element.style.display = "none"; +    document.body.appendChild(element); -        element.click(); +    element.click(); -        document.body.removeChild(element); -    } +    document.body.removeChild(element); +  } -    function playNextTrack() { -        resetHowler(); -        currentTracks.shift(); -        if (currentTracks.length <= 3) { -            getMusic(); -        } -        playMusic(); +  function playNextTrack() { +    resetHowler(); +    currentTracks.shift(); +    if (currentTracks.length <= 3) { +      getMusic();      } - -    function resetHowler(destroy = false) { -        howlerInstance.stop(); -        if (destroy) { -            howlerInstance.unload(); -            howlerInstance = null; -        } +    playMusic(); +  } + +  function resetHowler(destroy = false) { +    howlerInstance.stop(); +    if (destroy) { +      howlerInstance.unload(); +      howlerInstance = null;      } +  } -    function initControls() { -        refreshBtn.addEventListener("click", () => { -            playNextTrack(); -        }); +  function initControls() { +    refreshBtn.addEventListener("click", () => { +      playNextTrack(); +    }); + +    fullScreenBtn.addEventListener("click", () => { +      toggleFullScreen(); +    }); +  } + +  function toggleFullScreen() { +    if (!document.fullscreenElement) { +      document.documentElement.requestFullscreen(); +    } else { +      if (document.exitFullscreen) { +        document.exitFullscreen(); +      }      } +  } -    // function initCodef() { -    //     const width = window.innerWidth; -    //     const height = window.innerHeight; -    //     effectCanvas = new canvas(width, height, 'codef-canvas'); -    //     starField = new starfield3D(effectCanvas, 500, 2, width, height, width/2, height/2, '#ffffff', 100, 0, 0); -    //     line3D = new codef3D(effectCanvas, 320, 75, 1, 1500 ); -    //     line3D.line({x:-320, y:0, z:0},{x:320, y:0, z:0}, new LineBasicMaterial({ color: synthwaveColor, linewidth:2})); -    //     line3D.line({x: 0, y:-240, z:0},{x:0, y:240, z:0}, new LineBasicMaterial({ color: synthwaveColor, linewidth:2})); -    //     renderCodeFx(); -    // } - -    // function renderCodeFx() { -    //     effectCanvas.fill('#000000'); -    //     line3D.group.rotation.x+=0.01; -    //     line3D.group.rotation.y+=0.02; -    //     line3D.group.rotation.z+=0.04; -    //     starField.draw(); -    //     line3D.draw(); -    //     requestAnimationFrame(renderCodeFx); -    // } - -    function initHydra() { -        voronoi(350, 0.15) -            .modulateScale(osc(8).rotate(Math.sin(time)), .5) -            .thresh(.8) -            .modulateRotate(osc(7), .4) -            .thresh(.7) -            .diff(src(o0).scale(1.8)) -            .modulateScale(osc(2).modulateRotate(o0, .74)) -            .diff(src(o0).rotate([-.012, .01, -.002, 0]).scrollY(0, [-1 / 199800, 0].fast(0.7))) -            .brightness([-.02, -.17].smooth().fast(.5))//.modulate(o0, () => a.fft[1] * .2) -            .out() +  function toggleControls() { +    const toggleableElements = document.querySelectorAll(".toggleable"); +    toggleableElements.forEach((el) => { +        el.classList.toggle("hidden"); +    }); +  } + +  function toggleEverything() { +    musixPlayerEl.classList.toggle("hidden"); +    ovr.classList.toggle("hidden"); +  } + +  // function initCodef() { +  //     const width = window.innerWidth; +  //     const height = window.innerHeight; +  //     effectCanvas = new canvas(width, height, 'codef-canvas'); +  //     starField = new starfield3D(effectCanvas, 500, 2, width, height, width/2, height/2, '#ffffff', 100, 0, 0); +  //     line3D = new codef3D(effectCanvas, 320, 75, 1, 1500 ); +  //     line3D.line({x:-320, y:0, z:0},{x:320, y:0, z:0}, new LineBasicMaterial({ color: synthwaveColor, linewidth:2})); +  //     line3D.line({x: 0, y:-240, z:0},{x:0, y:240, z:0}, new LineBasicMaterial({ color: synthwaveColor, linewidth:2})); +  //     renderCodeFx(); +  // } + +  // function renderCodeFx() { +  //     effectCanvas.fill('#000000'); +  //     line3D.group.rotation.x+=0.01; +  //     line3D.group.rotation.y+=0.02; +  //     line3D.group.rotation.z+=0.04; +  //     starField.draw(); +  //     line3D.draw(); +  //     requestAnimationFrame(renderCodeFx); +  // } + +  function initHydra() { +    try { +      voronoi(350, 0.15) +        .modulateScale(osc(8).rotate(Math.sin(time)), 0.5) +        .thresh(0.8) +        .modulateRotate(osc(7), 0.4) +        .thresh(0.7) +        .diff(src(o0).scale(1.8)) +        .modulateScale(osc(2).modulateRotate(o0, 0.74)) +        .diff( +          src(o0) +            .rotate([-0.012, 0.01, -0.002, 0]) +            .scrollY(0, [-1 / 199800, 0].fast(0.7)) +        ) +        .brightness([-0.02, -0.17].smooth().fast(0.5)) //.modulate(o0, () => a.fft[1] * .2) +        .out(); +    } catch (error) { +      console.error("Hydra initialization failed:", error);      } +  }  })(); | 
