Mercurial > code > home > repos > light9
changeset 514:a33519c49871
new bin/webcontrol web client for playing songs and adjusting lights
Ignore-this: 84b62f641ed50971cf59035e6ba75223
author | drewp@bigasterisk.com |
---|---|
date | Mon, 29 Jun 2009 02:04:15 +0000 |
parents | 259436a06912 |
children | d541914c8716 |
files | bin/webcontrol light9/webcontrol.html |
diffstat | 2 files changed, 199 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/webcontrol Mon Jun 29 02:04:15 2009 +0000 @@ -0,0 +1,114 @@ +#!/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()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/light9/webcontrol.html Mon Jun 29 02:04:15 2009 +0000 @@ -0,0 +1,85 @@ +<?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