-
Notifications
You must be signed in to change notification settings - Fork 1
/
MidiToClick.py
71 lines (61 loc) · 2.59 KB
/
MidiToClick.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# pip install mido pyautogui python-rtmidi
import csv
import mido
import pyautogui
# Ask the user what action to take
user_action = input("Type 'move' to move the mouse or 'click' to click: ").strip().lower()
# Validate user input
if user_action not in ['move', 'click']:
print("Invalid action. The script will exit.")
exit(1)
def note_name_to_midi(note_name):
notes = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
note = ''.join([c for c in note_name if c.isalpha()])
octave = int(''.join([c for c in note_name if c.isdigit()]))
note_index = notes.index(note)
midi_number = (octave + 1) * 12 + note_index
return midi_number
def load_config_csv(config_path):
note_to_position = {}
with open(config_path, newline='') as csvfile:
csvreader = csv.reader(csvfile)
next(csvreader, None) # Skip the header row
for row in csvreader:
if not row or row[0].startswith("#"): # Skip empty lines or comments
continue
note_name, x, y = row
midi_note = note_name_to_midi(note_name)
note_to_position[midi_note] = (int(x), int(y))
return note_to_position
# Ask the user for the configuration file name
config_filename = input("Enter the configuration CSV file name: ").strip()
note_to_position = load_config_csv(config_filename)
# This function converts MIDI note numbers to note names (e.g., 60 -> 'C4')
def note_number_to_name(note_number):
return mido.get_note_name(note_number)
# Open the MIDI input port.
input_name = mido.get_input_names()[0]
inport = mido.open_input(input_name)
print(f"Listening for MIDI input on '{input_name}'... Press Ctrl+C to stop.")
try:
for msg in inport:
if msg.type == 'note_on':
note_name = note_number_to_name(msg.note)
note_number = msg.note
if msg.velocity > 0:
print(f"Note ON: {note_name} (Number: {note_number})")
if note_number in note_to_position:
x, y = note_to_position[note_number]
print(f" -> Clicking at position ({x}, {y})")
if user_action == 'click':
pyautogui.click(x, y) # Click at the mapped location
else: # default to move if not click
pyautogui.moveTo(x, y) # Move the mouse to the mapped location
else:
print(" -> Note OFF")
except KeyboardInterrupt:
print("Exiting...")
except Exception as e:
print(f"An error occurred: {e}")
finally:
inport.close() # Close the MIDI port when you're done