public void AppendSource(IConcatStreamSource source, bool optimizeIfPossible = true) { if (disposed) { throw new ObjectDisposedException(nameof(ConcatStream)); } if (source == null) { throw new ArgumentNullException(nameof(source)); } lock (sources) { // CanSeek = first source valid, every other source must be 0 or Length unless it's sourceIndex. Doesn't optimize // Can(not)Seek = always valid, does optimization // If reading and seeking have already occured, don't allow appending seekable sources, otherwise internal state can be messed up var priorCanSeek = CanSeek; if (source.CanSeek) { if (priorCanSeek && (HasFlags(PropertyFlags.EventSeekingOccured) || HasFlags(PropertyFlags.EventReadingOccured))) { throw new InvalidOperationException("Cannot append a seekable source to a seekable stream if reading or seeking has already occured"); } } var currentMeasuredIndexPosition = -1; if (priorCanSeek) { currentMeasuredIndexPosition = GetIndexPosition(); if (source.CanSeek && sources.Count != 0 && source.Position != 0 && source.Position != source.Length && currentMeasuredIndexPosition != sources.Count) { throw new ArgumentException("Invalid seekable source"); } } ReplaceFlags(PropertyFlags.DirtyMask, PropertyFlags.DirtyAll); sources.Add(source); if (priorCanSeek && (sources.Count > 1 || source.CanSeek)) { sourceIndex = Math.Min(sources.Count - 1, currentMeasuredIndexPosition); absPos = 0; for (int i = 0; i <= sourceIndex; i++) { absPos += sources[i].Position; } } if (!source.CanSeek && optimizeIfPossible) { OptimizeSources(); } } }
public void Setup() { concatStreamSourceData = Substitute.For <IConcatStreamSource>(); concatStreamSourceDataUsed = Substitute.For <IConcatStreamSource>(); concatStreamSourceNoData = Substitute.For <IConcatStreamSource>(); concatStreamSourceData.Position.Returns(0); concatStreamSourceData.Length.Returns(StreamSourceDefaultLength); concatStreamSourceData.CanSeek.Returns(true); concatStreamSourceDataUsed.Position.Returns(StreamSourceDefaultLength); concatStreamSourceDataUsed.Length.Returns(StreamSourceDefaultLength); concatStreamSourceDataUsed.CanSeek.Returns(true); concatStreamSourceNoData.Position.Returns(0); concatStreamSourceNoData.Length.Returns(0); concatStreamSourceNoData.CanSeek.Returns(true); }