def getDeviceList(self): midiin = MidiIn() midiout = MidiOut() try: return (midiin.get_ports(), midiout.get_ports()) except Exception as e: if DEBUG == True: print(e) return False
def list_ports(): midi_in = None midi_out = None try: api_out = MidiOut() api_in = MidiIn() ports = api_in.get_ports() return ports except: print("Unable to open MIDI ports") return
def __init__(self, interpreters, port): super(InStream, self).__init__() self.interpreters = interpreters self.port = port self.wallclock = timenow() try: self.midiin = MidiIn().open_port(port) print("Listening for midi on input port {}".format(port)) except Exception: print("WARNING: failed to open MIDI-in port {0}".format(port)) self.done = False self.run = self.run_bound if Parameters.SP.ATTRACTOR_MODE == 1 else self.run_att # print(self.run.__name__) self.start()
def setup_input(self): api_in = MidiIn() api_in.ignore_types(sysex=False) port_in = self.get_mixer_port(api_in) try: midi_in, port_name = open_midiinput(port_in, interactive=False) except InvalidPortError: return except NoDevicesError: return midi_in.ignore_types(sysex=False) midi_in.set_callback(self.listener) self.api_in = api_in self.input = midi_in return port_name
def read_midi(): alsa_midi = MidiIn(API_LINUX_ALSA) print(alsa_midi.get_ports()) selected_port = int(input("Select port: ")) with alsa_midi.open_port(selected_port) as open_port: timer = time.time() try: while True: message = open_port.get_message() if message: message, deltatime = message timer += deltatime print(" @%0.6f %r" % (timer, message)) print(message) except KeyboardInterrupt: print('') finally: print("Exit.")
def receive_sysex(midi_in: MidiIn) -> List[int]: message = None while True: raw_tuple = midi_in.get_message() if raw_tuple: message = raw_tuple[0] break sleep(0.01) assert len(message) == 117 assert message[4] == 103 # Flip 4-th position from DEC 103 (HEX 67) to DEC 100 (HEX 64) # to flip patch from 'Receive' to 'Send' message[4] = 100 message_hex = ''.join([str(hex(m))[2:].zfill(2) for m in message]) logging.debug(f'- RECEIVED {len(message)} BYTES. SYSEX:\n{message_hex}') return message
def _open_midi(self): """Starts MIDI without opening a port""" self.__log.info("Opening MIDI interfaces") try: self._midi_out = MidiOut() self._midi_in = MidiIn() #Note: if you need to catch SysEx, MIDI clock, and active sense #messages, then use the method: ignore_types as follows: #self._midi_in.ignore_types(sysex = False, timing = False, # active_sense = False) #They are ignored by default. I don't need this right now, so the #standard behaviour is OK for me except: error = traceback.format_exc() self.__log.info(error) self._free_midi() return False self.__log.debug("MIDI interfaces were opened") return True
def get_ports(port_name: str, *, clock_source: bool = False) -> Tuple[MidiIn, MidiOut]: midi_in = MidiIn() midi_out = MidiOut() midi_in_ports = midi_in.get_ports() midi_out_ports = midi_out.get_ports() try: midi_in.open_port(midi_in_ports.index(port_name)) except ValueError: raise ValueError(port_name) from None if clock_source: midi_in.ignore_types(timing=False) try: midi_out.open_port(midi_out_ports.index(port_name)) except ValueError: raise ValueError(port_name) from None return midi_in, midi_out
from miniaudio import Backend, Devices from rtmidi import MidiIn, MidiOut print("- Audio devices") for backend in Backend: try: devices = Devices([backend]).get_playbacks() print(f" - {backend}") for device in devices: name = device["name"] print(f" 🔊 {name}") except: pass print("- MIDI inputs") for port in MidiIn().get_ports(): print(f" 🎶 {port}") print("- MIDI outputs") for port in MidiOut().get_ports(): print(f" 🎶 {port}") print( """ Note that this script can display a lot of error or warning messages from other libraries when trying to open backends that don't exist, or when probing interfaces on some backends. Pay attention only to the lines with 🔊 and 🎶! """ )
class Device: MIDI_IN = None MIDI_OUT = None MIDI_PORT_COUNT = 0 IS_FIRST_CONNECTION = True UPDATE_LIST = [] KEY_BINDINGS = {} PULSE_AUDIO = PulseAudioHelper() XORG = XorgHelper() def __init__(self, name='Generic Device', regex=None): self.NAME = name self.DEVICE_REGEX = regex self.UPDATE_LIST.append(self.update_midi_connection_on_reconnect) def __enter__(self): self.MIDI_IN = MidiIn() self.MIDI_OUT = MidiOut() return self def __exit__(self, _type, _value, _traceback): del self.MIDI_IN, self.MIDI_OUT def __repr__(self): return self.NAME def update(self, ELAPSED_TIME): for update in self.UPDATE_LIST: update(ELAPSED_TIME) def send_signal(self, channel, key, payload): self.MIDI_OUT.send_message([channel, key, payload]) def update_midi_connection_on_reconnect(self, _elapsed_time): current_port_count = len([ x for x in self.MIDI_OUT.get_ports() if not re.search(r'[rR]t[Mm]idi', x) ]) if current_port_count != self.MIDI_PORT_COUNT: self.MIDI_PORT_COUNT = current_port_count self.activate() def activate(self): if self.DEVICE_REGEX is not None: self.activate_ports() def activate_ports(self): activated = False self.MIDI_IN.close_port() self.MIDI_OUT.close_port() if not self.IS_FIRST_CONNECTION: print(f'{self} disconnected!') sleep(1.0) for midi in (self.MIDI_IN, self.MIDI_OUT): port_number = None for i, port_name in enumerate(midi.get_ports()): if re.search(self.DEVICE_REGEX, port_name): port_number = i break if port_number is not None: midi.open_port(port_number) activated = True if activated: self.IS_FIRST_CONNECTION = False print(f'{self} connected!') self.MIDI_IN.set_callback(self.input_callback) def input_callback(self, midi_signal_in, *_args, **_kwargs): byte_signal = midi_signal_in[0] key = str(byte_signal[1]) if key in self.KEY_BINDINGS.keys(): self.KEY_BINDINGS[key](byte_signal) else: self.animation_callback(byte_signal) def animation_callback(self, byte_signal): print(f'{self}:{byte_signal}')
def __enter__(self): self.MIDI_IN = MidiIn() self.MIDI_OUT = MidiOut() return self
from serial import Serial from time import time, sleep from rtmidi import MidiIn, MidiOut from _thread import start_new_thread mode = 0 pir_mode_color = [False, False, True] open_ports = [] LEDs = [] PIRs = [] m_out = MidiOut().open_virtual_port("Python PIR Output") melody_in = MidiIn().open_virtual_port("Python Melody Input") drum_in = MidiIn().open_virtual_port("Python Drum Input") last_drum = 0 DRUM_TIMEOUT = 0.1 PIR_TIMEOUT = 0.7 stair_modes = [ [48, 50, 52, 53, 55, 57, 59, 60], [ [48, 52, 55], [50, 53, 57], [52, 55, 59], [53, 57, 60], [55, 59, 62],
name)) else: check_value(name, value) if name == 'data': vars(self)['data'] = SysexData(value) else: vars(self)[name] = value __setattr__ = _setattr def bytes(self): """Encode message and return as a list of integers.""" return encode_message(vars(self)) midi_in = MidiIn() midi_out = MidiOut() in_ports = midi_in.get_ports() out_ports = midi_out.get_ports() print("IN ports:", in_ports) print("OUT ports:", out_ports) def call_obs_api(command='pause-toggle'): url = f'http://localhost:28000/{command}' print("Calling:", url) response = requests.get(url).json() print("OBS RESPONSE:", response)
class InStream(threading.Thread): """ Polls midi-in and publish the events Based on the midiin_callback code from python rt-midi examples """ def __init__(self, interpreters, port): super(InStream, self).__init__() self.interpreters = interpreters self.port = port self.wallclock = timenow() try: self.midiin = MidiIn().open_port(port) print("Listening for midi on input port {}".format(port)) except Exception: print("WARNING: failed to open MIDI-in port {0}".format(port)) self.done = False self.run = self.run_bound if Parameters.SP.ATTRACTOR_MODE == 1 else self.run_att # print(self.run.__name__) self.start() def run_att(self): """ For use with attractor mode 2, which is old and bad """ # TODO experimental timings buffer_time = 0.05 while not self.done: started = timenow() buffer = list() while (timenow() - started) < buffer_time: msg = self.midiin.get_message() if msg: buffer.append(msg) sleep(0.002) chord_time = buffer_time if len(buffer) >= 1: if buffer[0]: chord_time = buffer[0][1] for msg in buffer: message, delta_time = msg # TODO for now only listen to NOTE_ON & OFF if 128 <= message[0] < 160: self.wallclock += delta_time # print("[%s] @%0.6f %r" % (self.port_name, self.wallclock, message)) # publish the message to every interpreter for interp in self.interpreters: interp.backwards_interpret(message, chord_time) sleep(0.01) # TODO need this? def run_bound(self): """ For use with attractor mode 1, and is not yet done """ # gather <event_time> seconds of notes and analyse them for: # - pitch min & range # - time min & range # - dynam min & range # - (if possible, the duration of notes, from note off messages) event_time = 0.5 # TODO maybe this should adapt to the pace of the music? buffer_time = 0.05 while not self.done: started = timenow() p_min, d_min, t_min = [float('inf')] * 3 p_max, d_max, t_max = [0] * 3 event_notes = list() # a single event while timenow() - started < event_time: b_started = timenow() delta_t = -1 # buffer, so chords count as simultaneous notes while timenow() - b_started < buffer_time: msg = self.midiin.get_message() if msg: message, d_t = msg if delta_t == -1: delta_t = d_t event_notes.append((message, delta_t)) sleep(0.002) num_note_ons = 0 # analyse event_notes for all the fun stuff for (message, time) in event_notes: if 144 <= message[0] < 160: note_on, pitch, dynam = message p_min = min(p_min, pitch) p_max = max(p_max, pitch) d_min = min(d_min, dynam) d_max = max(d_max, dynam) t_min = min(t_min, time) t_max = max(t_max, time) num_note_ons += 1 # TODO duration elif 128 < message[0] < 144: # until we do duration, we don't care pass # if there's anything to report if num_note_ons: p_rng, d_rng, t_rng = (p_max - p_min), (d_max - d_min), (t_max - t_min) for interp in self.interpreters: # print(p_min, p_rng, d_min, d_rng, t_min, t_rng) interp.change_bounds(p_min, p_rng, d_min, d_rng, t_min, t_rng) # pass sleep(0.5)