summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--README27
-rwxr-xr-xremote/Xsession4
-rw-r--r--remote/__init__.py0
-rwxr-xr-xremote/brause.py37
-rwxr-xr-xremote/projector.py128
-rwxr-xr-xreset_projector.py15
-rwxr-xr-xvideo_projector.py15
-rwxr-xr-xvnc_projector.py29
-rwxr-xr-xweb_projector.py15
10 files changed, 271 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/README b/README
new file mode 100644
index 0000000..be00307
--- /dev/null
+++ b/README
@@ -0,0 +1,27 @@
+This is "projector", a hacky way to supply
+input to a projector connected to a shared
+system.
+
+Using this collection of scripts, you can:
+ - display Web Pages
+ - play back video
+ - display your screen via vnc
+
+Usage:
+======
+
+This script assumes /usr/bin/python2 points to a python
+interpreter adhering to python language version >= 2.6
+If this is not true, you will either have to create a
+fitting symlink or change the scripts.
+
+The files in the 'remote' directory should be placed
+somewhere on the box attached to the projector. Xsession
+is an example how an Xsession file to start the projector
+might look. On the remote box, also TightVNC Viewer,
+python-cairo, python-webkit, Mplayer are required.
+
+The scripts in the top directory enable the user to control
+the projector. They should be pretty much self explanatory,
+the beamer URL is by default http://<beamer-ip>:8082/
+vnc_projector requires x11vnc.
diff --git a/remote/Xsession b/remote/Xsession
new file mode 100755
index 0000000..0939958
--- /dev/null
+++ b/remote/Xsession
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+metacity &
+python projector.py
diff --git a/remote/__init__.py b/remote/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/remote/__init__.py
diff --git a/remote/brause.py b/remote/brause.py
new file mode 100755
index 0000000..e9c0fce
--- /dev/null
+++ b/remote/brause.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python2
+
+# written by equinox in 5 mintes on 09-04-2010 :)
+
+import sys
+
+import gobject
+import pango
+import pygtk
+pygtk.require('2.0')
+import gtk
+from gtk import gdk
+import cairo
+
+import webkit
+
+class BrauseWindow(gtk.Window):
+ def _destroy(s, widget, event):
+ gtk.main_quit()
+
+ def __init__(s):
+ gtk.Window.__init__(s, type = gtk.WINDOW_TOPLEVEL)
+ s.connect('delete-event', s._destroy)
+ s.set_decorated(False)
+ s.fullscreen()
+
+ s.webkit = webkit.WebView()
+ s.add(s.webkit)
+ s.show_all()
+
+ s.webkit.open(sys.argv[1])
+
+ def run(s):
+ gtk.main()
+
+BrauseWindow().run()
+
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()
diff --git a/reset_projector.py b/reset_projector.py
new file mode 100755
index 0000000..660d387
--- /dev/null
+++ b/reset_projector.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python2
+
+import sys
+import xmlrpclib
+
+def main():
+ if len(sys.argv) != 2:
+ sys.stderr.write('Usage: %s <projector-url>\n' % sys.argv[0])
+ sys.exit(1)
+
+ projector = xmlrpclib.ServerProxy(sys.argv[1])
+ projector.reset_projection()
+
+if __name__ == '__main__':
+ main()
diff --git a/video_projector.py b/video_projector.py
new file mode 100755
index 0000000..6236010
--- /dev/null
+++ b/video_projector.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python2
+
+import sys
+import xmlrpclib
+
+def main():
+ if len(sys.argv) != 3:
+ sys.stderr.write('Usage: %s <projector-url> <url>\n' % sys.argv[0])
+ sys.exit(1)
+
+ projector = xmlrpclib.ServerProxy(sys.argv[1])
+ projector.display_video(sys.argv[2])
+
+if __name__ == '__main__':
+ main()
diff --git a/vnc_projector.py b/vnc_projector.py
new file mode 100755
index 0000000..dcb2d28
--- /dev/null
+++ b/vnc_projector.py
@@ -0,0 +1,29 @@
+#!/usr/bin/python2
+
+from remote.projector import ChildProcess
+
+import sys
+import xmlrpclib
+import time
+
+def main():
+ if len(sys.argv) not in [ 2, 3 ]:
+ sys.stderr.write('Usage: %s <projector-url> [port]\n' % sys.argv[0])
+ sys.exit(1)
+
+ if len(sys.argv) == 3:
+ port = int(sys.argv[2])
+ else:
+ port = 5900
+
+ cmdline = "x11vnc -listen 0.0.0.0 -viewonly -nopw -rfbport %d" % port
+ x11vnc = ChildProcess(cmdline.split())
+ time.sleep(2)
+
+ projector = xmlrpclib.ServerProxy(sys.argv[1])
+ projector.start_vnc(port)
+
+ x11vnc.communicate()
+
+if __name__ == '__main__':
+ main()
diff --git a/web_projector.py b/web_projector.py
new file mode 100755
index 0000000..64e9089
--- /dev/null
+++ b/web_projector.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python2
+
+import sys
+import xmlrpclib
+
+def main():
+ if len(sys.argv) != 3:
+ sys.stderr.write('Usage: %s <projector-url> <url>\n' % sys.argv[0])
+ sys.exit(1)
+
+ projector = xmlrpclib.ServerProxy(sys.argv[1])
+ projector.display_url(sys.argv[2])
+
+if __name__ == '__main__':
+ main()