Skip to content

Home

Welcome to the rtmidi2 documentation!

rtmidi2 is a wrapper for the C++ library RtMidi. It is written in cython, targets python 3 (>= 3.8 at the moment) and supports Linux, macOS and Windows.

RtMidi

RtMidi is a set of C++ classes (RtMidiIn, RtMidiOut and API-specific classes) that provides a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMIDI & JACK), and Windows (Multimedia Library) operating systems.

Installation

pip install rtmidi2

Quick Introduction

Read incomming MIDI from default port

from rtmidi2 import MidiIn, NOTEON, CC, splitchannel
midiin = MidiIn()
midiin.open_port()    # will get messages from the default port

def callback(msg: list, timestamp: float):
    # msg is a list of 1-byte strings
    # timestamp is a float with the time elapsed since last midi event
    msgtype, channel = splitchannel(msg[0])
    if msgtype == NOTEON:
        note, velocity = msg[1], msg[2]
        print(f"Noteon, {channel=}, {note=}, {velocity=}")
    elif msgtype == CC:
        cc, value = msg[1:]
        print(f"Control Change {channel=}, {cc=}, {value=}")

midiin.callback = callback

# The callback can be cancelled by setting it to None
midiin.callback = None

# When you are done, close the port
midiin.close_port()

Create a port for other clients to send MIDI to

This will create a client named "clientA" with a port "inport". Messages are received async via the given callback. Another client will send messages to it

from rtmidi2 import *
midiin = MidiIn("clientA")
midiin.open_virtual_port("inport")

def callback(msg, timestamp):
    # msg is a list of 1-byte strings
    # timestamp is a float with the time elapsed since last midi event
    msgtype, channel = splitchannel(msg[0])
    if msgtype == NOTEON:
        note, velocity = msg[1], msg[2]
        print(f"Noteon, {channel=}, {note=}, {velocity=}")
    elif msgtype == CC:
        cc, value = msg[1:]
        print(f"Control Change {channel=}, {cc=}, {value=}")

midiin.callback = callback

midiout = MidiOut("clientB")

# The name of the port will depend on the operating system and API used
# In Linux/ALSA, the port of clientA would appear as 'clientA:inport XXX:Y'
# We can use a glob pattern to match against the client and port names
midiout.open_port("clientA:inport*")

# Send a noteon C4 (midinote 60) with velocity 90 on channel 1
midiout.send_noteon(0, 60, 90)

# The callback will be called and print "noteon 60 90"

Receive messages from multiple sources

With rtmidi2 it is possible to listen to multiple sources simultaneously.

from rtmidi2 import *

def callback_with_source(src, msg, time):
    msgtype, channel = splitchannel(msg[0])
    print(f"Message generated from {src}: {channel=}, {msgtype=}, data: {msg[1:]}")

midiin = MidiInMulti().open_ports("*")
midiin.callback = callback_with_source   

Reference

See reference