Changeset - 8d6f6d8a4719
[Not reviewed]
default
0 6 0
drewp@bigasterisk.com - 15 years ago 2010-06-12 08:00:52
drewp@bigasterisk.com
clean up music client calls from curvecalc and musictime
Ignore-this: 4fd58f13cedae44ba9a21534ea127292
6 files changed with 78 insertions and 33 deletions:
0 comments (0 inline, 0 general)
bin/curvecalc
Show inline comments
 
@@ -14,14 +14,20 @@ import time,textwrap,math,random,os,optp
 
import Tix as tk
 
try:
 
    from dispatch import dispatcher
 
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
 
import logging
 
log = logging.getLogger()
 
logging.basicConfig(format="%(asctime)s %(levelname)-5s %(name)s %(filename)s:%(lineno)d: %(message)s")
 
@@ -34,39 +40,68 @@ from light9.zoomcontrol import Zoomcontr
 
from light9.curve import Curveset, Curvesetview
 
from light9.wavelength import wavelength
 
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,
 
    e.g. chases"""
 
    def __init__(self):
 
        self.effectGlobals = light9.Effects.configExprGlobals()
 
@@ -238,13 +273,12 @@ class Output:
 
        dispatcher.send("update status",val=e.getErrorMessage())
 
        if self.later and not self.later.cancelled and not self.later.called:
 
            self.later.cancel()
 
        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
 
        
 
        dispatcher.send("update status",
 
                        val="ok: receiving time from music player")
bin/musictime
Show inline comments
 
#!/usr/bin/env python
 
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
 

	
 
class MusicTimeTk(tk.Frame, MusicTime):
 
    def __init__(self, master, url):
bin/webcontrol
Show inline comments
 
@@ -13,12 +13,13 @@ 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(root, path, **args):
light9/ascoltami/webapp.py
Show inline comments
 
import web, jsonlib
 
from twisted.python.util import sibpath
 
from light9.namespaces import L9, MUS
 
from light9.namespaces import L9
 

	
 
player = None
 
graph = None
 
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):
 
    def GET(self):
 
        return jsonlib.write({"song" : player.playbin.get_property("uri"),
 
                              "started" : player.playStartTime,
 
@@ -46,20 +48,29 @@ class songs(object):
 

	
 
class songResource(object):
 
    def POST(self):
 
        """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
 
    player, graph, show = thePlayer, theGraph, theShow
 

	
 
    urls = ("/", "root",
 
            "/time", "timeResource",
 
            "/song", "songResource",
 
            "/songs", "songs",
 
            "/api/position", "timeResource", # old
 
            "/seekPlayOrPause", "seekPlayOrPause",
 
            )
 

	
 
    app = web.application(urls, globals(), autoreload=False)
 
    return app
light9/networking.py
Show inline comments
 
@@ -8,18 +8,14 @@ def dmxServerUrl():
 
    #url = "http://%s:8030" % host
 
    return "http://plus:%s" % dmxServerPort()
 

	
 
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
 

	
 
def mpdServer():
 
    """servername, port"""
light9/showconfig.py
Show inline comments
 
@@ -77,14 +77,15 @@ def songInMpd(song):
 
def songOnDisk(song):
 
    """given a song URI, where's the on-disk file that mpd would read?"""
 
    graph = getGraph()
 
    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):
 
    """
 
    'http://light9.bigasterisk.com/show/dance2007/song8' -> 'song8'
 

	
 
    everything that uses this should be deprecated for real URIs
0 comments (0 inline, 0 general)