Skip to content

Commit 008bc28

Browse files
on my way ...
1 parent 09ab182 commit 008bc28

File tree

7 files changed

+129
-153
lines changed

7 files changed

+129
-153
lines changed

examples/default.graa

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ delete("d")
1919
expand(circle(2, "guu1|dirt~4:bass:1", "guu1-500->guu1"))
2020

2121
add("""
22-
guu1|dirt~4:bass:0,
22+
guu1|dirt~4:bass:0|disk~c4:100:100,
2323
guu2|dirt~4:bass:1,
2424
guu3|dirt~4:bass:2,
25-
guu1-256:60->guu2,
26-
guu2-256:100->guu1,
27-
guu1-256:40->guu3,
28-
guu3-256:40->guu3,
29-
guu3-256:60->guu1
25+
26+
guu2--256|add<dur:10>%25|add<prob:10>-->guu1,
27+
guu1-256->guu3,
28+
guu3--256%40-->guu3,
29+
guu3--256%60-->guu1
30+
3031
""")
3132

3233
play("gaa")

graa.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
# centralized clock for collaborative graaing ?
77
# node locking mode ? (give nodes a duration ?)
88
# configurable resolution for non-realtime systems ? how, if it's strongly timed ... :(
9+
# !!! give up division between graphs and overlays ??
10+
# !!!! graa language functions controlled by graphs - recursion and stuff ???
11+
# !! if recursion, instances ? or overlay on every instance ??
12+
# !! inject functions into nodes ????
913

1014
# TO BE DONE (for next releases ...)
1115
# tbd: fix "lag" when manipulating graphs !!

graa_base.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,24 @@ def resume(self):
4848
self.play()
4949
def add_overlay(self, overlay_id):
5050
# add a copy of the overlay, as each overlay should act independent for each player
51-
self.overlays[overlay_id] = copy.deepcopy(session.overlays[overlay_id])
51+
self.overlays[overlay_id] = copy.deepcopy(session.graphs[overlay_id])
5252
def add_permalay(self, permalay_id):
5353
# add a copy of the overlay, as each overlay should act independent for each player
54-
self.permalays[permalay_id] = copy.deepcopy(session.overlays[permalay_id])
54+
self.permalays[permalay_id] = copy.deepcopy(session.graphs[permalay_id])
5555
def remove_overlay(self, overlay_id):
5656
del self.overlays[overlay_id]
5757
def remove_permalay(self, permalay_id):
5858
del self.permalays[permalay_id]
5959
def update_overlay(self, overlay_id):
6060
current_overlay = self.overlays[overlay_id]
61-
updated_overlay = copy.deepcopy(session.overlays[overlay_id])
61+
updated_overlay = copy.deepcopy(session.graphs[overlay_id])
6262
# update current node and step counter
6363
updated_overlay.current_node_id = current_overlay.current_node_id
6464
updated_overlay.nodes[updated_overlay.current_node_id].meta = current_overlay.nodes[current_overlay.current_node_id].meta
6565
self.overlays[overlay_id] = updated_overlay
6666
def update_permalay(self, permalay_id):
6767
current_permalay = self.permalays[permalay_id]
68-
updated_permalay = copy.deepcopy(session.overlays[permalay_id])
68+
updated_permalay = copy.deepcopy(session.graphs[permalay_id])
6969
# update current node and step counter
7070
updated_permalay.current_node_id = current_permalay.current_node_id
7171
updated_permalay.nodes[updated_permalay.current_node_id].meta = current_permalay.nodes[current_permalay.current_node_id].meta
@@ -97,7 +97,7 @@ def play(self, *args, **kwargs):
9797
# otherwise, just eval the current node
9898
self.eval_node(current_node, overlay_infos, permalay_infos)
9999
# collect current nodes and edges from over- and permalays
100-
def collect_overlay_infos(self, lays):
100+
def collect_edge_mod_infos(self, lays):
101101
current_lay_dicts = []
102102
current_lay_steps = []
103103
dur_modificators = []

