CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-python-rtmidi

A Python binding for the RtMidi C++ library providing cross-platform realtime MIDI input/output functionality.

Pending
Overview
Eval results
Files

midi-io.mddocs/

Core MIDI I/O

Primary interfaces for MIDI input and output operations, providing cross-platform realtime MIDI functionality with support for both hardware and virtual ports.

Capabilities

MidiIn Class

MIDI input client interface for receiving MIDI messages with support for polling and callback-based message handling.

class MidiIn:
    def __init__(self, rtapi=API_UNSPECIFIED, name="RtMidi Client", queue_size_limit=1024):
        """
        Create MIDI input instance.
        
        Parameters:
        - rtapi: API backend (API_UNSPECIFIED, API_LINUX_ALSA, API_MACOSX_CORE, etc.)
        - name: Client name for MIDI system
        - queue_size_limit: Internal ring buffer size for incoming MIDI events
        
        Raises:
        - SystemError: If RtMidi backend initialization fails
        - TypeError: If incompatible parameter type is passed  
        """

    def get_current_api(self):
        """
        Get the low-level MIDI backend API used by this instance.
        
        Returns:
        - int: One of the API_* constants
        """

    def get_port_count(self):
        """
        Get number of available MIDI input ports.
        
        Returns:
        - int: Number of available ports
        """

    def get_port_name(self, port, encoding='auto'):
        """
        Get name of MIDI input port by number.
        
        Parameters:
        - port: Port number (0-based)
        - encoding: Text encoding ('auto', 'utf-8', 'latin1', 'macroman', or None)
        
        Returns:
        - str: Port name (if encoding specified)
        - bytes: Port name (if encoding=None)
        - None: If port name is empty
        """

    def get_ports(self, encoding='auto'):
        """
        Get list of available MIDI input port names.
        
        Parameters:
        - encoding: Text encoding for port names
        
        Returns:
        - list[str]: List of port names with index corresponding to port number
        """

    def is_port_open(self):
        """
        Check if a port is currently open.
        
        Returns:
        - bool: True if port is open (including virtual ports)
        """

    def open_port(self, port=0, name=None):
        """
        Open MIDI input port by number.
        
        Parameters:
        - port: Port number to open (default: 0)
        - name: Port name (default: "RtMidi input")
        
        Returns:
        - MidiIn: Self for method chaining
        
        Raises:
        - InvalidPortError: Invalid port number
        - InvalidUseError: Port already open
        - TypeError: Incompatible parameter type
        """

    def open_virtual_port(self, name=None):
        """
        Open virtual MIDI input port.
        
        Parameters:
        - name: Virtual port name (default: "RtMidi virtual input")
        
        Returns:
        - MidiIn: Self for method chaining
        
        Raises:
        - InvalidUseError: Port already open
        - UnsupportedOperationError: Virtual ports not supported (Windows MM)
        - TypeError: Incompatible parameter type
        """

    def close_port(self):
        """
        Close opened MIDI input port and cancel any callbacks.
        Safe to call repeatedly or when no port is open.
        """

    def set_client_name(self, name):
        """
        Set MIDI client name (ALSA only).
        
        Parameters:
        - name: Client name string
        
        Raises:
        - UnsupportedOperationError: API doesn't support client name changes
        - TypeError: Incompatible parameter type
        """

    def set_port_name(self, name):
        """
        Set name of currently opened port (ALSA/JACK only).
        
        Parameters:
        - name: Port name string
        
        Raises:
        - InvalidUseError: No port currently open
        - UnsupportedOperationError: API doesn't support port name changes
        - TypeError: Incompatible parameter type
        """

    def get_message(self):
        """
        Poll for MIDI input message.
        
        Returns:
        - tuple[list[int], float]: (message_bytes, delta_time) if message available
        - None: If no message available
        
        Note: Non-blocking. Returns immediately if no message available.
        """

    def ignore_types(self, sysex=True, timing=True, active_sense=True):
        """
        Enable/disable filtering of MIDI event types.
        
        Parameters:
        - sysex: Filter System Exclusive messages (default: True)
        - timing: Filter MIDI Clock messages (default: True)  
        - active_sense: Filter Active Sensing messages (default: True)
        
        Note: Set to False to receive these message types.
        """

    def set_callback(self, func, data=None):
        """
        Register callback function for MIDI input.
        
        Parameters:
        - func: Callback function taking (message_tuple, data) arguments
        - data: User data passed to callback (can be any Python object)
        
        Note: Callback receives ((message_bytes, delta_time), data) arguments.
        Replaces any previously registered callback.
        """

    def cancel_callback(self):
        """
        Remove registered callback function.
        Safe to call when no callback is registered.
        """

    def set_error_callback(self, func, data=None):
        """
        Register error callback function.
        
        Parameters:
        - func: Error callback taking (error_type, error_message, data) arguments
        - data: User data passed to callback
        
        Note: Replaces default error handler that raises exceptions.
        """

    def cancel_error_callback(self):
        """
        Remove error callback and reinstate default error handler.
        """

    def delete(self):
        """
        Manually destroy C++ instance for immediate cleanup.
        
        Warning: Instance must not be used after calling this method.
        """

    @property
    def is_deleted(self):
        """Check if C++ instance has been destroyed."""

    def __enter__(self):
        """Context manager entry - returns self."""

    def __exit__(self, *exc_info):
        """Context manager exit - closes port automatically."""

