diff --git a/index.html b/index.html index 7a8f15d..1b2425c 100644 --- a/index.html +++ b/index.html @@ -420,37 +420,6 @@ - - - diff --git a/script.js b/script.js index e41841c..4e4f0f6 100644 --- a/script.js +++ b/script.js @@ -1816,23 +1816,12 @@ window.addEventListener('DOMContentLoaded', () => { updateManualGlow('A', settings.glowA); updateManualGlow('B', settings.glowB); - // Check if this is the listener page based on hostname or port - const isListenerPort = window.location.port === '5001'; - const isListenerHostname = window.location.hostname.startsWith('music.') || window.location.hostname.startsWith('listen.'); - const urlParams = new URLSearchParams(window.location.search); - - if (isListenerPort || isListenerHostname || urlParams.get('listen') === 'true') { - initListenerMode(); - } - - if (!isListenerPort && !isListenerHostname) { - // Set stream URL to the listener domain - const streamUrl = window.location.hostname.startsWith('dj.') - ? `${window.location.protocol}//music.${window.location.hostname.split('.').slice(1).join('.')}` - : `${window.location.protocol}//${window.location.hostname}:5001`; - const streamInput = document.getElementById('stream-url'); - if (streamInput) streamInput.value = streamUrl; - } + // Set stream URL in the streaming panel + const streamUrl = window.location.hostname.startsWith('dj.') + ? `${window.location.protocol}//music.${window.location.hostname.split('.').slice(1).join('.')}` + : `${window.location.protocol}//${window.location.hostname}:5001`; + const streamInput = document.getElementById('stream-url'); + if (streamInput) streamInput.value = streamUrl; }); // ========== LIVE STREAMING FUNCTIONALITY ========== @@ -1843,94 +1832,13 @@ let streamProcessor = null; let mediaRecorder = null; let isBroadcasting = false; let autoStartStream = false; -let listenerAudioContext = null; -let listenerGainNode = null; -let listenerAnalyserNode = null; -let listenerMediaElementSourceNode = null; -let listenerVuMeterRunning = false; -let listenerChunksReceived = 0; - -function startListenerVUMeter() { - if (listenerVuMeterRunning) return; - listenerVuMeterRunning = true; - - const draw = () => { - if (!listenerVuMeterRunning) return; - requestAnimationFrame(draw); - - const canvas = document.getElementById('viz-listener'); - if (!canvas || !listenerAnalyserNode) return; - - const ctx = canvas.getContext('2d'); - if (!ctx) return; - - // Keep canvas sized correctly for DPI - const dpr = window.devicePixelRatio || 1; - const rect = canvas.getBoundingClientRect(); - const targetW = Math.max(1, Math.floor(rect.width * dpr)); - const targetH = Math.max(1, Math.floor(rect.height * dpr)); - if (canvas.width !== targetW || canvas.height !== targetH) { - canvas.width = targetW; - canvas.height = targetH; - } - - const analyser = listenerAnalyserNode; - const bufferLength = analyser.frequencyBinCount; - const dataArray = new Uint8Array(bufferLength); - analyser.getByteFrequencyData(dataArray); - - const width = canvas.width; - const height = canvas.height; - const barCount = 32; - const barWidth = width / barCount; - - ctx.fillStyle = '#0a0a12'; - ctx.fillRect(0, 0, width, height); - - // Listener uses the magenta hue (matches Deck B styling) - const hue = 280; - for (let i = 0; i < barCount; i++) { - const freqIndex = Math.floor(Math.pow(i / barCount, 1.5) * bufferLength); - const value = (dataArray[freqIndex] || 0) / 255; - const barHeight = value * height; - - const lightness = 30 + (value * 50); - const gradient = ctx.createLinearGradient(0, height, 0, height - barHeight); - gradient.addColorStop(0, `hsl(${hue}, 100%, ${lightness}%)`); - gradient.addColorStop(1, `hsl(${hue}, 100%, ${Math.min(lightness + 20, 80)}%)`); - - ctx.fillStyle = gradient; - ctx.fillRect(i * barWidth, height - barHeight, barWidth - 2, barHeight); - } - }; - - draw(); -} let currentStreamMimeType = null; -function getMp3FallbackUrl() { - // Use same-origin so this works behind reverse proxies (e.g., Cloudflare) where :5001 may not be reachable. - return `${window.location.origin}/stream.mp3`; -} - // Initialise SocketIO connection function initSocket() { if (socket) return socket; - // Log connection details - const urlParams = new URLSearchParams(window.location.search); - const isListenerMode = - window.location.port === '5001' || - window.location.hostname.startsWith('music.') || - window.location.hostname.startsWith('listen.') || - urlParams.get('listen') === 'true'; - - // If someone opens listener mode on the DJ dev port (:5000?listen=true), - // use the listener backend (:5001). For proxied deployments (Cloudflare), - // do NOT force a port (it may be blocked); stick to same-origin. - const serverUrl = (isListenerMode && window.location.port === '5000') - ? `${window.location.protocol}//${window.location.hostname}:5001` - : window.location.origin; + const serverUrl = window.location.origin; console.log(`CONNECT Initializing Socket.IO connection to: ${serverUrl}`); console.log(` Protocol: ${window.location.protocol}`); console.log(` Host: ${window.location.host}`); @@ -2479,412 +2387,6 @@ function toggleAutoStream(enabled) { localStorage.setItem('autoStartStream', enabled); } -// ========== LISTENER MODE ========== - -function initListenerMode() { - console.log('STREAMPANEL Initializing listener mode (MP3 stream)...'); - - // UI Feedback for listener - const appContainer = document.querySelector('.app-container'); - const settingsBtn = document.querySelector('.settings-btn'); - const streamingBtn = document.querySelector('.streaming-btn'); - if (appContainer) appContainer.style.display = 'none'; - if (settingsBtn) settingsBtn.style.display = 'none'; - if (streamingBtn) streamingBtn.style.display = 'none'; - - const startOverlay = document.getElementById('start-overlay'); - if (startOverlay) startOverlay.style.display = 'none'; - - // Hide landscape prompt for listeners (not needed) - const landscapePrompt = document.getElementById('landscape-prompt'); - if (landscapePrompt) landscapePrompt.style.display = 'none'; - - const listenerMode = document.getElementById('listener-mode'); - if (listenerMode) listenerMode.style.display = 'flex'; - - // Add atmospheric glow for listeners - document.body.classList.add('listener-glow'); - document.body.classList.add('listening-active'); // For global CSS targeting - updateGlowIntensity(settings.glowIntensity || 30); - - // AudioContext will be created when user enables audio to avoid suspension - - // ALWAYS create a fresh audio element to avoid MediaSource/MediaElementSource conflicts - // This is critical for page refreshes - you can only create MediaElementSource once per element - let audio; - - // Clean up old audio element if it exists - if (window.listenerAudio) { - console.log('CLEAN Cleaning up old audio element and AudioContext nodes'); - try { - window.listenerAudio.pause(); - if (window.listenerAudio.src) { - URL.revokeObjectURL(window.listenerAudio.src); - } - window.listenerAudio.removeAttribute('src'); - window.listenerAudio.remove(); // Remove from DOM - } catch (e) { - console.warn('Error cleaning up old audio:', e); - } - - // Reset all AudioContext-related nodes - if (listenerMediaElementSourceNode) { - try { - listenerMediaElementSourceNode.disconnect(); - } catch (e) { } - listenerMediaElementSourceNode = null; - } - if (listenerAnalyserNode) { - try { - listenerAnalyserNode.disconnect(); - } catch (e) { } - listenerAnalyserNode = null; - } - if (listenerGainNode) { - try { - listenerGainNode.disconnect(); - } catch (e) { } - listenerGainNode = null; - } - - window.listenerAudio = null; - window.listenerMediaSource = null; - window.listenerAudioEnabled = false; - } - - // Create a new hidden media element. - // For MP3 we can use a plain