38018-vm/index.php
2026-02-01 20:04:21 +00:00

819 lines
27 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
require_once __DIR__ . '/db/config.php';
@ini_set('display_errors', '0');
@error_reporting(E_ALL);
session_start();
// Simple admin check: access via index.php?admin=lili
if (isset($_GET['admin']) && $_GET['admin'] === 'lili') {
$_SESSION['is_admin'] = true;
}
if (isset($_GET['logout'])) {
unset($_SESSION['is_admin']);
}
$isAdmin = !empty($_SESSION['is_admin']);
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Lili Records Radio - La mejor música en vivo.';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
$streamUrl = "https://play.radioking.io/lili-record-s-radio";
$whatsappNumber = "5359177041";
$whatsappLink = "https://wa.me/" . $whatsappNumber;
$whatsappGroupLink = "https://chat.whatsapp.com/G4l9N2i7J8L5K6M7N8O9P0"; // Placeholder for the group link
$youtubeUrl = "https://www.youtube.com/@lilirecords";
$promoImage = "assets/pasted-20260130-234122-115a4b49.png";
$qrImage = "assets/pasted-20260131-000858-4fff58f0.jpg";
$logoImage = "assets/pasted-20260131-002028-7985dfae.png";
// Social Share URLs
$currentUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$shareText = urlencode("Escuchando Lili Records Radio! 🎙️ La mejor música en vivo. #LiliRecords #RadioEnVivo #Musica2026");
$fbShare = "https://www.facebook.com/sharer/sharer.php?u=" . urlencode($currentUrl);
$xShare = "https://twitter.com/intent/tweet?text=$shareText&url=" . urlencode($currentUrl);
$waShare = "https://api.whatsapp.com/send?text=$shareText%20" . urlencode($currentUrl);
// Fetch latest requests
$requests = [];
try {
$stmt = db()->query("SELECT name, phone, message, created_at FROM listener_requests ORDER BY created_at DESC LIMIT 20");
$requests = $stmt->fetchAll();
} catch (Exception $e) {
// Silently fail if table doesn't exist yet or other DB error
}
?>
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Lili Records Radio</title>
<?php if ($projectDescription): ?>
<meta name="description" content="<?= htmlspecialchars($projectDescription) ?>" />
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
<style>
:root {
--primary-color: #ff2d55;
--glass-bg: rgba(0, 0, 0, 0.7);
--glass-border: rgba(255, 255, 255, 0.15);
}
body {
font-family: 'Inter', sans-serif;
background: #050505;
color: #fff;
min-height: 100vh;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow-x: hidden;
}
/* Background Image */
.bg-image {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url('<?= $promoImage ?>') center/cover no-repeat;
filter: brightness(0.25) blur(8px);
z-index: -1;
}
.main-wrapper {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: center;
width: 100%;
max-width: 1200px;
padding: 2rem;
gap: 2rem;
z-index: 1;
}
@media (max-width: 992px) {
.main-wrapper {
flex-direction: column;
align-items: center;
padding: 1rem;
}
.left-column {
position: static;
flex: none;
width: 100%;
max-width: 500px;
}
body {
overflow-y: auto;
height: auto;
}
}
.left-column {
position: sticky;
top: 2rem;
flex: 0 0 320px;
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.player-container {
background: var(--glass-bg);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid var(--glass-border);
border-radius: 30px;
padding: 2rem;
width: 100%;
text-align: center;
box-shadow: 0 25px 50px rgba(0,0,0,0.8);
position: relative;
overflow: hidden;
}
.right-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 2rem;
max-width: 700px;
width: 100%;
min-width: 0;
}
.promo-image {
width: 100%;
height: auto;
border-radius: 35px;
box-shadow: 0 35px 70px rgba(0,0,0,0.8);
border: 1px solid var(--glass-border);
}
.comments-window {
background: var(--glass-bg);
backdrop-filter: blur(25px);
-webkit-backdrop-filter: blur(25px);
border: 1px solid var(--glass-border);
border-radius: 35px;
padding: 2rem;
box-shadow: 0 35px 70px rgba(0,0,0,0.6);
display: flex;
flex-direction: column;
min-height: 450px;
}
.comments-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1.5rem;
padding-bottom: 1rem;
border-bottom: 1px solid var(--glass-border);
}
.comments-list {
overflow-y: auto;
flex: 1;
padding-right: 10px;
max-height: 550px;
}
.comment-item {
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.08);
border-radius: 20px;
padding: 1.5rem;
margin-bottom: 1.2rem;
transition: all 0.3s ease;
position: relative;
}
.comment-item:hover {
background: rgba(255,255,255,0.1);
transform: scale(1.02);
}
.comment-user {
font-weight: 700;
color: var(--primary-color);
display: block;
margin-bottom: 0.4rem;
}
.btn-wa-reply {
background: #25d366;
color: #fff;
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
box-shadow: 0 5px 15px rgba(37, 211, 102, 0.4);
text-decoration: none;
}
.btn-wa-reply:hover {
transform: scale(1.2) rotate(15deg);
color: #fff;
}
.form-control-glass {
background: #ffffff;
border: none;
color: #000;
border-radius: 18px;
padding: 0.9rem 1.4rem;
font-weight: 500;
}
.btn-send-request {
background: linear-gradient(45deg, var(--primary-color), #ff512f);
border: none;
border-radius: 18px;
font-weight: 700;
box-shadow: 0 10px 25px rgba(255, 45, 85, 0.4);
}
.radio-logo {
width: 85px;
height: 85px;
border-radius: 50%;
margin: 0 auto 1.2rem;
box-shadow: 0 0 30px rgba(255, 45, 85, 0.6);
animation: pulse 3s infinite;
overflow: hidden;
border: 4px solid rgba(255,255,255,0.25);
position: relative;
z-index: 2;
}
.radio-logo img {
width: 100%;
height: 100%;
object-fit: cover;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.btn-play {
width: 60px;
height: 60px;
border-radius: 50%;
background: #fff;
color: #000;
border: none;
font-size: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
position: relative;
z-index: 2;
}
.btn-play:hover {
background: var(--primary-color);
color: #fff;
transform: scale(1.15);
}
.whatsapp-btn {
position: fixed;
bottom: 30px;
left: 30px;
width: 70px;
height: 70px;
background: #25d366;
color: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
box-shadow: 0 15px 35px rgba(37, 211, 102, 0.5);
text-decoration: none;
z-index: 1000;
animation: bounce 2.5s infinite;
}
.btn-youtube-float {
position: fixed;
bottom: 115px;
left: 30px;
width: 70px;
height: 70px;
background: #ff0000;
color: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.2rem;
box-shadow: 0 15px 35px rgba(255, 0, 0, 0.5);
text-decoration: none;
z-index: 1000;
animation: bounce 2.8s infinite;
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {transform: translateY(0);}
40% {transform: translateY(-15px);}
60% {transform: translateY(-8px);}
}
.live-badge {
position: absolute;
top: 20px;
left: 20px;
background: var(--primary-color);
padding: 5px 12px;
border-radius: 20px;
font-size: 0.7rem;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 2px;
box-shadow: 0 5px 15px rgba(255, 45, 85, 0.5);
z-index: 3;
}
/* Visualizer Canvas */
#visualizer {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 140px;
z-index: 1;
opacity: 0.8;
pointer-events: none;
}
.song-info {
position: relative;
z-index: 2;
}
.player-controls-row {
position: relative;
z-index: 2;
}
.qr-container {
cursor: pointer;
transition: all 0.3s ease;
}
.qr-container:hover {
transform: scale(1.1);
}
.social-share-row {
position: relative;
z-index: 2;
display: flex;
justify-content: center;
gap: 15px;
margin-top: 20px;
}
.share-btn {
width: 35px;
height: 35px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 0.9rem;
transition: all 0.3s ease;
text-decoration: none;
border: 1px solid rgba(255,255,255,0.1);
}
.share-btn:hover {
transform: translateY(-3px) scale(1.1);
color: #fff;
}
.btn-fb { background: #3b5998; }
.btn-x { background: #000; }
.btn-wa-share { background: #25d366; }
.schedule-item {
background: rgba(255,255,255,0.03);
border: 1px solid var(--glass-border);
border-radius: 20px;
padding: 1.2rem;
transition: all 0.3s ease;
}
.schedule-item:hover {
background: rgba(255,255,255,0.06);
transform: translateY(-5px);
}
.artists-card {
background: linear-gradient(135deg, rgba(255,45,85,0.15) 0%, rgba(0,0,0,0.6) 100%);
border: 1px solid rgba(255,45,85,0.3);
border-radius: 35px;
padding: 2.5rem;
text-align: center;
}
.community-box {
background: linear-gradient(135deg, #25d366 0%, #128c7e 100%);
border-radius: 35px;
padding: 2rem;
color: #fff;
display: flex;
align-items: center;
gap: 1.5rem;
box-shadow: 0 20px 40px rgba(37, 211, 102, 0.3);
text-decoration: none;
transition: all 0.3s ease;
border: 1px solid rgba(255,255,255,0.2);
}
.community-box:hover {
transform: scale(1.02);
color: #fff;
box-shadow: 0 25px 50px rgba(37, 211, 102, 0.4);
}
.community-icon {
width: 60px;
height: 60px;
background: rgba(255,255,255,0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.8rem;
flex-shrink: 0;
}
</style>
</head>
<body>
<div class="bg-image"></div>
<div class="main-wrapper">
<!-- Left: Player -->
<div class="left-column">
<aside class="player-container">
<div class="live-badge">En Vivo</div>
<div class="radio-logo">
<img src="<?= $logoImage ?>" alt="Lili Records Logo">
</div>
<div class="song-info mb-4">
<span class="d-block fw-bold fs-5" id="songTitle">Conectando...</span>
<span class="d-block opacity-50 small" id="artistName">Lili Records Radio</span>
</div>
<div class="player-controls-row d-flex align-items-center gap-3 justify-content-center">
<button class="btn-play" id="playBtn">
<i class="fas fa-play" id="playIcon"></i>
</button>
<div class="d-flex align-items-center gap-2" style="width: 120px;">
<i class="fas fa-volume-up opacity-50"></i>
<input type="range" class="form-range" id="volumeSlider" min="0" max="1" step="0.01" value="0.8">
</div>
</div>
<div class="social-share-row">
<a href="<?= $fbShare ?>" target="_blank" class="share-btn btn-fb" title="Compartir en Facebook">
<i class="fab fa-facebook-f"></i>
</a>
<a href="<?= $xShare ?>" target="_blank" class="share-btn btn-x" title="Compartir en X">
<i class="fab fa-x-twitter"></i>
</a>
<a href="<?= $waShare ?>" target="_blank" class="share-btn btn-wa-share" title="Compartir en WhatsApp">
<i class="fab fa-whatsapp"></i>
</a>
</div>
<canvas id="visualizer"></canvas>
<div class="mt-4 pt-3 border-top border-white border-opacity-10 position-relative" style="z-index: 2;">
<?php if ($isAdmin): ?>
<div class="mt-2 small text-primary fw-bold"><i class="fas fa-user-shield me-1"></i> PANEL ADMINISTRADOR</div>
<a href="?logout=1" class="btn btn-sm btn-outline-danger px-4 rounded-pill mt-2 w-100">Cerrar Sesión</a>
<?php else: ?>
<p class="small opacity-40 mb-0">¡Sintoniza la mejor vibra!</p>
<?php endif; ?>
</div>
</aside>
</div>
<!-- Right: Image + Content -->
<div class="right-content">
<img src="<?= $promoImage ?>" alt="Lili Records Promo" class="promo-image">
<!-- WhatsApp Group Community -->
<a href="<?= $whatsappGroupLink ?>" target="_blank" class="community-box">
<div class="community-icon">
<i class="fab fa-whatsapp"></i>
</div>
<div>
<h5 class="fw-bold mb-1">Comunidad "Lili Records Radio"</h5>
<p class="small mb-0 opacity-90">¡Únete para recibir noticias, anuncios y el enlace de transmisión directamente!</p>
</div>
<div class="ms-auto d-none d-sm-block">
<i class="fas fa-chevron-right opacity-50"></i>
</div>
</a>
<!-- Messages Window -->
<div class="comments-window">
<div class="comments-header border-0 mb-3">
<div>
<h5 class="mb-1"><i class="fas fa-paper-plane me-2 text-primary"></i><?= $isAdmin ? 'Mensajes de Oyentes' : '¡Envía tu dedicatoria!' ?></h5>
<p class="small opacity-60 mb-0"><?= $isAdmin ? 'Peticiones en tiempo real' : 'Pide una canción, envía un saludo o una dedicatoria.' ?></p>
</div>
<div class="text-center qr-container" style="width: 90px;" data-bs-toggle="modal" data-bs-target="#qrModal">
<img src="<?= $qrImage ?>" alt="QR Pago" class="w-100 rounded-3 mb-1">
<p class="small fw-bold mb-0"><?= $isAdmin ? 'QR' : 'APOYAR' ?></p>
</div>
</div>
<div class="comments-list" id="commentsList">
<?php if (empty($requests)): ?>
<div class="text-center py-5 opacity-30">
<i class="fas fa-comment-slash fa-4x mb-3"></i>
<p>No hay mensajes todavía.</p>
</div>
<?php else: ?>
<?php foreach ($requests as $req): ?>
<div class="comment-item">
<span class="comment-user"><?= htmlspecialchars($req['name']) ?></span>
<p class="mb-2"><?= htmlspecialchars($req['message']) ?></p>
<div class="d-flex justify-content-between align-items-center">
<span class="small opacity-40"><?= date('d M, H:i', strtotime($req['created_at'])) ?></span>
<?php if ($isAdmin && !empty($req['phone'])): ?>
<a href="https://wa.me/<?= preg_replace('/[^0-9]/', '', $req['phone']) ?>" class="btn-wa-reply" target="_blank">
<i class="fab fa-whatsapp"></i>
</a>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<form action="submit_request.php" method="POST" class="request-form mt-auto pt-4">
<div class="row g-2 mb-2">
<div class="col-sm-6">
<input type="text" name="name" class="form-control glass-input" placeholder="Tu nombre" required style="background: #fff; border: none; color: #000; border-radius: 18px; padding: 0.9rem 1.4rem; font-weight: 500; width: 100%;">
</div>
<div class="col-sm-6">
<input type="text" name="phone" class="form-control glass-input" placeholder="Tu WhatsApp (opcional)" style="background: #fff; border: none; color: #000; border-radius: 18px; padding: 0.9rem 1.4rem; font-weight: 500; width: 100%;">
</div>
</div>
<div class="input-group">
<textarea name="message" class="form-control glass-input" rows="1" placeholder="Escribe tu dedicatoria aquí..." required style="background: #fff; border: none; color: #000; border-radius: 18px; padding: 0.9rem 1.4rem; font-weight: 500;"></textarea>
<button type="submit" class="btn btn-send-request text-white px-4">
<i class="fas fa-paper-plane"></i>
</button>
</div>
<div class="text-center mt-3">
<a href="#" class="text-white opacity-40 small text-decoration-none" data-bs-toggle="modal" data-bs-target="#policyModal">Ver Políticas de Privacidad</a>
</div>
</form>
</div>
<!-- Weekly Schedule -->
<div class="schedule-section">
<h4 class="mb-4 fw-bold"><i class="far fa-calendar-alt me-2 text-primary"></i>PROGRAMACIÓN SEMANAL</h4>
<div class="row g-3">
<div class="col-md-4">
<div class="schedule-item h-100">
<h6 class="text-primary fw-bold mb-2">Lunes a Viernes</h6>
<p class="small mb-1 opacity-70">08:00 - 10:00<br>Mañana Musical</p>
<p class="small mb-0 opacity-70">14:00 - 16:00<br>Tarde de Éxitos</p>
</div>
</div>
<div class="col-md-4">
<div class="schedule-item h-100">
<h6 class="text-primary fw-bold mb-2">Sábados</h6>
<p class="small mb-0 opacity-70">18:00 - 22:00<br>Party Mix Live 🎧</p>
</div>
</div>
<div class="col-md-4">
<div class="schedule-item h-100">
<h6 class="text-primary fw-bold mb-2">Domingos</h6>
<p class="small mb-0 opacity-70">10:00 - 14:00<br>Top 40 Lili Records</p>
</div>
</div>
</div>
</div>
<!-- Local Artists -->
<div class="artists-card mt-2">
<h3 class="fw-bold mb-3">🤝 COLABORA CON NOSOTROS</h3>
<p class="opacity-70 mb-4 mx-auto" style="max-width: 500px;">¿Eres artista local y quieres que tu música suene en Lili Records Radio? Queremos apoyarte.</p>
<div class="d-flex flex-wrap justify-content-center gap-3">
<a href="<?= $whatsappLink ?>?text=Hola,%20soy%20artista%20y%20quiero%20colaborar%20con%20Lili%20Records" target="_blank" class="btn btn-primary rounded-pill px-4 py-2 fw-bold border-0">
<i class="fas fa-music me-2"></i>ENVIAR MI MÚSICA
</a>
</div>
</div>
<div class="mt-4 text-center pb-5">
<p class="small text-white opacity-30 mb-0">&copy; 2026 Lili Record´s Radio. Música que conecta.</p>
</div>
</div>
</div>
<!-- Modal Política de Privacidad -->
<div class="modal fade" id="policyModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content border-0" style="background: rgba(15,15,15,0.98); border-radius: 35px; backdrop-filter: blur(30px);">
<div class="modal-header border-white border-opacity-10 px-5 py-4">
<h5 class="modal-title fw-bold">POLÍTICA DE PRIVACIDAD</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body px-5 py-4" style="font-size: 1rem; line-height: 1.8; opacity: 0.8;">
<ul class="list-unstyled">
<li class="mb-3 d-flex gap-3"><i class="fas fa-check text-primary mt-1"></i> Respeto absoluto: No se permiten comentarios ofensivos o discriminatorios.</li>
<li class="mb-3 d-flex gap-3"><i class="fas fa-check text-primary mt-1"></i> Neutralidad: No aceptamos contenidos políticos ni religiosos.</li>
<li class="mb-3 d-flex gap-3"><i class="fas fa-check text-primary mt-1"></i> Privacidad: Tus datos (WhatsApp/Nombre) solo se usan para identificarte en el aire.</li>
<li class="mb-3 d-flex gap-3"><i class="fas fa-check text-primary mt-1"></i> Seguridad: No compartimos tu información con terceros.</li>
</ul>
</div>
<div class="modal-footer border-0 px-5 pb-5">
<button type="button" class="btn btn-primary px-5 py-2 rounded-pill fw-bold" data-bs-dismiss="modal">ACEPTAR</button>
</div>
</div>
</div>
</div>
<!-- Modal QR Ampliado -->
<div class="modal fade" id="qrModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content bg-transparent border-0">
<div class="modal-body p-0 text-center">
<img src="<?= $qrImage ?>" alt="QR Pago Ampliado" class="img-fluid rounded-4 shadow-lg" style="max-width: 90vw; max-height: 80vh; border: 5px solid rgba(255,255,255,0.1);">
<div class="mt-4">
<button type="button" class="btn btn-light rounded-pill px-5 fw-bold" data-bs-dismiss="modal">CERRAR</button>
</div>
</div>
</div>
</div>
</div>
<a href="<?= $youtubeUrl ?>" target="_blank" class="btn-youtube-float" title="YouTube">
<i class="fab fa-youtube"></i>
</a>
<!-- WhatsApp Float for Dedications -->
<a href="track_click.php?type=whatsapp_dedication&redirect=<?= urlencode($whatsappLink . "?text=Hola! Quiero enviar una dedicatoria:") ?>" class="whatsapp-btn" title="Envía tu dedicatoria por WhatsApp">
<i class="fab fa-whatsapp"></i>
</a>
<audio id="audioPlayer" src="<?= $streamUrl ?>" crossorigin="anonymous"></audio>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
const audio = document.getElementById('audioPlayer');
const playBtn = document.getElementById('playBtn');
const playIcon = document.getElementById('playIcon');
const volumeSlider = document.getElementById('volumeSlider');
const songTitle = document.getElementById('songTitle');
const artistName = document.getElementById('artistName');
const canvas = document.getElementById('visualizer');
const ctx = canvas.getContext('2d');
let isPlaying = false;
let audioContext;
let analyser;
let source;
let dataArray;
let animationId;
function initVisualizer() {
if (!audioContext) {
try {
audioContext = new (window.AudioContext || window.webkitAudioContext)();
analyser = audioContext.createAnalyser();
source = audioContext.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(audioContext.destination);
analyser.fftSize = 64;
const bufferLength = analyser.frequencyBinCount;
dataArray = new Uint8Array(bufferLength);
} catch (e) {
console.warn("Visualizer failed to init:", e);
}
}
}
function draw() {
animationId = requestAnimationFrame(draw);
if (!analyser) return;
analyser.getByteFrequencyData(dataArray);
ctx.clearRect(0, 0, canvas.width, canvas.height);
const width = canvas.width;
const height = canvas.height;
const barCount = dataArray.length / 1.2;
const barWidth = (width / barCount);
let x = 0;
for (let i = 0; i < barCount; i++) {
let barHeight = (dataArray[i] / 255) * height * 0.8;
if (barHeight < 5) barHeight = 5;
const gradient = ctx.createLinearGradient(0, height - barHeight, 0, height);
gradient.addColorStop(0, '#ff2d55');
gradient.addColorStop(0.5, '#ff512f');
gradient.addColorStop(1, 'rgba(255, 45, 85, 0.2)');
ctx.fillStyle = gradient;
const bx = x + 2;
const bw = barWidth - 4;
const bh = barHeight;
const by = height - bh;
const radius = bw / 2;
ctx.beginPath();
ctx.roundRect(bx, by, bw, bh, [radius, radius, 0, 0]);
ctx.fill();
x += barWidth;
}
}
function resizeCanvas() {
canvas.width = canvas.parentElement.offsetWidth;
canvas.height = 140;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
playBtn.addEventListener('click', () => {
if (isPlaying) {
audio.pause();
playIcon.classList.replace('fa-pause', 'fa-play');
if (animationId) cancelAnimationFrame(animationId);
} else {
initVisualizer();
if (audioContext && audioContext.state === 'suspended') {
audioContext.resume();
}
audio.play().catch(e => console.error("Error playing audio:", e));
playIcon.classList.replace('fa-play', 'fa-pause');
draw();
}
isPlaying = !isPlaying;
});
volumeSlider.addEventListener('input', (e) => {
audio.volume = e.target.value;
});
async function fetchMetadata() {
try {
const response = await fetch('https://api.radioking.io/widget/radio/lili-record-s-radio/track/current');
const data = await response.json();
if (data && data.title) {
songTitle.textContent = data.title;
artistName.textContent = data.artist || 'Lili Records Radio';
}
} catch (error) {
console.error('Error fetching metadata:', error);
}
}
setInterval(fetchMetadata, 10000);
fetchMetadata();
</script>
</body>
</html>