AlexM posted Sep 23 '16, 15:26:
Hey all
I've noticed when using 2 midi devices (eg Korg MicroKey + nanoKontrol2, or a Novation LaunchKey which is recognised as 2 devices), I get this error after every few notes played:
MidiInAlsa::alsaMidiHandler: unknown MIDI input error!
I found that Joseph has had this issue over a year ago: https://github.com/superquadratic/rtmidi-python/issues/18 -- any leads here? It would be great to utilise 2 midi devices so that I can assign pots and faders to various parameters (I'm tinkering with Erik's SamplerBox2 which utilises freeverb and some tone controls)
Cheers!
AlexM posted Sep 26 '16, 09:30:
SOLVED! Or so I hope...
Had a bit of a look around for a different MIDI module and came across RTMIDI2 which specifically says can open multiple ports at once https://pypi.python.org/pypi/rtmidi2
Installed, imported, and replaced the Midi Devices Detection / Main Loop section with the following:
midi_in = rtmidi2.MidiInMulti().open_ports("*")
midi_in.callback = MidiCallback
No more errors, ghost notes or strange behaviours.
HansEhv posted Sep 26 '16, 21:43:
Hello Alex,
Thanks for sharing this!
But how does your main loop now look like?
The original:
---snip---
while True:
for port in midi_in[0].ports:
if port not in previous and 'Midi Through' not in port:
midi_in.append(rtmidi.MidiIn())
midi_in[-1].callback = MidiCallback
midi_in[-1].open_port(port)
print 'Opened MIDI: '+ port
previous = midi_in[0].ports
time.sleep(2)
---snip---
This one relies on the individual ports, how does your version test and loop?
HansEhv posted Sep 26 '16, 21:45:
..and now with dashes showing the indent :-)
while True:
- for port in midi_in[0].ports:
-- if port not in previous and 'Midi Through' not in port:
-- midi_in.append(rtmidi.MidiIn())
-- midi_in[-1].callback = MidiCallback
-- midi_in[-1].open_port(port)
-- print 'Opened MIDI: '+ port
- previous = midi_in[0].ports
- time.sleep(2)
AlexM posted Sep 27 '16, 09:39:
I actually just replaced the whole loop/section with those 2 lines. What would you suggest?
HansEhv posted Sep 27 '16, 12:12:
I thought of having the 'while true:' infinite loop with :
-These 2 statements
-The sleep delay. This to give more room for the other processes. It could even be longer as you don't plug/replug your midi interfaces that often.
HansEhv posted Sep 27 '16, 12:19:
Sorry, forgot a question: how do you now see the opened port(s)?
AlexM posted Sep 27 '16, 16:08:
Hey Hans,
I added these lines below (I'm hoping BB code works here otherwise I'll need to post again!)
This will also close all ports when a device change is detected and attempt to reopen whatever is now connected. (although when disconnecting my nanoKontrol, RPi wigs out with "usb 1-1.3: urb status -32" errors)
[code]
stopit = False
midi_in = rtmidi2.MidiInMulti()
curr_ports = []
prev_ports = []
first_loop = True
while True:
if stopit:
break
curr_ports = rtmidi2.get_in_ports()
if (len(prev_ports) != len(curr_ports)):
midi_in.close_ports()
prev_ports = []
for port in curr_ports:
if port not in prev_ports and 'Midi Through' not in port and (len(prev_ports) != len(curr_ports)):
midi_in.open_ports(port)
midi_in.callback = MidiCallback
if first_loop:
print 'Opened MIDI port: ' + port
else:
print 'Reopening MIDI port: ' + port
prev_ports = curr_ports
first_loop = False
time.sleep(2)
[/code]
AlexM posted Sep 27 '16, 16:10:
Ah damn - does anyone know how to format code in this forum? :(
remi posted Sep 27 '16, 17:35:
If i'm not wrong this should works like github
https://help.github.com/articles/creating-and-highlighting-code-blocks/
Or just past your code in here : https://gist.github.com/ (you don't need an account)
Test
stopit = False
midi_in = rtmidi2.MidiInMulti()
curr_ports = []
prev_ports = []
first_loop = True
while True:
if stopit:
break
curr_ports = rtmidi2.get_in_ports()
if (len(prev_ports) != len(curr_ports)):
midi_in.close_ports()
prev_ports = []
for port in curr_ports:
if port not in prev_ports and 'Midi Through' not in port and (len(prev_ports) != len(curr_ports)):
midi_in.open_ports(port)
midi_in.callback = MidiCallback
if first_loop:
print 'Opened MIDI port: ' + port
else:
print 'Reopening MIDI port: ' + port
prev_ports = curr_ports
first_loop = False
time.sleep(2)
AlexM posted Sep 27 '16, 17:45:
HansEhv posted Sep 27 '16, 23:40:
Many thanks guys, this is very useful.
Kevin Chau posted Nov 7 '16, 23:29:
Installing rtmidi2 also solved ghost notes and bad midi input for the mpkmini mk2 that i am using. Thanks for the solution
AlexM posted Nov 8 '16, 06:57:
Good to know!
There's still a bug that causes SamplerBox to crash when connecting/disconnecting midi devices. I have a few ideas on the cause(s) which I'll test in time. But for the time being this solution seems to be working well for the most part!
David Dawkins posted Nov 29 '23, 22:39:
If anyone else finds this thread useful (as I did), then I think this was the intended indentation for AlexM's code:
stopit = False
midi_in = rtmidi2.MidiInMulti()
curr_ports = []
prev_ports = []
first_loop = True
while True:
if stopit:
break
curr_ports = rtmidi2.get_in_ports()
if (len(prev_ports) != len(curr_ports)):
midi_in.close_ports()
prev_ports = []
for port in curr_ports:
if port not in prev_ports and 'Midi Through' not in port and (len(prev_ports) != len(curr_ports)):
midi_in.open_ports(port)
midi_in.callback = MidiCallback
if first_loop:
print ('Opened MIDI port: ' + port)
else:
print ('Reopening MIDI port: ' + port)
prev_ports = curr_ports
first_loop = False
time.sleep(2)