'Blocks until a matching mido.Message arrives or the timeout occurs.
Exactly one of `signal` or `timeout` must be specified. Using a timeout
with a threading.Condition object causes additional delays when notified.
Args:
signal: A MidiSignal to use as a signal to stop waiting, or None.
timeout: A float timeout in seconds, or None.
Raises:
MidiHubException: If neither `signal` nor `timeout` or both are specified.'

@concurrency.serialized
def wait_for_event(self, signal=None, timeout=None):

    if ((signal, timeout).count(None) != 1):
        raise MidiHubException('Exactly    one    of    `signal`    or    `timeout`    must    be    provided    to    `wait_for_event`    call.')
    if (signal is None):
        concurrency.Sleeper().sleep(timeout)
        return
    signal_pattern = str(signal)
    cond_var = None
    for (regex, cond_var) in self._signals:
        if (regex.pattern == signal_pattern):
            break
    if (cond_var is None):
        cond_var = threading.Condition(self._lock)
        self._signals[re.compile(signal_pattern)] = cond_var
    cond_var.wait()