MidiOut Class

MIDI output client interface for sending MIDI messages to hardware and virtual ports.

class MidiOut:
    def __init__(self, rtapi=API_UNSPECIFIED, name="RtMidi Client"):
        """
        Create MIDI output instance.
        
        Parameters:
        - rtapi: API backend (API_UNSPECIFIED, API_LINUX_ALSA, API_MACOSX_CORE, etc.)
        - name: Client name for MIDI system
        
        Raises:
        - SystemError: If RtMidi backend initialization fails
        - TypeError: If incompatible parameter type is passed
        """

    def get_current_api(self):
        """
        Get the low-level MIDI backend API used by this instance.
        
        Returns:
        - int: One of the API_* constants
        """

    def get_port_count(self):
        """
        Get number of available MIDI output ports.
        
        Returns:
        - int: Number of available ports
        """

    def get_port_name(self, port, encoding='auto'):
        """
        Get name of MIDI output port by number.
        
        Parameters:
        - port: Port number (0-based)
        - encoding: Text encoding ('auto', 'utf-8', 'latin1', 'macroman', or None)
        
        Returns:
        - str: Port name (if encoding specified)
        - bytes: Port name (if encoding=None)
        - None: If port name is empty
        """

    def get_ports(self, encoding='auto'):
        """
        Get list of available MIDI output port names.
        
        Parameters:
        - encoding: Text encoding for port names
        
        Returns:
        - list[str]: List of port names with index corresponding to port number
        """

    def is_port_open(self):
        """
        Check if a port is currently open.
        
        Returns:
        - bool: True if port is open (including virtual ports)
        """

    def open_port(self, port=0, name=None):
        """
        Open MIDI output port by number.
        
        Parameters:
        - port: Port number to open (default: 0)
        - name: Port name (default: "RtMidi output")
        
        Returns:
        - MidiOut: Self for method chaining
        
        Raises:
        - InvalidPortError: Invalid port number
        - InvalidUseError: Port already open
        - TypeError: Incompatible parameter type
        """

    def open_virtual_port(self, name=None):
        """
        Open virtual MIDI output port.
        
        Parameters:
        - name: Virtual port name (default: "RtMidi virtual output")
        
        Returns:
        - MidiOut: Self for method chaining
        
        Raises:
        - InvalidUseError: Port already open
        - UnsupportedOperationError: Virtual ports not supported (Windows MM)
        - TypeError: Incompatible parameter type
        """

    def close_port(self):
        """
        Close opened MIDI output port.
        Safe to call repeatedly or when no port is open.
        """

    def set_client_name(self, name):
        """
        Set MIDI client name (ALSA only).
        
        Parameters:
        - name: Client name string
        
        Raises:
        - UnsupportedOperationError: API doesn't support client name changes
        - TypeError: Incompatible parameter type
        """

    def set_port_name(self, name):
        """
        Set name of currently opened port (ALSA/JACK only).
        
        Parameters:
        - name: Port name string
        
        Raises:
        - InvalidUseError: No port currently open
        - UnsupportedOperationError: API doesn't support port name changes
        - TypeError: Incompatible parameter type
        """

    def send_message(self, message):
        """
        Send MIDI message to output port.
        
        Parameters:
        - message: Iterable of integers (0-255) representing MIDI message bytes
        
        Raises:
        - ValueError: Empty message or invalid SysEx message format
        
        Notes:
        - Normal MIDI messages: 1-3 bytes
        - SysEx messages: Must start with 0xF0 if longer than 3 bytes
        - With some APIs (Windows MM) this function blocks until message is sent
        """

    def set_error_callback(self, func, data=None):
        """
        Register error callback function.
        
        Parameters:
        - func: Error callback taking (error_type, error_message, data) arguments
        - data: User data passed to callback
        
        Note: Replaces default error handler that raises exceptions.
        """

    def cancel_error_callback(self):
        """
        Remove error callback and reinstate default error handler.
        """

    def delete(self):
        """
        Manually destroy C++ instance for immediate cleanup.
        
        Warning: Instance must not be used after calling this method.
        """

    @property
    def is_deleted(self):
        """Check if C++ instance has been destroyed."""

    def __enter__(self):
        """Context manager entry - returns self."""

    def __exit__(self, *exc_info):
        """Context manager exit - closes port automatically."""

