almost final app

This commit is contained in:
2025-05-11 19:18:28 +03:00
parent 3ca470f6e1
commit 9790d8be36
4 changed files with 122 additions and 33 deletions

BIN
app/__pycache__/app.cpython-312.pyc Executable file → Normal file

Binary file not shown.

View File

@@ -4,6 +4,8 @@ import os
import json
import requests
import logging
import threading
import time
# Configure logging
logging.basicConfig(level=logging.INFO)
@@ -217,7 +219,27 @@ def initialize_playlist():
download_playlist_files_from_server()
Logger.info("Playlist initialization complete.")
# Function to check for playlist updates every 5 minutes
def periodic_playlist_check():
while True:
try:
Logger.info("Checking for playlist updates...")
# Download the playlist files from the server
download_playlist_files_from_server()
# Create the updated playlist with local file paths
create_updated_playlist()
Logger.info("Playlist check complete.")
except Exception as e:
Logger.error(f"Error during playlist check: {e}")
time.sleep(300) # Wait for 5 minutes (300 seconds) before checking again
# Start the periodic playlist check in a background thread
def start_playlist_check_thread():
thread = threading.Thread(target=periodic_playlist_check, daemon=True)
thread.start()
if __name__ == '__main__':
initialize_playlist() # Check and download playlist on startup
create_updated_playlist() # Create the updated playlist
start_playlist_check_thread() # Start the background thread for periodic checks
app.run(host='0.0.0.0', port=1025)

21
app/run_app.sh Normal file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
# Exit immediately if a command exits with a non-zero status
set -e
# Activate the virtual environment
source venv/bin/activate
# Run the Gunicorn server
echo "Starting Gunicorn server..."
python3 run_gunicorn.py &
# Wait for 5 seconds to ensure the server is up
sleep 5
# Launch Chromium in fullscreen and kiosk mode
echo "Launching Chromium in fullscreen and kiosk mode..."
chromium-browser --kiosk --start-fullscreen http://localhost:1025
# Deactivate the virtual environment when done
deactivate

View File

@@ -14,6 +14,7 @@
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden; /* Prevent scrolling */
}
.playlist-container {
flex: 1;
@@ -22,30 +23,32 @@
justify-content: center;
align-items: center;
background-color: black;
position: relative; /* Enable positioning of child elements */
}
ul {
list-style-type: none;
padding: 0;
display: none; /* Hide the playlist list */
.playlist-container img,
.playlist-container video {
max-width: 100%;
max-height: 100%;
object-fit: contain; /* Ensure content fits within 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;
width: 33.33%; /* 1/3 of the page width */
margin: 0 auto;
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 */
}
.controls {
display: flex;
justify-content: center;
gap: 15px; /* Space between buttons */
padding: 10px;
background-color: #222;
}
button {
margin: 5px;
padding: 10px;
@@ -62,10 +65,6 @@
button i {
pointer-events: none;
}
img, video {
max-width: 100%;
max-height: 100%;
}
</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">
@@ -75,22 +74,24 @@
<!-- Content will be dynamically added here -->
</div>
<div class="controls-wrapper" id="controls-wrapper">
<div class="controls">
<button onclick="previousMedia()"><i class="fas fa-step-backward"></i></button> <!-- Previous -->
<button onclick="loadPlaylist()"><i class="fas fa-sync-alt"></i></button> <!-- Refresh Playlist -->
<button onclick="playMedia()"><i class="fas fa-play"></i></button> <!-- Play -->
<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>
<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;
// Function to load the playlist from updated_playlist.json
async function loadPlaylist() {
@@ -100,9 +101,12 @@
throw new Error(`Failed to load playlist: ${response.statusText}`);
}
const data = await response.json();
playlist = data; // Use the updated playlist
console.log("Loaded playlist:", playlist); // Debug log
startPlaylist(); // Start playing the playlist after loading
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);
}
@@ -133,9 +137,11 @@
// Display the image for the specified duration
playbackInterval = setTimeout(() => {
currentIndex++;
playCurrentItem();
}, currentItem.duration * 1000);
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;
@@ -145,8 +151,10 @@
// Play the video and move to the next item after it ends
video.onended = () => {
currentIndex++;
playCurrentItem();
if (!isPaused) {
currentIndex++;
playCurrentItem();
}
};
}
}
@@ -164,6 +172,22 @@
playCurrentItem();
}
// Function to refresh the playlist
function refreshPlaylist() {
loadPlaylist(); // Reload the playlist
}
// Function to toggle play/pause
function togglePlayPause() {
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() {
stopMedia();
@@ -175,8 +199,30 @@
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>