'Updates sequence being played by the MidiPlayer.
Adds events to close any notes that are no longer being closed by the
new sequence using the times when they would have been closed by the
previous sequence.
Args:
sequence: The NoteSequence to play back.
start_time: The float time before which to strip events. Defaults to call
time.
Raises:
MidiHubException: If called when _allow_updates is False.'

@concurrency.serialized
def update_sequence(self, sequence, start_time=None):

    if (start_time is None):
        start_time = time.time()
    if (not self._allow_updates):
        raise MidiHubException('Attempted    to    update    a    MidiPlayer    sequence    with    updates    disabled.')
    new_message_list = []
    closed_notes = set()
    for note in sequence.notes:
        if (note.start_time >= start_time):
            new_message_list.append(mido.Message(type='note_on', note=note.pitch, velocity=note.velocity, time=note.start_time))
            new_message_list.append(mido.Message(type='note_off', note=note.pitch, time=note.end_time))
        elif ((note.end_time >= start_time) and (note.pitch in self._open_notes)):
            new_message_list.append(mido.Message(type='note_off', note=note.pitch, time=note.end_time))
            closed_notes.add(note.pitch)
    notes_to_close = (self._open_notes - closed_notes)
    if notes_to_close:
        next_event_time = (min((msg.time for msg in new_message_list)) if new_message_list else 0)
        for note in notes_to_close:
            new_message_list.append(mido.Message(type='note_off', note=note, time=next_event_time))
    for msg in new_message_list:
        msg.channel = self._channel
        msg.time += self._offset
    self._message_queue = deque(sorted(new_message_list, key=(lambda msg: (msg.time, msg.note))))
    self._update_cv.notify()
