#!/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'' 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())