def read(self, filename): self.filename = filename data = open(filename).read() v2 = data.find('Nord Modular patch 2.10') v3 = data.find('Nord Modular patch 3.0') if v2 < 0 and v3 < 0: raise NM1Error('%s not valid .pch file' % filename) data = open(filename).read() if data.find('\r\r') > -1: data = data.replace('\r\r','\n\n') data = data.replace('\r','') lines = [ line.strip() for line in data.split('\n') ] lines = filter(lambda s: s != '', lines) if not len(lines): raise NM1Error('%s no valid data: not parsing' % filename) if lines[0] != '[Header]': printf('added missing [Header]\n') lines.insert(0, '[Header]') if filename[-4:].lower() != '.pch': self.filename += '.pch' if v3 > -1: self.readv3(data) elif v2 > -1: self.readv2(data)
def build_file(self, filename): filelines = [] module = [] module_name = '' in_module = 0 for lineno, line in self.files[filename]: #debug('%d: %s\n', lineno, line) args = clean_line(line).split() #debug('args=%s\n', args) if len(args) < 1: continue cmd = args.pop(0) if cmd == 'model': in_module = 1 module_name = args[0] elif cmd == 'endmodel': self.build_group(module_name, module) in_module = 0 module = [] elif cmd == 'include': path = self.find_include(args[0]) filelines += self.build_file(path) elif in_module: module.append((lineno, line)) else: filelines.append((lineno, line)) if in_module: printf('%s: no endmodel tag found\n', self.topfile) return return filelines
def parse_area(self, area, bitstream): _, ncables = bitstream.read_bitsa([6, 16]) area.cables = [None] * ncables for i in xrange(ncables): cable = Cable(area) cable.color, source, src_conn, direction, dest, dest_conn = \ bitstream.read_bitsa([3, 8, 6, 1, 8, 6]) src_module = area.find_module(source) dest_module = area.find_module(dest) if invalid_cable(src_module, src_conn, direction, dest_module, dest_conn): printf('Invalid cable %d: "%s"(%d,%d) -%d-> "%s"(%d,%d)\n', i, src_module.type.shortnm, src_module.index, src_conn, direction, dest_module.type.shortnm, dest_module.index, dest_conn) continue if direction == 1: cable.source = src_module.outputs[src_conn] else: cable.source = src_module.inputs[src_conn] cable.dest = dest_module.inputs[dest_conn] area.cables[i] = cable cable.source.cables.append(cable) cable.dest.cables.append(cable) area.netlist.add(cable.source, cable.dest)
def parse_module(self, module, bitstream): modlen = bitstream.read_bits(8) if module.type.id == 121: # SeqNote # extra editor parameters # [0, 1, mag, 0, 1, octave] # mag: 0=3-octaves, 1=2-octaves, 2=1-octave # octave: 0-9 (c0-c9) module.editmodes = bitstream.read_bytes(modlen) else: while modlen > 0: stri, paramlen, parami = bitstream.read_bitsa([8, 8, 8]) modlen -= 3 param = module.params[parami] paramlen -= 1 # decrease because we got param index if paramlen: param.labels = [ read_string(bitstream, 7, pad=True) for i in xrange(paramlen / 7) ] modlen -= paramlen else: param.labels = [''] if section_debug: printf('%d %s %d %d %s\n', module.index, module.type.shortnm, paramlen, parami, param.labels)
def cmd_list(command): JUMP, SKIP, BANK, MODE, CONTINUE = [1, 2, 3, 4, 5] LAST = CONTINUE PATCH_MODE, PERFORMANCE_MODE, END_MODE = range(3) modes = ['Pch2', 'Prf2'] mode = PATCH_MODE bank = 0 patch = 0 while mode < END_MODE: cmd = [CMD_SYS, 0x41, g2QueryBankPatchList, mode, bank, patch] data = g2usb.send_message(cmd) data = str(data[9:-2]) while len(data): c = ord(data[0]) if c > LAST: name, data = parse_name(data) category, data = ord(data[0]), data[1:] printf('%s %-6s %-9s %s\n', modes[mode], '%d:%d' % (bank+1, patch+1), g2categories[category], name) patch += 1 elif c == CONTINUE: data = data[1:] elif c == BANK: bank, patch, data = ord(data[1]), ord(data[2]), data[3:] elif c == JUMP: patch, data = ord(data[1]), data[2:] elif c == SKIP: patch, data = patch+1, data[1:] elif c == MODE: mode, bank, patch, data = mode+1, 0, 0, data[1:] return 0
def parse_area(self, area, bitstream): _, ncables = bitstream.read_bitsa([6, 16]) area.cables = [ None ] * ncables for i in xrange(ncables): cable = Cable(area) cable.color, source, src_conn, direction, dest, dest_conn = \ bitstream.read_bitsa([3, 8, 6, 1, 8, 6]) src_module = area.find_module(source) dest_module = area.find_module(dest) if invalid_cable(src_module, src_conn, direction, dest_module, dest_conn): printf('Invalid cable %d: "%s"(%d,%d) -%d-> "%s"(%d,%d)\n', i, src_module.type.shortnm, src_module.index, src_conn, direction, dest_module.type.shortnm, dest_module.index, dest_conn) continue if direction == 1: cable.source = src_module.outputs[src_conn] else: cable.source = src_module.inputs[src_conn] cable.dest = dest_module.inputs[dest_conn] area.cables[i] = cable cable.source.cables.append(cable) cable.dest.cables.append(cable) area.netlist.add(cable.source, cable.dest)
def read_g2_file(filename): data = open(filename).read() null = data.find('\0') if null < 0: printf('invalid pch2 %s\n', filename) return [] return data[null:]
def read(self, filename): self.filename = filename data = open(filename).read() v2 = data.find('Nord Modular patch 2.10') v3 = data.find('Nord Modular patch 3.0') if v2 < 0 and v3 < 0: raise NM1Error('%s not valid .pch file' % filename) data = open(filename).read() if data.find('\r\r') > -1: data = data.replace('\r\r', '\n\n') data = data.replace('\r', '') lines = [line.strip() for line in data.split('\n')] lines = filter(lambda s: s != '', lines) if not len(lines): raise NM1Error('%s no valid data: not parsing' % filename) if lines[0] != '[Header]': printf('added missing [Header]\n') lines.insert(0, '[Header]') if filename[-4:].lower() != '.pch': self.filename += '.pch' if v3 > -1: self.readv3(data) elif v2 > -1: self.readv2(data)
def embedded_message(self, din, data): dil = din.pop(0)>>4 # length encoded in upper nibble of header byte ecrc = crc(din[:dil-2]) # expected crc acrc = (din[dil-2]<<8)|din[dil-1] # actual crc if ecrc != acrc: printf('bad crc exp: 0x%04x act: 0x%04x\n', ecrc, acrc) return din[:dil]
def printvariations(patch): settings = patch.settings printf('variations:\n') for attr in [ 'activemuted', 'patchvol', 'glide', 'glidetime', 'bend', 'semi', 'vibrato', 'cents', 'rate', 'arpeggiator', 'arptime', 'arptype', 'octaves', 'octaveshift', 'sustain' ]: printf(' %-16s %s\n', (attr+':'), getattr(settings, attr).variations)
def read(self, filename): self.filename = filename self.data = bytearray(open(filename, 'rb').read()) memview = self.parse_header(memoryview(self.data), filename) bytes = len(self.parse(memview[2:-2])) ecrc = unpack('>H', self.data[-2:])[0] acrc = crc(memview[:-2]) if ecrc != acrc: printf('Bad CRC 0x%x 0x%x\n' % (ecrc, acrc))
def parse_section(self, section, patch_or_perf, memview): type, l = unpack('>BH', memview[:3]) l += 3 if section_debug: nm = section.__class__.__name__ printf('0x%02x %-25s len:0x%04x\n', type, nm, l) printf('%s\n', binhexdump(memview[:l].tobytes())) section.parse(patch_or_perf, memview[3:l]) return memview[l:]
def parse_bank_patch(location): bank, patch = map(int, location.split(':')) if bank < 1 or bank > 32: printf('invalid bank %d, must be 1 to 32\n', bank) return -1, -1 if patch < 1 or patch > 127: printf('invalid patch %d, must be 1 to 127\n', patch) return -1, -1 return bank-1, patch-1
def printcables(patch): printf('cables:\n') for cable in patch.voice.cables: source, dest = cable.source, cable.dest smod, dmod = source.module, dest.module stype, dtype = smod.type, dmod.type snm = source.type.name dnm = dest.type.name printf(' %s.%s -%s %s.%s: c=%d\n', stype.shortnm, snm, '->'[source.direction], dtype.shortnm, dnm, cable.color)
def domodule(self): nmm, g2m = self.nmmodule, self.g2module nmmp, g2mp = nmm.params, g2m.params handlegate(self, 'Trigger') # handle special parameters updatevals(g2mp, ['Attack', 'Release'], adsrtime_map) if self.options.adsrforad: printf('%s\n', g2m.type.shortnm) setv(g2mp.Sustain, 0) setv(g2mp.Decay, getv(g2mp.Release))
def parse_command(self, line, lineno): args = line.split() if len(args) < 1: return cmd = args.pop(0).lower() debug('%d: %s(%s)\n', lineno, cmd, args) try: self.g2patch.actions[cmd](*args) except Exception as e: printf('%d: %s\n\t%s\n', lineno, line.rstrip(), e) debug('%s\n', traceback.format_exc())
def parse_header(self, memview, filename): header2x = bytearray(memview[:2*len(self.standard_text_header)]) null = header2x.find('\0') if null < 0: raise G2Error('Invalid G2File "%s" missing null terminator.' % filename) self.txthdr = str(header2x[:null]) self.binhdr = header2x[null+1], header2x[null+2] if self.binhdr[0] != self.binary_version: printf('Warning: %s version %d\n', filename, self.binhdr[0]) printf(' version %d supported. it may fail to load.\n', self.binary_version) return memview[null+1:] # include binhdr for crc
def cmd_parameterpage(command, page): row = 'abcde'.find(page[0].lower()) if row < 0: printf('Invalid row %s\n', page[0].lower()) return -1 col = int(page[1]) - 1 if col < 0 or 2 < col: printf('Invalid col %d\n', col) return -1 slota = g2usb.send_message([CMD_SYS, 0x41, 0x35, 0x00]) g2usb.send_message([0x08, slota[6], 0x2d, (row*3)+col]) return 0
def parse_header(self, memview, filename): header2x = bytearray(memview[:2 * len(self.standard_text_header)]) null = header2x.find('\0') if null < 0: raise G2Error('Invalid G2File "%s" missing null terminator.' % filename) self.txthdr = str(header2x[:null]) self.binhdr = header2x[null + 1], header2x[null + 2] if self.binhdr[0] != self.binary_version: printf('Warning: %s version %d\n', filename, self.binhdr[0]) printf(' version %d supported. it may fail to load.\n', self.binary_version) return memview[null + 1:] # include binhdr for crc
def cmd_dump(command, bank): bank, patch = parse_bank_patch(location) if bank < 1: return -1 for patch in range(128): data = g2usb.send_message([CMD_SYS, 0x41, 0x17, 0x00, bank, patch]) if data[3] == 0x18: continue data = data[5:] #bank, patch = data[:2] name, data = parse_name(data[2:]) printf('%d:%d %s\n', bank+1, patch+1, name) #print hexdump(pch2) return 0
def cmd_help(command): global prog printf('usage: %s [commands]*\n', prog) printf(' commands:\n') for command in commandlist: sep = '' if len(command.params): sep = ' ' params = [ '<%s>' % p for p in command.params ] usage = '%s%s%s:' % (command.name, sep, ' '.join(params)) desc = wrap_lines(command.description, 80-30) printf(' %-25s %s\n', usage, desc.pop(0)) while len(desc): printf(' %-25s %s\n', '', desc.pop(0)) printf('\n multiple commands are executed consecutively\n') return 0
def printmidicc(patch): printf('midicc:\n') for ctrl in patch.ctrls: param = ctrl.param if param.module.area.index == 2: name = param.name else: name = param.module.name + ':' + param.type.name if midicctable.has_key(ctrl.midicc): s = '"' + midicctable[ctrl.midicc] + '"' else: s = '' area = param.module.area.index printf(' %-8s midicc=%2d %s(%d, %d) %s\n', {0:'fx', 1:'voice', 2:'settings'}[area], ctrl.midicc, name, param.module.index, param.index, s)
def add(self, source, dest): snet, dnet = source.net, dest.net if snet and dnet and snet == dnet: printf('net already created\n') printf('%r %r\n', snet, dnet) printf(' %d:%s -> %d:%s\n', source.module.index, source.type.name, dest.module.index, dest.type.name) printf('source net: %s\n', self.nettos(snet)) printf('dest net: %s\n', self.nettos(dnet)) return if snet and dnet: # two separate nets need to be combined self.combine(source, dest) return if snet: net = snet net.inputs.append(dest) elif dnet: net = dnet if source.direction: if net.output and source != net.output: raise NetError( 'both nets have outputs: source=%s:%s net.source=%s:%s' % ( source.module.type.shortnm, source.type.name, net.output.module.type.shortnm, net.output.type.name)) net.output = source else: net.inputs.append(source) else: net = None # add new net if one not found if not net: if source.direction: net = Net(source, [dest]) else: net = Net(None, [dest, source]) self.nets.append(net) # update source and dest nets list if not source.net: source.net = net if not dest.net: dest.net = net
def format_section(self, section, patch_or_perf, memview): #print section.__class__.__name__ bits = section.format(patch_or_perf, memview[3:]) # skip type, size bytes = (bits + 7) >> 3 # write type, size memview[:3] = pack('>BH', section.type, bytes) if section_debug: nm = section.__class__.__name__ printf('0x%02x %-25s len:0x%04x\n', section.type, nm, bytes) tbl = string.maketrans(string.ascii_lowercase, ' '*26) nm = nm.translate(tbl).replace(' ', '') printf('%s\n', nm) #if title_section and len(nm) < len(f): # f = nm+f[len(nm):] return memview[bytes + 3:]
def format_section(self, section, patch_or_perf, memview): #print section.__class__.__name__ bits = section.format(patch_or_perf, memview[3:]) # skip type, size bytes = (bits + 7) >> 3 # write type, size memview[:3] = pack('>BH', section.type, bytes) if section_debug: nm = section.__class__.__name__ printf('0x%02x %-25s len:0x%04x\n', section.type, nm, bytes) tbl = string.maketrans(string.ascii_lowercase, ' ' * 26) nm = nm.translate(tbl).replace(' ', '') printf('%s\n', nm) #if title_section and len(nm) < len(f): # f = nm+f[len(nm):] return memview[bytes + 3:]
def add(self, source, dest): snet, dnet = source.net, dest.net if snet and dnet and snet == dnet: printf('net already created\n') printf('%r %r\n', snet, dnet) printf(' %d:%s -> %d:%s\n', source.module.index, source.type.name, dest.module.index, dest.type.name) printf('source net: %s\n', self.nettos(snet)) printf('dest net: %s\n', self.nettos(dnet)) return if snet and dnet: # two separate nets need to be combined self.combine(source, dest) return if snet: net = snet net.inputs.append(dest) elif dnet: net = dnet if source.direction: if net.output and source != net.output: raise NetError( 'both nets have outputs: source=%s:%s net.source=%s:%s' % (source.module.type.shortnm, source.type.name, net.output.module.type.shortnm, net.output.type.name)) net.output = source else: net.inputs.append(source) else: net = None # add new net if one not found if not net: if source.direction: net = Net(source, [dest]) else: net = Net(None, [dest, source]) self.nets.append(net) # update source and dest nets list if not source.net: source.net = net if not dest.net: dest.net = net
def cmd_showslot(command, slot): slot = 'abcd'.find(slot.lower()) if slot < 0: return -1 version = g2usb.send_message([CMD_SYS, 0x41, 0x35, slot])[5] data = g2usb.send_message([CMD_A+slot, version, 0x3c]) name = g2usb.send_message([CMD_A+slot, version, 0x28]) name, junk = parse_name(name[4:]) #printf("%s\n", hexdump(data[1:-2])) pch2 = Pch2File() data = data[0x03:0x15] + data[0x17:-2] pch2.parse(data.tostring(), 0) from pch2tog2 import print_patch printf('# %s\n', name) print print_patch(pch2.patch) return 0
def format_module(self, module, bitstream): s = '' if module.type.id == 121: # SeqNote s += str(bytearray(module.editmodes)) else: # build up the labels and then write them for i, param in enumerate(module.params): if not hasattr(param, 'labels'): continue if section_debug: printf('%d %s %d %d %s\n', module.index, module.type.shortnm, 7*len(param.labels), i, param.labels) labels = [format_string(lbl, 7, pad=True) for lbl in param.labels] ps = chr(i) + ''.join(labels) s += chr(1)+chr(len(ps))+ps bitstream.write_bitsa([8, 8], [module.index, len(s)]) bitstream.write_str(s)
def parsev3data(self, data, sections): l = len(sections) for i, section in enumerate(sections): tag, start, end = section if start < 0: printf('no start tag %s\n', tag) continue if end < 0: if i < l - 1: ntag, nstart, nend = sections[i + 1] end = nstart else: end = None lines = [f.strip() for f in data[start:end].splitlines()] lines = [line for line in lines if line] if len(lines) > 2: sect_class = globals()[tag + 'V3'] sect = sect_class(self.patch, lines[1:-1])
def parsev3data(self, data, sections): l = len(sections) for i, section in enumerate(sections): tag, start, end = section if start < 0: printf('no start tag %s\n', tag) continue if end < 0: if i < l-1: ntag, nstart, nend = sections[i+1] end = nstart else: end = None lines = [ f.strip() for f in data[start:end].splitlines() ] lines = [ line for line in lines if line ] if len(lines) > 2: sect_class = globals()[tag + 'V3'] sect = sect_class(self.patch, lines[1:-1])
def combine(self, source, dest): sout, dout = source.net.output, dest.net.output if sout and dout and (sout != dout): # shouldn't happen printf('source %s\n', self.nettos(source.net)) printf('dest %s\n', self.nettos(dest.net)) raise NetError( 'source and dest both have outputs: source=%s:%s dest=%s:%s' % ( sout.module.type.shortnm, sout.type.name, dout.module.type.shortnm, dout.type.name)) self.nets.remove(dest.net) if dout: source.net.output = dout source.net.output.net = source.net source.net.inputs += dest.net.inputs for input in dest.net.inputs: input.net = source.net
def midicc(self, cc, control): cc = int(cc) if control.startswith('setting'): return if midicc_reserved(cc): #raise G2Exception('midicc %d reserved' % cc) printf('midicc %d reserved\n', cc) return new_ctrl = None ctrls = self.pch2.patch.ctrls for ctrl in ctrls: if ctrl.midicc == cc: new_ctrl = ctrl break if new_ctrl == None: new_ctrl = Ctrl() ctrls.append(new_ctrl) new_ctrl.midicc = cc new_ctrl.param, new_ctrl.type = self.parse_control(control)
def combine(self, source, dest): sout, dout = source.net.output, dest.net.output if sout and dout and (sout != dout): # shouldn't happen printf('source %s\n', self.nettos(source.net)) printf('dest %s\n', self.nettos(dest.net)) raise NetError( 'source and dest both have outputs: source=%s:%s dest=%s:%s' % (sout.module.type.shortnm, sout.type.name, dout.module.type.shortnm, dout.type.name)) self.nets.remove(dest.net) if dout: source.net.output = dout source.net.output.net = source.net source.net.inputs += dest.net.inputs for input in dest.net.inputs: input.net = source.net
def printknobs(patch): printf('knobs:\n') for i, knob in enumerate(patch.knobs): if knob.assigned: printf(' %s%d:%d ', 'ABCDE'[i/24], (i/8)%3, i&7) if hasattr(knob.param, 'module'): printf('%s:"%s":%s isled=0x%02x\n', ['fx', 'voice'][knob.param.module.area.index], knob.param.module.name, knob.param.type.name, knob.isled) else: printf('morph:%d:"%s"\n', knob.param.index, knob.param.label)
def parse(self): if not len(self.lines): return sect = int(self.lines[0]) if sect: area = self.patch.voice else: area = self.patch.fx for line in self.lines[1:]: vals = line.split(' ', 1) if len(vals) > 1: name = vals[1] else: name = '' module = area.find_module(int(vals[0])) if module == None: printf("[NameDump]: module index %d not found\n", int(vals[0])) continue module.name = name
def build_files(self, filename): lines = [ line.rstrip() for line in open(filename).readlines() ] self.file_stack = [ filename ] #self.files[filename] = list(enumerate(lines, 1) self.files[filename] = zip(range(1, 1+len(lines)), lines) in_module = False for lineno, line in self.files[filename]: line = clean_line(line) if not line: continue fields = line.strip().split() if fields[0] == 'model': in_module = True elif fields[0] == 'endmodel': in_module = False elif fields[0] == 'include': if in_module: printf('%s:%d - include inside model definition\n', filename, lineno) else: self.handle_include(fields[1])
def format_module(self, module, bitstream): s = '' if module.type.id == 121: # SeqNote s += str(bytearray(module.editmodes)) else: # build up the labels and then write them for i, param in enumerate(module.params): if not hasattr(param, 'labels'): continue if section_debug: printf('%d %s %d %d %s\n', module.index, module.type.shortnm, 7 * len(param.labels), i, param.labels) labels = [ format_string(lbl, 7, pad=True) for lbl in param.labels ] ps = chr(i) + ''.join(labels) s += chr(1) + chr(len(ps)) + ps bitstream.write_bitsa([8, 8], [module.index, len(s)]) bitstream.write_str(s)
def run(name, args): error = -1 if commands.has_key(name): command = commands[name] func = command.func l = len(command.params) a = args[:l] if len(a) < l: printf('error: %s missing %s\n', name, ' '.join([ '<%s>' % p for p in command.params[len(a):]])) error = -1 else: args[:l] = [] printf('%s %s\n', name, ' '.join(a)) error = func(command, *a) if error: printf('usage: %s %s\n', name, ' '.join(['<%s>' % p for p in command.params ])) printf('\n') else: printf('error: bad command "%s"\n', name) return error
def cmd_store(command, location, filename): data = read_g2_file(filename) l = len(data) if l == 0: return -1 bank, patch = parse_bank_patch(location) if bank < 0: return -1 name, ext = os.path.splitext(os.path.basename(filename)) name = format_name(name) printf('%s %s\n', name, ext) if ext.lower() == '.prf2': mode = 1 else: mode = 0 printf("%d:%d %s\n", bank, patch, name) a = bytearray([CMD_SYS, 0x41, 0x19, mode, bank-1, patch-1]) a.fromstring(name) a.extend([ (l>>8)&0xff, l&0xff, 0x17 ]) a.fromstring(data) g2usb.send_message(a.tolist()) return 0
def extended_message(self, din, data): sz = (din[1]<<8)|din[2] bin = [] retries = 5 # the message has to return within 5 tries while retries != 0 and sz != len(bin): bin = self.bread(self.g2bin, sz) retries -= 1 s = hexdump(bin).replace('\n','\n ') debug('<%d %s\n', self.g2bin & 0x7f, s) if retries == 0: raise Exception('Could not get result') elif bin[0] == CMD_INIT: # special case pass elif bin[1] == data[0]: # if result is same as command we got message pass else: return None ecrc = crc(bin[:-2]) # expected crc acrc = (bin[-2]<<8)|bin[-1] # actual crc if ecrc != acrc: printf('bad crc exp: 0x%04x act: 0x%04x\n', ecrc, acrc) return bin
def add(self, area, **kw): gm = G2Model(self.g2patch) gm.name = kw['name'] d = ' '.join('%s=%s' % (k, kw[k]) for k in kw) # save colors, setup models colors gm.cable_color = orig_cable_color = self.g2patch.cable_color gm.module_color = orig_module_color = self.g2patch.module_color for lineno, line in self.code: self.g2patch.cable_color = gm.cable_color self.g2patch.module_color = gm.module_color args = [ l.lower() for l in line.split() ] cmd = args.pop(0) debug('model %d: %s(%s) %s\n', lineno, cmd, args, d) try: getattr(gm, cmd)(*args) except G2Exception as e: printf('%d: %s\n\t%s\n', lineno, line.strip(), e) debug('%s\n', traceback.format_exc()) gm.height = 0 # height calculated on each module # restore colors self.g2patch.cable_color = orig_cable_color self.g2patch.module_color = orig_module_color return gm
def main(argv): global prog prog = argv[0] try: args = argv[1:] rc = 0 printf('\n') if len(args) == 0: process(['help']) rc = process(args) if rc: printf('use "help" command to see list of commands and arguments.\n') rc = -1 except: import traceback printf('%s\n', traceback.format_exc()) rc = -1 sys.exit(rc)