예제 #1
0
 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
예제 #2
0
 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
예제 #3
0
    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()
예제 #4
0
    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
예제 #5
0
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.")
예제 #6
0
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
예제 #8
0
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
예제 #9
0
파일: lsdev.py 프로젝트: ambv/aiotone
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 🎶!
"""
)
예제 #10
0
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}')
예제 #11
0
 def __enter__(self):
     self.MIDI_IN = MidiIn()
     self.MIDI_OUT = MidiOut()
     return self
예제 #12
0
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],
예제 #13
0
                                                       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)

예제 #14
0
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)