graa_dispatcher.py

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
class GraaDispatcher():
1111
def __init__(self):
1212
self.dispatcher_map = {}
13-
self.dispatcher_map[parser.OVERLAY_NODE] = self.dispatch_overlay_node
14-
self.dispatcher_map[parser.NORMAL_NODE] = self.dispatch_normal_node
13+
self.dispatcher_map[parser.NODE] = self.dispatch_node
1514
self.dispatcher_map[parser.EDGE] = self.dispatch_edge
1615
# The main dispatcher function, bridge between parser and code execution
1716
def dispatch(self, parser_output):
@@ -21,47 +20,9 @@ def dispatch(self, parser_output):
2120
except KeyError:
2221
log.action("Can't dispatch '{}', no dispatcher present!".format(elem))
2322
except DispatcherError as de:
24-
log.action(de.message)
25-
# dispatch overlay output from parser
26-
def dispatch_overlay_node(self, ol_id, ol_node):
27-
if ol_id in session.graphs:
28-
raise DispatcherError("Can't add overlay element to a graph!")
29-
if ol_id not in session.overlays:
30-
session.overlays[ol_id] = Graph()
31-
log.action("Initialized overlay with id: '{}'".format(ol_id))
32-
#initialize step counter with 0
33-
ol_node.meta = 0
34-
session.overlays[ol_id].add_node(ol_node)
35-
# updating player copies of overlays
36-
for player_id in session.players:
37-
if ol_id in session.players[player_id].overlays:
38-
session.players[player_id].update_overlay(ol_id)
39-
if ol_id in session.players[player_id].permalays:
40-
session.players[player_id].update_permalay(ol_id)
41-
log.action("Adding node: {} to overlay: '{}'".format(ol_node, ol_id))
42-
def dispatch_edge(self, graph_id, edge, src):
43-
if graph_id in session.overlays:
44-
self.dispatch_overlay_edge(graph_id, edge, src)
45-
elif graph_id in session.graphs:
46-
self.dispatch_normal_edge(graph_id, edge, src)
47-
else:
48-
raise DispatcherError("Graph '{}' not present, can't add edge!".format(ol_id))
49-
def dispatch_overlay_edge(self, ol_id, ol_edge, src):
50-
overlay = session.overlays[ol_id]
51-
if src not in overlay.nodes or ol_edge.dest not in overlay.nodes:
52-
raise DispatcherError("Invalid overlay edge, source or destination node not present! Src: '{}' Dest: '{}'".format(src, ol_edge.dest))
53-
overlay.add_edge(src, ol_edge)
54-
# updating player copies of overlays
55-
for player_id in session.players:
56-
if ol_id in session.players[player_id].overlays:
57-
session.players[player_id].update_overlay(ol_id)
58-
if ol_id in session.players[player_id].permalays:
59-
session.players[player_id].update_permalay(ol_id)
60-
log.action("Adding edge: '{}' to overlay: '{}'".format(ol_edge, ol_id))
23+
log.action(de.message)
6124
# dispatch command to add a normal graph node
62-
def dispatch_normal_node(self, graph_id, node):
63-
if graph_id in session.overlays:
64-
raise DispatcherError("Can't add graph element to overlay!")
25+
def dispatch_node(self, graph_id, node):
6526
if graph_id not in session.graphs:
6627
session.graphs[graph_id] = Graph()
6728
log.action("Initialized graph with id: '{}'".format(graph_id))
@@ -74,7 +35,7 @@ def dispatch_normal_node(self, graph_id, node):
7435
except KeyError as e:
7536
log.action(" No player copy for graph: '{}', not updating!".format(graph_id))
7637
log.action("Adding node: '{}' to graph: '{}'".format(node, graph_id))
77-
def dispatch_normal_edge(self, graph_id, edge, src):
38+
def dispatch_edge(self, graph_id, edge, src):
7839
if graph_id not in session.graphs:
7940
raise DispatcherError("Graph '{}' not present, can't add edge!".format(graph_id))
8041
graph = session.graphs[graph_id]

graa_parser.py

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77

