diff --git a/pikaraoke/karaoke.py b/pikaraoke/karaoke.py index 4335281a..c0a72c9d 100644 --- a/pikaraoke/karaoke.py +++ b/pikaraoke/karaoke.py @@ -5,6 +5,7 @@ import random import socket import subprocess +import threading import time from pathlib import Path from queue import Queue @@ -620,7 +621,7 @@ def queue_edit(self, song_name, action): def skip(self): if self.is_file_playing(): logging.info("Skipping: " + self.now_playing) - self.now_playing_command = "skip" + self.end_song() return True else: logging.warning("Tried to skip, but no file is playing!") @@ -629,7 +630,6 @@ def skip(self): def pause(self): if self.is_file_playing(): logging.info("Toggling pause: " + self.now_playing) - self.now_playing_command = "pause" self.is_paused = not self.is_paused return True else: @@ -639,8 +639,6 @@ def pause(self): def volume_change(self, vol_level): self.volume = vol_level logging.debug(f"Setting volume to: {self.volume}") - if self.is_file_playing(): - self.now_playing_command = f"volume_change: {self.volume}" return True def vol_up(self): @@ -650,12 +648,6 @@ def vol_up(self): self.volume = 1.0 logging.debug("max volume reached.") logging.debug(f"Increasing volume by 10%: {self.volume}") - if self.is_file_playing(): - self.now_playing_command = "vol_up" - return True - else: - logging.warning("Tried to volume up, but no file is playing!") - return False def vol_down(self): self.volume -= 0.1 @@ -664,16 +656,15 @@ def vol_down(self): self.volume = 0 logging.debug("minimum volume reached.") logging.debug(f"Decreasing volume by 10%: {self.volume}") - if self.is_file_playing(): - self.now_playing_command = "vol_down" - return True - else: - logging.warning("Tried to volume down, but no file is playing!") - return False + + def send_command(self, command): + self.now_playing_command = command + threading.Timer(2, self.reset_now_playing_command).start() + # Clear the command asynchronously. 2s should be enough for client polling to pick it up def restart(self): if self.is_file_playing(): - self.now_playing_command = "restart" + self.send_command("restart") return True else: logging.warning("Tried to restart, but no file is playing!") @@ -685,6 +676,9 @@ def stop(self): def handle_run_loop(self): time.sleep(self.loop_interval / 1000) + def reset_now_playing_command(self): + self.now_playing_command = None + def reset_now_playing(self): self.now_playing = None self.now_playing_filename = None diff --git a/pikaraoke/templates/splash.html b/pikaraoke/templates/splash.html index b92a6a68..dc290ec0 100644 --- a/pikaraoke/templates/splash.html +++ b/pikaraoke/templates/splash.html @@ -23,9 +23,9 @@ parseInt("{{ screensaver_timeout }}") * 1000 || 300000; let screensaverTimeout; - var isPlaying = false; - var isPaused = false; var nowPlayingInterval = null; + var pollingInterval = 1000; + var nowPlayingHash = null; var nowPlaying = {}; var showMenu = false; @@ -34,7 +34,7 @@ var volume = 0.85; function startNowPlayingPolling() { - nowPlayingInterval = setInterval(getNowPlaying, 1000); + nowPlayingInterval = setInterval(getNowPlaying, pollingInterval); } function handleConfirmation() { @@ -46,10 +46,13 @@ $.get('{{ url_for("clear_command") }}'); } - function endSong() { + function stopVideo() { $("#video-container").hide(); + } + + function endSong() { + stopVideo(); $.get('{{ url_for("end_song") }}'); - setTimeout(() => (isPlaying = false), 1100); } function executeCommand(callback) { @@ -100,13 +103,16 @@ const video = $("#video")[0]; // Start playback if a valid now_playing_url is provided - if (obj.now_playing_url && !isPlaying) { + if ( + obj.now_playing_url && + !isVideoPlaying(video) && + $("#video-container").is(":hidden") + ) { if (!confirmationDismissed) { console.log( "Browser is unable to play video. User did not confirm interaction prompt." ); } - isPlaying = true; $("#video-source").attr("src", obj.now_playing_url); video.load(); if (volume != obj.volume) { @@ -117,61 +123,39 @@ // handle timeout if video fails to play setTimeout(() => { - if (!isVideoPlaying(video) && !isPaused) { + if (!isVideoPlaying(video) && !video.paused) { endSong(); } }, 10000); } - // Handle vol up - if (obj.now_playing_command == "vol_up" && isPlaying) { - executeCommand(() => { - const volume = video.volume; - video.volume = Math.min(1, volume + 0.1); - }); + // Stop video if we're out of sync with server + if (isVideoPlaying(video) && !obj.now_playing) { + video.pause(); + stopVideo(); } - // Handle vol down - if (obj.now_playing_command == "vol_down" && isPlaying) { - executeCommand(() => { - const volume = video.volume; - video.volume = Math.max(0, volume - 0.1); - }); + // Handle pause/play + if (obj.now_playing && !video.paused && obj.is_paused) { + video.pause(); } - - // Handle pause - if (obj.now_playing_command == "pause" && isPlaying) { - executeCommand(() => { - isPaused ? video.play() : video.pause(); - isPaused = !isPaused; - }); + if (obj.now_playing && video.paused && !obj.is_paused) { + video.play(); } - // Handle skip - if (obj.now_playing_command == "skip" && isPlaying) { - executeCommand(() => { - video.pause(); - endSong(); - }); + // Handle volume change + if (volume != obj.volume) { + volume = obj.volume; + video.volume = volume; } // Handle restart - if (obj.now_playing_command == "restart" && isPlaying) { - executeCommand(() => { - video.currentTime = 0; - }); - } - - // Handle volume change if ( - obj.now_playing_command && - obj.now_playing_command.startsWith("volume_change:") && - isPlaying + isVideoPlaying(video) && + obj.now_playing_command == "restart" && + video.currentTime > 3 ) { - executeCommand(() => { - const volLevel = parseFloat(obj.now_playing_command.split(":")[1]); - video.volume = volLevel; - }); + video.currentTime = 0; } } @@ -179,7 +163,7 @@ let screensaver = document.getElementById("screensaver"); if ( !nowPlaying.up_next && - !isPlaying && + !isVideoPlaying(video) && !screensaverTimeout && !cursorVisible ) { @@ -188,7 +172,7 @@ startScreensaver(); }, screensaverTimeoutMs); } else { - if (nowPlaying.up_next || isPlaying || cursorVisible) { + if (nowPlaying.up_next || isVideoPlaying(video) || cursorVisible) { screensaver.style.visibility = "hidden"; stopScreensaver(); screensaverTimeout = clearTimeout(screensaverTimeout);