'Handles a single incoming MIDI message.
-If the message is being used as a signal, notifies threads waiting on the
appropriate condition variable.
-Adds the message to any capture queues.
-Passes the message through to the output port, if appropriate.
Args:
msg: The mido.Message MIDI message to handle.'

@concurrency.serialized
def _handle_message(self, msg):

    msg_str = str(msg)
    for regex in list(self._signals):
        if (regex.match(msg_str) is not None):
            self._signals[regex].notify_all()
            del self._signals[regex]
    for regex in list(self._callbacks):
        if (regex.match(msg_str) is not None):
            for fn in self._callbacks[regex]:
                threading.Thread(target=fn, args=(msg,)).start()
            del self._callbacks[regex]
    self._captors[:] = [t for t in self._captors if t.is_alive()]
    for t in self._captors:
        t.receive(msg.copy())
    if (msg.type == 'control_change'):
        if (self._control_values.get(msg.control, None) != msg.value):
            tf.logging.debug('Control    change    %d:    %d', msg.control, msg.value)
        self._control_values[msg.control] = msg.value
    if (not self._passthrough):
        pass
    elif (self._texture_type == TextureType.POLYPHONIC):
        if ((msg.type == 'note_on') and (msg.velocity > 0)):
            self._open_notes.add(msg.note)
        elif ((msg.type == 'note_off') or ((msg.type == 'note_on') and (msg.velocity == 0))):
            self._open_notes.discard(msg.note)
        self._outport.send(msg)
    elif (self._texture_type == TextureType.MONOPHONIC):
        assert (len(self._open_notes) <= 1)
        if (msg.type not in ['note_on', 'note_off']):
            self._outport.send(msg)
        elif (((msg.type == 'note_off') or ((msg.type == 'note_on') and (msg.velocity == 0))) and (msg.note in self._open_notes)):
            self._outport.send(msg)
            self._open_notes.remove(msg.note)
        elif ((msg.type == 'note_on') and (msg.velocity > 0)):
            if self._open_notes:
                self._outport.send(mido.Message('note_off', note=self._open_notes.pop()))
            self._outport.send(msg)
            self._open_notes.add(msg.note)
