Skip to content

Commit c7c6f1a

Browse files
authored
Merge pull request #10 from flipcoder/vjp/refactor-player-pt2
Vjp/refactor player pt2
2 parents e3ee591 + 974a2ae commit c7c6f1a

File tree

1 file changed

+204
-162
lines changed

1 file changed

+204
-162
lines changed

textbeat/player.py

Lines changed: 204 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -343,168 +343,10 @@ async def run(self):
343343

344344
# TODO: global 'silent' commands (doesn't consume time)
345345
if self.line.startswith('%'):
346-
self.line = self.line[1:].strip() # remove % and spaces
347-
for tok in self.line.split(' '):
348-
if not tok:
349-
break
350-
if tok[0]==' ':
351-
tok = tok[1:]
352-
var = tok[0].upper()
353-
if var in 'TGXNPSRCKFDR': # global vars %
354-
cmd = tok.split(' ')[0]
355-
op = cmd[1]
356-
try:
357-
val = cmd[2:]
358-
except:
359-
val = ''
360-
# log("op val %s %s" % (op,val))
361-
if op == ':': op = '='
362-
if not op in '*/=-+':
363-
# implicit =
364-
val = str(op) + str(val)
365-
op='='
366-
if not val or op=='.':
367-
val = op + val # append
368-
# TODO: add numbers after dots like other ops
369-
if val[0]=='.':
370-
note_value(val)
371-
ct = count_seq(val)
372-
val = pow(0.5,count)
373-
op = '/'
374-
num,ct = peel_uint(val[:ct])
375-
elif val[0]=='*':
376-
op = '*'
377-
val = pow(2.0,count_seq(val))
378-
if op=='/':
379-
if var in 'GX': self.grid/=float(val)
380-
elif var=='N': self.grid/=float(val) #!
381-
elif var=='T': self.tempo/=float(val)
382-
else: assert False
383-
elif op=='*':
384-
if var in 'GX': self.grid*=float(val)
385-
elif var=='N': self.grid*=float(val) #!
386-
elif var=='T': self.tempo*=float(val)
387-
else: assert False
388-
elif op=='+':
389-
if var=='K': self.transpose += note_offset('#1' if val=='+' else val)
390-
# elif var=='O': self.octave += int(1 if val=='+' else val)
391-
elif var=='T': self.tempo += max(0,float(val))
392-
elif var in 'GX': self.grid += max(0,float(val))
393-
else: assert False
394-
# if var=='K':
395-
# self.octave += -1*sgn(self.transpose)*(self.transpose//12)
396-
# self.transpose = self.transpose%12
397-
elif op=='-':
398-
if var=='K':
399-
self.transpose -= note_offset(val)
400-
out(note_offset(val))
401-
# elif var=='O': self.octave -= int(1 if val=='-' else val)
402-
elif var=='T': self.tempo -= max(0,float(val))
403-
elif var in 'GX': self.grid -= max(0,float(val))
404-
else: assert False
405-
# self.octave += -1*sgn(self.transpose)*(self.transpose//12)
406-
# if var=='K':
407-
# self.octave += -1*sgn(self.transpose)*(self.transpose//12)
408-
# self.transpose = self.transpose%12
409-
elif op=='=':
410-
if var in 'GX': self.grid=float(val)
411-
elif var=='R':
412-
if not 'auto' in self.devices:
413-
self.devices = ['auto'] + self.devices
414-
self.set_plugins(val.split(','))
415-
elif var=='V': self.version = val
416-
elif var=='D':
417-
self.devices = val.split(',')
418-
self.refresh_devices()
419-
# elif var=='O': self.octave = int(val)
420-
elif var=='N': self.grid=float(val)/4.0 #!
421-
elif var=='T':
422-
vals = val.split('x')
423-
self.tempo=float(vals[0])
424-
try:
425-
self.grid = float(vals[1])
426-
except:
427-
pass
428-
elif var=='C':
429-
vals = val.split(',')
430-
self.columns = int(vals[0])
431-
try:
432-
self.column_shift = int(vals[1])
433-
except:
434-
pass
435-
elif var=='P':
436-
vals = val.split(',')
437-
for i in range(len(vals)):
438-
p = vals[i]
439-
if p.strip().isdigit():
440-
self.tracks[i].patch(int(p))
441-
else:
442-
self.tracks[i].patch(p)
443-
elif var=='F': # flags
444-
self.add_flags(val.split(','))
445-
# for i in range(len(vals)): # TODO: ?
446-
# self.tracks[i].add_flags(val.split(','))
447-
# elif var=='O':
448-
# self.octave = int(val)
449-
elif var=='K':
450-
self.transpose = note_offset(val)
451-
# self.octave += -1*sgn(self.transpose)*(self.transpose//12)
452-
# self.transpose = self.transpose%12
453-
elif var=='S':
454-
# var R=relative usage deprecated
455-
try:
456-
if val:
457-
val = val.lower()
458-
# ambigous alts
459-
460-
if val.isdigit():
461-
modescale = (self.scale.name,int(val))
462-
else:
463-
alts = {'major':'ionian','minor':'aeolian'}
464-
# try:
465-
# modescale = (alts[val[0],val[1])
466-
# except KeyError:
467-
# pass
468-
val = val.lower().replace(' ','')
469-
470-
try:
471-
modescale = MODES[val]
472-
except KeyError:
473-
raise NoSuchScale()
474-
475-
try:
476-
self.scale = SCALES[modescale[0]]
477-
self.mode = modescale[1]
478-
inter = self.scale.intervals
479-
self.transpose = 0
480-
# log(self.mode-1)
481-
482-
if var=='R':
483-
for i in range(self.mode-1):
484-
inc = 0
485-
try:
486-
inc = int(inter[i])
487-
except ValueError:
488-
pass
489-
self.transpose += inc
490-
elif var=='S':
491-
pass
492-
except ValueError:
493-
raise NoSuchScale()
494-
# else:
495-
# self.transpose = 0
496-
497-
except NoSuchScale:
498-
out(FG.RED + 'No such scale.')
499-
pass
500-
else: assert False # no such var
501-
else: assert False # no such op
502-
503-
if var=='T':
504-
self.write_midi_tempo(int(val.split('x')[0]))
505-
self.row += 1
506-
continue
507-
346+
loop_result = self.handle_set_variable_commands()
347+
if loop_result == LoopResult.CONTINUE: continue
348+
elif loop_result == LoopResult.BREAK: break
349+
508350
# set marker here
509351
if (self.line[0]=='|' or self.line.startswith(':|')) and self.line[-1]==':':
510352
# allow override of markers in case of reuse
@@ -1941,3 +1783,203 @@ async def mk_prompt(self, prompt_session:PromptSession):
19411783
bufline = list(map(lambda b: b.replace(';',' '), bufline))
19421784

