Fix fragments with zero length,
        enlarging them to have length ``duration``,
        reclaiming the difference from the next fragment(s),
        or moving the next fragment(s) forward.

        This function assumes the fragments to be adjacent.

        :param duration: set the zero length fragments to have this duration
        :type  duration: :class:`~aeneas.exacttiming.TimeValue`
        :param int min_index: examine fragments with index greater than or equal to this index (i.e., included)
        :param int max_index: examine fragments with index smaller than this index (i.e., excluded)
        :raises ValueError: if ``min_index`` is negative or ``max_index``
                            is bigger than the current number of fragments

def fix_zero_length_fragments(self, duration=TimeValue("0.001"), min_index=None, max_index=None, ensure_adjacent=True):
        """
        Fix fragments with zero length,
        enlarging them to have length ``duration``,
        reclaiming the difference from the next fragment(s),
        or moving the next fragment(s) forward.

        This function assumes the fragments to be adjacent.

        :param duration: set the zero length fragments to have this duration
        :type  duration: :class:`~aeneas.exacttiming.TimeValue`
        :param int min_index: examine fragments with index greater than or equal to this index (i.e., included)
        :param int max_index: examine fragments with index smaller than this index (i.e., excluded)
        :raises ValueError: if ``min_index`` is negative or ``max_index``
                            is bigger than the current number of fragments
        """
        self.log(u"Called fix_zero_length_fragments")
        self.log([u"  Duration %.3f", duration])
        min_index, max_index = self._check_min_max_indices(min_index, max_index)
        if len(self) < 1:
            self.log(u"The list has no fragments: returning")
            return
        if not self.has_adjacent_fragments_only(min_index, max_index):
            self.log_warn(u"There are non adjacent fragments: aborting")
            return
        original_first_begin = None
        if (
                (ensure_adjacent) and
                (min_index > 0) and
                (self[min_index - 1].interval.is_adjacent_before(self[min_index].interval))
        ):
            original_first_begin = self[min_index].begin
            self.log([u"Original first was adjacent with previous, starting at %.3f", original_first_begin])
        original_last_end = None
        if (
                (ensure_adjacent) and
                (len(self) > 1) and
                (max_index < len(self)) and
                (self[max_index - 1].interval.is_adjacent_before(self[max_index].interval))
        ):
            original_last_end = self[max_index - 1].end
            self.log([u"Original last was adjacent with next, ending at %.3f", original_last_end])
        i = min_index
        while i < max_index:
            if self[i].has_zero_length:
                self.log([u"  Fragment %d (%s) has zero length => ENLARGE", i, self[i].interval])
                moves = [(i, "ENLARGE", duration)]
                slack = duration
                j = i + 1
                self.log([u"  Entered while with j == %d", j])
                while (j < max_index) and (self[j].interval.length < slack):
                    if self[j].has_zero_length:
                        self.log([u"  Fragment %d (%s) has zero length => ENLARGE", j, self[j].interval])
                        moves.append((j, "ENLARGE", duration))
                        slack += duration
                    else:
                        self.log([u"  Fragment %d (%s) has non zero length => MOVE", j, self[j].interval])
                        moves.append((j, "MOVE", None))
                    j += 1
                self.log([u"  Exited while with j == %d", j])
                fixable = False
                if (j == max_index) and (self[j - 1].interval.end + slack <= self.end):
                    self.log(u"  Fixable by moving back")
                    current_time = self[j - 1].interval.end + slack
                    fixable = True
                elif j < max_index:
                    self.log(u"  Fixable by shrinking")
                    self[j].interval.shrink(slack)
                    current_time = self[j].interval.begin
                    fixable = True
                if fixable:
                    for index, move_type, move_amount in moves[::-1]:
                        self.log([u"    Calling move_end_at with %.3f at index %d", current_time, index])
                        self[index].interval.move_end_at(current_time)
                        if move_type == "ENLARGE":
                            self.log([u"    Calling enlarge with %.3f at index %d", move_amount, index])
                            self[index].interval.enlarge(move_amount)
                        self.log([u"    Interval %d is now: %s", index, self[index].interval])
                        current_time = self[index].interval.begin
                else:
                    self.log([u"Unable to fix fragment %d (%s)", i, self[i].interval])
                i = j - 1
            i += 1
        if original_first_begin is not None:
            if self[min_index].begin != self[min_index - 1].end:
                self.log(u"First fragment begin moved, restoring adjacency")
                self.log([u"  Original was %.3f", original_first_begin])
                self.log([u"  New      is  %.3f", self[min_index - 1].end])
                self[min_index].begin = self[min_index - 1].end
        if original_last_end is not None:
            if self[max_index].begin != self[max_index - 1].end:
                self.log(u"Last fragment end moved, restoring adjacency")
                self.log([u"  Original was %.3f", original_last_end])
                self.log([u"  New      is  %.3f", self[max_index].begin])
                self[max_index].begin = self[max_index - 1].end
        self.log(u"Fragments after fixing:")
        for i, fragment in enumerate(self):
            self.log([u"  %d => %.3f %.3f", i, fragment.interval.begin, fragment.interval.end])