Beispiel #1
0
    def __init__(self, video_url, log_uuid, show_loading_screen):
        self.__logger = Logger().set_namespace(self.__class__.__name__)
        if log_uuid:
            Logger.set_uuid(log_uuid)
        else:
            Logger.set_uuid(Logger.make_uuid())

        self.__config_loader = ConfigLoader()
        self.__video_url = video_url
        self.__show_loading_screen = show_loading_screen

        # 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
        self.__video_broadcast_proc_pgid = None
        self.__download_and_convert_video_proc_pgid = None

        # Metadata about the video we are using, such as title, resolution, file extension, etc
        # Access should go through self.get_video_info() to populate it lazily
        self.__video_info = None

        # Bind multicast traffic to eth0. Otherwise it might send over wlan0 -- multicast doesn't work well over wifi.
        # `|| true` to avoid 'RTNETLINK answers: File exists' if the route has already been added.
        (subprocess.check_output(
            f"sudo ip route add {MulticastHelper.ADDRESS}/32 dev eth0 || true",
            shell=True,
            executable='/usr/bin/bash',
            stderr=subprocess.STDOUT))

        self.__control_message_helper = ControlMessageHelper(
        ).setup_for_broadcaster()
        self.__do_housekeeping(for_end_of_video=False)
        self.__register_signal_handlers()
Beispiel #2
0
 def __play_screensaver(self):
     log_uuid = 'SCREENSAVER__' + Logger.make_uuid()
     Logger.set_uuid(log_uuid)
     # choose random screensaver video to play
     screensavers_config = self.__config_loader.get_raw_config(
     )['screensavers']
     if self.__config_loader.is_any_receiver_dual_video_output():
         options = screensavers_config['720p']
     else:
         options = screensavers_config['1080p']
     screensaver_data = random.choice(list(options.values()))
     path = DirectoryUtils().root_dir + '/' + screensaver_data['video_path']
     self.__logger.info("Starting broadcast of screensaver...")
     self.__do_broadcast(path, log_uuid)
Beispiel #3
0
 def __stop_loading_screen_playback_if_playing(self, reset_log_uuid):
     if not self.__is_loading_screen_playback_in_progress:
         return
     if self.__loading_screen_pgid:
         self.__logger.info("Killing loading_screen proc (if it's still running)...")
         try:
             os.killpg(self.__loading_screen_pgid, signal.SIGTERM)
         except Exception:
             # might raise: `ProcessLookupError: [Errno 3] No such process`
             pass
     if reset_log_uuid:
         Logger.set_uuid('')
     self.__is_loading_screen_playback_in_progress = False
     self.__loading_screen_crop_args = None
     self.__loading_screen_crop_args2 = None
Beispiel #4
0
 def __show_loading_screen(self, ctrl_msg):
     ctrl_msg_content = ctrl_msg[ControlMessageHelper.CONTENT_KEY]
     Logger.set_uuid(ctrl_msg_content['log_uuid'])
     cmd, self.__loading_screen_crop_args, self.__loading_screen_crop_args2 = (
         self.__receiver_command_builder.build_loading_screen_command_and_get_crop_args(
             self.__video_player_volume_pct, self.__display_mode, self.__display_mode2,
             ctrl_msg_content['loading_screen_data']
         )
     )
     self.__logger.info(f"Showing loading screen with command: {cmd}")
     self.__is_loading_screen_playback_in_progress = True
     proc = subprocess.Popen(
         cmd, shell = True, executable = '/usr/bin/bash', start_new_session = True
     )
     return proc
Beispiel #5
0
 def __receive_and_play_video(self, ctrl_msg):
     ctrl_msg_content = ctrl_msg[ControlMessageHelper.CONTENT_KEY]
     Logger.set_uuid(ctrl_msg_content['log_uuid'])
     cmd, self.__video_crop_args, self.__video_crop_args2 = (
         self.__receiver_command_builder.build_receive_and_play_video_command_and_get_crop_args(
             ctrl_msg_content['log_uuid'], ctrl_msg_content['video_width'],
             ctrl_msg_content['video_height'], self.__video_player_volume_pct,
             self.__display_mode, self.__display_mode2
         )
     )
     self.__logger.info(f"Running receive_and_play_video command: {cmd}")
     self.__is_video_playback_in_progress = True
     proc = subprocess.Popen(
         cmd, shell = True, executable = '/usr/bin/bash', start_new_session = True
     )
     return proc
Beispiel #6
0
 def __play_playlist_item(self, playlist_item):
     if not self.__playlist.set_current_video(
             playlist_item["playlist_video_id"]):
         # Someone deleted the item from the queue in between getting the item and starting it.
         return
     log_uuid = Logger.make_uuid()
     Logger.set_uuid(log_uuid)
     self.__logger.info(
         f"Starting broadcast for playlist_video_id: {playlist_item['playlist_video_id']}"
     )
     msg = {
         'log_uuid': log_uuid,
         'loading_screen_data': self.__choose_random_loading_screen()
     }
     self.__control_message_helper.send_msg(
         ControlMessageHelper.TYPE_SHOW_LOADING_SCREEN, msg)
     self.__do_broadcast(playlist_item['url'], log_uuid)
     self.__playlist_item = playlist_item
Beispiel #7
0
 def __stop_video_playback_if_playing(self, stop_loading_screen_playback):
     if stop_loading_screen_playback:
         self.__stop_loading_screen_playback_if_playing(reset_log_uuid = False)
     if not self.__is_video_playback_in_progress:
         if stop_loading_screen_playback:
             Logger.set_uuid('')
         return
     if self.__receive_and_play_video_proc_pgid:
         self.__logger.info("Killing receive_and_play_video proc (if it's still running)...")
         try:
             os.killpg(self.__receive_and_play_video_proc_pgid, signal.SIGTERM)
         except Exception:
             # might raise: `ProcessLookupError: [Errno 3] No such process`
             pass
     Logger.set_uuid('')
     self.__is_video_playback_in_progress = False
     self.__video_crop_args = None
     self.__video_crop_args2 = None
Beispiel #8
0
    def __stop_broadcast_if_broadcasting(self, was_skipped=False):
        if not self.__is_broadcast_in_progress:
            return

        if self.__broadcast_proc:
            self.__logger.info(
                "Killing broadcast proc (if it's still running)...")
            was_killed = True
            try:
                os.kill(self.__broadcast_proc.pid, signal.SIGTERM)
            except Exception:
                # might raise: `ProcessLookupError: [Errno 3] No such process`
                was_killed = False
            exit_status = self.__broadcast_proc.wait()
            if exit_status != 0:
                if was_killed and exit_status == signal.SIGTERM:
                    pass  # We expect a specific non-zero exit code if the broadcast was killed.
                else:
                    self.__logger.error(
                        f'Got non-zero exit_status for broadcast proc: {exit_status}'
                    )

        self.__control_message_helper.send_msg(
            ControlMessageHelper.TYPE_SKIP_VIDEO, {})

        if self.__playlist_item:
            if self.__should_reenqueue_current_playlist_item(was_skipped):
                self.__playlist.reenqueue(
                    self.__playlist_item["playlist_video_id"])
            else:
                self.__playlist.end_video(
                    self.__playlist_item["playlist_video_id"])

        self.__logger.info("Ended video broadcast.")
        Logger.set_uuid('')
        self.__broadcast_proc = None
        self.__playlist_item = None
        self.__is_broadcast_in_progress = False