Skip to content

Commit 8ed2edf

Browse files
midi cc out
1 parent 33b0620 commit 8ed2edf

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

src/goofi/nodes/outputs/midiccout.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import threading
2+
import mido
3+
from goofi.data import Data, DataType
4+
from goofi.node import Node
5+
from goofi.params import StringParam, IntParam, BoolParam
6+
7+
class MidiCCout(Node):
8+
def config_input_slots():
9+
return {
10+
"cc1": DataType.ARRAY,
11+
"cc2": DataType.ARRAY,
12+
"cc3": DataType.ARRAY,
13+
"cc4": DataType.ARRAY,
14+
"cc5": DataType.ARRAY
15+
}
16+
17+
def config_output_slots():
18+
return {
19+
"midi_status": DataType.STRING
20+
}
21+
22+
def config_params():
23+
available_ports = mido.get_output_names()
24+
return {
25+
"MIDI": {
26+
"port_name": StringParam("", options=available_ports, doc="MIDI output port name"),
27+
"channel": IntParam(1, 1, 15, doc="MIDI channel"),
28+
"cc1": IntParam(1, 0, 127, doc="MIDI CC number for input 1"),
29+
"cc2": IntParam(2, 0, 127, doc="MIDI CC number for input 2"),
30+
"cc3": IntParam(3, 0, 127, doc="MIDI CC number for input 3"),
31+
"cc4": IntParam(4, 0, 127, doc="MIDI CC number for input 4"),
32+
"cc5": IntParam(5, 0, 127, doc="MIDI CC number for input 5")
33+
}
34+
}
35+
36+
def send_cc(self, outport, cc_number, value, channel):
37+
"""Send a MIDI CC message."""
38+
# convert cc_number to int
39+
cc_number = int(cc_number)
40+
value = int(value)
41+
outport.send(mido.Message('control_change', control=cc_number, value=value, channel=channel))
42+
43+
def process(self, cc1: Data, cc2: Data, cc3: Data, cc4: Data, cc5: Data):
44+
port_name = self.params.MIDI["port_name"].value
45+
channel = self.params.MIDI["channel"].value
46+
channel = channel - 1 # MIDI channels are 0-indexed
47+
cc_numbers = [
48+
self.params.MIDI["cc1"].value,
49+
self.params.MIDI["cc2"].value,
50+
self.params.MIDI["cc3"].value,
51+
self.params.MIDI["cc4"].value,
52+
self.params.MIDI["cc5"].value
53+
]
54+
cc_data = [cc1, cc2, cc3, cc4, cc5]
55+
56+
outport = mido.open_output(port_name) if port_name != 'goofi' else self.goofi_port
57+
58+
alert_on = False
59+
try:
60+
threads = []
61+
for i, data in enumerate(cc_data):
62+
if data is not None and len(data.data) > 0:
63+
for value in data.data:
64+
if value < 0 or value > 127:
65+
print(f'Value outside of MIDI 0-127 range: {value}')
66+
alert_on = True
67+
error_message = f'Value outside of MIDI 0-127 range: {value}'
68+
pass
69+
t = threading.Thread(target=self.send_cc, args=(outport, cc_numbers[i], value, channel))
70+
t.start()
71+
threads.append(t)
72+
73+
for t in threads:
74+
t.join()
75+
finally:
76+
if port_name != 'goofi':
77+
outport.close() # Ensure that the MIDI port is closed when done
78+
79+
if alert_on:
80+
return {
81+
"midi_status": (f"CC messages sent with errors\n{error_message}", cc1.meta)
82+
}
83+
else:
84+
return {
85+
"midi_status": ("CC messages sent successfully", cc1.meta)
86+
}

0 commit comments

Comments
 (0)