Well, it's all been finished up. The finishing touches (more elaborate comments, etc) have not been applied just yet, but it appears to work with the script.
Not sure how this works on a Mac, but it shouldn't be difficult if the RTMIDI toolkit has been properly installed. I don't have a Mac, so am not sure what to say. With windows, I installed RTMIDI without any trouble once I had Visual C++ 2008 Express Edition installed. Apparently you need it for RTMIDI when you set it up. Something to do with VCVARSALL.BAT...which before the VC++2008 install it was missing ;)
Here is the code. It's not all that complicated, but it took me a good week to refine it.
import rtmidi_python as rtmidi
import sched, time, unittest
import sys
import optparse
import math
import xmlrpclib
port_to_open = 2
chord_str = ""
midi_num = 0
chord_array = [0, 0, 0, 0, 0, 0 ,0, 0]
mdelay = 0.01 # 10ms
chord_str = ""
# use callback instead
def midi_callback(message, time_stamp):
global chord_str
global chord_array
global midi_num
global port_to_open
# print "MSG: ", message[0], message[1], message[2], midi_num
if message[0] > 143:
if message[0] 7: # number of NOTE_ON messages
midi_num = 7
# main program params
prog_condition = True
old_time_count = 0 # main initial time counter
time_count = 0 # main time counter
#command line data structure
intportval = 0
floattiming = 0.250
boolchordprint = True
# time params
midi_port_count = 0 #define the port count integer
#midi param specifics
midi_num_events = 0 # total events in a xxx-second cycle
#important for determining the chord size. 3 events = 3 notes, etc.
midi_data_whole = 0
midi_data_1 = 0
midi_data_2 = 0
midi_in = None
midi_in = rtmidi.MidiIn()
for port_name in midi_in.ports:
print port_name, midi_port_count
midi_port_count = midi_port_count + 1
old_time_count = time.time()
# main program
stored_time = time.time() #we set the stored time to the current time
#start up the server
belscript=xmlrpclib.Server('http://localhost:55553')
# let's determine what options the user has specified in the command line
print 'ARGV :', sys.argv[1:]
parser = optparse.OptionParser()
parser.add_option('-p', '--p',
dest="portval",
default=0,
)
parser.add_option('-c', '--c',
dest="chordprintval",
default=False,
action="store_true",
)
parser.add_option('-t', '--t',
dest="timingval",
default=0.25,
type="float",
)
options, remainder = parser.parse_args()
print 'PORT NUMBER : ', options.portval
print 'PRINTING OFF : ', options.chordprintval
print 'TIMING SEC : ', options.timingval
intportval = int(options.portval)
floattiming = options.timingval
boolchordprint = options.chordprintval
# open MIDI port
print ("opening MIDI port")
midi_num = 0
note_index = 0
midi_in.callback = midi_callback
midi_in.open_port(intportval) # we open the port now
stored_time = time.time()
chord_tonic = ""
chord_name = ""
chord_sdat = ""
tonic_belcanto = ""
# tell belcanto to ensure all agents will respond to commands
belcommand = "all join"
belscript.execBelcanto(belcommand)
while (prog_condition == True):
time_count = time.time() - old_time_count
current_time = time.time()
if (time_count > floattiming): #default to 0.25 seconds
# do the chord check here:
#if midi_num > 0: print ("Chord check")
time_count = time.time()
old_time_count = time.time() #reset timer
# test chord tonic
if chord_array[0] % 12 is 0:
chord_tonic = "C"
tonic_belcanto = "notec"
if chord_array[0] % 12 is 1:
chord_tonic = "C#"
tonic_belcanto = "notecsharp"
if chord_array[0] % 12 is 2:
chord_tonic = "D"
tonic_belcanto = "noted"
if chord_array[0] % 12 is 3:
chord_tonic = "D#"
tonic_belcanto = "notedsharp"
if chord_array[0] % 12 is 4:
chord_tonic = "E"
tonic_belcanto = "notee"
if chord_array[0] % 12 is 5:
chord_tonic = "F"
tonic_belcanto = "notef"
if chord_array[0] % 12 is 6:
chord_tonic = "F#"
tonic_belcanto = "notefsharp"
if chord_array[0] % 12 is 7:
chord_tonic = "G"
tonic_belcanto = "noteg"
if chord_array[0] % 12 is 8:
chord_tonic = "G#"
tonic_belcanto = "notegsharp"
if chord_array[0] % 12 is 9:
chord_tonic = "A"
tonic_belcanto = "notea"
if chord_array[0] % 12 is 10:
chord_tonic = "A#"
tonic_belcanto = "noteasharp"
if chord_array[0] % 12 is 11:
chord_tonic = "B"
tonic_belcanto = "noteb"
# determine chord structure
if midi_num > 0:
while note_index 0: chord_sdat = chord_sdat + "," + str(chord_array[note_index] - chord_array[0])
note_index = note_index + 1
#print "Chord string data: ", chord_sdat, " tonic = ", chord_tonic
# determine what the chord is, talk to Belcanto
if chord_sdat == "0,5,7": chord_name = "CHORD_Sus4"
if chord_sdat == "0,5,7,10": chord_name = "CHORD_7Sus4"
if chord_sdat == "0,5,7,10,16": chord_name = "CHORD_7Sus4(10)"
if chord_sdat == "0,2,7": chord_name = "CHORD_Sus2"
if chord_sdat == "0,4,8": chord_name = "CHORD_Aug"
if chord_sdat == "0,4,8,10": chord_name = "CHORD_7(#5)"
if chord_sdat == "0,4,8,11": chord_name = "CHORD_Maj7(#5)"
if chord_sdat == "0,4,7": chord_name = "CHORD_Major"
if chord_sdat == "0,2,4,7": chord_name = "CHORD_Add2"
if chord_sdat == "0,4,5,7": chord_name = "CHORD_Add4"
if chord_sdat == "0,4,7,9": chord_name = "CHORD_6"
if chord_sdat == "0,4,7,10": chord_name = "CHORD_7"
if chord_sdat == "0,4,7,11": chord_name = "CHORD_Maj7"
if chord_sdat == "0,4,7,14": chord_name = "CHORD_Add9"
if chord_sdat == "0,4,5,7,9": chord_name = "CHORD_6Add4"
if chord_sdat == "0,4,5,7,11": chord_name = "CHORD_Maj7Add4"
if chord_sdat == "0,4,7,9,14": chord_name = "CHORD_6Add9"
if chord_sdat == "0,4,7,10,13": chord_name = "CHORD_7(b9)"
if chord_sdat == "0,4,7,10,14": chord_name = "CHORD_9"
if chord_sdat == "0,4,7,10,15": chord_name = "CHORD_7(#9)"
if chord_sdat == "0,4,7,10,21": chord_name = "CHORD_7(13)"
if chord_sdat == "0,4,7,11,14": chord_name = "CHORD_Maj7(9)"
if chord_sdat == "0,4,7,11,21": chord_name = "CHORD_Maj7(13)"
if chord_sdat == "0,4,7,10,13,15": chord_name = "CHORD_7(b9#9)"
if chord_sdat == "0,4,7,10,14,18": chord_name = "CHORD_7(9#11)"
if chord_sdat == "0,4,7,10,14,21": chord_name = "CHORD_7(913)"
if chord_sdat == "0,4,7,11,14,17": chord_name = "CHORD_Maj7(911)"
if chord_sdat == "0,4,7,10,14,17,21": chord_name = "CHORD_7(91113)"
if chord_sdat == "0,4,6": chord_name = "CHORD_b5"
if chord_sdat == "0,4,6,9": chord_name = "CHORD_6(b5)"
if chord_sdat == "0,4,6,10": chord_name = "CHORD_7(b5)"
if chord_sdat == "0,4,6,11": chord_name = "CHORD_Maj7(b5)"
if chord_sdat == "0,4,6,10,15": chord_name = "CHORD_7(b5#9)"
if chord_sdat == "0,3,8,10": chord_name = "CHORD_m7(#5)"
if chord_sdat == "0,3,7": chord_name = "CHORD_Minor"
if chord_sdat == "0,3,7,9": chord_name = "CHORD_m6"
if chord_sdat == "0,3,7,10": chord_name = "CHORD_m7"
if chord_sdat == "0,3,7,11": chord_name = "CHORD_m(Maj7)"
if chord_sdat == "0,3,5,7,10": chord_name = "CHORD_m7Sus4"
if chord_sdat == "0,3,7,9,14": chord_name = "CHORD_m6Add9"
if chord_sdat == "0,3,7,10,13": chord_name = "CHORD_m7(b9)"
if chord_sdat == "0,3,7,10,14": chord_name = "CHORD_m9"
if chord_sdat == "0,3,7,10,14,17": chord_name = "CHORD_m11"
if chord_sdat == "0,3,7,10,14,17,21": chord_name = "CHORD_m13"
if chord_sdat == "0,3,6": chord_name = "CHORD_Dim"
if chord_sdat == "0,3,6,9": chord_name = "CHORD_Dim7"
if chord_sdat == "0,3,6,10": chord_name = "CHORD_m7(b5)"
if boolchordprint == False: print chord_tonic, chord_name, midi_num, "notes" #if printout is enabled, print the chord info
note_index = 0
midi_num = 0
chord_sdat = ""
# talk to belcanto here
# set up the scale (to play notes of the chord)
if chord_name "":
belcommand = "scale to " + chord_name + " set"
belscript.execBelcanto(belcommand)
belcommand = "tonic to " + tonic_belcanto + " set"
belscript.execBelcanto(belcommand)
# the MIDI message printout
midi_in.close_port() # close the port
midi_in = None
midi_out = None
exit