323 lines
10 KiB
PHP
323 lines
10 KiB
PHP
<?php
|
|
|
|
if (!isset($segments) || !defined('APP_ROUTER')) {
|
|
http_response_code(403);
|
|
include $baseDir . "/error-pages/403.php";
|
|
exit;
|
|
}
|
|
|
|
$type = $segments[1] ?? null;
|
|
$requested_geraet = htmlspecialchars($segments[2] ?? '');
|
|
|
|
$allowed_types = ["audioplayer"];
|
|
|
|
if (!in_array($type, $allowed_types)) {
|
|
http_response_code(400);
|
|
include $baseDir . "/error-pages/400.html";
|
|
exit;
|
|
}
|
|
|
|
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
|
|
require_once $baseDir . '/../scripts/session_functions.php';
|
|
|
|
ini_wkvs_session(true);
|
|
|
|
$csrf_token = $_SESSION['csrf_token'] ?? '';
|
|
|
|
require $baseDir . '/../scripts/websocket/ws-create-token.php';
|
|
|
|
$WSaccesstype = "audio";
|
|
$WSaccessPermission = "R";
|
|
|
|
require_once $baseDir . '/../scripts/db/db-verbindung-script-guest.php';
|
|
require_once $baseDir . '/../scripts/db/db-functions.php';
|
|
require_once $baseDir . '/../scripts/db/db-tables.php';
|
|
|
|
$stmt = $guest->prepare("SELECT `name`, `id` FROM $tableGeraete WHERE `audiofile` = '1' ORDER BY start_index ASC");
|
|
|
|
if (!$stmt->execute()) {
|
|
http_response_code(500);
|
|
exit;
|
|
}
|
|
|
|
$result = $stmt->get_result();
|
|
$disciplines = $result->fetch_all(MYSQLI_ASSOC);
|
|
|
|
$lowerDisciplines = array_change_key_case(
|
|
array_column($disciplines, 'id', 'name'),
|
|
CASE_LOWER
|
|
);
|
|
|
|
$disciplines_indexed = array_column($disciplines, 'name', 'id');
|
|
|
|
|
|
if (!array_key_exists($requested_geraet, $lowerDisciplines)) {
|
|
http_response_code(400);
|
|
$message = 'Das gesuchte Gerät kann nicht gefunden werden';
|
|
include $baseDir . "/error-pages/400.php";
|
|
exit;
|
|
}
|
|
|
|
if (!isset($lowerDisciplines[$requested_geraet])) {
|
|
http_response_code(500);
|
|
include $baseDir . "/error-pages/500.html";
|
|
exit;
|
|
}
|
|
|
|
$geraetId = $lowerDisciplines[$requested_geraet];
|
|
|
|
$WSaccess = (string) $geraetId;
|
|
|
|
$jsonUrl = '/externe-geraete/json/audio-id-' . $geraetId . '.json';
|
|
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Remote Audioplayer</title>
|
|
<meta name="robots" content="noindex">
|
|
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
|
|
<script src="/intern/js/custom-msg-display.js"></script>
|
|
<link rel="stylesheet" href="/intern/css/custom-msg-display.css">
|
|
<link rel="stylesheet" href="/externe-geraete/css/audio.css">
|
|
|
|
</head>
|
|
<body>
|
|
<section>
|
|
<div class="header">
|
|
<h1 id="title">Audioplayer</h1>
|
|
<p id="subtitle"><?= $disciplines_indexed[$geraetId] ?></p>
|
|
</div>
|
|
|
|
<button class="startButton">
|
|
Audioplayer starten
|
|
</button>
|
|
|
|
<div class="currentyPlaying hidden">
|
|
Aktuell laufendes Audio:
|
|
<div class="subDivCurrentyPlaying">
|
|
<span>Dateiname: <span class="spanFilename"></span></span>
|
|
<span class="spanPersonname">Name der Person:
|
|
<span class="spanPersonnameName"></span>,
|
|
<span class="spanPersonnameVorname"></span>
|
|
</span>
|
|
</div>
|
|
|
|
<div class="progressDiv">
|
|
<div id="progressContainer">
|
|
<div id="progressBar"></div>
|
|
</div>
|
|
|
|
<span class="progressText"><span id="currentText">0:00</span> / <span id="durationText">0:00</span></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="content">
|
|
Dies ist der Live Audioplayer. Audio kann über die Kampfrichteransicht gestartet werden.
|
|
</div>
|
|
</section>
|
|
|
|
<audio id="peep" preload="auto"></audio>
|
|
<audio id="musicPlayer" preload="auto"></audio>
|
|
<script>
|
|
const WSaccesstype = "<?= $WSaccesstype ?>";
|
|
const WSaccess = "<?= $WSaccess ?>";
|
|
const csrf_token = "<?= $csrf_token ?>";
|
|
const WSaccessPermission = "<?= $WSaccessPermission ?>"
|
|
|
|
const jsonUrl = "<?php echo $jsonUrl; ?>";
|
|
|
|
let ws;
|
|
|
|
let firstConnect = true;
|
|
const RETRY_DELAY = 2000;
|
|
|
|
const urlAjaxNewWSToken = '/intern/scripts/ajax-create-ws-token.php';
|
|
|
|
async function fetchNewWSToken(accesstype, access, accessPermission) {
|
|
try {
|
|
const response = await fetch(urlAjaxNewWSToken, {
|
|
method: "POST",
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
body: new URLSearchParams({
|
|
csrf_token,
|
|
accesstype,
|
|
access,
|
|
accessPermission
|
|
})
|
|
});
|
|
|
|
if (!response.ok) return null;
|
|
|
|
const data = await response.json();
|
|
return data.success ? data.token : null;
|
|
} catch (error) {
|
|
console.error("Token fetch failed:", error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function startWebSocket() {
|
|
console.log("Attempting WebSocket connection...");
|
|
|
|
let token;
|
|
if (firstConnect) {
|
|
token = '<?= generateWSReadToken($WSaccesstype, $WSaccess) ?>';
|
|
} else {
|
|
token = await fetchNewWSToken(WSaccesstype, WSaccess, WSaccessPermission);
|
|
}
|
|
|
|
if (!token) {
|
|
console.error("No valid token available. Retrying...");
|
|
scheduleRetry();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
ws = new WebSocket(`wss://${window.location.hostname}/ws/?access=token&token=${token}`);
|
|
} catch (err) {
|
|
console.error("Malformed WebSocket URL", err);
|
|
scheduleRetry();
|
|
return;
|
|
}
|
|
|
|
ws.onopen = () => {
|
|
console.log("WebSocket connected!");
|
|
if (!firstConnect) {
|
|
displayMsg(1, "Live Syncronisation wieder verfügbar");
|
|
}
|
|
firstConnect = true;
|
|
};
|
|
|
|
ws.onerror = (event) => {
|
|
console.error("WebSocket error observed.");
|
|
};
|
|
|
|
ws.onclose = (event) => {
|
|
displayMsg(0, "Live Syncronisation verloren");
|
|
firstConnect = false;
|
|
|
|
scheduleRetry();
|
|
};
|
|
}
|
|
|
|
function scheduleRetry() {
|
|
console.log(`Retrying in ${RETRY_DELAY}ms...`);
|
|
setTimeout(startWebSocket, RETRY_DELAY);
|
|
}
|
|
|
|
startWebSocket();
|
|
|
|
const spanFilename = $('.spanFilename');
|
|
const spanPersonname = $('.spanPersonname');
|
|
const spanPersonnameName = $('.spanPersonnameName');
|
|
const spanPersonnameVorname = $('.spanPersonnameVorname');
|
|
|
|
const currentyPlaying = $('.currentyPlaying');
|
|
|
|
const $progressBar = $('#progressBar');
|
|
const $progressContainer = $('#progressContainer');
|
|
|
|
const peep = document.getElementById('peep');
|
|
const music = document.getElementById('musicPlayer');
|
|
const $audio = $('#musicPlayer');
|
|
|
|
let lastMusicUrl = null;
|
|
let pollingStarted = false; // ensure we start polling only once
|
|
|
|
async function fetchAndHandleMusic() {
|
|
try {
|
|
const response = await fetch(jsonUrl + '?t=' + Date.now(), { cache: 'no-store' });
|
|
const data = await response.json();
|
|
|
|
if (!data.audio_path || data.audio_path === 'nan' || data.start == false) {
|
|
if (!music.paused) {
|
|
music.pause();
|
|
music.currentTime = 0;
|
|
}
|
|
if (!peep.paused) {
|
|
peep.pause();
|
|
peep.currentTime = 0;
|
|
}
|
|
lastMusicUrl = null;
|
|
return;
|
|
}
|
|
|
|
peep.src = '/files/music/piep.mp3';
|
|
music.src = data.audio_path;
|
|
music.currentTime = 0;
|
|
peep.play().then(() => {
|
|
setTimeout(() => {
|
|
music.play().catch(err => console.log('Music play error:', err));
|
|
}, 2000);
|
|
}).catch(err => console.log('Peep play error:', err));
|
|
|
|
spanFilename.text(data.audio_name ?? '');
|
|
spanPersonnameName.text(data.person.name ?? '');
|
|
spanPersonnameVorname.text(data.person.vorname ?? '');
|
|
|
|
} catch (err) {
|
|
console.error('Error fetching JSON:', err);
|
|
}
|
|
}
|
|
|
|
function formatTime(seconds) {
|
|
if (isNaN(seconds)) return "0:00";
|
|
const mins = Math.floor(seconds / 60);
|
|
const secs = Math.floor(seconds % 60);
|
|
return mins + ":" + (secs < 10 ? '0' : '') + secs;
|
|
}
|
|
|
|
const audioDOM = $audio[0];
|
|
|
|
$audio.on('timeupdate', function() {
|
|
if (audioDOM.duration) {
|
|
const percentage = (audioDOM.currentTime / audioDOM.duration) * 100;
|
|
$progressBar.css('width', percentage + '%');
|
|
$('#currentText').text(formatTime(audioDOM.currentTime));
|
|
}
|
|
});
|
|
|
|
$audio.on('loadedmetadata', function() {
|
|
$('#durationText').text(formatTime(audioDOM.duration));
|
|
});
|
|
|
|
let isActive = false;
|
|
|
|
$('.startButton').on('click', function() {
|
|
isActive = !isActive;
|
|
if (isActive) {
|
|
$(this).text('Audioplayer stoppen');
|
|
} else {
|
|
$(this).text('Audioplayer starten');
|
|
currentyPlaying.addClass('hidden');
|
|
if (!music.paused) {
|
|
music.pause();
|
|
music.currentTime = 0;
|
|
}
|
|
if (!peep.paused) {
|
|
peep.pause();
|
|
peep.currentTime = 0;
|
|
}
|
|
}
|
|
$('section').toggleClass('playerActive', isActive);
|
|
|
|
|
|
if (!pollingStarted) {
|
|
pollingStarted = true;
|
|
ws.addEventListener("message", () => {
|
|
if (isActive) {
|
|
fetchAndHandleMusic();
|
|
currentyPlaying.removeClass('hidden');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|