summaryrefslogtreecommitdiff
path: root/remote/projector.py
blob: 64717d0065b58b7aa1e9983888a296cfe1b8f262 (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
129
130
131
132
#!/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',
        'file://%s' % os.path.join(os.path.abspath(os.path.dirname(__file__)), 'default_page', 'index.html')
]
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',
        '-vo',
        'x11',
        '-ao',
        'pulse',
        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()