Skip to content

Commit

Permalink
fix: support concurrent splash screens #448 (#451)
Browse files Browse the repository at this point in the history
Concurrent splash screens cause playback issues on one another. We can
do better with synchronizing them.

Probably not going to work miracles, the playback positions might be out
of sync by up to 1 second. And weird stuff happens when opening/closing
browsers mid-song. But at least they wont totally clobber the playback
between the two like it currently does.
  • Loading branch information
vicwomg authored Dec 28, 2024
1 parent f074cee commit 4122096
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 66 deletions.
28 changes: 11 additions & 17 deletions pikaraoke/karaoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import random
import socket
import subprocess
import threading
import time
from pathlib import Path
from queue import Queue
Expand Down Expand Up @@ -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!")
Expand All @@ -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:
Expand All @@ -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):
Expand All @@ -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
Expand All @@ -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!")
Expand All @@ -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
Expand Down
82 changes: 33 additions & 49 deletions pikaraoke/templates/splash.html
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -34,7 +34,7 @@
var volume = 0.85;

function startNowPlayingPolling() {
nowPlayingInterval = setInterval(getNowPlaying, 1000);
nowPlayingInterval = setInterval(getNowPlaying, pollingInterval);
}

function handleConfirmation() {
Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -117,69 +123,47 @@

// 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;
}
}

//handle screensaver
let screensaver = document.getElementById("screensaver");
if (
!nowPlaying.up_next &&
!isPlaying &&
!isVideoPlaying(video) &&
!screensaverTimeout &&
!cursorVisible
) {
Expand All @@ -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);
Expand Down

0 comments on commit 4122096

Please sign in to comment.