summaryrefslogtreecommitdiff
path: root/remote/projector.py
blob: 16cceb80258e2e72b653daf1b620db5bc2596085 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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()