88
class GraaParser():
99
# command constants for dispatcher
10-
EDGE = "edge"
11-
OVERLAY_NODE = "ol_node"
12-
NORMAL_NODE = "n_node"
10+
EDGE = "edge"
11+
NODE = "node"
1312
# some literals
1413
PARAM_DIVIDER = Suppress(Literal(":"))
1514
LPAREN = Suppress(Literal("<"))
@@ -30,27 +29,29 @@ class GraaParser():
3029
lvar = Word("$." + alphanums)
3130
graph_id = Word(alphas)
3231
node_id = graph_id + Word(nums).setParseAction(lambda t: GraaParser.typify(t[0]))
33-
node_type = Word(alphanums)
34-
func_id = Word(alphanums)
3532
# function parsing
3633
func = Forward()
3734
param = gvar ^ ivar ^ pitch ^ lvar.setParseAction(lambda t: GraaParser.typify(t[0])) ^ func
3835
func_param = ZeroOrMore(param + Optional(PARAM_DIVIDER))
39-
func << func_id + LPAREN + func_param + RPAREN
36+
func << Word(alphanums) + LPAREN + func_param + RPAREN
4037
func.setParseAction(lambda t: GraaParser.parse_func(t.asList()))
4138
assign = lvar + Suppress("=") + param
4239
assign.setParseAction(lambda t: GraaParser.parse_assign(t.asList()))
4340
# node definitions
44-
ol_node_def = node_id + Suppress("|") + OneOrMore((assign + Optional(PARAM_DIVIDER)) ^ Literal("nil") ^ Literal("mute") ^ Literal("unmute"))
45-
ol_node_def.setParseAction(lambda t: GraaParser.parse_ol_node(t))
46-
node_def = node_id + Suppress("|") + node_type + Suppress("~") + Group(ZeroOrMore((gvar ^ ivar ^ pitch ^ lvar ^ assign) + Optional(PARAM_DIVIDER)))
41+
sound_func = Word(alphas) + "~" + Group(ZeroOrMore((gvar ^ ivar ^ pitch ^ lvar ^ assign) + Optional(PARAM_DIVIDER)))
42+
mod_func = assign + Optional(PARAM_DIVIDER)
43+
ctrl_func = Word(alphas) + "#" + Group(ZeroOrMore((gvar ^ ivar ^ pitch ^ lvar ^ assign) + Optional(PARAM_DIVIDER)))
44+
slot = Suppress("|") + Group(sound_func ^ mod_func ^ ctrl_func)
45+
node_def = node_id + OneOrMore(slot)
4746
node_def.setParseAction(lambda t: GraaParser.parse_node(t))
48-
#edge definitions
49-
transition = Group((Literal("nil") ^ param) + Optional(PARAM_DIVIDER + param))
50-
edge_def = node_id + Optional(Suppress("-") + transition) + Suppress("->") + node_id
47+
#edge definitions
48+
trans_dur = Group((param ^ Literal("nil")) + Optional(Suppress("|") + param))
49+
trans_prob = Group(Literal("%") + (param ^ Literal("nil")) + Optional(Suppress("|") + param))
50+
transition = Suppress("--") + Group(Optional(trans_dur) + Optional(trans_prob)) + Suppress("-->")
51+
edge_def = node_id + (transition ^ Suppress("-->")) + node_id
5152
edge_def.setParseAction(lambda t: GraaParser.parse_edge(t))
5253
# line definition
53-
line = node_def ^ edge_def ^ ol_node_def
54+
line = node_def ^ edge_def
5455
line.setParseAction(lambda t: t.asList())
5556
# convert string representation to actual (typed) value
5657
def typify(arg):
@@ -74,7 +75,7 @@ def parse_ivar(arg):
7475
return getattr(__main__, arg[0][0])
7576
def parse_func(arg):
7677
#print(arg)
77-
return Func(arg[0], arg[1:], {})
78+
return Func("misc", arg[0], arg[1:], {})
7879
def parse_assign(arg):
7980
return {arg[0] : arg[1]}
8081
def parse_pitch(arg):
@@ -91,56 +92,57 @@ def parse_duration(arg):
9192
pass
9293
#tbd
9394
def parse_node(arg):
95+
print("NODE: " + str(arg))
9496
graph_id = arg[0]
9597
node_id = arg[1]
96-
node_params = Func(arg[2], [], {})
97-
for param in arg[3]:
98-
if isinstance(param, dict):
99-
node_params.kwargs.update(param)
98+
node_params = []
99+
for param in arg[2:]:
100+
if isinstance(param[0], dict):
101+
node_params.append(param[0])
100102
else:
101-
node_params.args.append(param)
103+
kwargs = {}
104+
args = []
105+
for arg in param[2]:
106+
if type(arg) is dict:
107+
kwargs.update(arg)
108+
else:
109+
args.append(arg)
110+
node_params.append(Func(param[1], param[0], args, kwargs))
102111
# create and return node
103-
return (GraaParser.NORMAL_NODE, graph_id, Node(graph_id, node_id, node_params))
104-
def parse_ol_node(arg):
105-
#print(arg)
106-
graph_id = arg[0]
107-
node_id = arg[1]
108-
node_params = {}
109-
for param in arg[2:]:
110-
if type(param) is str:
111-
node_params = param
112-
else:
113-
node_params.update(param)
114-
node = Node(graph_id, node_id, node_params)
115-
return (GraaParser.OVERLAY_NODE, graph_id, node)
112+
return (GraaParser.NODE, graph_id, Node(graph_id, node_id, node_params))
116113
def parse_edge(arg):
117-
#print(arg)
114+
print("EDGE: " + str(arg))
118115
graph_id = arg[0]
119116
source_node_id = arg[1]
120117
destination_node_id = arg[-1]
121-
edge = None
118+
edge = Edge(graph_id, source_node_id, destination_node_id)
122119
if(len(arg) == 5):
123-
transition = arg[2]
124-
edge = Edge(graph_id, source_node_id, destination_node_id, transition[0])
125-
if len(transition) == 2:
126-
edge.prob = transition[1]
127-
else:
128-
edge = Edge(graph_id, source_node_id, destination_node_id, None)
120+
transition = arg[2]
121+
for elem in transition:
122+
if elem[0] == "%":
123+
if elem[1] != "nil":
124+
edge.prob = elem[1]
125+
if len(elem) == 3:
126+
edge.prob_mod = elem[2]
127+
else:
128+
if elem[0] != "nil":
129+
edge.dur = elem[0]
130+
if len(elem) == 2:
131+
edge.dur_mod = elem[1]
129132
return (GraaParser.EDGE, graph_id, edge, source_node_id)
130133
def parse(arg):
131134
return GraaParser.line.parseString(arg)
132135

