So, I started doing some coding and I'm wondering if you could give me some advice. Since you are the developer of this library, you know for sure what it is needed to be done for a proper execution. You can for sure use my code if you want to write your own example.
Right now, I'm only handling NOTE ON events, but I will extend it to the other messages. Here my code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# midiinputhandler.py
#
"""Wrap MidiIn to add convenience methods for catching common MIDI events."""
from __future__ import print_function
from rtmidi.midiconstants import (ALL_NOTES_OFF, ALL_SOUND_OFF, BALANCE,
BANK_SELECT_LSB, BANK_SELECT_MSB,
BREATH_CONTROLLER, CHANNEL_PRESSURE,
CHANNEL_VOLUME, CONTROL_CHANGE,
DATA_ENTRY_LSB, DATA_ENTRY_MSB,
END_OF_EXCLUSIVE, EXPRESSION_CONTROLLER,
FOOT_CONTROLLER, LOCAL_CONTROL,
MIDI_TIME_CODE, MODULATION, NOTE_OFF,
NOTE_ON, NRPN_LSB, NRPN_MSB, PAN, PITCH_BEND,
POLY_PRESSURE, PROGRAM_CHANGE,
RESET_ALL_CONTROLLERS, RPN_LSB, RPN_MSB,
SONG_POSITION_POINTER, SONG_SELECT,
TIMING_CLOCK)
import time
class MidiInWrapper:
def __init__(self, midi_in, midi_out):
"""
Initializes the class attributes
Parameters:
* midi_in: MIDI IN interface to use
* midi_out: MIDI OUT interface to use
"""
#I don't really know if I really need this clock for a real world use case
self._wallclock = time.time()
self._midi_in = midi_in
self._midi_out = midi_out
self._note_on_callback = None
#Sets the main MIDI callback where all preprocessing will be done
print("Setting callback")
self._midi_in.set_callback(self)
def __call__(self, event, data = None):
message, deltatime = event
self._wallclock += deltatime
message_type = message[0] & 0xF0
if (message_type == NOTE_ON):
print("Note on was detected")
self._handle_note_on(message, data)
else:
print("Nothing was detected")
#Raise error here
pass
def _handle_note_on(self, message, data = None):
"""
Handles a NOTE ON message. By default it just sends it back
"""
if self._note_on_callback == None:
print("Sending message normally")
self._midi_out.send_message(message)
else:
print("Sending message through callback")
callback, data = self._note_on_callback
callback(message, data)
def set_note_on(self, callback, data = None):
"""
Sets the NOTE ON callback
Parameters:
* callback: function that will be executed each time a NOTE ON message
is catched
* data: pointer to user data that can be used inside the callback. It
can be litterally everything you want: an integer, an string, an
object, etc..
"""
self._note_on_callback = callback, data
if __name__ == '__main__':
#Note: this section serves for demostrative purposes. In a real use case,
# you should define your own callback function or a class with
# callback methods
from rtmidi.midiutil import open_midioutput, open_midiinput
#You can use callback functions or a class defining your callbacks. This is
#up to you
def send_note_on(message, data):
"""
Callback function
Parameters:
* message: Contains a list with the bytes of the MIDI Message, ie:
[147, 60, 112] (in Hexadecimal: 93 00 64) represents a sending a
middle C NOTE ON with a velocity of 112 through the MIDI channel
4.
* data: pointer to user data that can be used inside the callback.
It can be litterally everything you want: an integer, an string,
an object, etc.. If you don't need it, then you should change the
signature of the function to:
def send_note_on(message, data = None):
"""
print("Note on callback")
data.send_message(message)
class MidiCallbacks:
"""
Class defining the callbacks
"""
def __init__(self, midi_in, midi_out):
"""
Initializes the class attributes
"""
self._midi_in = midi_in
self._midi_out = midi_out
def send_note_on(self, message, data = None):
"""
Callback method for NOTE ON messages
Parameters:
* message: Contains a list with the bytes of the MIDI Message, ie:
[147, 60, 112] (in Hexadecimal: 93 00 64) represents a sending a
middle C NOTE ON with a velocity of 112 through the MIDI channel
4.
* data: pointer to user data that can be used inside the callback.
It can be litterally everything you want: an integer, an string,
an object, etc.. On this case, I'm not using it.
"""
print("Note on callback")
self._midi_out.send_message(message)
print("")
#Open a MIDI IN and OUT ports. Let's say you have two ports: Port01 and
#Port02. For testing, first start this script and set the following:
#* Input port: Port01
#* Output port: Port02
#Then start an application that sends and receives MIDI messages, ie: Bome
#SendSX, there set the ports as follows:
#* Input port: Port02
#* Output port: Port01
#Finally start sending MIDI messages from your MIDI application. You should
#see the same messages in the MIDI IN and OUT. In the console there should
#be some debug messages
midi_out, out_port = open_midioutput(interactive = True)
midi_in_wrapper = MidiInWrapper(midi_in, midi_out)
#Uncomment this to use with a callback function
#midi_in_wrapper.set_note_on(send_note_on, midi_out)
#I preffer to use a class for my callbacks.
#First an instance must be created
midi_callbacks = MidiCallbacks(midi_in, midi_out)
#Then each callback must be set in the MidiInWrapper object
midi_in_wrapper.set_note_on(midi_callbacks.send_note_on)
print("Entering main loop. Press Control-C to exit.")
try:
# Just wait for keyboard interrupt,
# everything else is handled via the input callback.
while True:
time.sleep(1)
except KeyboardInterrupt:
print('')
finally:
print("Exit.")
midi_in.close_port()
midi_out.close_port()
del midi_in
del midi_out