Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 39 additions & 16 deletions infoboard/video.py
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -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))
8 changes: 6 additions & 2 deletions infoboard/videoplayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 4 additions & 3 deletions infoboard/watcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
33 changes: 22 additions & 11 deletions server.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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')
Expand All @@ -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()