133136

134137
if __name__ == "__main__":
135-
#print(GraaParser.param.parseString("4"))
136-
#print(GraaParser.func.parseString("add<add<$3:4>:%as:4>"))
137-
#print(GraaParser.assign.parseString("$3=add<add<$3:4>:%as:>"))
138-
#print(GraaParser.assign.parseString("$step=5"))
139-
#print(GraaParser.node_def.parseString("d1|dirt~0:db:1:$gain=5"))
140-
#print(GraaParser.ol_node_def.parseString("d1|$3=add<$3:1>:$2=add<$2:1>"))
141-
#print("STRING: d1-add<$dur:add<1:%as>:4>:100->d1")
142-
#print(GraaParser.edge_def.parseString("d1-add<$dur:add<1:%as>:4>:100->d1"))
143-
#print(GraaParser.edge_def.parseString("d1->d1"))
144-
#print(GraaParser.line.parseString("d1-%t:100->d1"))
145-
#print(GraaParser.line.parseString("d1|rebuzz~150:100:245:$gain=10"))
146-
print(GraaParser.func.parseString("bounds<brownian<60:1>:500:300>"))
138+
#print(GraaParser.edge_def.parseString("guu1-->guu2"))
139+
#print(GraaParser.edge_def.parseString("guu1--500-->guu2"))
140+
#print(GraaParser.edge_def.parseString("guu1--%50-->guu2"))
141+
#print(GraaParser.edge_def.parseString("guu1--500%25-->guu2"))
142+
#print(GraaParser.edge_def.parseString("guu1--512|add<dur:25>-->guu2"))
143+
#print(GraaParser.edge_def.parseString("guu1--512|add<dur:25>%25-->guu2"))
144+
#print(GraaParser.edge_def.parseString("guu1--%25|add<prob:10>-->guu2"))
145+
#print(GraaParser.edge_def.parseString("guu1--512|add<dur:25>%25|add<prob:10>-->guu2"))
146+
print(GraaParser.edge_def.parseString("guu1--nil|add<dur:25>%25|add<prob:10>-->guu2"))
147+
print(GraaParser.edge_def.parseString("guu1--512|add<dur:25>%nil|add<prob:10>-->guu2"))
148+
#print(GraaParser.node_def.parseString("guu1|disk~c4:500:50:gain=0.05:acc=0.5|play#guu:gaa|$3=add<$3:4>"))

graa_session.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ class GraaSession():
1111
delay = 4
1212
graphs = {}
1313
players = {}
14-
overlays = {}
1514
# 117bpm results in 512ms per beat ... a nice, round number!
1615
tempo = 117
16+
# one beat as default
17+
default_duration = 512
1718
active = False
1819
# the 'executors' to render the statements to time
1920
beat = None

0 commit comments

Comments
 (0)