Files
2026-06-13 15:35:45 +02:00

293 lines
9.2 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Winamp Poweramp Remote</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #000000;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Courier New', monospace;
padding: 20px;
}
.winamp {
background: linear-gradient(135deg, #2c2c2c 0%, #1a1a1f 100%);
border: 3px solid #3a6ea5;
border-radius: 16px;
padding: 20px;
box-shadow: 0 0 0 2px #0a0a0a, 0 10px 30px rgba(0,0,0,0.8);
width: 500px;
}
.title-bar {
background: linear-gradient(90deg, #1a3a5c 0%, #0d1f33 100%);
padding: 8px 12px;
margin: -20px -20px 15px -20px;
border-radius: 13px 13px 0 0;
display: flex;
justify-content: space-between;
border-bottom: 2px solid #3a6ea5;
}
.title-text {
color: #ffffff;
font-weight: bold;
font-size: 14px;
text-shadow: 0 0 3px #3a6ea5;
}
.vis {
height: 30px;
background: repeating-linear-gradient(90deg, #0f0 0px, #0f0 2px, #000 2px, #000 4px);
margin-bottom: 20px;
animation: pulse 0.5s ease infinite alternate;
}
@keyframes pulse {
from { opacity: 0.7; }
to { opacity: 1; }
}
.btn-row {
display: flex;
gap: 10px;
margin-bottom: 12px;
justify-content: center;
}
.winamp-btn {
background: linear-gradient(180deg, #3c3c44 0%, #1a1a22 100%);
border: 1px solid #3a6ea5;
border-radius: 6px;
color: #eee;
font-family: 'Arial', sans-serif;
font-size: 13px;
font-weight: bold;
padding: 12px 20px;
cursor: pointer;
min-width: 85px;
text-align: center;
}
.winamp-btn:active {
transform: translateY(1px);
}
.winamp-btn.disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
}
.btn-play { background: linear-gradient(180deg, #2a6a2a 0%, #1a4a1a 100%); color: #0f0; }
.btn-vol { background: linear-gradient(180deg, #6a6a2a 0%, #4a4a1a 100%); color: #ff0; }
.btn-nav { background: linear-gradient(180deg, #3a3a6a 0%, #1a1a4a 100%); color: #88f; }
.eq {
display: flex;
gap: 4px;
justify-content: center;
margin: 15px 0;
height: 40px;
align-items: flex-end;
}
.eq-bar {
width: 8px;
background: #0f0;
animation: bounce 0.8s ease infinite alternate;
}
.eq-bar:nth-child(1) { height: 15px; animation-delay: 0s; }
.eq-bar:nth-child(2) { height: 25px; animation-delay: 0.1s; }
.eq-bar:nth-child(3) { height: 35px; animation-delay: 0.2s; }
.eq-bar:nth-child(4) { height: 20px; animation-delay: 0.3s; }
.eq-bar:nth-child(5) { height: 30px; animation-delay: 0.4s; }
.eq-bar:nth-child(6) { height: 15px; animation-delay: 0.5s; }
.eq-bar:nth-child(7) { height: 28px; animation-delay: 0.6s; }
.eq-bar:nth-child(8) { height: 22px; animation-delay: 0.7s; }
@keyframes bounce {
0% { height: 5px; opacity: 0.5; }
100% { height: 40px; opacity: 1; }
}
.song-frame {
background: #000;
border: 2px inset #3a6ea5;
border-radius: 6px;
margin-top: 15px;
width: 100%;
height: 60px;
}
.song-frame iframe {
width: 100%;
height: 60px;
border: none;
background: #000;
}
.status-window {
background: #000;
border: 2px inset #3a6ea5;
border-radius: 6px;
padding: 10px;
margin-top: 15px;
height: 100px;
overflow: auto;
color: #0f0;
font-family: 'Courier New', monospace;
font-size: 10px;
white-space: pre-wrap;
}
.target-text {
font-size: 9px;
color: #3a6ea5;
text-align: center;
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid #2a2a2a;
}
.instruction {
background: #0a1a2a;
border: 1px solid #3a6ea5;
border-radius: 4px;
padding: 6px;
margin-top: 8px;
font-family: monospace;
font-size: 9px;
color: #0f0;
text-align: center;
}
</style>
</head>
<body>
<div class="winamp">
<div class="title-bar">
<div class="title-text">🔊 WINAMP - POWERAMP REMOTE</div>
<div class="title-buttons">─ □ ✕</div>
</div>
<div class="vis"></div>
<div class="btn-row">
<button class="winamp-btn btn-nav" id="btnPrev" onclick="sendCmd(5)">⏮ PREV</button>
<button class="winamp-btn btn-play" id="btnPlay" onclick="sendCmd(1)">⏯ PLAY/PAUSE</button>
<button class="winamp-btn btn-nav" id="btnNext" onclick="sendCmd(4)">⏭ NEXT</button>
</div>
<div class="btn-row">
<button class="winamp-btn btn-nav" id="btnPrevAlbum" onclick="sendCmd(6)">⬅ PREV ALBUM</button>
<button class="winamp-btn btn-nav" id="btnNextAlbum" onclick="sendCmd(7)">➡ NEXT ALBUM</button>
</div>
<div class="btn-row">
<button class="winamp-btn btn-vol" id="btnVolUp" onclick="volumeUp()">🔊 VOL +</button>
<button class="winamp-btn btn-vol" id="btnVolDown" onclick="volumeDown()">🔉 VOL -</button>
</div>
<div class="eq">
<div class="eq-bar"></div><div class="eq-bar"></div><div class="eq-bar"></div>
<div class="eq-bar"></div><div class="eq-bar"></div><div class="eq-bar"></div>
<div class="eq-bar"></div><div class="eq-bar"></div>
</div>
<div class="song-frame">
<iframe id="songIframe" src="songinfo.html"></iframe>
</div>
<div class="status-window" id="output">Ready...</div>
<div class="target-text">
🔌 NC: 192.168.0.190:8023 | 1=Play 4=Next 5=Prev 6=PrevAlbum 7=NextAlbum
</div>
<div class="instruction">
💡 Termux: <strong>busybox telnetd -p 8023</strong>
</div>
</div>
<script>
const baseUrl = '/card/ext/cgi-bin/exec.sh?script=sh/powerampctrl/powerampctrl.sh&cmd=';
let isRunning = false;
let queue = [];
function refreshSongInfo() {
const iframe = document.getElementById('songIframe');
const timestamp = Date.now();
iframe.src = `songinfo.html?t=${timestamp}`;
}
async function processQueue() {
if (isRunning) return;
if (queue.length === 0) return;
isRunning = true;
const { cmd, label } = queue.shift();
const output = document.getElementById('output');
output.textContent = `▶ Sending: ${label}\n`;
try {
const url = baseUrl + encodeURIComponent(cmd);
const response = await fetch(url);
const text = await response.text();
output.textContent = text;
// Refresh song info after command
setTimeout(() => refreshSongInfo(), 1500);
} catch (err) {
output.textContent = `❌ Error: ${err.message}`;
}
isRunning = false;
// Process next in queue after a short delay
setTimeout(() => processQueue(), 200);
}
async function queueCommand(cmd, label) {
queue.push({ cmd, label });
processQueue();
}
async function sendCmd(cmdNum) {
const cmd = `am broadcast 'intent:#Intent;action=com.maxmpz.audioplayer.API_COMMAND;package=com.maxmpz.audioplayer;i.cmd=${cmdNum};end'`;
const labels = {1:'PLAY/PAUSE',4:'NEXT',5:'PREV',6:'PREV ALBUM',7:'NEXT ALBUM'};
const output = document.getElementById('output');
output.textContent = `⏳ Queued: ${labels[cmdNum]}\n\n${output.textContent}`;
await queueCommand(cmd, labels[cmdNum]);
}
async function volumeUp() {
const output = document.getElementById('output');
output.textContent = `⏳ Queued: VOL +\n\n${output.textContent}`;
await queueCommand('cmd media_session volume --show --stream 3 --adj raise', 'VOL +');
}
async function volumeDown() {
const output = document.getElementById('output');
output.textContent = `⏳ Queued: VOL -\n\n${output.textContent}`;
await queueCommand('cmd media_session volume --show --stream 3 --adj lower', 'VOL -');
}
// Initial refresh
setTimeout(() => refreshSongInfo(), 500);
</script>
</body>
</html>