diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | README | 27 | ||||
| -rwxr-xr-x | remote/Xsession | 4 | ||||
| -rw-r--r-- | remote/__init__.py | 0 | ||||
| -rwxr-xr-x | remote/brause.py | 37 | ||||
| -rwxr-xr-x | remote/projector.py | 128 | ||||
| -rwxr-xr-x | reset_projector.py | 15 | ||||
| -rwxr-xr-x | video_projector.py | 15 | ||||
| -rwxr-xr-x | vnc_projector.py | 29 | ||||
| -rwxr-xr-x | web_projector.py | 15 | 
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 @@ -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()  | 
