269 lines
10 KiB
HTML
Executable File
269 lines
10 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Media Player</title>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
margin: 0;
|
|
padding: 0;
|
|
background-color: black;
|
|
color: white;
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100vh;
|
|
overflow: hidden; /* Prevent scrolling */
|
|
}
|
|
.playlist-container {
|
|
flex: 1;
|
|
overflow: hidden;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
background-color: black;
|
|
position: relative; /* Enable positioning of child elements */
|
|
}
|
|
.playlist-container img,
|
|
.playlist-container video {
|
|
width: 100%; /* Make the video fill the width */
|
|
height: 100%; /* Make the video fill the height */
|
|
object-fit: cover; /* Ensure the video scales to cover the container */
|
|
}
|
|
.controls-wrapper {
|
|
position: fixed; /* Fix the controls at the bottom of the page */
|
|
bottom: 0; /* Align to the bottom */
|
|
left: 0; /* Align to the left */
|
|
width: 100%; /* Full width */
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 15px; /* Space between buttons */
|
|
padding: 10px;
|
|
background-color: rgba(0, 0, 0, 0.5); /* Increased transparency */
|
|
border-top: 2px solid #444; /* Add a border at the top */
|
|
z-index: 100; /* Ensure buttons are above the media */
|
|
transition: opacity 0.5s ease; /* Smooth fade effect */
|
|
}
|
|
.controls-wrapper.hidden {
|
|
opacity: 0; /* Hide the buttons */
|
|
pointer-events: none; /* Disable interaction when hidden */
|
|
}
|
|
button {
|
|
margin: 5px;
|
|
padding: 10px;
|
|
background-color: #444;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
font-size: 20px;
|
|
}
|
|
button:hover {
|
|
background-color: #666;
|
|
}
|
|
button i {
|
|
pointer-events: none;
|
|
}
|
|
</style>
|
|
<!-- Add Font Awesome for icons -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
|
</head>
|
|
<body>
|
|
<div class="playlist-container" id="playlist-container">
|
|
<!-- Content will be dynamically added here -->
|
|
</div>
|
|
<div class="controls-wrapper" id="controls-wrapper">
|
|
<button onclick="previousMedia()"><i class="fas fa-step-backward"></i></button> <!-- Previous -->
|
|
<button onclick="refreshPlaylist()"><i class="fas fa-sync-alt"></i></button> <!-- Refresh Playlist -->
|
|
<button id="playPauseButton" onclick="togglePlayPause()"><i class="fas fa-play"></i></button> <!-- Play/Pause -->
|
|
<button onclick="nextMedia()"><i class="fas fa-step-forward"></i></button> <!-- Next -->
|
|
<button onclick="stopMedia()"><i class="fas fa-stop"></i></button> <!-- Stop -->
|
|
<button onclick="goToSettings()"><i class="fas fa-cog"></i></button> <!-- Settings -->
|
|
</div>
|
|
|
|
<script>
|
|
const apiBase = 'http://localhost:1025'; // Update to match your Flask app's port
|
|
const playlistContainer = document.getElementById('playlist-container');
|
|
const controlsWrapper = document.getElementById('controls-wrapper');
|
|
const playPauseButton = document.getElementById('playPauseButton');
|
|
let playlist = [];
|
|
let currentIndex = 0;
|
|
let playbackInterval;
|
|
let inactivityTimer;
|
|
let isPaused = false;
|
|
let isMuted = true; // Start with muted video
|
|
|
|
// Function to load the playlist from updated_playlist.json
|
|
async function loadPlaylist() {
|
|
try {
|
|
const response = await fetch(`${apiBase}/updated_playlist.json`);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to load playlist: ${response.statusText}`);
|
|
}
|
|
const data = await response.json();
|
|
if (JSON.stringify(data) !== JSON.stringify(playlist)) {
|
|
playlist = data; // Update the playlist only if it has changed
|
|
console.log("Playlist updated:", playlist); // Debug log
|
|
currentIndex = 0; // Reset to the first item
|
|
startPlaylist(); // Restart the playlist
|
|
}
|
|
} catch (error) {
|
|
console.error("Error loading playlist:", error);
|
|
}
|
|
}
|
|
|
|
// Function to start playing the playlist
|
|
function startPlaylist() {
|
|
if (playlist.length === 0) {
|
|
console.error("No items in the playlist.");
|
|
return;
|
|
}
|
|
playCurrentItem();
|
|
}
|
|
|
|
// Function to play the current item in the playlist
|
|
async function playCurrentItem() {
|
|
if (currentIndex >= playlist.length) {
|
|
currentIndex = 0; // Loop back to the beginning
|
|
}
|
|
|
|
const currentItem = playlist[currentIndex];
|
|
playlistContainer.innerHTML = ''; // Clear the container
|
|
|
|
if (currentItem.type === 'image') {
|
|
const img = document.createElement('img');
|
|
img.src = currentItem.url;
|
|
|
|
// Fetch the orientation setting from app_config.json
|
|
const response = await fetch('/static/app_config.json');
|
|
const config = await response.json();
|
|
const playerOrientation = config.player_orientation; // "landscape" or "portrait"
|
|
|
|
// Check the orientation of the image and adjust the object-fit property
|
|
const image = new Image();
|
|
image.src = currentItem.url;
|
|
image.onload = () => {
|
|
const isImageLandscape = image.width > image.height;
|
|
if (
|
|
(playerOrientation === 'landscape' && !isImageLandscape) ||
|
|
(playerOrientation === 'portrait' && isImageLandscape)
|
|
) {
|
|
img.style.objectFit = 'contain'; // Show the full image without cropping
|
|
} else {
|
|
img.style.objectFit = 'cover'; // Crop to fit the container
|
|
}
|
|
};
|
|
|
|
playlistContainer.appendChild(img);
|
|
|
|
// Display the image for the specified duration
|
|
playbackInterval = setTimeout(() => {
|
|
if (!isPaused) {
|
|
currentIndex++;
|
|
playCurrentItem();
|
|
}
|
|
}, currentItem.duration * 1000 + (isPaused ? 10000 : 0)); // Add 10 seconds if paused
|
|
} else if (currentItem.type === 'video') {
|
|
const video = document.createElement('video');
|
|
video.src = currentItem.url;
|
|
video.autoplay = true;
|
|
video.controls = false;
|
|
video.muted = isMuted; // Start muted if isMuted is true
|
|
playlistContainer.appendChild(video);
|
|
|
|
// Ensure the video starts playing
|
|
video.play().catch(error => {
|
|
console.error("Error starting video playback:", error);
|
|
});
|
|
|
|
// Play the video and move to the next item after it ends
|
|
video.onended = () => {
|
|
if (!isPaused) {
|
|
currentIndex++;
|
|
playCurrentItem();
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
// Function to unmute the video
|
|
function unmuteVideo() {
|
|
isMuted = false; // Set isMuted to false
|
|
const video = playlistContainer.querySelector('video');
|
|
if (video) {
|
|
video.muted = false; // Unmute the video
|
|
}
|
|
}
|
|
|
|
// Function to stop playback
|
|
function stopMedia() {
|
|
clearTimeout(playbackInterval);
|
|
playlistContainer.innerHTML = ''; // Clear the container
|
|
}
|
|
|
|
// Function to play the previous item
|
|
function previousMedia() {
|
|
unmuteVideo(); // Unmute the video
|
|
stopMedia();
|
|
currentIndex = (currentIndex - 1 + playlist.length) % playlist.length;
|
|
playCurrentItem();
|
|
}
|
|
|
|
// Function to refresh the playlist
|
|
function refreshPlaylist() {
|
|
unmuteVideo(); // Unmute the video
|
|
loadPlaylist(); // Reload the playlist
|
|
}
|
|
|
|
// Function to toggle play/pause
|
|
function togglePlayPause() {
|
|
unmuteVideo(); // Unmute the video
|
|
isPaused = !isPaused;
|
|
if (isPaused) {
|
|
playPauseButton.innerHTML = '<i class="fas fa-pause"></i>'; // Change to pause icon
|
|
} else {
|
|
playPauseButton.innerHTML = '<i class="fas fa-play"></i>'; // Change to play icon
|
|
playCurrentItem(); // Resume playback
|
|
}
|
|
}
|
|
|
|
// Function to play the next item
|
|
function nextMedia() {
|
|
unmuteVideo(); // Unmute the video
|
|
stopMedia();
|
|
currentIndex = (currentIndex + 1) % playlist.length;
|
|
playCurrentItem();
|
|
}
|
|
|
|
function goToSettings() {
|
|
window.location.href = '/static/settings.html';
|
|
}
|
|
|
|
// Function to hide controls after inactivity
|
|
function hideControls() {
|
|
controlsWrapper.classList.add('hidden');
|
|
}
|
|
|
|
// Function to reset inactivity timer
|
|
function resetInactivityTimer() {
|
|
controlsWrapper.classList.remove('hidden'); // Show controls
|
|
clearTimeout(inactivityTimer); // Clear the previous timer
|
|
inactivityTimer = setTimeout(hideControls, 10000); // Set a new timer for 10 seconds
|
|
}
|
|
|
|
// Add event listeners for mouse movement
|
|
document.addEventListener('mousemove', resetInactivityTimer);
|
|
document.addEventListener('keydown', resetInactivityTimer);
|
|
|
|
// Initialize inactivity timer on page load
|
|
resetInactivityTimer();
|
|
|
|
// Load playlist on page load
|
|
loadPlaylist();
|
|
|
|
// Start periodic playlist reload
|
|
setInterval(loadPlaylist, 300000); // Check every 5 minutes (300,000 ms)
|
|
</script>
|
|
</body>
|
|
</html> |