diff --git a/bin/curvecalc b/bin/curvecalc --- a/bin/curvecalc +++ b/bin/curvecalc @@ -17,8 +17,14 @@ try: except ImportError: import louie as dispatcher from twisted.internet import reactor,tksupport +import jsonlib import twisted -from twisted.web.xmlrpc import Proxy +from twisted.web.client import Agent +from twisted.internet.protocol import Protocol +from twisted.internet.defer import Deferred +from zope.interface import implements +from twisted.internet.defer import succeed +from twisted.web.iweb import IBodyProducer from rdflib import Literal, URIRef, RDF, RDFS from rdflib.Graph import Graph import rdflib @@ -37,33 +43,62 @@ from light9.uihelpers import toplevelat from light9.namespaces import L9 import light9.Effects +class GatherJson(Protocol): + """calls back the 'finished' deferred with the parsed json data we + received""" + def __init__(self, finished): + self.finished = finished + self.buf = "" + + def dataReceived(self, bytes): + self.buf += bytes + + def connectionLost(self, reason): + self.finished.callback(jsonlib.read(self.buf, use_float=True)) + +class StringProducer(object): + # http://twistedmatrix.com/documents/current/web/howto/client.html + implements(IBodyProducer) + + def __init__(self, body): + self.body = body + self.length = len(body) + + def startProducing(self, consumer): + consumer.write(self.body) + return succeed(None) + + def pauseProducing(self): + pass + + def stopProducing(self): + pass + class Music: def __init__(self): - self.player=None # xmlrpc Proxy to player self.recenttime=0 - + self.player = Agent(reactor) dispatcher.connect(self.seekplay_or_pause,"music seek") def current_time(self): """return deferred which gets called with the current time""" - if self.player is None: - print "connect to player" - self.player = Proxy(networking.musicUrl()) -# d = self.player.callRemote("songlength") -# d.addCallback(lambda l: dispatcher.send("max time",maxtime=l)) -# d = self.player.callRemote("songname") -# d.addCallback(lambda n: dispatcher.send("songname",name=n)) - d = self.player.callRemote('gettime') - def sendtime(t): - dispatcher.send("input time",val=t) - return t # pass along to the real receiver - def error(e): - pass#self.player=None - d.addCallback(sendtime) + d = self.player.request("GET", networking.musicUrl() + "time") + d.addCallback(self._timeReturned) return d + + def _timeReturned(self, response): + done = Deferred() + done.addCallback(self._bodyReceived) + response.deliverBody(GatherJson(done)) + return done + + def _bodyReceived(self, data): + dispatcher.send("input time",val=data['t']) + return data['t'] # pass along to the real receiver def seekplay_or_pause(self,t): - self.player.callRemote('seekplay_or_pause',t) + d = self.player.request("POST", + networking.musicUrl() + "seekPlayOrPause", bodyProducer=StringProducer(jsonlib.write({"t" : t}))) class Expr(object): """singleton, provides functions for use in subterm expressions, @@ -241,7 +276,6 @@ class Output: self.later = reactor.callLater(1,self.update) def update2(self,t): - # spot alsa soundcard offset is always 0, we get times about a # second ahead of what's really getting played #t = t - .7 diff --git a/bin/musictime b/bin/musictime --- a/bin/musictime +++ b/bin/musictime @@ -3,17 +3,19 @@ import run_local import light9.networking import Tkinter as tk -import xmlrpclib, socket, time +import time +import restkit, jsonlib class MusicTime: def __init__(self, url): - self.player = xmlrpclib.Server(url) + self.player = restkit.Resource(url) def get_music_time(self): playtime = None while not playtime: try: - playtime = self.player.gettime() - except socket.error, e: + playtime = jsonlib.read(self.player.get("time").body, + use_float=True)['t'] + except restkit.RequestError, e: print "Server error %s, waiting" % e time.sleep(2) return playtime diff --git a/bin/webcontrol b/bin/webcontrol --- a/bin/webcontrol +++ b/bin/webcontrol @@ -16,6 +16,7 @@ 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 diff --git a/light9/ascoltami/webapp.py b/light9/ascoltami/webapp.py --- a/light9/ascoltami/webapp.py +++ b/light9/ascoltami/webapp.py @@ -1,6 +1,6 @@ import web, jsonlib from twisted.python.util import sibpath -from light9.namespaces import L9, MUS +from light9.namespaces import L9 player = None graph = None @@ -9,6 +9,8 @@ show = None class root(object): def GET(self): web.header("Content-type", "application/xhtml+xml") + # todo: use a template; embed the show name and the intro/post + # times into the page return open(sibpath(__file__, "index.html")).read() class timeResource(object): @@ -49,6 +51,15 @@ class songResource(object): """post a uri of song to switch to (and start playing)""" player.setSong(web.data()) return "ok" + +class seekPlayOrPause(object): + def POST(self): + data = jsonlib.read(web.data(), use_float=True) + if player.isPlaying(): + player.pause() + else: + player.seek(data['t']) + player.resume() def makeApp(thePlayer, theGraph, theShow): global player, graph, show @@ -58,7 +69,7 @@ def makeApp(thePlayer, theGraph, theShow "/time", "timeResource", "/song", "songResource", "/songs", "songs", - "/api/position", "timeResource", # old + "/seekPlayOrPause", "seekPlayOrPause", ) app = web.application(urls, globals(), autoreload=False) diff --git a/light9/networking.py b/light9/networking.py --- a/light9/networking.py +++ b/light9/networking.py @@ -11,12 +11,8 @@ def dmxServerUrl(): def dmxServerPort(): return 8030 -def musicUrl(api='xmlrpc'): - site = "http://dash:%s/" % musicPort() - if api == 'rest': - return site + "api/" - else: - return site + "RPC2" +def musicUrl(): + return "http://dash:%s/" % musicPort() def musicPort(): return 8040 diff --git a/light9/showconfig.py b/light9/showconfig.py --- a/light9/showconfig.py +++ b/light9/showconfig.py @@ -80,8 +80,9 @@ def songOnDisk(song): showPath = graph.value(song, L9['showPath']) if not showPath: raise ValueError("no mpd path found for subject=%r" % song) - songFullPath = path.join(findMpdHome(), showPath) - return songFullPath + if showPath.startswith("file://"): + showPath = showPath[7:] + return showPath def songFilenameFromURI(uri): """