'Yields the captured sequence at every signal message or time period.
Exactly one of `signal` or `period` must be specified. Continues until the
captor terminates, at which point the final captured sequence is yielded
before returning.
If consecutive calls to iterate are longer than the period, immediately
yields and logs a warning.
Args:
signal: A MidiSignal to use as a signal to yield, or None.
period: A float period in seconds, or None.
Yields:
The captured NoteSequence at event time.
Raises:
MidiHubException: If neither `signal` nor `period` or both are specified.'

def iterate(self, signal=None, period=None):

    if ((signal, period).count(None) != 1):
        raise MidiHubException('Exactly    one    of    `signal`    or    `period`    must    be    provided    to    `iterate`    call.')
    if (signal is None):
        sleeper = concurrency.Sleeper()
        next_yield_time = (time.time() + period)
    else:
        regex = re.compile(str(signal))
        queue = Queue.Queue()
        with self._lock:
            self._iter_signals.append((regex, queue))
    while self.is_alive():
        if (signal is None):
            skipped_periods = ((time.time() - next_yield_time) // period)
            if (skipped_periods > 0):
                tf.logging.warn('Skipping    %d    %.3fs    period(s)    to    catch    up    on    iteration.', skipped_periods, period)
                next_yield_time += (skipped_periods * period)
            else:
                sleeper.sleep_until(next_yield_time)
            end_time = next_yield_time
            next_yield_time += period
        else:
            signal_msg = queue.get()
            if (signal_msg is MidiCaptor._WAKE_MESSAGE):
                self.join()
                break
            end_time = signal_msg.time
        with self._lock:
            if (not self.is_alive()):
                break
            captured_sequence = self.captured_sequence(end_time)
        (yield captured_sequence)
    (yield self.captured_sequence())
