#!/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 sys.path.append(".") from light9 import showconfig, networking from light9.namespaces import L9 from urllib import urlencode # move to web lib def post(url, **args): return getPage(url, method='POST', postdata=urlencode(args)) class Commands(object): @staticmethod def playSong(graph, songUri): s = xmlrpclib.ServerProxy(networking.musicPlayer.url) 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.musicPlayer.url) return s.stop() @staticmethod def worklightsOn(graph): return post(networking.keyboardComposer.path('fadesub'), subname='scoop', level=.5, secs=.5) @staticmethod def worklightsOff(graph): return post(networking.keyboardComposer.path('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): 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() show = showconfig.showUri() log.startLogging(sys.stdout) reactor.listenTCP(9000, NevowSite(Main(graph))) reactor.run()