// 1. Sélection des éléments du DOM const vinyl = document.getElementById('vinyl'); const audio = document.getElementById('audio'); const progress = document.getElementById('progress'); const currentTimeEl = document.getElementById('currentTime'); const durationEl = document.getElementById('duration'); const backwardBtn = document.getElementById('backward'); const forwardBtn = document.getElementById('forward'); const loopBtn = document.getElementById('loop'); // 2. Variables utiles let isPlaying = false; let isLooping = false; let idleTimeout = null; let reverseInterval = null; // 3. Variables pour calculer la vitesse de rotation let lastPosition = null; let lastTime = null; // 4. Connexion Socket.io const socket = io(); socket.on('position', (position) => { const now = Date.now(); if (lastPosition !== null && lastTime !== null) { const deltaPos = position - lastPosition; const deltaTime = (now - lastTime) / 1000; const speed = deltaPos / deltaTime; console.log('instant speed:', speed); clearTimeout(idleTimeout); if (Math.abs(speed) < 2) { stopPlayback(); } else { const isReverse = speed < 0; // Simuler reverse if (isReverse) { simulateReverse(Math.abs(speed)); } else { stopReverse(); let playbackSpeed = 1 + speed * 0.01; playbackSpeed = Math.max(0.5, Math.min(2, playbackSpeed)); controlPlayback(playbackSpeed); } } } lastPosition = position; lastTime = now; // Détecter l'inactivité : si pas de mise à jour pendant 300ms → stop idleTimeout = setTimeout(() => { stopPlayback(); }, 300); }); // 5. Fonctions function togglePlay() { if (isPlaying) { audio.pause(); vinyl.style.animationPlayState = 'paused'; } else { audio.play(); vinyl.style.animationPlayState = 'running'; } isPlaying = !isPlaying; } function updateProgress() { const progressPercent = (audio.currentTime / audio.duration) * 100; progress.value = progressPercent; currentTimeEl.textContent = formatTime(audio.currentTime); } function formatTime(time) { const minutes = Math.floor(time / 60); const seconds = Math.floor(time % 60); return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; } function setProgress(e) { const width = progress.clientWidth; const clickX = e.offsetX; const duration = audio.duration; audio.currentTime = (clickX / width) * duration; } // Fonction pour régler la lecture selon la vitesse function controlPlayback(speed) { stopReverse(); // On stoppe le reverse si actif if (speed > 0) { if (!isPlaying) { audio.play(); vinyl.style.animationPlayState = 'running'; isPlaying = true; } audio.playbackRate = speed; } } function stopPlayback() { audio.pause(); vinyl.style.animationPlayState = 'paused'; isPlaying = false; } function simulateReverse(speed) { // vitesse = ticks/sec → convertir en vitesse de recul const reverseSpeed = Math.min(speed * 0.01, 2); // seconds per step if (!reverseInterval) { reverseInterval = setInterval(() => { if (audio.currentTime > 0.05) { audio.currentTime -= reverseSpeed * 0.1; vinyl.style.animationPlayState = 'running'; } else { stopPlayback(); } }, 100); if (!isPlaying) { isPlaying = true; } } audio.pause(); // on met en pause le vrai son pour éviter conflit } function stopReverse() { if (reverseInterval) { clearInterval(reverseInterval); reverseInterval = null; } } // 6. Événements vinyl.addEventListener('click', togglePlay); audio.addEventListener('timeupdate', updateProgress); audio.addEventListener('loadedmetadata', () => { durationEl.textContent = formatTime(audio.duration); }); progress.addEventListener('click', setProgress); backwardBtn.addEventListener('click', () => { audio.currentTime = Math.max(0, audio.currentTime - 10); }); forwardBtn.addEventListener('click', () => { audio.currentTime = Math.min(audio.duration, audio.currentTime + 10); }); loopBtn.addEventListener('click', () => { isLooping = !isLooping; loopBtn.style.backgroundColor = isLooping ? 'white' : 'transparent'; loopBtn.style.color = isLooping ? '#18344b' : 'white'; }); audio.addEventListener('ended', () => { if (isLooping) { audio.currentTime = 0; audio.play(); } else { vinyl.style.animationPlayState = 'paused'; isPlaying = false; } });