ver. 2.1.1

This commit is contained in:
root
2026-01-28 16:45:31 +01:00
parent e4d39e3303
commit 9737f7f606
34 changed files with 14593 additions and 14613 deletions

View File

@@ -2,6 +2,14 @@
<changelog> <changelog>
<version>
<number>2.1.1</number>
<logs>
<log>Corretti alcuni bug che impedivano l'accesso al player dal link esterno</log>
<log>Correzione e bugfix di problematiche varie.</log>
</logs>
</version>
<version> <version>
<number>2.1.0</number> <number>2.1.0</number>
<logs> <logs>

381
js/app.js
View File

@@ -25,12 +25,26 @@ document.addEventListener('DOMContentLoaded', function() {
function getCurrentPageFromPath() { function getCurrentPageFromPath() {
let path = window.location.pathname; let path = window.location.pathname;
// Rimuovi il base path se presente
if (BASE_PATH && path.startsWith(BASE_PATH)) { if (BASE_PATH && path.startsWith(BASE_PATH)) {
path = path.substring(BASE_PATH.length); path = path.substring(BASE_PATH.length);
} }
// Rimuovi slash iniziali e finali
path = path.replace(/^\/|\/$/g, ''); path = path.replace(/^\/|\/$/g, '');
// IMPORTANTE: Se il path è vuoto o è solo "index.php", controlla il parametro redirect
if (!path || path === '' || path === 'index.php') {
const urlParams = new URLSearchParams(window.location.search);
const redirect = urlParams.get('redirect');
if (redirect) {
console.log('📍 Trovato parametro redirect:', redirect);
return redirect;
}
}
console.log('📍 Path rilevato:', path || 'home');
return path || 'home'; return path || 'home';
} }
@@ -191,20 +205,29 @@ document.addEventListener('DOMContentLoaded', function() {
* Aggiorna la navigazione attiva * Aggiorna la navigazione attiva
*/ */
function updateActiveNavigation(page) { function updateActiveNavigation(page) {
console.log('Aggiornamento navigazione per pagina:', page); // Debug
const navLinks = document.querySelectorAll('.navLink'); const navLinks = document.querySelectorAll('.navLink');
navLinks.forEach(link => { navLinks.forEach(link => {
link.classList.remove('active'); link.classList.remove('active');
const linkPage = link.getAttribute('data-page'); const linkPage = link.getAttribute('data-page');
// Log di debug per vedere i confronti
console.log('Confronto:', linkPage, 'con', page);
if (linkPage === page) { if (linkPage === page) {
link.classList.add('active'); link.classList.add('active');
console.log('✓ Match esatto:', linkPage);
} else if (page.startsWith('play/') && linkPage === 'radio') { } else if (page.startsWith('play/') && linkPage === 'radio') {
link.classList.add('active'); link.classList.add('active');
console.log('✓ Match play/ -> radio');
} else if (page.startsWith('playtv/') && linkPage === 'tv') { } else if (page.startsWith('playtv/') && linkPage === 'tv') {
link.classList.add('active'); link.classList.add('active');
console.log('✓ Match playtv/ -> tv');
} else if (page.startsWith('page/') && linkPage === page) { } else if (page.startsWith('page/') && linkPage === page) {
link.classList.add('active'); link.classList.add('active');
console.log('✓ Match page/');
} }
}); });
} }
@@ -284,286 +307,230 @@ document.addEventListener('DOMContentLoaded', function() {
/** /**
* Inizializza il player audio con gestione HLS migliorata * Inizializza il player audio con gestione HLS migliorata
*/ */
function initializePlayer() { function initializePlayer() {
console.log('Inizializzazione player audio...'); console.log('Inizializzazione player audio...');
// Pulisci eventuali istanze precedenti
cleanupPlayer();
const playPauseBtn = document.getElementById('playPauseBtn'); const playPauseBtn = document.getElementById('playPauseBtn');
const playIcon = document.querySelector('.play-icon');
const pauseIcon = document.querySelector('.pause-icon');
const playerStatus = document.getElementById('playerStatus');
const artistElement = document.getElementById('artist');
if (!playPauseBtn) { if (!playPauseBtn) {
console.error('Pulsante play/pause non trovato'); console.error('Pulsante play/pause non trovato');
return; return;
} }
const playIcon = document.querySelector('.play-icon'); // Pulisci il player precedente
const pauseIcon = document.querySelector('.pause-icon'); cleanupPlayer();
const hlsUrl = playPauseBtn.getAttribute('data-stream-hls');
const fallbackUrl = playPauseBtn.getAttribute('data-stream-fallback'); // Ottieni il nuovo audio player dal DOM
audioPlayer = document.getElementById('hlsAudioPlayer');
if (!audioPlayer) {
console.error('Elemento audio non trovato');
return;
}
const streamHLS = playPauseBtn.getAttribute('data-stream-hls');
const streamFallback = playPauseBtn.getAttribute('data-stream-fallback');
const stationName = playPauseBtn.getAttribute('data-station-name'); const stationName = playPauseBtn.getAttribute('data-station-name');
const stationSlogan = playPauseBtn.getAttribute('data-station-slogan'); const stationSlogan = playPauseBtn.getAttribute('data-station-slogan');
const stationLogo = playPauseBtn.getAttribute('data-station-logo'); const stationLogo = playPauseBtn.getAttribute('data-station-logo');
const statusElement = document.getElementById('playerStatus');
console.log('Stream HLS:', streamHLS);
console.log('Stream Fallback:', streamFallback);
console.log('Stazione:', stationName); console.log('Stazione:', stationName);
console.log('URL HLS:', hlsUrl);
console.log('URL Fallback:', fallbackUrl);
// Setup Media Session let isPlaying = false;
setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon); let streamType = 'hls'; // 'hls' o 'direct'
// Ottieni riferimento al player audio
audioPlayer = document.getElementById('hlsAudioPlayer');
if (!audioPlayer) {
console.error('Elemento audio player non trovato nel DOM');
return;
}
audioPlayer.preload = 'none';
/** /**
* Aggiorna lo stato visualizzato * Inizializza HLS stream
*/ */
function updateStatus(msg, isError = false) { function initHLSStream() {
console.log('Status:', msg); if (!window.Hls) {
if (statusElement) { console.error('HLS.js non caricato');
statusElement.textContent = msg;
statusElement.className = 'station-status' + (isError ? ' error' : '');
}
}
/**
* Verifica supporto HLS nativo (Safari)
*/
function canPlayHLS() {
const video = document.createElement('video');
return video.canPlayType('application/vnd.apple.mpegurl') !== '';
}
/**
* Setup HLS.js con gestione errori robusta
*/
function setupHLS() {
if (!window.Hls || !Hls.isSupported()) {
console.log('HLS.js non disponibile o non supportato');
return false; return false;
} }
console.log('Utilizzo HLS.js per lo streaming'); if (Hls.isSupported()) {
updateStatus('Caricamento stream...'); console.log('HLS supportato - uso HLS.js');
const hlsConfig = { hlsInstance = new Hls({
debug: false,
enableWorker: true, enableWorker: true,
lowLatencyMode: true, lowLatencyMode: true,
maxBufferLength: 30, backBufferLength: 90
maxMaxBufferLength: 60, });
maxBufferSize: 60 * 1000 * 1000,
manifestLoadingTimeOut: 10000,
manifestLoadingMaxRetry: 3,
manifestLoadingRetryDelay: 500,
levelLoadingTimeOut: 10000,
levelLoadingMaxRetry: 4,
fragLoadingTimeOut: 20000,
fragLoadingMaxRetry: 6
};
hlsInstance = new Hls(hlsConfig); hlsInstance.loadSource(streamHLS);
let networkErrorCount = 0;
let mediaErrorCount = 0;
const MAX_NETWORK_ERRORS = 3;
const MAX_MEDIA_ERRORS = 2;
hlsInstance.loadSource(hlsUrl);
hlsInstance.attachMedia(audioPlayer); hlsInstance.attachMedia(audioPlayer);
hlsInstance.on(Hls.Events.MANIFEST_PARSED, function () { hlsInstance.on(Hls.Events.MANIFEST_PARSED, function () {
console.log('Manifest HLS caricato con successo'); console.log('Manifest HLS caricato');
updateStatus('Pronto per la riproduzione'); audioPlayer.play().then(() => {
networkErrorCount = 0; console.log('Riproduzione HLS avviata');
mediaErrorCount = 0; updatePlayState(true);
}).catch(err => {
console.error('Errore avvio riproduzione HLS:', err);
tryFallbackStream();
});
}); });
hlsInstance.on(Hls.Events.ERROR, function (event, data) { hlsInstance.on(Hls.Events.ERROR, function (event, data) {
console.error('Errore HLS:', data.type, data.details); console.error('Errore HLS:', data.type, data.details);
if (data.fatal) { if (data.fatal) {
switch (data.type) { switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR: case Hls.ErrorTypes.NETWORK_ERROR:
networkErrorCount++; console.log('Errore di rete, tentativo fallback...');
console.log(`Errore di rete ${networkErrorCount}/${MAX_NETWORK_ERRORS}`); tryFallbackStream();
if (networkErrorCount < MAX_NETWORK_ERRORS) {
updateStatus('Riconnessione in corso...');
// Backoff esponenziale
setTimeout(() => {
console.log('Tentativo di riconnessione...');
hlsInstance.startLoad();
}, 1000 * networkErrorCount);
} else {
console.error('Troppi errori di rete, utilizzo stream fallback');
updateStatus('Utilizzo stream alternativo...', true);
hlsInstance.destroy();
hlsInstance = null;
useFallback();
}
break; break;
case Hls.ErrorTypes.MEDIA_ERROR: case Hls.ErrorTypes.MEDIA_ERROR:
mediaErrorCount++; console.log('Errore media, tentativo recupero...');
console.log(`Errore media ${mediaErrorCount}/${MAX_MEDIA_ERRORS}`);
if (mediaErrorCount < MAX_MEDIA_ERRORS) {
updateStatus('Recupero errore media...');
hlsInstance.recoverMediaError(); hlsInstance.recoverMediaError();
} else {
console.error('Troppi errori media, utilizzo stream fallback');
updateStatus('Utilizzo stream alternativo...', true);
hlsInstance.destroy();
hlsInstance = null;
useFallback();
}
break; break;
default: default:
console.error('Errore fatale non recuperabile:', data.details); console.log('Errore fatale, tentativo fallback...');
updateStatus('Stream non disponibile', true); tryFallbackStream();
hlsInstance.destroy();
hlsInstance = null;
useFallback();
break; break;
} }
} else {
// Errori non fatali
console.warn('Errore HLS non fatale:', data.details);
} }
}); });
return true; return true;
} else if (audioPlayer.canPlayType('application/vnd.apple.mpegurl')) {
console.log('HLS nativo supportato');
audioPlayer.src = streamHLS;
audioPlayer.play().then(() => {
console.log('Riproduzione HLS nativa avviata');
updatePlayState(true);
}).catch(err => {
console.error('Errore HLS nativo:', err);
tryFallbackStream();
});
return true;
}
return false;
} }
/** /**
* Utilizza stream fallback MP3 * Usa stream diretto come fallback
*/ */
function useFallback() { function tryFallbackStream() {
console.log('Utilizzo stream fallback MP3:', fallbackUrl); console.log('Tentativo stream fallback:', streamFallback);
if (fallbackUrl) {
try {
audioPlayer.src = fallbackUrl;
audioPlayer.load();
updateStatus('Pronto (MP3)');
} catch (e) {
console.error('Errore nel caricamento del fallback:', e);
updateStatus('Stream non disponibile', true);
}
} else {
console.error('Nessuno stream fallback disponibile');
updateStatus('Stream non disponibile', true);
}
}
// Inizializza lo streaming if (hlsInstance) {
if (hlsUrl) {
if (canPlayHLS()) {
console.log('Utilizzo supporto HLS nativo (Safari)');
audioPlayer.src = hlsUrl;
updateStatus('Pronto');
} else if (!setupHLS()) {
useFallback();
}
} else {
useFallback();
}
// Event handler per il pulsante play/pause
playPauseBtn.addEventListener('click', function() {
if (audioPlayer.paused) {
updateStatus('Connessione allo stream...');
audioPlayer.play()
.then(() => {
playIcon.style.display = 'none';
pauseIcon.style.display = 'block';
updateStatus('In riproduzione');
updateMediaSessionPlaybackState('playing');
console.log('Riproduzione avviata');
})
.catch(error => {
console.error('Errore nella riproduzione:', error);
updateStatus('Errore riproduzione', true);
updateMediaSessionPlaybackState('paused');
// Tentativo con fallback se HLS fallisce
if (hlsInstance && fallbackUrl) {
console.log('Tentativo con stream fallback...');
hlsInstance.destroy(); hlsInstance.destroy();
hlsInstance = null; hlsInstance = null;
useFallback(); }
setTimeout(() => { streamType = 'direct';
audioPlayer.play().catch(e => { audioPlayer.src = streamFallback;
console.error('Anche il fallback è fallito:', e); audioPlayer.load();
alert('Impossibile riprodurre lo stream audio. Verifica la tua connessione e riprova.');
}); audioPlayer.play().then(() => {
}, 500); console.log('Riproduzione stream diretto avviata');
} else { updatePlayState(true);
alert('Impossibile riprodurre lo stream audio. Verifica la tua connessione e riprova.'); }).catch(err => {
console.error('Errore stream diretto:', err);
updatePlayState(false);
if (playerStatus) {
playerStatus.textContent = 'Errore di riproduzione';
} }
}); });
} else {
audioPlayer.pause();
playIcon.style.display = 'block';
pauseIcon.style.display = 'none';
updateStatus('In pausa');
updateMediaSessionPlaybackState('paused');
console.log('Riproduzione in pausa');
} }
});
// Event listeners per sincronizzazione UI e Media Session /**
audioPlayer.addEventListener('play', function() { * Aggiorna stato visuale play/pause
updateMediaSessionPlaybackState('playing'); */
updateStatus('In riproduzione'); function updatePlayState(playing) {
isPlaying = playing;
if (playing) {
playIcon.style.display = 'none'; playIcon.style.display = 'none';
pauseIcon.style.display = 'block'; pauseIcon.style.display = 'inline-block';
if (playerStatus) {
playerStatus.textContent = 'In riproduzione...';
}
} else {
playIcon.style.display = 'inline-block';
pauseIcon.style.display = 'none';
if (playerStatus) {
playerStatus.textContent = stationSlogan || 'In pausa';
}
}
}
/**
* Gestione click play/pause
*/
playPauseBtn.addEventListener('click', function () {
if (!audioPlayer) return;
if (isPlaying) {
// Pausa
audioPlayer.pause();
updatePlayState(false);
console.log('Riproduzione in pausa');
} else {
// Play
if (!audioPlayer.src && !hlsInstance) {
// Prima riproduzione - inizializza lo stream
if (streamHLS && !initHLSStream()) {
// Se HLS fallisce, usa direttamente il fallback
tryFallbackStream();
}
} else {
// Riprendi riproduzione
audioPlayer.play().then(() => {
updatePlayState(true);
console.log('Riproduzione ripresa');
}).catch(err => {
console.error('Errore ripresa riproduzione:', err);
updatePlayState(false);
});
}
}
});
/**
* Event listeners audio player
*/
audioPlayer.addEventListener('play', function () {
updatePlayState(true);
}); });
audioPlayer.addEventListener('pause', function () { audioPlayer.addEventListener('pause', function () {
updateMediaSessionPlaybackState('paused'); updatePlayState(false);
updateStatus('In pausa');
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 (e) { audioPlayer.addEventListener('error', function (e) {
playIcon.style.display = 'block';
pauseIcon.style.display = 'none';
updateStatus('Errore stream', true);
updateMediaSessionPlaybackState('paused');
console.error('Errore audio player:', e); console.error('Errore audio player:', e);
alert('Si è verificato un errore durante la riproduzione. Riprova più tardi.'); updatePlayState(false);
if (playerStatus) {
playerStatus.textContent = 'Errore di riproduzione';
}
}); });
audioPlayer.addEventListener('waiting', () => { audioPlayer.addEventListener('waiting', function () {
updateStatus('Buffering...'); if (playerStatus) {
playerStatus.textContent = 'Buffering...';
}
}); });
audioPlayer.addEventListener('playing', () => { audioPlayer.addEventListener('playing', function () {
updateStatus('In riproduzione'); if (playerStatus) {
playerStatus.textContent = 'In riproduzione...';
}
}); });
audioPlayer.addEventListener('stalled', () => { // Setup Media Session
console.warn('Stream stalled'); setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon);
updateStatus('Connessione lenta...');
});
console.log('Player audio inizializzato correttamente'); console.log('Player audio inizializzato');
} }
/** /**

View File

@@ -1,3 +1,8 @@
<?php
// Debug: verifica valori delle variabili (rimuovi dopo aver risolto)
// echo "<!-- DEBUG - Page: " . htmlspecialchars($page) . " | Param: " . htmlspecialchars($param) . " -->\n";
?>
<div class="header"> <div class="header">
<div class="logo-section"> <div class="logo-section">
<img src="<?=$base_path?>/img/RpiGroupPlayWHITE.png" alt="Logo"> <img src="<?=$base_path?>/img/RpiGroupPlayWHITE.png" alt="Logo">
@@ -94,5 +99,5 @@
<a href="<?php echo $base_path; ?>/page/policy-privacy" data-page="page/policy-privacy" class="navLink">Policy Privacy</a> • <a href="<?php echo $base_path; ?>/page/policy-privacy" data-page="page/policy-privacy" class="navLink">Policy Privacy</a> •
<a href="<?php echo $base_path; ?>/page/changelog" data-page="page/changelog" class="navLink">Changelog</a> <a href="<?php echo $base_path; ?>/page/changelog" data-page="page/changelog" class="navLink">Changelog</a>
</div> </div>
<div class="copyright-section" <?php if($is_mobile){ ?> style="padding: 10px 0 25px;" <? } ?>>&copy; 2025 RPIGroup • Versione: <?php echo $version_app; ?></div> <div class="copyright-section" <?php if($is_mobile){ ?> style="padding: 10px 0 25px;" <?php } ?>>© 2025 RPIGroup • Versione: <?php echo $version_app; ?></div>
</div> </div>