document.addEventListener('DOMContentLoaded', function() { const BASE_PATH = window.BASE_PATH || ''; let currentPage = getCurrentPageFromPath(); let audioPlayer = null; let hlsInstance = null; loadHlsLibrary(); function loadHlsLibrary() { if (window.Hls) return; const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest'; script.onload = () => console.log('HLS.js caricato'); script.onerror = () => console.error('Errore caricamento HLS.js'); document.head.appendChild(script); } function getCurrentPageFromPath() { let path = window.location.pathname; if (BASE_PATH && path.startsWith(BASE_PATH)) { path = path.substring(BASE_PATH.length); } path = path.replace(/^\/|\/$/g, ''); return path || 'home'; } function loadPage(page) { const contentContainer = document.getElementById('content'); if (!contentContainer) return; contentContainer.classList.remove('fade-in'); contentContainer.classList.add('fade-out'); setTimeout(() => { const url = BASE_PATH + '/index.php/' + page; const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.onload = function() { if (xhr.status === 200) { contentContainer.innerHTML = xhr.responseText; contentContainer.classList.remove('fade-out'); contentContainer.classList.add('fade-in'); const historyUrl = page === 'home' ? BASE_PATH + '/' : BASE_PATH + '/' + page; history.pushState({page: page}, null, historyUrl); currentPage = page; updateActiveNavigation(page); if (page.startsWith('play/')) { initializePlayer(); } if (page.startsWith('playtv/')) { initializeTVPlayer(); } attachLinkListeners(); if (page === 'page/contact') { initializeContactForm(); } window.scrollTo({ top: 0, behavior: 'smooth' }); } else { contentContainer.innerHTML = '

Errore

Impossibile caricare la pagina. Codice errore: ' + xhr.status + '

'; contentContainer.classList.remove('fade-out'); contentContainer.classList.add('fade-in'); } }; xhr.onerror = function() { contentContainer.innerHTML = '

Errore di connessione

Controlla la tua connessione internet.

'; contentContainer.classList.remove('fade-out'); contentContainer.classList.add('fade-in'); }; xhr.send(); }, 200); } function updateActiveNavigation(page) { const navLinks = document.querySelectorAll('.navLink'); navLinks.forEach(link => { link.classList.remove('active'); const linkPage = link.getAttribute('data-page'); if (linkPage === page) { link.classList.add('active'); } else if (page.startsWith('play/') && linkPage === 'radio') { link.classList.add('active'); } else if (page.startsWith('playtv/') && linkPage === 'tv') { link.classList.add('active'); } else if (page.startsWith('page/')) { if (linkPage === page) { link.classList.add('active'); } } }); } // NUOVA FUNZIONE: Setup Media Session API function setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon) { if (!('mediaSession' in navigator)) { console.log('Media Session API non supportata'); return; } console.log('Setup Media Session:', stationName, stationSlogan); // Imposta i metadati navigator.mediaSession.metadata = new MediaMetadata({ title: stationName, artist: stationSlogan, album: 'RPIGroup Play', artwork: [ { src: stationLogo, sizes: '96x96', type: 'image/png' }, { src: stationLogo, sizes: '128x128', type: 'image/png' }, { src: stationLogo, sizes: '192x192', type: 'image/png' }, { src: stationLogo, sizes: '256x256', type: 'image/png' }, { src: stationLogo, sizes: '384x384', type: 'image/png' }, { src: stationLogo, sizes: '512x512', type: 'image/png' } ] }); // Gestisci i controlli del centro notifiche navigator.mediaSession.setActionHandler('play', () => { console.log('Media Session: Play richiesto dal centro notifiche'); if (audioPlayer) { audioPlayer.play().then(() => { // Aggiorna UI if (playIcon && pauseIcon) { playIcon.style.display = 'none'; pauseIcon.style.display = 'block'; } }); } }); navigator.mediaSession.setActionHandler('pause', () => { console.log('Media Session: Pause richiesto dal centro notifiche'); if (audioPlayer) { audioPlayer.pause(); // Aggiorna UI if (playIcon && pauseIcon) { playIcon.style.display = 'block'; pauseIcon.style.display = 'none'; } } }); // Opzionale: gestisci skip (per radio potrebbe non servire) navigator.mediaSession.setActionHandler('seekbackward', null); navigator.mediaSession.setActionHandler('seekforward', null); navigator.mediaSession.setActionHandler('previoustrack', null); navigator.mediaSession.setActionHandler('nexttrack', null); } // NUOVA FUNZIONE: Aggiorna playback state function updateMediaSessionPlaybackState(state) { if ('mediaSession' in navigator) { navigator.mediaSession.playbackState = state; console.log('Media Session playback state:', state); } } function initializePlayer() { console.log('Inizializzazione player...'); const playPauseBtn = document.getElementById('playPauseBtn'); if (!playPauseBtn) return; const playIcon = document.querySelector('.play-icon'); const pauseIcon = document.querySelector('.pause-icon'); const hlsUrl = playPauseBtn.getAttribute('data-stream-hls'); const fallbackUrl = playPauseBtn.getAttribute('data-stream-fallback'); const stationName = playPauseBtn.getAttribute('data-station-name'); const stationSlogan = playPauseBtn.getAttribute('data-station-slogan'); const stationLogo = playPauseBtn.getAttribute('data-station-logo'); const statusElement = document.getElementById('playerStatus'); console.log('Station:', stationName); console.log('HLS URL:', hlsUrl); console.log('Fallback URL:', fallbackUrl); // Setup Media Session all'inizio passando anche le icone setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon); if (hlsInstance) { hlsInstance.destroy(); hlsInstance = null; } if (audioPlayer) { audioPlayer.pause(); audioPlayer = null; } audioPlayer = document.getElementById('hlsAudioPlayer'); if (!audioPlayer) { audioPlayer = new Audio(); } audioPlayer.preload = 'none'; function updateStatus(msg, isError = false) { console.log('Status:', msg); if (statusElement) { statusElement.textContent = msg; statusElement.className = 'station-status' + (isError ? ' error' : ''); } } function canPlayHLS() { const video = document.createElement('video'); return video.canPlayType('application/vnd.apple.mpegurl') !== ''; } function setupHLS() { if (!window.Hls || !Hls.isSupported()) { console.log('HLS.js non disponibile'); return false; } console.log('Uso HLS.js'); updateStatus('Caricamento...'); hlsInstance = new Hls({ enableWorker: true, lowLatencyMode: true }); hlsInstance.loadSource(hlsUrl); hlsInstance.attachMedia(audioPlayer); hlsInstance.on(Hls.Events.MANIFEST_PARSED, function() { console.log('HLS manifest caricato'); updateStatus('Pronto'); }); hlsInstance.on(Hls.Events.ERROR, function(event, data) { console.error('Errore HLS:', data.type, data.details); if (data.fatal) { switch(data.type) { case Hls.ErrorTypes.NETWORK_ERROR: console.log('Errore rete, riprovo...'); hlsInstance.startLoad(); break; case Hls.ErrorTypes.MEDIA_ERROR: console.log('Errore media, riprovo...'); hlsInstance.recoverMediaError(); break; default: console.error('Errore fatale, uso fallback'); hlsInstance.destroy(); hlsInstance = null; useFallback(); break; } } }); return true; } function useFallback() { console.log('Uso fallback:', fallbackUrl); if (fallbackUrl) { audioPlayer.src = fallbackUrl; audioPlayer.load(); updateStatus('Pronto (MP3)'); } else { updateStatus('Stream non disponibile', true); } } if (hlsUrl) { if (canPlayHLS()) { console.log('Uso HLS nativo (Safari)'); audioPlayer.src = hlsUrl; updateStatus('Pronto'); } else if (!setupHLS()) { useFallback(); } } else { useFallback(); } // Gestore pulsante play/pause playPauseBtn.addEventListener('click', function() { if (audioPlayer.paused) { updateStatus('Connessione...'); audioPlayer.play() .then(() => { playIcon.style.display = 'none'; pauseIcon.style.display = 'block'; updateStatus('In riproduzione'); updateMediaSessionPlaybackState('playing'); }) .catch(error => { console.error('Errore nella riproduzione:', error); updateStatus('Errore riproduzione', true); updateMediaSessionPlaybackState('paused'); if (hlsInstance && fallbackUrl) { console.log('Tentativo con fallback...'); hlsInstance.destroy(); hlsInstance = null; useFallback(); setTimeout(() => { audioPlayer.play().catch(e => { console.error('Fallback fallito:', e); alert('Impossibile riprodurre lo stream audio. Riprova più tardi.'); }); }, 500); } else { alert('Impossibile riprodurre lo stream audio. Riprova più tardi.'); } }); } else { audioPlayer.pause(); playIcon.style.display = 'block'; pauseIcon.style.display = 'none'; updateStatus('In pausa'); updateMediaSessionPlaybackState('paused'); } }); // Event listeners con Media Session updates e sincronizzazione UI audioPlayer.addEventListener('play', function() { updateMediaSessionPlaybackState('playing'); updateStatus('In riproduzione'); // Sincronizza UI quando l'audio parte (da qualsiasi fonte) playIcon.style.display = 'none'; pauseIcon.style.display = 'block'; }); audioPlayer.addEventListener('pause', function() { updateMediaSessionPlaybackState('paused'); updateStatus('In pausa'); // Sincronizza UI quando l'audio va in pausa (da qualsiasi fonte) playIcon.style.display = 'block'; pauseIcon.style.display = 'none'; }); audioPlayer.addEventListener('ended', function() { playIcon.style.display = 'block'; pauseIcon.style.display = 'none'; updateStatus('Terminato'); updateMediaSessionPlaybackState('paused'); }); audioPlayer.addEventListener('error', function() { playIcon.style.display = 'block'; pauseIcon.style.display = 'none'; updateStatus('Errore stream', true); updateMediaSessionPlaybackState('paused'); alert('Si è verificato un errore durante la riproduzione. Riprova più tardi.'); }); audioPlayer.addEventListener('waiting', () => updateStatus('Buffering...')); audioPlayer.addEventListener('playing', () => updateStatus('In riproduzione')); console.log('Player inizializzato con Media Session'); } function initializeTVPlayer() { console.log('TV Player inizializzato'); } function initializeContactForm() { const contactForm = document.getElementById('contactForm'); if (!contactForm) return; contactForm.addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(contactForm); const formResponse = document.getElementById('formResponse'); formResponse.innerHTML = 'Invio in corso...'; formResponse.className = 'form-response'; formResponse.style.display = 'block'; const xhr = new XMLHttpRequest(); xhr.open('POST', BASE_PATH + '/process_contact.php', true); xhr.onload = function() { if (xhr.status === 200) { try { const response = JSON.parse(xhr.responseText); if (response.success) { formResponse.innerHTML = 'Messaggio inviato con successo! Ti risponderemo presto.'; formResponse.className = 'form-response success'; contactForm.reset(); } else { formResponse.innerHTML = 'Errore: ' + (response.message || 'Si è verificato un errore durante l\'invio del messaggio.'); formResponse.className = 'form-response error'; } } catch (e) { formResponse.innerHTML = 'Si è verificato un errore durante l\'elaborazione della risposta.'; formResponse.className = 'form-response error'; } } else { formResponse.innerHTML = 'Si è verificato un errore durante l\'invio del messaggio.'; formResponse.className = 'form-response error'; } }; xhr.onerror = function() { formResponse.innerHTML = 'Errore di connessione. Controlla la tua connessione internet.'; formResponse.className = 'form-response error'; }; xhr.send(formData); }); } function attachLinkListeners() { const navLinks = document.querySelectorAll('.navLink, .nav-link, .station-link, .linkBox'); navLinks.forEach(link => { const newLink = link.cloneNode(true); link.parentNode.replaceChild(newLink, link); newLink.addEventListener('click', function(e) { const href = this.getAttribute('href'); const target = this.getAttribute('target'); const page = this.getAttribute('data-page'); const isExternal = href && ( href.startsWith('http://') || href.startsWith('https://') || href.startsWith('//') || target === '_blank' ); if (isExternal) { console.log('Link esterno rilevato:', href); e.preventDefault(); window.location.href = href; return; } e.preventDefault(); e.stopPropagation(); console.log('Link cliccato, pagina:', page, 'currentPage:', currentPage); if (page && page !== currentPage) { if (audioPlayer && !audioPlayer.paused) { audioPlayer.pause(); } loadPage(page); } }); }); } function setupOpenAppButton() { const openAppBtn = document.getElementById('openAppBtn'); if (openAppBtn) { openAppBtn.addEventListener('click', function(e) { e.preventDefault(); const currentPath = window.location.pathname; const pathWithoutBase = currentPath.replace(BASE_PATH, '').replace(/^\//, ''); const redirectParam = pathWithoutBase ? '&redirect=' + encodeURIComponent(pathWithoutBase) : ''; const width = 375; const height = 667; const left = (window.screen.width / 2) - (width / 2); const top = (window.screen.height / 2) - (height / 2); const windowFeatures = 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',resizable=yes,scrollbars=yes,status=yes'; window.open(BASE_PATH + '/?app=true' + redirectParam, 'RadioApp', windowFeatures); }); } } function setupHistoryNavigation() { window.addEventListener('popstate', function(e) { if (e.state && e.state.page) { if (e.state.page !== currentPage) { loadPage(e.state.page); } } else { if (currentPage !== 'home') { loadPage('home'); } } }); history.replaceState({page: currentPage}, null, window.location.pathname); } function setupStandaloneMode() { const appContainer = document.querySelector('.container'); if (!appContainer) return; if (window.opener && !window.opener.closed) { appContainer.classList.add('standalone-app'); } if (window.navigator.standalone || window.matchMedia('(display-mode: standalone)').matches) { appContainer.classList.add('standalone-app'); } } function init() { setupOpenAppButton(); if (document.querySelector('.container')) { setupStandaloneMode(); attachLinkListeners(); setupHistoryNavigation(); initializeCurrentPage(); } } function initializeCurrentPage() { console.log('Inizializzazione pagina corrente:', currentPage); updateActiveNavigation(currentPage); if (currentPage.startsWith('play/')) { setTimeout(function() { initializePlayer(); }, 100); } if (currentPage.startsWith('playtv/')) { setTimeout(function() { initializeTVPlayer(); }, 100); } if (currentPage === 'page/contact') { setTimeout(function() { initializeContactForm(); }, 100); } } init(); }); // Funzione per bloccare l'orientamento (funziona solo in PWA/fullscreen) function lockScreenOrientation() { // Prova a bloccare l'orientamento con Screen Orientation API if (screen.orientation && screen.orientation.lock) { screen.orientation.lock('portrait').then(() => { console.log('Orientamento bloccato in portrait'); }).catch((err) => { console.log('Impossibile bloccare orientamento:', err.message); // Non è un errore grave, il CSS gestirà la situazione }); } // Alternativa per browser più vecchi if (screen.lockOrientation) { screen.lockOrientation('portrait'); } else if (screen.mozLockOrientation) { screen.mozLockOrientation('portrait'); } else if (screen.msLockOrientation) { screen.msLockOrientation('portrait'); } } // Prova a bloccare quando l'app è in fullscreen/standalone function tryLockOrientation() { // Controlla se siamo in modalità standalone (PWA) const isStandalone = window.navigator.standalone || window.matchMedia('(display-mode: standalone)').matches; if (isStandalone) { lockScreenOrientation(); } // Prova anche quando entriamo in fullscreen document.addEventListener('fullscreenchange', () => { if (document.fullscreenElement) { lockScreenOrientation(); } }); } // Event listeners per cambio orientamento window.addEventListener('orientationchange', handleOrientationChange); window.addEventListener('resize', handleOrientationChange); // Inizializza al caricamento document.addEventListener('DOMContentLoaded', () => { tryLockOrientation(); handleOrientationChange(); }); // Inizializza subito se il DOM è già pronto if (document.readyState !== 'loading') { tryLockOrientation(); handleOrientationChange(); }