19431785
return bufline
1786+
1787+
def handle_set_variable_commands(self):
1788+
"""Function used to parse/handle variable setting commands. E.g: Set tempo, grid"""
1789+
1790+
#--------------------------#
1791+
# Sub-function definitions #
1792+
#--------------------------#
1793+
# We define sub-functions since we don't want the entire module scope to have access to
1794+
# these. If it turns out that these are useful in a broader context, we can just rip em out
1795+
# at that point
1796+
def read_operands(cmd) -> tuple[str,str]:
1797+
"""Read the operator and value to use when modifying variables.
1798+
E.g: `+`, `-`, `=`
1799+
"""
1800+
op = cmd[1]
1801+
try:
1802+
val = cmd[2:]
1803+
except:
1804+
val = ''
1805+
# log("op val %s %s" % (op,val))
1806+
if op == ':': op = '='
1807+
if not op in '*/=-+':
1808+
# implicit =
1809+
val = str(op) + str(val)
1810+
op='='
1811+
return (val,op)
1812+
1813+
def handle_division(var, val):
1814+
"""Use /= to modify a global variable"""
1815+
if var in 'GX': self.grid/=float(val)
1816+
elif var=='N': self.grid/=float(val) #!
1817+
elif var=='T': self.tempo/=float(val)
1818+
else: assert False
1819+
1820+
def handle_multiply(var, val):
1821+
"""Use *= to modify a global variable"""
1822+
if var in 'GX': self.grid*=float(val)
1823+
elif var=='N': self.grid*=float(val) #!
1824+
elif var=='T': self.tempo*=float(val)
1825+
else: assert False
1826+
1827+
def handle_add(var, val):
1828+
"""Use += to modify a global variable"""
1829+
if var=='K': self.transpose += note_offset('#1' if val=='+' else val)
1830+
# elif var=='O': self.octave += int(1 if val=='+' else val)
1831+
elif var=='T': self.tempo += max(0,float(val))
1832+
elif var in 'GX': self.grid += max(0,float(val))
1833+
else: assert False
1834+
# if var=='K':
1835+
# self.octave += -1*sgn(self.transpose)*(self.transpose//12)
1836+
# self.transpose = self.transpose%12
1837+
1838+
def handle_sub(var, val):
1839+
"""Use -= to modify a global variable"""
1840+
if var=='K':
1841+
self.transpose -= note_offset(val)
1842+
out(note_offset(val))
1843+
# elif var=='O': self.octave -= int(1 if val=='-' else val)
1844+
elif var=='T': self.tempo -= max(0,float(val))
1845+
elif var in 'GX': self.grid -= max(0,float(val))
1846+
else: assert False
1847+
# self.octave += -1*sgn(self.transpose)*(self.transpose//12)
1848+
# if var=='K':
1849+
# self.octave += -1*sgn(self.transpose)*(self.transpose//12)
1850+
# self.transpose = self.transpose%12
1851+
1852+
def handle_assign(var, val):
1853+
"""Use = to modify a global variable"""
1854+
if var in 'GX': self.grid=float(val)
1855+
elif var=='R':
1856+
if not 'auto' in self.devices:
1857+
self.devices = ['auto'] + self.devices
1858+
self.set_plugins(val.split(','))
1859+
elif var=='V': self.version = val
1860+
elif var=='D':
1861+
self.devices = val.split(',')
1862+
self.refresh_devices()
1863+
# elif var=='O': self.octave = int(val)
1864+
elif var=='N': self.grid=float(val)/4.0 #!
1865+
elif var=='T':
1866+
vals = val.split('x')
1867+
self.tempo=float(vals[0])
1868+
try:
1869+
self.grid = float(vals[1])
1870+
except:
1871+
pass
1872+
elif var=='C':
1873+
vals = val.split(',')
1874+
self.columns = int(vals[0])
1875+
try:
1876+
self.column_shift = int(vals[1])
1877+
except:
1878+
pass
1879+
elif var=='P':
1880+
vals = val.split(',')
1881+
for i in range(len(vals)):
1882+
p = vals[i]
1883+
if p.strip().isdigit():
1884+
self.tracks[i].patch(int(p))
1885+
else:
1886+
self.tracks[i].patch(p)
1887+
elif var=='F': # flags
1888+
self.add_flags(val.split(','))
1889+
# for i in range(len(vals)): # TODO: ?
1890+
# self.tracks[i].add_flags(val.split(','))
1891+
# elif var=='O':
1892+
# self.octave = int(val)
1893+
elif var=='K':
1894+
self.transpose = note_offset(val)
1895+
# self.octave += -1*sgn(self.transpose)*(self.transpose//12)
1896+
# self.transpose = self.transpose%12
1897+
elif var=='S':
1898+
# var R=relative usage deprecated
1899+
try:
1900+
if val:
1901+
val = val.lower()
1902+
# ambigous alts
1903+
1904+
if val.isdigit():
1905+
modescale = (self.scale.name,int(val))
1906+
else:
1907+
alts = {'major':'ionian','minor':'aeolian'}
1908+
# try:
1909+
# modescale = (alts[val[0],val[1])
1910+
# except KeyError:
1911+
# pass
1912+
val = val.lower().replace(' ','')
1913+
1914+
try:
1915+
modescale = MODES[val]
1916+
except KeyError:
1917+
raise NoSuchScale()
1918+
1919+
try:
1920+
self.scale = SCALES[modescale[0]]
1921+
self.mode = modescale[1]
1922+
inter = self.scale.intervals
1923+
self.transpose = 0
1924+
# log(self.mode-1)
1925+
1926+
if var=='R':
1927+
for i in range(self.mode-1):
1928+
inc = 0
1929+
try:
1930+
inc = int(inter[i])
1931+
except ValueError:
1932+
pass
1933+
self.transpose += inc
1934+
elif var=='S':
1935+
pass
1936+
except ValueError:
1937+
raise NoSuchScale()
1938+
# else:
1939+
# self.transpose = 0
1940+
1941+
except NoSuchScale:
1942+
out(FG.RED + 'No such scale.')
1943+
pass
1944+
else: assert False # no such var
1945+
1946+
def adjust_operands(val: str, op:str) -> tuple[str,str]:
1947+
val = op + val # append
1948+
# TODO: add numbers after dots like other ops
1949+
if val[0]=='.':
1950+
note_value(val)
1951+
ct = count_seq(val)
1952+
val = pow(0.5,count)
1953+
op = '/'
1954+
num,ct = peel_uint(val[:ct])
1955+
elif val[0]=='*':
1956+
op = '*'
1957+
val = pow(2.0,count_seq(val))
1958+
return (val,op)
1959+
1960+
#------------------------#
1961+
# Function's Entry Point #
1962+
#------------------------#
1963+
self.line = self.line[1:].strip() # remove % and spaces
1964+
for tok in self.line.split(' '):
1965+
if not tok:
1966+
return LoopResult.BREAK
1967+
if tok[0]==' ':
1968+
tok = tok[1:]
1969+
var = tok[0].upper()
1970+
if var in 'TGXNPSRCKFDR': # global vars %
1971+
cmd = tok.split(' ')[0]
1972+
(val,op) = read_operands(cmd)
1973+
if not val or op=='.': (val,op) = adjust_operands(val,op)
1974+
1975+
if op=='/': handle_division(var,val)
1976+
elif op=='*': handle_multiply(var,val)
1977+
elif op=='+': handle_add(var,val)
1978+
elif op=='-': handle_sub(var,val)
1979+
elif op=='=': handle_assign(var,val)
1980+
else: assert False # no such op
1981+
1982+
if var=='T':
1983+
self.write_midi_tempo(int(val.split('x')[0]))
1984+
self.row += 1
1985+
return LoopResult.CONTINUE

0 commit comments

Comments
 (0)