Neale Pickett
·
2026-02-10
mklayouts.py
1#! /usr/bin/python3
2
3import re
4import sys
5
6baseMidiNote = {
7 'C': 60,
8 'D': 62,
9 'E': 64,
10 'F': 65,
11 'G': 67,
12 'A': 69,
13 'B': 71,
14}
15
16def abc2midi(s):
17 if s in ('', '-'):
18 return -1
19 note = baseMidiNote[s[0].upper()]
20 if s[0] in 'cdefgab':
21 note += 12
22 for m in s[1:]:
23 if m == '^':
24 note += 1
25 elif m == '_':
26 note -= 1
27 elif m == ',':
28 note -= 12
29 elif m == "'":
30 note += 12
31 return note
32
33assert abc2midi('C') == 60
34assert abc2midi('c') == 72
35assert abc2midi("c^'") == 85
36
37
38class Layout:
39 def __init__(self, name):
40 self.name = name
41 self.notes = [[], []]
42
43 def add_row(self, buttons):
44 assert len(buttons) == 10
45 self.notes[0].append(buttons[:5])
46 self.notes[1].append(buttons[5:])
47
48 def write(self, fd):
49 assert len(self.notes) == 2
50 fd.write(' { "%s",\n' % self.name)
51 fd.write(' { // sides\n');
52 for side in self.notes:
53 assert len(side) == 4
54 fd.write(' { // rows\n')
55 for row in side:
56 assert len(row) == 5
57 fd.write(' { // buttons\n')
58 for button in row:
59 fd.write(' {%d, %d}, // %s\n' % button)
60 fd.write(' },\n')
61 fd.write(' },\n')
62 fd.write(' }\n')
63 fd.write(' },\n')
64
65with sys.stdout as f:
66 f.write('''/* Generated from layouts.txt by mklayouts.py */
67#pragma once
68
69struct layout_t {
70 char const *name;
71 int8_t notes[2][4][5][2]; /* side, row, col, push/draw */
72};
73
74const layout_t layouts[] = {
75''')
76 layout = None
77 for line in open(sys.argv[1]):
78 line = line.strip()
79 parts = line.split()
80 if line == '':
81 continue
82 if len(parts) < 11:
83 if layout:
84 layout.write(f)
85 layout = Layout(line)
86 continue
87 if len(parts) != 11:
88 raise RuntimeError("Wrong number of buttons")
89 if parts[5] != '|':
90 raise RuntimeError("Expecting separator, got %s" % parts[5])
91 buttons = []
92 for part in parts:
93 if part == '|':
94 continue
95 button = part.replace('♯', '^').replace('♭', '_')
96 names = button.split('/')
97 if len(names) == 1:
98 names.append(names[0])
99 notes = [abc2midi(n) for n in names]
100 buttons.append((notes[0], notes[1], button))
101 layout.add_row(buttons)
102
103 if layout:
104 layout.write(f)
105 f.write("};\n")
106
107
108