#!/usr/bin/env python3 import time import mido def match_device_name(input_name, output_list): # Function to match device names flexibly for device in output_list: if any(substring in device for substring in input_name.split()): return device return None def determine_host(devices_in): master = None """ Determine the host by listening for 'start' messages on input ports. Args: - devices_in (list of str): The names of the MIDI input ports to listen to. Returns: - str: The name of the input port that received the 'start' message. """ # Open all the input ports inports = [mido.open_input(device) for device in devices_in] # Create a MultiPort to listen on all input ports #ports = MultiPort(inports, True) print("Listening for messages...") try: while not master: for port in inports: for message in port.iter_pending(): #print(f"Received message: ({port.name}, {message})") if 'start' in str(message): master = port.name break except KeyboardInterrupt: print("Interrupted by user.") finally: # Ensure all ports are closed for port in inports: port.close() print("Closed all input ports.") if master: return master def relay_midi_host_to_out(host_name, devices_out): """ Relay MIDI messages from a specific input port to all specified output ports. Args: - host_name (str): The name of the MIDI input port to listen to. - devices_out (list of str): The names of the MIDI output ports to send messages to. """ #host_name = f'{host_name}' reset = False # Open the input port print("Opening Input ffsk", host_name) input_port = mido.open_input(host_name) output_ports = [mido.open_output(device) for device in devices_out] print(f"Listening for messages on {host_name} and relaying to {devices_out}") recent_messages = [] try: print(reset) while not reset: # Process all pending messages #print("Entering loop", input_port.iter_pending() ) for message in input_port.iter_pending(): read_message = str(message) #spread_the_word = MultiPort(output_ports) #print(read_message) if 'start' in read_message or 'stop' in read_message: for dev in output_ports: dev.send(message) recent_messages.append(read_message) #print("SS") elif 'clock' in read_message: for dev in output_ports: dev.send(message) #print("clock") # Keep only the last 3 messages if len(recent_messages) > 3: recent_messages.pop(0) # Check if the last 3 messages are all 'stop' if recent_messages[-3:] == ['stop time=0', 'stop time=0', 'stop time=0']: #print("Received 'stop' three times in a row") # Perform the desired action when 'stop' is received three times in a row # For example, resetting the list recent_messages.clear() reset = True break except KeyboardInterrupt: # Handle user interrupt (e.g., Ctrl+C) print("MIDI relay interrupted by user.") finally: # Close all ports input_port.close() print(input_port) for port in output_ports: #port.reset() port.close() print(port) print("Closed all MIDI ports.") #Repeat host detection a nd main loop time.sleep(1) main_run() def main_run(): # Retrieve the list of available input devices devices_in = mido.get_input_names() devices_out = mido.get_output_names() print("Available MIDI input devices:", devices_in) # Call the function to start receiving messages from all devices midi_host_in = determine_host(devices_in) print(midi_host_in) # Find and remove the matching output device to avoid feedback matching_output_device = match_device_name(midi_host_in, devices_out) if matching_output_device: devices_out.remove(matching_output_device) print(devices_out) #time.sleep(3) if midi_host_in: relay_midi_host_to_out(midi_host_in, devices_out) print("mido died") main_run()