Skip to content

Instantly share code, notes, and snippets.

@dasl-
Created May 24, 2022 04:31
Show Gist options
  • Save dasl-/08352b0a8ac7b79e2979c92fc7b3f928 to your computer and use it in GitHub Desktop.
Save dasl-/08352b0a8ac7b79e2979c92fc7b3f928 to your computer and use it in GitHub Desktop.
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