Changeset - a33519c49871
[Not reviewed]
default
0 0 2
drewp@bigasterisk.com - 16 years ago 2009-06-29 02:04:15
drewp@bigasterisk.com
new bin/webcontrol web client for playing songs and adjusting lights
Ignore-this: 84b62f641ed50971cf59035e6ba75223
2 files changed with 199 insertions and 0 deletions:
0 comments (0 inline, 0 general)
bin/webcontrol
Show inline comments
 
new file 100644
 
#!/usr/bin/python
 
"""
 
web UI for various commands that we might want to run from remote
 
computers and phones
 

	
 
todo:
 
disable buttons that don't make sense
 
"""
 
import sys, xmlrpclib, traceback
 
from twisted.internet import reactor
 
from twisted.python import log
 
from twisted.python.util import sibpath
 
from twisted.internet.defer import inlineCallbacks, returnValue
 
from twisted.web.client import getPage
 
from nevow.appserver import NevowSite
 
from nevow import rend, static, loaders, inevow, url, tags as T
 
from rdflib import URIRef
 
from louie.robustapply import robust_apply
 
from light9 import showconfig, networking
 
from light9.namespaces import L9
 
from urllib import urlencode
 

	
 
# move to web lib
 
def post(root, path, **args):
 
    return getPage(root.rstrip('/') + '/' + path.lstrip('/'),
 
                   method='POST',
 
                   postdata=urlencode(args))
 

	
 

	
 
class Commands(object):
 
    @staticmethod
 
    def playSong(graph, songUri):
 
        s = xmlrpclib.ServerProxy(networking.musicUrl())
 
        songPath = graph.value(URIRef(songUri), L9.showPath)
 
        if songPath is None:
 
            raise ValueError("unknown song %s" % songUri)
 
        return s.playfile(songPath.encode('ascii'))
 

	
 
    @staticmethod
 
    def stopMusic(graph):
 
        s = xmlrpclib.ServerProxy(networking.musicUrl())
 
        return s.stop()
 

	
 
    @staticmethod
 
    def worklightsOn(graph):
 
        return post(networking.keyboardComposerUrl(), 'fadesub',
 
                    subname='scoop', level=.5, secs=.5)
 

	
 
    @staticmethod
 
    def worklightsOff(graph):
 
        return post(networking.keyboardComposerUrl(), 'fadesub',
 
                    subname='scoop', level=0, secs=.5)
 

	
 
    @staticmethod
 
    def dimmerSet(graph, dimmer, value):
 
        raise NotImplementedError("subcomposer doesnt have an http port yet")
 

	
 
class Main(rend.Page):
 
    docFactory = loaders.xmlfile(sibpath(__file__, "../light9/webcontrol.html"))
 

	
 
    def __init__(self, graph):
 
        self.graph = graph
 
        rend.Page.__init__(self)
 

	
 
    def render_status(self, ctx, data):
 
        pic = T.img(src="icon/enabled.png")
 
        if ctx.arg('error'):
 
            pic = T.img(src="icon/warning.png")
 
        return [pic, ctx.arg('status') or 'ready']
 

	
 
    def render_songButtons(self, ctx, data):
 
        show = URIRef("http://light9.bigasterisk.com/show/dance2009") # ?
 
        playList = graph.value(show, L9['playList'])
 
        songs = list(graph.items(playList))
 
        out = []
 
        for song in songs:
 
            out.append(
 
                T.form(method="post", action="playSong")[
 
                    T.input(type='hidden', name='songUri', value=song),
 
                    T.button(type='submit')[graph.label(song)]])
 
        return out
 

	
 
    @inlineCallbacks
 
    def locateChild(self, ctx, segments):
 
        try:
 
            func = getattr(Commands, segments[0])
 
            req = inevow.IRequest(ctx)
 
            simpleArgDict = dict((k, v[0]) for k,v in req.args.items())
 
            try:
 
                ret = yield robust_apply(func, func, self.graph,
 
                                         **simpleArgDict)
 
            except KeyboardInterrupt: raise
 
            except Exception, e:
 
                print "Error on command %s" % segments[0]
 
                traceback.print_exc()
 
                returnValue((url.here.up().
 
                             add('status', str(e)).
 
                             add('error', 1), segments[1:]))
 
                
 
            returnValue((url.here.up().add('status', ret), segments[1:]))
 
            #actually return the orig page, with a status message from the func
 
        except AttributeError:
 
            pass
 
        returnValue(rend.Page.locateChild(self, ctx, segments))
 

	
 
    def child_icon(self, ctx):
 
        return static.File("/usr/share/pyshared/elisa/plugins/poblesec/tango")
 
            
 
graph = showconfig.getGraph()
 

	
 
log.startLogging(sys.stdout)
 

	
 
reactor.listenTCP(9000, NevowSite(Main(graph)))
 
reactor.run()
light9/webcontrol.html
Show inline comments
 
new file 100644
 
<?xml version="1.0" encoding="iso-8859-1"?>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml"
 
      xmlns:n="http://nevow.com/ns/nevow/0.1">
 
  <head>
 
    <title>light9 remote</title>
 
    <style type="text/css" media="all">
 
      /* <![CDATA[ */
 

	
 
body {
 
    background:black none repeat scroll 0 0;
 
    color:white;
 
    width:320px;
 
}
 
div.section {
 
    border:2px groove #060;
 
    margin:5px;
 
    padding:5px;
 
}
 
.doubleWide {
 
    width:120px;
 
    background:#610;
 
}
 
.section img {
 
    width:36px;
 
    vertical-align: middle;
 
}
 
form {
 
    display:inline;
 
}
 
button {
 
    height:64px;
 
    width:64px;
 
    background:#035;
 
    color:white;
 
    margin:5px;
 
    vertical-align:top;
 
    border:1px #035 outset;
 
    -moz-border-radius:8px;
 
}
 

	
 
div.status {
 
    color:#FFFF00;
 
    font-family:monospace;
 
    text-align:center;
 
}
 

	
 
div.status img {
 
    width: 32px;
 
    vertical-align: middle;
 
    margin-right: 3px;
 
}
 

	
 
      /* ]]> */
 
    </style>
 

	
 
  </head>
 
  <body>
 

	
 
    <div class="status"><n:invisible n:render="status"/></div>
 

	
 
    <div class="section music">
 
      <div class="title"><img src="icon/music.png"/> Music control</div>
 
      <n:invisible n:render="songButtons"/>
 

	
 
      <form method="post" action="stopMusic">
 
	<button type="submit" class="doubleWide">Stop music</button>
 
      </form>
 
    </div>
 

	
 
    <div class="section light">
 
      <div class="title"><img src="icon/tvshow.png"/> Light control</div>
 
      <div>
 
	<form style="display: inline" method="post" action="worklightsOn">
 
	  <button type="submit">Works on</button>
 
	</form>
 
	<form style="display: inline" method="post" action="worklightsOff">
 
	  <button type="submit">Works off</button>
 
	</form>
 
      </div>
 
    </div>
 

	
 
  </body>
 
</html>
 
\ No newline at end of file
0 comments (0 inline, 0 general)