Skip to content

Commit 7bfe6ab

Browse files
committed
added loop flag, metronome example
1 parent 2ed2149 commit 7bfe6ab

File tree

5 files changed

+85
-11
lines changed

5 files changed

+85
-11
lines changed

decadence.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
decadence.py song.dc play song
99
1010
Usage:
11-
decadence.py [--dev=<device> | --verbose | --midi=<fn> | --ring | --follow | --csound | --supercollider] [-eftnpsrxhv] [SONGNAME]
12-
decadence.py [+RANGE] [--dev=<device> | --midi=<fn> | --ring | --follow | --csound | --supercollider] [-eftnpsrxhv] [SONGNAME]
11+
decadence.py [--dev=<device> | --verbose | --midi=<fn> | --ring | --follow | --csound | --supercollider | --loop] [-eftnpsrxhv] [SONGNAME]
12+
decadence.py [+RANGE] [--dev=<device> | --midi=<fn> | --ring | --follow | --csound | --supercollider | --loop] [-eftnpsrxhv] [SONGNAME]
1313
decadence.py -c [COMMANDS ...]
1414
decadence.py -l [LINE_CONTENT ...]
1515
@@ -26,6 +26,7 @@
2626
-l execute commands simultaenously
2727
-r --remote (STUB) remote/daemon mode, keep alive
2828
--ring don't mute midi on end
29+
--loop loop song
2930
--midi=<fn> generate midi file
3031
+<range> play from line or maker, for range use start:end
3132
-e --edit (STUB) open file in editor
@@ -103,6 +104,7 @@
103104
elif arg == '--edit': pass
104105
elif arg == '-l' and val: dc.dcmode = 'l'
105106
elif arg == '-c' and val: dc.dcmode = 'c'
107+
elif arg == '--loop': dc.add_flags(Player.Flag.LOOP)
106108

107109
if dc.dcmode=='l':
108110
dc.buf = ' '.join(ARGS['LINE_CONTENT']).split(';') # ;

examples/metronome.dc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
%n=8 p=drums c10,-2 f=loop
2+
1
3+
b5
4+
3
5+
b5

src/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
CCHAR_START = 'TV' # control chars
4343
PRINT = True
4444

45+
def bit(x):
46+
return 1 << x
4547
def cmp(a,b):
4648
return bool(a>b) - bool(a<b)
4749
def sgn(a):

src/player.py

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@ def __init__(self, row, caller, count):
1313
# self.returns[row] = 0
1414

1515
class Player:
16+
17+
class Flag:
18+
ROMAN = bit(0)
19+
TRANSPOSE = bit(1)
20+
LOOP = bit(2)
21+
FLAGS = [
22+
'roman',
23+
'transpose',
24+
'loop'
25+
]
26+
# FLAGS = set([
27+
# 'roman', # STUB: fit roman chord in scale shape
28+
# 'transpose', # allow transposition of note letters
29+
# 'loop'
30+
# ])
31+
1632
def __init__(self):
1733
self.quitflag = False
1834
self.vimode = False
@@ -62,6 +78,35 @@ def __init__(self):
6278
self.last_follow = 0
6379
self.last_marker = -1
6480
self.midifile = None
81+
self.flags = 0
82+
83+
def add_flags(self, f):
84+
if isinstance(f, basestring):
85+
f = 1 << self.FLAGS.index(f)
86+
elif isinstance(f, int):
87+
assert f > 0
88+
else:
89+
for e in f:
90+
self.add_flags(e)
91+
return
92+
self.flags |= f
93+
def has_flags(self, f):
94+
if isinstance(f, basestring):
95+
f = 1 << self.FLAGS.index(f)
96+
elif isinstance(f, int):
97+
assert f > 0
98+
else:
99+
vals = f
100+
f = 0
101+
i = 0
102+
for e in self.FLAGS:
103+
if e in vals:
104+
f |= 1 << i
105+
i += 1
106+
# for e in vals:
107+
# f |= 1 << self.FLAGS.index(e)
108+
return
109+
return self.flags & f
65110

66111
def follow(self):
67112
if self.startrow==-1 and self.canfollow:
@@ -100,6 +145,10 @@ def run(self):
100145
self.buf = []
101146
raise IndexError
102147
except IndexError:
148+
if self.has_flags(Player.Flag.LOOP):
149+
self.row = 0
150+
continue
151+
103152
self.row = len(self.buf)
104153
# done with file, finish playing some stuff
105154

@@ -196,7 +245,7 @@ def run(self):
196245
if tok[0]==' ':
197246
tok = tok[1:]
198247
var = tok[0].upper()
199-
if var in 'TGXNPSRCKO': # global vars %
248+
if var in 'TGXNPSRCKOF': # global vars %
200249
cmd = tok.split(' ')[0]
201250
op = cmd[1]
202251
try:
@@ -277,8 +326,9 @@ def run(self):
277326
else:
278327
self.tracks[i].patch(p)
279328
elif var=='F': # flags
280-
for i in range(len(vals)):
281-
self.tracks[i].add_flags(val.split(','))
329+
self.add_flags(val.split(','))
330+
# for i in range(len(vals)): # TODO: ?
331+
# self.tracks[i].add_flags(val.split(','))
282332
elif var=='O':
283333
self.octave = int(val)
284334
elif var=='K':

src/track.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ def reset(self):
2525
self.sustain_notes = [False] * RANGE
2626

2727
class Track(Lane):
28-
FLAGS = set([
28+
class Flag:
29+
ROMAN = bit(0)
30+
# TRANSPOSE = bit(1)
31+
FLAGS = [
2932
'roman', # STUB: fit roman chord in scale shape
30-
'transpose', # allow transposition of note letters
31-
])
33+
# 'transpose', # allow transposition of note letters
34+
]
3235
def __init__(self, ctx, idx, midich):
3336
Lane.__init__(self,ctx,idx,midich)
3437
# self.players = [player]
@@ -76,7 +79,7 @@ def reset(self):
7679
self.use_sustain_pedal = False # whether to use midi sustain instead of track
7780
self.sustain_pedal_state = False # current midi pedal state
7881
# self.schedule.clear_channel(self)
79-
self.flags = set()
82+
self.flags = 0 # set()
8083
self.enabled = True
8184
self.soloed = False
8285
self.volval = 1.0
@@ -106,9 +109,21 @@ def refresh(self):
106109
self.volume(self.volval)
107110
self.ccs[7] = v
108111
def add_flags(self, f):
109-
if f != f & FLAGS:
110-
raise ParseError('invalid flags')
112+
if isinstance(f, str):
113+
f = 1 << FLAGS.index(f)
114+
else:
115+
assert f > 0
116+
# if f != f & FLAGS:
117+
# raise ParseError('invalid flags')
111118
self.flags |= f
119+
def has_flags(self, f):
120+
if isinstance(f, str):
121+
f = 1 << FLAGS.index(f)
122+
else:
123+
assert f > 0
124+
# if f != f & FLAGS:
125+
# raise ParseError('invalid flags')
126+
return self.flags & f
112127
def enable(self, v=True):
113128
was = v
114129
if not was and v:

0 commit comments

Comments
 (0)