Created
May 24, 2022 04:31
-
-
Save dasl-/08352b0a8ac7b79e2979c92fc7b3f928 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/piwall2/broadcaster/videobroadcaster.py b/piwall2/broadcaster/videobroadcaster.py | |
index 87fe66e..85eab4c 100644 | |
--- a/piwall2/broadcaster/videobroadcaster.py | |
+++ b/piwall2/broadcaster/videobroadcaster.py | |
@@ -1,3 +1,5 @@ | |
+import errno | |
+import fcntl | |
import os | |
import shlex | |
import signal | |
@@ -20,6 +22,14 @@ from piwall2.receiver.receiver import Receiver | |
class VideoBroadcaster: | |
END_OF_VIDEO_MAGIC_BYTES = b'PIWALL2_END_OF_VIDEO_MAGIC_BYTES' | |
+ BROADCAST_LOCK_FILE = '/run/lock/piwall2_broadcast_lock' | |
+ VIDEO_BROADCASTER_LOCK_SLEEP_TIME = 0.05 | |
+ | |
+ # Ensure this is greater than VIDEO_BROADCASTER_LOCK_SLEEP_TIME to prevent a potential scenario | |
+ # where videos started manually with ./bin/broadcast (as opposed to started by the queue) never acquiring the lock. The intended behavior | |
+ # is the videos started | |
+ # 1) | |
+ QUEUE_LOCK_SLEEP_TIME = 2 * VIDEO_BROADCASTER_LOCK_SLEEP_TIME | |
__VIDEO_URL_TYPE_YOUTUBE = 'video_url_type_youtube' | |
__VIDEO_URL_TYPE_LOCAL_FILE = 'video_url_type_local_file' | |
@@ -29,11 +39,15 @@ class VideoBroadcaster: | |
# We check for its existence to determine when video playback is over. | |
__VIDEO_PLAYBACK_DONE_FILE = '/tmp/video_playback_done.file' | |
- # video_url may be a youtube url or a path to a file on disk | |
- # Loading screen may also get shown by the queue process. Sending the signal to show it from | |
- # the queue is faster than showing it in the videobroadcaster process. But one may still wish | |
- # to show a loading screen when playing videos via the command line. | |
- def __init__(self, video_url, log_uuid, show_loading_screen): | |
+ # video_url: may be a youtube url or a path to a file on disk | |
+ # show_loading_screen: Loading screen may also get shown by the queue process. Sending the | |
+ # signal to show it from the queue is faster than showing it in the videobroadcaster | |
+ # process. But one may still wish to show a loading screen when playing videos via the | |
+ # command line. | |
+ # force_acquire_broadcast_lock: will be False when starting a video from the queue. This | |
+ # means that by default, videos started manually via `./bin/broadcast` will take precedence | |
+ # over queue videos. | |
+ def __init__(self, video_url, log_uuid, show_loading_screen, force_acquire_broadcast_lock): | |
self.__logger = Logger().set_namespace(self.__class__.__name__) | |
if log_uuid: | |
Logger.set_uuid(log_uuid) | |
@@ -43,6 +57,7 @@ class VideoBroadcaster: | |
self.__config_loader = ConfigLoader() | |
self.__video_url = video_url | |
self.__show_loading_screen = show_loading_screen | |
+ self.__force_acquire_broadcast_lock = force_acquire_broadcast_lock | |
# Store the PGIDs separately, because attempting to get the PGID later via `os.getpgid` can | |
# raise `ProcessLookupError: [Errno 3] No such process` if the process is no longer running | |
@@ -67,6 +82,8 @@ class VideoBroadcaster: | |
self.__register_signal_handlers() | |
def broadcast(self): | |
+ self.__acquire_broadcast_lock() | |
+ | |
attempt = 1 | |
max_attempts = 2 | |
while attempt <= max_attempts: | |
@@ -432,6 +449,34 @@ class VideoBroadcaster: | |
pass | |
self.__video_info = None | |
+ def __acquire_broadcast_lock(self): | |
+ lock_file = open(self.BROADCAST_LOCK_FILE, 'r+') | |
+ if not self.__force_acquire_broadcast_lock: | |
+ return | |
+ | |
+ self.__logger('Trying to acquire broadcast lock...') | |
+ while True: | |
+ is_lock_acquired = True | |
+ try: | |
+ fcntl.lockf(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB) | |
+ except OSError as e: | |
+ if e.errno == errno.EAGAIN or e.errno == errno.EACCES: | |
+ is_lock_acquired = False | |
+ else: | |
+ raise e | |
+ | |
+ if is_lock_acquired: | |
+ break | |
+ else: | |
+ time.sleep(0.05) | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
def __register_signal_handlers(self): | |
signal.signal(signal.SIGINT, self.__signal_handler) | |
signal.signal(signal.SIGHUP, self.__signal_handler) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment