Initial commit

This commit is contained in:
2026-01-14 19:25:43 +02:00
commit 79c15a953c
3 changed files with 140 additions and 0 deletions

123
main.py Normal file
View File

@@ -0,0 +1,123 @@
#!/usr/bin/env python3.11
import itertools
import sys
import time
import rtmidi
from typing import Tuple
G_STATUS_NAMES = {
0x80: "NOTE_OFF",
0x90: "NOTE_ON",
0xa0: "KEY_PRESSR",
0xb0: "CTRL_CHANGE",
0xc0: "PROG_CHANGE",
0xd0: "CHAN_PRESSR",
0xe0: "PITCH_BEND",
0xf0: "XXX",
}
def note_on(chan: int, note: int, velocity: int) -> Tuple[int, int, int]:
assert 0 < chan <= 16, chan
assert 0 <= note <= 0xFF, note
assert 0 <= velocity <= 0xFF, velocity
msg_byte = 0x90 + (chan - 1)
return msg_byte, note, velocity
def note_off(chan: int, note: int) -> Tuple[int, int, int]:
assert 0 < chan <= 16, chan
assert 0 <= note <= 0xFF, note
msg_byte = 0x80 + (chan - 1)
return msg_byte, note, 0
def get_status_name(status: int) -> str:
return G_STATUS_NAMES.get(status & 0xF0) or f'<? {status:02x} ?>'
def test_midi_out() -> int:
midi_out = rtmidi.MidiOut()
ports: list[str] = midi_out.get_ports()
print('Ports:')
for i, port_name in enumerate(ports):
print(f'{i:2d} {port_name}')
# nanokey_index: int = ([i for i, port_name in enumerate(ports) if 'nanoKEY' in port_name] or [-1])[0]
# if nanokey_index < 0:
# print(f'nanoKEY2 port -> NOT FOUND [{ports}]', file=sys.stderr)
# return 1
#
# print(f'nanoKEY2 port -> {nanokey_index} ({ports[nanokey_index]})')
# midi_out.open_port(nanokey_index)
midi_out.open_port(0)
with midi_out:
midi_out.send_message(note_on(1, 60, 112))
time.sleep(0.5)
midi_out.send_message(note_off(1, 60))
time.sleep(0.1)
return 0
def handle_midi_event(msg, midi_out):
midi_msg, delay = msg
status, b1, b2 = midi_msg
b_hi = b1 + (b2 << 8)
status_name = get_status_name(status)
# if status_name == "PITCH_BEND":
print(f'[d:{delay:2.2f}] {status_name:11s} [ch {1 + (status & 0x0f)}] -> {b1:02x}[{b1:3d}] {b2:02x}[{b2:3d}] hi: {b_hi}')
midi_out.send_message([status, b1, 127])
def set_all(midi_out, value):
for ch, btn_id in itertools.product([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16], range(128)):
midi_out.send_message(note_on(ch, btn_id, value))
def test_midi_in() -> int:
midi_in = rtmidi.MidiIn()
ports: list[str] = midi_in.get_ports()
print('Ports:')
for i, port_name in enumerate(ports):
print(f'{i:2d} {port_name}')
midi_out = rtmidi.MidiOut()
port = 1
midi_in.set_callback(handle_midi_event, midi_out)
midi_in.open_port(port)
midi_out.open_port(port)
try:
set_all(midi_out, 127)
time.sleep(0.5)
set_all(midi_out, 0)
i = 0
levels = list(range(3))
while True:
if i >= len(levels):
i = -len(levels) + 1
midi_out.send_message(note_on(3, 2, levels[abs(i)]))
i += 1
time.sleep(0.5)
except KeyboardInterrupt:
print('CTRL+C TRIGGERED')
finally:
set_all(midi_out, 0)
midi_in.cancel_callback()
midi_in.close_port()
return 0
def main() -> int:
return test_midi_in()
if __name__ == '__main__':
raise SystemExit(main())