Usage Examples

Basic MIDI Output

import rtmidi

# Create and open MIDI output
midiout = rtmidi.MidiOut()
ports = midiout.get_ports()

if ports:
    print("Available output ports:")
    for i, port in enumerate(ports):
        print(f"  {i}: {port}")
    
    midiout.open_port(0)
    print(f"Opened: {ports[0]}")
else:
    midiout.open_virtual_port("Python Virtual Out")
    print("Created virtual output port")

# Send MIDI messages
note_on = [0x90, 60, 100]  # Note On, Middle C, velocity 100
note_off = [0x80, 60, 0]   # Note Off, Middle C

midiout.send_message(note_on)
time.sleep(1.0)
midiout.send_message(note_off)

# Clean up
midiout.close_port()
del midiout

Callback-based MIDI Input

import rtmidi
import time

def midi_callback(message_data, user_data):
    message, delta_time = message_data
    print(f"MIDI: {message} (dt: {delta_time:.3f}s)")

# Create and configure MIDI input
midiin = rtmidi.MidiIn()
midiin.ignore_types(sysex=False)  # Enable SysEx reception

ports = midiin.get_ports()
if ports:
    midiin.open_port(0)
else:
    midiin.open_virtual_port("Python Virtual In")

# Set callback and wait for messages
midiin.set_callback(midi_callback)
print("Listening for MIDI messages. Press Enter to exit.")
input()

# Clean up
midiin.cancel_callback()
midiin.close_port()
del midiin

Context Manager Usage

import rtmidi

# Automatic resource cleanup with context manager
with rtmidi.MidiOut() as midiout:
    if midiout.get_port_count() > 0:
        midiout.open_port(0)
        midiout.send_message([0x90, 64, 100])  # Send note
        time.sleep(0.5)
        midiout.send_message([0x80, 64, 0])    # Stop note
    # Port automatically closed when exiting context

Install with Tessl CLI

npx tessl i tessl/pypi-python-rtmidi

docs

index.md

midi-constants.md

midi-io.md

midi-utilities.md

tile.json