annotate bin/effecteval @ 1053:9937e2e3d17b

effecteval faster loop, stats page Ignore-this: d107f2e01d73fc6629249e5fec98cb85
author Drew Perttula <drewp@bigasterisk.com>
date Sun, 01 Jun 2014 10:05:50 +0000
parents b370618ce723
children 4595a82f5a90
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
1 #!bin/python
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
2 from __future__ import division
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
3 from run_local import log
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
4 from twisted.internet import reactor
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
5 from twisted.internet.defer import inlineCallbacks, returnValue
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
6 import cyclone.web, cyclone.websocket, cyclone.httpclient
1052
b370618ce723 split EffectNode out of effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1051
diff changeset
7 import sys, optparse, logging, subprocess, json, time, traceback
1051
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
8 from rdflib import URIRef, Literal
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
9
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
10 sys.path.append(".")
1033
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
11 from light9 import networking, showconfig, Submaster, dmxclient
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
12 from light9.rdfdb.syncedgraph import SyncedGraph
1052
b370618ce723 split EffectNode out of effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1051
diff changeset
13 from light9.namespaces import L9, RDF, RDFS
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
14 from light9.rdfdb.patch import Patch
1052
b370618ce723 split EffectNode out of effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1051
diff changeset
15 from light9.effecteval.effect import EffectNode
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
16 from light9.greplin_cyclone import StatsForCyclone
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
17 from greplin import scales
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
18
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
19 sys.path.append("/my/proj/homeauto/lib")
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
20 sys.path.append("/home/drewp/projects/homeauto/lib")
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
21 from cycloneerr import PrettyErrorHandler
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
22
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
23 class EffectEdit(cyclone.web.RequestHandler):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
24 def get(self):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
25 self.write(open("light9/effecteval/effect.html").read())
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
26
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
27 class SongEffects(PrettyErrorHandler, cyclone.web.RequestHandler):
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
28 def post(self):
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
29 song = URIRef(self.get_argument('uri'))
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
30 drop = URIRef(self.get_argument('drop'))
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
31 ctx = song
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
32 now = time.time()
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
33 effect = song + "/effect/e-%f" % now
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
34 curve = song + "/curve/c-%f" % now
1051
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
35
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
36 with self.settings.graph.currentState(
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
37 tripleFilter=(drop, RDFS.label, None)) as g:
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
38 dropSubLabel = g.label(drop)
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
39
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
40 self.settings.graph.patch(Patch(addQuads=[
1051
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
41 (song, L9['curve'], curve, ctx),
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
42 (song, L9['effect'], effect, ctx),
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
43 (effect, RDF.type, L9['Effect'], ctx),
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
44 (effect, L9['code'],
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
45 Literal('out = sub(%s, intensity=%s)' % (drop.n3(), curve.n3())),
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
46 ctx),
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
47 (curve, RDF.type, L9['Curve'], ctx),
1051
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
48 (curve, RDFS.label, Literal('sub %s' % dropSubLabel), ctx),
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
49 (curve, L9['points'], Literal('0 0'), ctx),
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
50 ]))
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
51
1043
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
52 class SongEffectsUpdates(cyclone.websocket.WebSocketHandler):
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
53 def connectionMade(self, *args, **kwargs):
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
54 self.graph = self.settings.graph
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
55 self.graph.addHandler(self.updateClient)
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
56
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
57 def updateClient(self):
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
58 # todo: abort if client is gone
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
59 playlist = self.graph.value(showconfig.showUri(), L9['playList'])
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
60 songs = list(self.graph.items(playlist))
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
61 out = []
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
62 for s in songs:
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
63 out.append({'uri': s, 'label': self.graph.label(s)})
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
64 out[-1]['effects'] = sorted(self.graph.objects(s, L9['effect']))
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
65 self.sendMessage({'songs': out})
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
66
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
67
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
68 class EffectUpdates(cyclone.websocket.WebSocketHandler):
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
69 """
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
70 stays alive for the life of the effect page
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
71 """
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
72 def connectionMade(self, *args, **kwargs):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
73 log.info("websocket opened")
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
74 self.uri = URIRef(self.get_argument('uri'))
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
75 self.sendMessage({'hello': repr(self)})
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
76
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
77 self.graph = self.settings.graph
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
78 self.graph.addHandler(self.updateClient)
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
79
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
80 def updateClient(self):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
81 # todo: if client has dropped, abort and don't get any more
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
82 # graph updates
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
83 self.sendMessage({'code': self.graph.value(self.uri, L9['code'])})
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
84
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
85 def connectionLost(self, reason):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
86 log.info("websocket closed")
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
87
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
88 def messageReceived(self, message):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
89 log.info("got message %s" % message)
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
90 # write a patch back to the graph
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
91
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
92
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
93 class EffectEval(PrettyErrorHandler, cyclone.web.RequestHandler):
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
94 @inlineCallbacks
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
95 def get(self):
1033
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
96 # return dmx list for that effect
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
97 uri = URIRef(self.get_argument('uri'))
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
98 response = yield cyclone.httpclient.fetch(
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
99 networking.musicPlayer.path('time'))
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
100 songTime = json.loads(response.body)['t']
1033
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
101
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
102 node = EffectNode(self.settings.graph, uri)
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
103 outSub = node.eval(songTime)
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
104 self.write(json.dumps(outSub.get_dmx_list()))
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
105
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
106
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
107 # Completely not sure where the effect background loop should
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
108 # go. Another process could own it, and get this request repeatedly:
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
109 class SongEffectsEval(PrettyErrorHandler, cyclone.web.RequestHandler):
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
110 def get(self):
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
111 song = URIRef(self.get_argument('song'))
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
112 effects = effectsForSong(self.settings.graph, song)
1033
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
113 raise NotImplementedError
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
114 self.write(maxDict(effectDmxDict(e) for e in effects))
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
115 # return dmx dict for all effects in the song, already combined
1033
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
116
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
117 class EffectLoop(object):
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
118 """maintains a collection of the current EffectNodes, gets time from
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
119 music player, sends dmx"""
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
120 def __init__(self, graph, stats):
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
121 self.graph, self.stats = graph, stats
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
122 self.currentSong = None
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
123 self.currentEffects = []
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
124 self.graph.addHandler(self.setEffects)
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
125 self.period = 1 / 30
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
126 self.coastSecs = .3 # main reason to keep this low is to notice play/pause
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
127
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
128 self.songTimeFromRequest = 0
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
129 self.requestTime = 0 # unix sec for when we fetched songTime
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
130 reactor.callLater(self.period, self.sendLevels)
1033
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
131
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
132 def setEffects(self):
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
133 self.currentEffects = []
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
134 if self.currentSong is None:
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
135 return
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
136
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
137 for effectUri in self.graph.objects(self.currentSong, L9['effect']):
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
138 self.currentEffects.append(EffectNode(self.graph, effectUri))
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
139
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
140 @inlineCallbacks
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
141 def getSongTime(self):
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
142 now = time.time()
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
143 if now - self.requestTime < self.coastSecs:
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
144 estimated = self.songTimeFromRequest
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
145 if self.currentSong is not None and self.currentPlaying:
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
146 estimated += now - self.requestTime
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
147 returnValue((estimated, self.currentSong))
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
148 else:
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
149 response = json.loads((yield cyclone.httpclient.fetch(
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
150 networking.musicPlayer.path('time'))).body)
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
151 self.requestTime = now
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
152 self.currentPlaying = response['playing']
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
153 self.songTimeFromRequest = response['t']
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
154 returnValue(
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
155 (response['t'], (response['song'] and URIRef(response['song']))))
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
156
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
157 @inlineCallbacks
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
158 def sendLevels(self):
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
159 t1 = time.time()
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
160 try:
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
161 with self.stats.sendLevels.time():
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
162 with self.stats.getMusic.time():
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
163 songTime, song = yield self.getSongTime()
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
164
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
165 if song != self.currentSong:
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
166 self.currentSong = song
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
167 # this may be piling on the handlers
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
168 self.graph.addHandler(self.setEffects)
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
169
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
170 if song is None:
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
171 return
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
172
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
173 outSubs = []
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
174 for e in self.currentEffects:
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
175 outSubs.append(e.eval(songTime))
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
176 out = Submaster.sub_maxes(*outSubs)
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
177
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
178 dmx = out.get_dmx_list()
1033
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
179
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
180 if log.isEnabledFor(logging.DEBUG):
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
181 log.debug("send dmx: %r", out.get_levels())
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
182
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
183 with self.stats.writeDmx.time():
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
184 yield dmxclient.outputlevels(dmx, twisted=True)
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
185
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
186 elapsed = time.time() - t1
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
187 dt = max(0, self.period - elapsed)
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
188 except Exception:
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
189 self.stats.errors.mark()
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
190 traceback.print_exc()
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
191 dt = 1
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
192
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
193 reactor.callLater(dt, self.sendLevels)
1033
b5ee7aa9341a effecteval now runs effects in the background, following the current song, and sends dmx output
Drew Perttula <drewp@bigasterisk.com>
parents: 1027
diff changeset
194
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
195 class App(object):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
196 def __init__(self, show):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
197 self.show = show
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
198 self.graph = SyncedGraph("effectEval")
1043
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
199 self.graph.initiallySynced.addCallback(self.launch)
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
200
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
201 self.stats = scales.collection('/',
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
202 scales.PmfStat('sendLevels'),
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
203 scales.PmfStat('getMusic'),
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
204 scales.PmfStat('writeDmx'),
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
205 scales.IntStat('errors'),
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
206 )
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
207
1043
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
208 def launch(self, *args):
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
209 self.loop = EffectLoop(self.graph, self.stats)
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
210
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
211 SFH = cyclone.web.StaticFileHandler
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
212 self.cycloneApp = cyclone.web.Application(handlers=[
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
213 (r'/()', SFH,
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
214 {'path': 'light9/effecteval', 'default_filename': 'index.html'}),
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
215 (r'/effect', EffectEdit),
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
216 (r'/(websocket\.js)', SFH, {'path': 'light9/rdfdb/web/'}),
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
217 (r'/effect\.js', StaticCoffee, {'src': 'light9/effecteval/effect.coffee'}),
1041
a4632a7b2e17 upgrade knockout and jquery, simplify the static/ dirs for all web services
Drew Perttula <drewp@bigasterisk.com>
parents: 1033
diff changeset
218 (r'/index\.js', StaticCoffee, {'src': 'light9/effecteval/index.coffee'}),
a4632a7b2e17 upgrade knockout and jquery, simplify the static/ dirs for all web services
Drew Perttula <drewp@bigasterisk.com>
parents: 1033
diff changeset
219 (r'/effectUpdates', EffectUpdates),
a4632a7b2e17 upgrade knockout and jquery, simplify the static/ dirs for all web services
Drew Perttula <drewp@bigasterisk.com>
parents: 1033
diff changeset
220 (r'/songEffectsUpdates', SongEffectsUpdates),
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
221 (r'/static/(.*)', SFH, {'path': 'static/'}),
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
222 (r'/effect/eval', EffectEval),
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
223 (r'/songEffects', SongEffects),
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
224 (r'/songEffects/eval', SongEffectsEval),
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
225 (r'/stats', StatsForCyclone),
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
226 ], debug=True, graph=self.graph, stats=self.stats)
1043
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
227 reactor.listenTCP(networking.effectEval.port, self.cycloneApp)
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
228 log.info("listening on %s" % networking.effectEval.port)
1053
9937e2e3d17b effecteval faster loop, stats page
Drew Perttula <drewp@bigasterisk.com>
parents: 1052
diff changeset
229
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
230 class StaticCoffee(PrettyErrorHandler, cyclone.web.RequestHandler):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
231 def initialize(self, src):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
232 super(StaticCoffee, self).initialize()
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
233 self.src = src
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
234 def get(self):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
235 self.set_header('Content-Type', 'application/javascript')
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
236 self.write(subprocess.check_output([
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
237 '/usr/bin/coffee', '--compile', '--print', self.src]))
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
238
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
239
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
240 if __name__ == "__main__":
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
241 parser = optparse.OptionParser()
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
242 parser.add_option('--show',
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
243 help='show URI, like http://light9.bigasterisk.com/show/dance2008',
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
244 default=showconfig.showUri())
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
245 parser.add_option("-v", "--verbose", action="store_true",
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
246 help="logging.DEBUG")
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
247 parser.add_option("--twistedlog", action="store_true",
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
248 help="twisted logging")
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
249 (options, args) = parser.parse_args()
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
250
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
251 log.setLevel(logging.DEBUG if options.verbose else logging.INFO)
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
252
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
253 if not options.show:
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
254 raise ValueError("missing --show http://...")
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
255
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
256 app = App(URIRef(options.show))
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
257 if options.twistedlog:
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
258 from twisted.python import log as twlog
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
259 twlog.startLogging(sys.stderr)
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
260 reactor.run()