diff --git a/infoboard/video.py b/infoboard/video.py index c13f918..4f35999 100644 --- a/infoboard/video.py +++ b/infoboard/video.py @@ -1,9 +1,26 @@ import os.path import logging import subprocess +import multiprocessing from datetime import date from subprocess import PIPE +def _runInSequence(first_process, second_process): + """ + Spawns new process which manages to run two processes in sequence. + These two are specified by subprocess.Popen args argument. + """ + def runInProcess(first_process, second_process): + proc = subprocess.Popen(first_process) + proc.wait() + subprocess.Popen(second_process) + return + process = multiprocessing.Process(target=runInProcess, + args=(first_process, second_process)) + process.start() + # returns immediately after the process starts + return process + class Video: """Parses line containing description of a video. @@ -49,19 +66,25 @@ def __init__(self, line): def _from_image(self, filename, duration): """Created video from picture with requested duration unless it already exists.""" - if not os.path.isfile('videos/' + filename + '.' + duration + '.avi'): - command = ['/usr/bin/mencoder', - # reads commands from stdin - 'mf://pictures/' + filename, - # don't quit when there is no file to play - '-o', 'videos/' + filename + '.' + duration + '.avi', - # fullscreen - '-ovc', 'lavc', - # no way to control mplayer in other way - '-lavcopts', 'vcodec=mjpeg', - # reuse same window for playing all videos - '-fps', '1/' + duration, - # don't print progress - '-ofps', '30' - ] - self.mp_process = subprocess.Popen(command) + videoname = filename + '.' + duration + '.avi' + if os.path.isfile('/tmp/' + videoname): + return + if os.path.isfile('videos/' + videoname): + return + encode = ['/usr/bin/mencoder', + # reads commands from stdin + 'mf://pictures/' + filename, + # don't quit when there is no file to play + '-o', '/tmp/' + videoname, + # fullscreen + '-ovc', 'lavc', + # no way to control mplayer in other way + '-lavcopts', 'vcodec=mjpeg', + # reuse same window for playing all videos + '-fps', '1/' + duration, + # don't print progress + '-ofps', '30' + ] + move_product = ['/bin/mv', '/tmp/' + videoname, 'videos/' + videoname] + _runInSequence(encode, move_product) + raise ValueError('Picture "{0}" is not yet encoded'.format(filename)) diff --git a/infoboard/videoplayer.py b/infoboard/videoplayer.py index 87042fc..ce35d54 100644 --- a/infoboard/videoplayer.py +++ b/infoboard/videoplayer.py @@ -10,8 +10,12 @@ def __init__(self): '-slave', # don't quit when there is no file to play '-idle', - # fullscreen - '-fs', + # Fullscreen is hard to setup on second screen, + # which is currently our use case. + # We use fixed window size instead + # and maximize it with external program "maximus". + # '-fs', + '-zoom', '-x', '1920', '-y', '1080', # no way to control mplayer in other way '-input', 'nodefault-bindings:conf=/dev/null', # reuse same window for playing all videos diff --git a/infoboard/watcher.py b/infoboard/watcher.py index 1ea36b5..3eabe4f 100644 --- a/infoboard/watcher.py +++ b/infoboard/watcher.py @@ -4,12 +4,13 @@ class Watcher: """Executes provided function when chosen file changes.""" - def __init__(self, filename, folder, callback=lambda x: None): + def __init__(self, folder, callback=lambda x: None): self.callback = callback event_handler = FileSystemEventHandler() def handler(e): - if e.src_path.endswith('/' + filename): - self.callback(read_text_file(e.src_path)) + path = e.src_path + if path.endswith('.txt'): + self.callback(path, read_text_file(path)) # this happens also when file is created event_handler.on_modified = handler self.observer = Observer() diff --git a/server.py b/server.py index 1febd6e..9a7b720 100644 --- a/server.py +++ b/server.py @@ -1,8 +1,10 @@ +import glob import sys import time import re import logging import infoboard +import os from datetime import date from infoboard.video import Video from infoboard.videoplayer import VideoPlayer @@ -11,13 +13,13 @@ class Infoboard: - def __init__(self, watcher, player, schedule_file): - self.videos = [] + def __init__(self, watcher, player, schedule_dir): + self.videos = {} self._setup_logging() watcher.set_callback(self.process_schedule) self.watcher = watcher self.player = player - self.schedule_file = schedule_file + self.schedule_dir = schedule_dir def _setup_logging(self): logger = logging.getLogger('infoboard') @@ -32,29 +34,38 @@ def _setup_logging(self): logger.addHandler(ch) def run(self): - self.process_schedule(read_text_file(self.schedule_file)) + self.process_all_schedules() self.watcher.start() self.player.play(self) - def process_schedule(self, schedule): - self.videos = [] + def process_schedule(self, key, schedule): + self.videos[key] = [] for line in schedule.split('\n'): line = line.strip() if (not line) or line.startswith('#'): continue try: - self.videos.append(infoboard.video.Video(line)) + self.videos[key].append(infoboard.video.Video(line)) except ValueError: pass + def process_all_schedules(self): + for filename in glob.glob(self.schedule_dir + '/*.txt'): + filename = os.path.abspath(filename) + self.process_schedule(filename, read_text_file(filename)) + + def get_playlist(self): + self.process_all_schedules() today = date.today() - return [video.filename for video in self.videos + all_videos = [] + for key in sorted(self.videos.keys()): + all_videos += self.videos[key] + return [video.filename for video in all_videos if video.start_date <= today and video.end_date >= today] if __name__ == "__main__": - schedule_file = 'schedule.txt' v = infoboard.videoplayer.VideoPlayer() - w = infoboard.watcher.Watcher(schedule_file, 'schedule') - ib = Infoboard(w, v, 'schedule/'+schedule_file) + w = infoboard.watcher.Watcher('schedule') + ib = Infoboard(w, v, 'schedule') ib.run()