summaryrefslogtreecommitdiff
path: root/remote/projector.py
diff options
context:
space:
mode:
Diffstat (limited to 'remote/projector.py')
-rwxr-xr-xremote/projector.py128
1 files changed, 128 insertions, 0 deletions
diff --git a/remote/projector.py b/remote/projector.py
new file mode 100755
index 0000000..16cceb8
--- /dev/null
+++ b/remote/projector.py
@@ -0,0 +1,128 @@
+#!/usr/bin/python2
+
+import subprocess
+import os
+import time
+import sys
+import signal
+import select
+import errno
+import inspect
+
+from SimpleXMLRPCServer import SimpleXMLRPCServer
+
+projection_process = None
+default_task = [
+ './brause.py',
+ 'http://sublab.rotefraktion.org/loungescreen/'
+]
+projection_task = default_task
+
+class ChildProcess(subprocess.Popen):
+ def __init__(self, *args, **kwargs):
+ subprocess.Popen.__init__(self, *args, **kwargs)
+ self._kill = os.kill
+ def __del__(self):
+ try:
+ self._kill(self.pid, 9)
+ self.poll()
+ except EnvironmentError as e:
+ if e.args[0] != errno.ESRCH:
+ raise
+
+def restart_projection(dummy=None):
+ global projection_process
+ global projection_task
+
+ print "Replacing projection_process..."
+ projection_process = ChildProcess(projection_task)
+
+def sigchld(signum, trace):
+ global projection_process
+
+ print "Got SIGCHLD"
+ if projection_process is not None and \
+ projection_process.poll() is None:
+ # This info was not about the current projection_process...
+ return
+
+ # Current projection_process exited, fallback to default
+ reset_projection()
+
+def display_url(url):
+ global projection_task
+
+ projection_task = [
+ './brause.py',
+ url
+ ]
+ restart_projection()
+
+ return 0 # For RPC
+
+def display_video(url):
+ global projection_task
+
+ if not (url.startswith('http://') or \
+ url.startswith('ftp://')):
+ raise ValueError('URL should point to a http/ftp resource...')
+
+ projection_task = [
+ 'mplayer',
+ '-fs',
+ url
+ ]
+ restart_projection()
+
+ return 0 # For RPC
+
+def reset_projection():
+ global projection_task
+ global default_task
+
+ projection_task = default_task
+ restart_projection()
+
+ return 0 # For RPC
+
+def start_vnc(port):
+ global projection_task
+
+ if type(port) is not int:
+ raise TypeError("start_vnc expects (port:int) as arguments")
+
+ # Worst Monkey Patch ever (tm)
+ host = inspect.stack()[3][0].f_locals['self'].client_address[0]
+ print 'Connecting vncviewer to %s:%d' % (host,port)
+
+ projection_task = [
+ "vncviewer", "-fullscreen",
+ "-viewonly", "%s::%d" % (host,port) ]
+ restart_projection()
+
+ return 0
+
+def main():
+ global projecting
+ subprocess.check_call("xset s off".split())
+ subprocess.check_call("xset -dpms".split())
+
+ signal.signal(signal.SIGCHLD, sigchld)
+ restart_projection()
+
+ server = SimpleXMLRPCServer(("0.0.0.0", 8082))
+ server.register_function(display_url)
+ server.register_function(display_video)
+ server.register_function(reset_projection)
+ server.register_function(start_vnc)
+
+ while True:
+ try:
+ server.serve_forever()
+ except select.error as e:
+ if e.args[0] == errno.EINTR:
+ continue
+ raise
+
+if __name__ == '__main__':
+ main()