161 lines
3.4 KiB
HTML
Executable File
161 lines
3.4 KiB
HTML
Executable File
<!doctype html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>CANCOM Simple Signage Player</title>
|
|
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
|
|
|
<style>
|
|
html, body {
|
|
margin: 0;
|
|
padding: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: black;
|
|
overflow: hidden;
|
|
}
|
|
|
|
img, video {
|
|
width: 100vw;
|
|
height: 100vh;
|
|
object-fit: contain;
|
|
background: black;
|
|
display: none;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<img id="image">
|
|
<video id="video" muted autoplay playsinline></video>
|
|
|
|
<script>
|
|
/* -----------------------------
|
|
Daten vom Server
|
|
----------------------------- */
|
|
const normalFiles = {{ normal_files | tojson }};
|
|
const prioFiles = {{ prio_files | tojson }};
|
|
const interval = {{ interval }} * 1000;
|
|
const screen = "{{ screen }}";
|
|
|
|
/* -----------------------------
|
|
Player State
|
|
----------------------------- */
|
|
let normalIndex = 0;
|
|
let prioIndex = 0;
|
|
let playPrioNext = false;
|
|
let mode = "normal"; // "normal" oder "prio"
|
|
|
|
|
|
const img = document.getElementById("image");
|
|
const vid = document.getElementById("video");
|
|
|
|
/* -----------------------------
|
|
Hilfsfunktionen
|
|
----------------------------- */
|
|
function isVideo(file) {
|
|
return file.toLowerCase().endsWith(".mp4");
|
|
}
|
|
|
|
|
|
function getNextItem() {
|
|
|
|
// ✅ Sonderfall: nur Priority vorhanden
|
|
if (normalFiles.length === 0 && prioFiles.length > 0) {
|
|
return {
|
|
file: prioFiles[prioIndex++ % prioFiles.length],
|
|
isPrio: true
|
|
};
|
|
}
|
|
|
|
// ✅ Sonderfall: nur normale Playlist vorhanden
|
|
if (prioFiles.length === 0 && normalFiles.length > 0) {
|
|
return {
|
|
file: normalFiles[normalIndex++ % normalFiles.length],
|
|
isPrio: false
|
|
};
|
|
}
|
|
|
|
// ✅ Normal-Phase
|
|
if (mode === "normal") {
|
|
const file = normalFiles[normalIndex++];
|
|
if (normalIndex >= normalFiles.length) {
|
|
normalIndex = 0;
|
|
if (prioFiles.length > 0) {
|
|
mode = "prio"; // ➜ nach kompletter Normal-Playlist wechseln
|
|
}
|
|
}
|
|
return { file, isPrio: false };
|
|
}
|
|
|
|
// ✅ Priority-Phase
|
|
if (mode === "prio") {
|
|
const file = prioFiles[prioIndex++];
|
|
if (prioIndex >= prioFiles.length) {
|
|
prioIndex = 0;
|
|
mode = "normal"; // ➜ nach kompletter Priority zurück
|
|
}
|
|
return { file, isPrio: true };
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
/* -----------------------------
|
|
Medien abspielen
|
|
----------------------------- */
|
|
function playNext() {
|
|
const item = getNextItem();
|
|
if (!item) return;
|
|
|
|
const basePath = item.isPrio ? "priority" : screen;
|
|
const src = `/media/${basePath}/${item.file}`;
|
|
|
|
if (isVideo(item.file)) {
|
|
img.style.display = "none";
|
|
vid.style.display = "block";
|
|
vid.src = src;
|
|
vid.onended = playNext;
|
|
vid.play();
|
|
} else {
|
|
vid.pause();
|
|
vid.style.display = "none";
|
|
img.style.display = "block";
|
|
img.src = src;
|
|
setTimeout(playNext, interval);
|
|
}
|
|
}
|
|
|
|
/* -----------------------------
|
|
Auto-Reload bei Änderungen
|
|
----------------------------- */
|
|
let lastHash = null;
|
|
|
|
async function checkForUpdates() {
|
|
try {
|
|
const res = await fetch(`/playlist/${screen}/hash`, { cache: "no-store" });
|
|
const hash = await res.text();
|
|
|
|
if (lastHash && lastHash !== hash) {
|
|
location.reload();
|
|
}
|
|
lastHash = hash;
|
|
} catch (e) {
|
|
console.warn("Playlist-Check fehlgeschlagen", e);
|
|
}
|
|
}
|
|
|
|
/* -----------------------------
|
|
Start
|
|
----------------------------- */
|
|
playNext();
|
|
setInterval(checkForUpdates, 5000);
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|
|
|