New Features
* Implements Terminal
This commit is contained in:
210
hg.css
210
hg.css
@@ -325,6 +325,10 @@ canvas {
|
|||||||
color: #ffff;
|
color: #ffff;
|
||||||
right: 0;
|
right: 0;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-top-right-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ERRORS {
|
.ERRORS {
|
||||||
@@ -344,3 +348,209 @@ canvas {
|
|||||||
border: 2px solid red;
|
border: 2px solid red;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Terminal Overlay Styles - ORED Initial Console Emulator Style */
|
||||||
|
.terminal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(192, 192, 192, 0.3);
|
||||||
|
backdrop-filter: none;
|
||||||
|
z-index: 10001;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-window {
|
||||||
|
width: 80%;
|
||||||
|
max-width: 600px;
|
||||||
|
height: 65%;
|
||||||
|
max-height: 450px;
|
||||||
|
min-height: 300px;
|
||||||
|
background: #c0c0c0;
|
||||||
|
border: 4px outset #c0c0c0;
|
||||||
|
border-radius: 0;
|
||||||
|
font-family: 'VCR', 'Monaco', 'Courier New', monospace;
|
||||||
|
box-shadow: 3px 3px 8px rgba(0, 0, 0, 0.6);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-header {
|
||||||
|
background: #c0c0c0;
|
||||||
|
color: #000000;
|
||||||
|
padding: 1px 0;
|
||||||
|
border-bottom: 2px inset #c0c0c0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: 'VCR', 'Geneva', 'Helvetica', sans-serif;
|
||||||
|
min-height: 16px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-title {
|
||||||
|
color: #000000;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-close {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 16px;
|
||||||
|
height: 14px;
|
||||||
|
border: 1px outset #c0c0c0;
|
||||||
|
background: #c0c0c0;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 12px;
|
||||||
|
border-radius: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 2px;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-close:hover {
|
||||||
|
background: #b0b0b0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-close:active {
|
||||||
|
border: 1px inset #c0c0c0;
|
||||||
|
background: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #c0c0c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal-output {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 9px;
|
||||||
|
line-height: 1.1;
|
||||||
|
font-family: 'VCR', 'Monaco', 'Courier New', monospace;
|
||||||
|
background: #c0c0c0;
|
||||||
|
border: 2px inset #c0c0c0;
|
||||||
|
padding: 2px 4px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-line {
|
||||||
|
margin-bottom: 0;
|
||||||
|
word-wrap: break-word;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 9px;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-input-line {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 9px;
|
||||||
|
background: #c0c0c0;
|
||||||
|
border: 2px inset #c0c0c0;
|
||||||
|
padding: 1px 4px;
|
||||||
|
min-height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-prompt {
|
||||||
|
color: #000000;
|
||||||
|
margin-right: 2px;
|
||||||
|
font-weight: normal;
|
||||||
|
font-family: 'VCR', 'Monaco', 'Courier New', monospace;
|
||||||
|
font-size: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-input {
|
||||||
|
flex: 1;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: #000000;
|
||||||
|
font-family: 'VCR', 'Monaco', 'Courier New', monospace;
|
||||||
|
font-size: 9px;
|
||||||
|
outline: none;
|
||||||
|
caret-color: #000000;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-input::selection {
|
||||||
|
background: #000080;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-btn {
|
||||||
|
float: right;
|
||||||
|
margin-right: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #565656;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-btn:hover {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-overlay.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom scrollbar for terminal output - Classic style */
|
||||||
|
#terminal-output::-webkit-scrollbar {
|
||||||
|
width: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal-output::-webkit-scrollbar-track {
|
||||||
|
background: #c0c0c0;
|
||||||
|
border: 1px inset #c0c0c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal-output::-webkit-scrollbar-thumb {
|
||||||
|
background: linear-gradient(to bottom, #e0e0e0 0%, #c0c0c0 50%, #a0a0a0 100%);
|
||||||
|
border: 1px outset #c0c0c0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal-output::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: linear-gradient(to bottom, #d0d0d0 0%, #b0b0b0 50%, #909090 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal-output::-webkit-scrollbar-thumb:active {
|
||||||
|
border: 1px inset #c0c0c0;
|
||||||
|
background: linear-gradient(to bottom, #a0a0a0 0%, #b0b0b0 50%, #d0d0d0 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal-output::-webkit-scrollbar-corner {
|
||||||
|
background: #c0c0c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal-output::-webkit-scrollbar-button {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background: linear-gradient(to bottom, #e0e0e0 0%, #c0c0c0 50%, #a0a0a0 100%);
|
||||||
|
border: 1px outset #c0c0c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal-output::-webkit-scrollbar-button:hover {
|
||||||
|
background: linear-gradient(to bottom, #d0d0d0 0%, #b0b0b0 50%, #909090 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal-output::-webkit-scrollbar-button:active {
|
||||||
|
border: 1px inset #c0c0c0;
|
||||||
|
background: linear-gradient(to bottom, #a0a0a0 0%, #b0b0b0 50%, #d0d0d0 100%);
|
||||||
|
}
|
||||||
|
|||||||
70
index.html
70
index.html
@@ -16,29 +16,32 @@
|
|||||||
<div class="modal" id="intro-modal">
|
<div class="modal" id="intro-modal">
|
||||||
<div class="modal-bg modal-exit"></div>
|
<div class="modal-bg modal-exit"></div>
|
||||||
<div class="modal-container">
|
<div class="modal-container">
|
||||||
<h3 class="text-center">Welcome to Retrowave Player</h3>
|
<h3 class="text-center">WELCOME TO RETROWAVE PLAYER</h3>
|
||||||
<p class="mt-5">Here are the controls:</p>
|
<p class="mt-5">HERE ARE THE CONTROLS:</p>
|
||||||
<h4 class="mt-5">
|
<h4 class="mt-5">
|
||||||
Play/Pause <span class="controls">SPACE or Click or Touch</span>
|
PLAY/PAUSE <span class="controls">SPACE OR CLICK OR TOUCH</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h4 class="mt-5">
|
<h4 class="mt-5">
|
||||||
Volume Up <span class="controls">w or Swipe Up</span>
|
VOLUME UP <span class="controls">W OR SWIPE UP</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h4 class="mt-5">
|
<h4 class="mt-5">
|
||||||
Volume Down <span class="controls">s or Swipe Down</span>
|
VOLUME DOWN <span class="controls">S OR SWIPE DOWN</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h4 class="mt-5">
|
<h4 class="mt-5">
|
||||||
Next Track<span class="controls"> n or Press the Refresh Button</span>
|
NEXT TRACK<span class="controls"> N OR PRESS THE REFRESH BUTTON</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h4 class="mt-5">
|
<h4 class="mt-5">
|
||||||
Toggle Controls<span class="controls"> h</span>
|
TOGGLE CONTROLS<span class="controls"> H</span>
|
||||||
|
</h4>
|
||||||
|
<h4 class="mt-5">
|
||||||
|
OPEN TERMINAL<span class="controls"> T</span>
|
||||||
</h4>
|
</h4>
|
||||||
<p class="mt-5">
|
<p class="mt-5">
|
||||||
(You can download the music history of your current browser by
|
(YOU CAN DOWNLOAD THE MUSIC HISTORY OF YOUR CURRENT BROWSER BY
|
||||||
clicking the history link on the player)
|
CLICKING THE HISTORY LINK ON THE PLAYER)
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-5">All the music is fetched from retrowave.ru</p>
|
<p class="mt-5">ALL THE MUSIC IS FETCHED FROM RETROWAVE.RU</p>
|
||||||
<div id="warning">⚠️ WARNING: This application contains strobing/flashing lights</div>
|
<div id="warning">⚠️ WARNING: THIS APPLICATION CONTAINS STROBING/FLASHING LIGHTS</div>
|
||||||
<button class="modal-close modal-exit" id="initButton">X</button>
|
<button class="modal-close modal-exit" id="initButton">X</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -78,22 +81,23 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div class="no-pause buttons refresh toggleable" title="NEXT TRACK">🔃</div>
|
<div class="no-pause buttons refresh toggleable" title="NEXT TRACK">🔃</div>
|
||||||
|
<div class="no-pause buttons terminal-btn toggleable" title="OPEN TERMINAL">⌨️</div>
|
||||||
<div class="title-content">
|
<div class="title-content">
|
||||||
<div class="intro">Now Playing</div>
|
<div class="intro">NOW PLAYING</div>
|
||||||
<hr />
|
<hr />
|
||||||
<h3 id="track-name">Retrowave Player</h3>
|
<h3 id="track-name">RETROWAVE PLAYER</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="gradient-overlay"></div>
|
<div class="gradient-overlay"></div>
|
||||||
<div class="color-overlay"></div>
|
<div class="color-overlay"></div>
|
||||||
<div class="footer toggleable">
|
<div class="footer toggleable">
|
||||||
<div title="DOWNLOAD YOUR PLAYLIST HISTORY" id="history" class="no-pause footer-items">history</div>
|
<div title="DOWNLOAD YOUR PLAYLIST HISTORY" id="history" class="no-pause footer-items">HISTORY</div>
|
||||||
<div id="source">
|
<div id="source">
|
||||||
<a
|
<a
|
||||||
title="SOURCE CODE"
|
title="SOURCE CODE"
|
||||||
class="no-pause footer-items"
|
class="no-pause footer-items"
|
||||||
href="https://git.indrajith.dev/retrowave-player/"
|
href="https://git.indrajith.dev/retrowave-player/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>source code</a
|
>SOURCE CODE</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div id="retrowaveru" class="no-pause">
|
<div id="retrowaveru" class="no-pause">
|
||||||
@@ -102,7 +106,7 @@
|
|||||||
class="no-pause footer-items"
|
class="no-pause footer-items"
|
||||||
href="http://retrowave.ru/"
|
href="http://retrowave.ru/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>retrowave.ru</a
|
>RETROWAVE.RU</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div id="guestbook" class="no-pause">
|
<div id="guestbook" class="no-pause">
|
||||||
@@ -111,13 +115,45 @@
|
|||||||
class="no-pause footer-items"
|
class="no-pause footer-items"
|
||||||
href="https://indrajith.atabook.org/"
|
href="https://indrajith.atabook.org/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>guestbook</a
|
>GUESTBOOK</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div id="upload-info" class="no-pause" title="Upload a playlist (downloaded from history)">Upload</div> -->
|
<!-- <div id="upload-info" class="no-pause" title="Upload a playlist (downloaded from history)">Upload</div> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="terminal-overlay" class="terminal-overlay hidden">
|
||||||
|
<div class="terminal-window">
|
||||||
|
<div class="terminal-header">
|
||||||
|
<span class="terminal-title">Retrowave Terminal</span>
|
||||||
|
<span class="terminal-close">□</span>
|
||||||
|
</div>
|
||||||
|
<div class="terminal-content">
|
||||||
|
<div id="terminal-output">
|
||||||
|
<div class="terminal-line">Welcome to Retrowave Terminal</div>
|
||||||
|
<div class="terminal-line">Type 'help' for available commands</div>
|
||||||
|
<div class="terminal-line"></div>
|
||||||
|
<div class="terminal-line">Available commands:</div>
|
||||||
|
<div class="terminal-line"> help - Show this help message</div>
|
||||||
|
<div class="terminal-line"> play - Start/resume playback</div>
|
||||||
|
<div class="terminal-line"> pause - Pause playback</div>
|
||||||
|
<div class="terminal-line"> next - Skip to next track</div>
|
||||||
|
<div class="terminal-line"> volume [0-10] - Set volume (0-10)</div>
|
||||||
|
<div class="terminal-line"> status - Show current track info</div>
|
||||||
|
<div class="terminal-line"> history - Download playlist history</div>
|
||||||
|
<div class="terminal-line"> effect - Change visual effect</div>
|
||||||
|
<div class="terminal-line"> fullscreen - Toggle fullscreen mode</div>
|
||||||
|
<div class="terminal-line"> clear - Clear terminal</div>
|
||||||
|
<div class="terminal-line"> exit - Close terminal</div>
|
||||||
|
<div class="terminal-line"></div>
|
||||||
|
</div>
|
||||||
|
<div class="terminal-input-line">
|
||||||
|
<span class="terminal-prompt">indrajith@retrowave:$ </span>
|
||||||
|
<input type="text" id="terminal-input" class="terminal-input" autocomplete="off" spellcheck="false">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="codef-canvas"></div>
|
<div id="codef-canvas"></div>
|
||||||
<div class="OVR hidden"></div>
|
<div class="OVR hidden"></div>
|
||||||
<div class="ERRORS hidden"></div>
|
<div class="ERRORS hidden"></div>
|
||||||
|
|||||||
217
player.js
217
player.js
@@ -9,6 +9,11 @@
|
|||||||
let refreshBtn = document.querySelector(".refresh");
|
let refreshBtn = document.querySelector(".refresh");
|
||||||
let ovr = document.querySelector(".OVR");
|
let ovr = document.querySelector(".OVR");
|
||||||
let fullScreenBtn = document.querySelector(".fullscreen");
|
let fullScreenBtn = document.querySelector(".fullscreen");
|
||||||
|
let terminalBtn = document.querySelector(".terminal-btn");
|
||||||
|
let terminalOverlay = document.getElementById("terminal-overlay");
|
||||||
|
let terminalInput = document.getElementById("terminal-input");
|
||||||
|
let terminalOutput = document.getElementById("terminal-output");
|
||||||
|
let terminalClose = document.querySelector(".terminal-close");
|
||||||
let errorEl = document.querySelector(".ERRORS");
|
let errorEl = document.querySelector(".ERRORS");
|
||||||
let currentEffectIndex = 0;
|
let currentEffectIndex = 0;
|
||||||
const modalEl = document.getElementById("intro-modal");
|
const modalEl = document.getElementById("intro-modal");
|
||||||
@@ -113,15 +118,15 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("keyup", (event) => {
|
document.addEventListener("keyup", (event) => {
|
||||||
|
if (!terminalOverlay.classList.contains("hidden")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { key } = event;
|
const { key } = event;
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case " ":
|
case " ":
|
||||||
togglePlay();
|
togglePlay();
|
||||||
break;
|
break;
|
||||||
case "a":
|
|
||||||
break;
|
|
||||||
case "d":
|
|
||||||
break;
|
|
||||||
case "w":
|
case "w":
|
||||||
volumeUp();
|
volumeUp();
|
||||||
break;
|
break;
|
||||||
@@ -143,6 +148,9 @@
|
|||||||
case "e":
|
case "e":
|
||||||
rotateHydraEffect();
|
rotateHydraEffect();
|
||||||
break;
|
break;
|
||||||
|
case "t":
|
||||||
|
toggleTerminal();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -255,10 +263,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateInfo(trackDetails) {
|
function updateInfo(trackDetails) {
|
||||||
titleEl.innerText = trackDetails.title;
|
const trackTitle = trackDetails.title.toString().toUpperCase() || "Unknown Track";
|
||||||
document.title = `Now Playing... ${trackDetails.title}`;
|
titleEl.innerText = trackTitle;
|
||||||
|
document.title = `Now Playing... ${trackTitle}`;
|
||||||
coverArtEl.style.backgroundImage = `url("${retroWaveRu}${trackDetails.artworkUrl}")`;
|
coverArtEl.style.backgroundImage = `url("${retroWaveRu}${trackDetails.artworkUrl}")`;
|
||||||
ovr.innerHTML = `${trackDetails.title}`;
|
ovr.innerHTML = `> ${trackTitle}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHistory() {
|
function getHistory() {
|
||||||
@@ -324,6 +333,27 @@ https://retrowave.ru/${musicData.streamUrl}
|
|||||||
fullScreenBtn.addEventListener("click", () => {
|
fullScreenBtn.addEventListener("click", () => {
|
||||||
toggleFullScreen();
|
toggleFullScreen();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
terminalBtn.addEventListener("click", () => {
|
||||||
|
toggleTerminal();
|
||||||
|
});
|
||||||
|
|
||||||
|
terminalClose.addEventListener("click", () => {
|
||||||
|
closeTerminal();
|
||||||
|
});
|
||||||
|
|
||||||
|
terminalInput.addEventListener("keydown", (e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
executeCommand(terminalInput.value.trim());
|
||||||
|
terminalInput.value = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("keydown", (e) => {
|
||||||
|
if (e.key === "Escape" && !terminalOverlay.classList.contains("hidden")) {
|
||||||
|
closeTerminal();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleFullScreen() {
|
async function toggleFullScreen() {
|
||||||
@@ -469,4 +499,177 @@ https://retrowave.ru/${musicData.streamUrl}
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleTerminal() {
|
||||||
|
terminalOverlay.classList.toggle("hidden");
|
||||||
|
if (!terminalOverlay.classList.contains("hidden")) {
|
||||||
|
terminalInput.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeTerminal() {
|
||||||
|
terminalOverlay.classList.add("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTerminalLine(text, isCommand = false) {
|
||||||
|
const line = document.createElement("div");
|
||||||
|
line.className = "terminal-line";
|
||||||
|
if (isCommand) {
|
||||||
|
line.innerHTML = `<span style="color: #000000; font-weight: normal;">indrajith@retrowave:$ ${text}</span>`;
|
||||||
|
} else {
|
||||||
|
line.textContent = text;
|
||||||
|
}
|
||||||
|
terminalOutput.appendChild(line);
|
||||||
|
terminalOutput.scrollTop = terminalOutput.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeCommand(command) {
|
||||||
|
if (!command) return;
|
||||||
|
|
||||||
|
addTerminalLine(command, true);
|
||||||
|
|
||||||
|
const args = command.toLowerCase().split(' ');
|
||||||
|
const cmd = args[0];
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case 'help':
|
||||||
|
addTerminalLine('Available commands:');
|
||||||
|
addTerminalLine(' help - Show this help message');
|
||||||
|
addTerminalLine(' play - Start/resume playback');
|
||||||
|
addTerminalLine(' pause - Pause playback');
|
||||||
|
addTerminalLine(' next - Skip to next track');
|
||||||
|
addTerminalLine(' volume [0-10] - Set volume (0-10)');
|
||||||
|
addTerminalLine(' status - Show current track info');
|
||||||
|
addTerminalLine(' history - Download playlist history');
|
||||||
|
addTerminalLine(' effect [list|name] - Change/list visual effects');
|
||||||
|
addTerminalLine(' fullscreen - Toggle fullscreen mode');
|
||||||
|
addTerminalLine(' clear - Clear terminal');
|
||||||
|
addTerminalLine(' exit - Close terminal');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'play':
|
||||||
|
if (howlerInstance && !isPlaying) {
|
||||||
|
togglePlay();
|
||||||
|
addTerminalLine('Playback resumed.');
|
||||||
|
} else if (isPlaying) {
|
||||||
|
addTerminalLine('Already playing.');
|
||||||
|
} else {
|
||||||
|
addTerminalLine('No track loaded.');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'pause':
|
||||||
|
if (howlerInstance && isPlaying) {
|
||||||
|
togglePlay();
|
||||||
|
addTerminalLine('Playback paused.');
|
||||||
|
} else {
|
||||||
|
addTerminalLine('Not currently playing.');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'next':
|
||||||
|
if (howlerInstance) {
|
||||||
|
playNextTrack();
|
||||||
|
addTerminalLine('Skipped to next track.');
|
||||||
|
} else {
|
||||||
|
addTerminalLine('No track loaded.');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'volume':
|
||||||
|
if (args[1]) {
|
||||||
|
const vol = parseInt(args[1]);
|
||||||
|
if (vol >= 0 && vol <= 10) {
|
||||||
|
volume = vol / 10;
|
||||||
|
if (howlerInstance) setVolume();
|
||||||
|
addTerminalLine(`Volume set to ${vol}/10`);
|
||||||
|
} else {
|
||||||
|
addTerminalLine('Volume must be between 0 and 10.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addTerminalLine(`Current volume: ${Math.round(volume * 10)}/10`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'status':
|
||||||
|
if (currentTracks.length > 0) {
|
||||||
|
const track = currentTracks[0];
|
||||||
|
addTerminalLine(`Now playing: ${track.title}`);
|
||||||
|
addTerminalLine(`Status: ${isPlaying ? 'Playing' : 'Paused'}`);
|
||||||
|
addTerminalLine(`Volume: ${Math.round(volume * 10)}/10`);
|
||||||
|
} else {
|
||||||
|
addTerminalLine('No track loaded.');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'history':
|
||||||
|
downloadHistory();
|
||||||
|
addTerminalLine('Playlist history downloaded.');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'effect':
|
||||||
|
if (args[1]) {
|
||||||
|
if (args[1] === 'list') {
|
||||||
|
addTerminalLine('Available effects:');
|
||||||
|
addTerminalLine(' vernoi - Voronoi pattern effect');
|
||||||
|
addTerminalLine(' waveyzz - Wave synthesis effect');
|
||||||
|
addTerminalLine(' oscrotate - Oscillating rotation effect');
|
||||||
|
addTerminalLine('Usage: effect <effect_name> or effect list');
|
||||||
|
} else {
|
||||||
|
const effectName = args[1].toLowerCase();
|
||||||
|
let effectIndex = -1;
|
||||||
|
|
||||||
|
switch (effectName) {
|
||||||
|
case 'vernoi':
|
||||||
|
effectIndex = 0;
|
||||||
|
break;
|
||||||
|
case 'waveyzz':
|
||||||
|
effectIndex = 1;
|
||||||
|
break;
|
||||||
|
case 'oscrotate':
|
||||||
|
effectIndex = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
addTerminalLine(`Unknown effect: ${effectName}`);
|
||||||
|
addTerminalLine('Type "effect list" to see available effects.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effectIndex !== -1) {
|
||||||
|
try {
|
||||||
|
hydraEffects[effectIndex]();
|
||||||
|
currentEffectIndex = effectIndex;
|
||||||
|
addTerminalLine(`Effect changed to: ${effectName}`);
|
||||||
|
} catch (error) {
|
||||||
|
addTerminalLine('Failed to apply effect.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rotateHydraEffect();
|
||||||
|
addTerminalLine('Visualization changed to next effect.');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'fullscreen':
|
||||||
|
toggleFullScreen();
|
||||||
|
addTerminalLine('Toggled fullscreen mode.');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'clear':
|
||||||
|
terminalOutput.innerHTML = '';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'exit':
|
||||||
|
closeTerminal();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
addTerminalLine(`Command not found: ${cmd}`);
|
||||||
|
addTerminalLine('Type "help" for available commands.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
addTerminalLine('');
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user