annotate bin/effecteval @ 1051:be016cd5e5c5

effecteval names its new curve after the sub you drop on it Ignore-this: e1d00b8519515373d846ac78dfbd95d1
author Drew Perttula <drewp@bigasterisk.com>
date Thu, 29 May 2014 08:06:15 +0000
parents a2081b9adfe4
children b370618ce723
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
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
2 from run_local import log
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
3 from twisted.internet import reactor, task
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
4 from twisted.internet.defer import inlineCallbacks
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
5 import cyclone.web, cyclone.websocket, cyclone.httpclient
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
6 import sys, optparse, logging, subprocess, json, re, 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
7 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
8
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
9 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
10 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
11 from light9.rdfdb.syncedgraph import SyncedGraph
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
12 from light9.curvecalc.curve import Curve
1051
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
13 from light9.namespaces import L9, DCTERMS, 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
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
15
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
16 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
17 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
18 from cycloneerr import PrettyErrorHandler
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
19
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
20 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
21 def get(self):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
22 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
23
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
24 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
25 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
26 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
27 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
28 ctx = song
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
29 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
30 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
31 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
32
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
33 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
34 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
35 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
36
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
37 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
38 (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
39 (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
40 (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
41 (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
42 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
43 ctx),
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
44 (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
45 (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
46 (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
47 ]))
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
48
1043
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
49 class SongEffectsUpdates(cyclone.websocket.WebSocketHandler):
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
50 def connectionMade(self, *args, **kwargs):
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
51 self.graph = self.settings.graph
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
52 self.graph.addHandler(self.updateClient)
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
53
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
54 def updateClient(self):
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
55 # todo: abort if client is gone
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
56 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
57 songs = list(self.graph.items(playlist))
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
58 out = []
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
59 for s in songs:
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
60 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
61 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
62 self.sendMessage({'songs': out})
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
63
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
64
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
65 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
66 """
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
67 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
68 """
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
69 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
70 log.info("websocket opened")
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
71 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
72 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
73
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
74 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
75 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
76
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
77 def updateClient(self):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
78 # 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
79 # graph updates
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
80 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
81
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
82 def connectionLost(self, reason):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
83 log.info("websocket closed")
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 messageReceived(self, message):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
86 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
87 # write a patch back to the graph
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
88
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
89 def uriFromCode(s):
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
90 # i thought this was something a graph could do with its namespace manager
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
91 if s.startswith('sub:'):
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
92 return URIRef('http://light9.bigasterisk.com/show/dance2014/sub/' + s[4:])
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
93 if s.startswith('song1:'):
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
94 return URIRef('http://ex/effect/song1/' + s[6:])
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
95 if (s[0], s[-1]) == ('<', '>'):
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
96 return URIRef(s[1:-1])
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
97 raise NotImplementedError
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
98
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
99 class EffectNode(object):
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
100 def __init__(self, graph, uri):
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
101 self.graph, self.uri = graph, uri
1051
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
102 # this is not expiring at the right time, when an effect goes away
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
103 self.graph.addHandler(self.prepare)
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
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 def prepare(self):
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 self.code = self.graph.value(self.uri, L9['code'])
1051
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
107 if self.code is None:
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
108 raise ValueError("effect %s has no code" % self.uri)
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
109 m = re.match(r'^out = sub\((.*?), intensity=(.*?)\)', self.code)
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
110 if not m:
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
111 raise NotImplementedError
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
112 subUri = uriFromCode(m.group(1))
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 subs = Submaster.get_global_submasters(self.graph)
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
114 self.sub = subs.get_sub_by_uri(subUri)
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
115
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 intensityCurve = uriFromCode(m.group(2))
1051
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
117 self.curve = Curve(uri=intensityCurve)
1043
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
118
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
119 # read from disk ok? how do we know to reread? start with
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
120 # mtime. the mtime check could be done occasionally so on
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
121 # average we read at most one curve's mtime per effectLoop.
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
122
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
123 pts = self.graph.value(intensityCurve, L9['points'])
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
124 if pts is None:
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
125 log.info("curve %r has no points" % intensityCurve)
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
126 else:
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
127 self.curve.set_from_string(pts)
1043
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
128
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
129
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
130 def eval(self, 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
131 # consider http://waxeye.org/ for a parser that can be used in py and js
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
132 level = self.curve.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
133 scaledSubs = self.sub * level
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
134 return scaledSubs
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
135
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
136
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
137 class EffectEval(PrettyErrorHandler, cyclone.web.RequestHandler):
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
138 @inlineCallbacks
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
139 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
140 # return dmx list for that effect
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
141 uri = URIRef(self.get_argument('uri'))
1027
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
142 response = yield cyclone.httpclient.fetch(
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
143 networking.musicPlayer.path('time'))
a38414bd3929 hacking on effecteval
Drew Perttula <drewp@bigasterisk.com>
parents: 1019
diff changeset
144 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
145
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
146 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
147 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
148 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
149
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
150
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
151 # 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
152 # go. Another process could own it, and get this request repeatedly:
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
153 class SongEffectsEval(PrettyErrorHandler, cyclone.web.RequestHandler):
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
154 def get(self):
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
155 song = URIRef(self.get_argument('song'))
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
156 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
157 raise NotImplementedError
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
158 self.write(maxDict(effectDmxDict(e) for e in effects))
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
159 # 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
160
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
161 # Or, we could own that loop, like this:
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
162 @inlineCallbacks
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
163 def effectLoop(graph):
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
164 t1 = time.time()
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
165 try:
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
166 response = json.loads((yield cyclone.httpclient.fetch(
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
167 networking.musicPlayer.path('time'))).body)
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
168 if response['song'] is not None:
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
169 song = URIRef(response['song'])
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
170 songTime = response['t']
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
171 # Possibilities to make this shut up about graph copies:
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
172 # - implement the cheap readonly currentState response
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
173 # - do multiple little currentState calls (in this code) over just
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
174 # the required triples
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
175 # - use addHandler instead and only fire dmx when there is a data
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
176 # change (and also somehow call it when there is a time change)
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
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 outSubs = []
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
179 with graph.currentState(tripleFilter=(song, L9['effect'], None)) as g:
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
180 for effectUri in g.objects(song, L9['effect']):
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
181 # these should be built once, not per (frequent) update
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
182 node = EffectNode(graph, effectUri)
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
183 outSubs.append(node.eval(songTime))
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
184 out = Submaster.sub_maxes(*outSubs)
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
185 # out.get_levels() for a more readable view
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
186 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
187
1044
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
188 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
189 log.debug("send dmx: %r", out.get_levels())
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
190 yield dmxclient.outputlevels(dmx, twisted=True)
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
191 except Exception:
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
192 traceback.print_exc()
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
193 time.sleep(1)
a2081b9adfe4 effecteval now takes dropped subs and makes new effects out of them
Drew Perttula <drewp@bigasterisk.com>
parents: 1043
diff changeset
194
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
195 loopTime = time.time() - t1
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
196 log.debug('loopTime %.1f ms', 1000 * loopTime)
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
197
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
198 class App(object):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
199 def __init__(self, show):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
200 self.show = show
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
201 self.graph = SyncedGraph("effectEval")
1043
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
202 self.graph.initiallySynced.addCallback(self.launch)
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
203
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
204 def launch(self, *args):
1051
be016cd5e5c5 effecteval names its new curve after the sub you drop on it
Drew Perttula <drewp@bigasterisk.com>
parents: 1044
diff changeset
205 task.LoopingCall(effectLoop, self.graph).start(.3)
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
206 SFH = cyclone.web.StaticFileHandler
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
207 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
208 (r'/()', SFH,
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
209 {'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
210 (r'/effect', EffectEdit),
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
211 (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
212 (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
213 (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
214 (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
215 (r'/songEffectsUpdates', SongEffectsUpdates),
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
216 (r'/static/(.*)', SFH, {'path': 'static/'}),
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
217 (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
218 (r'/songEffects', SongEffects),
1019
5939fce98fad notes for next step
drewp@bigasterisk.com
parents: 1018
diff changeset
219 (r'/songEffects/eval', SongEffectsEval),
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
220 ], debug=True, graph=self.graph)
1043
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
221 reactor.listenTCP(networking.effectEval.port, self.cycloneApp)
aa45e5379c5a effecteval improvements. displays current song+effect tree
Drew Perttula <drewp@bigasterisk.com>
parents: 1041
diff changeset
222 log.info("listening on %s" % networking.effectEval.port)
1018
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
223
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
224 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
225 def initialize(self, src):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
226 super(StaticCoffee, self).initialize()
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
227 self.src = src
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
228 def get(self):
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
229 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
230 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
231 '/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
232
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
233
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
234 if __name__ == "__main__":
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
235 parser = optparse.OptionParser()
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
236 parser.add_option('--show',
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
237 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
238 default=showconfig.showUri())
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
239 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
240 help="logging.DEBUG")
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
241 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
242 help="twisted logging")
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
243 (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
244
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
245 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
246
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
247 if not options.show:
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
248 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
249
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
250 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
251 if options.twistedlog:
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
252 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
253 twlog.startLogging(sys.stderr)
e28a443bd153 initial effecteval that can propagate changes from the graph to a web page
drewp@bigasterisk.com
parents:
diff changeset
254 reactor.run()