Example #1
0
        /// <summary>
        /// Creates a <see cref="Stream"/> which can be used to access the given <see cref="TorrentFile"/>
        /// while it is downloading. This stream is seekable and readable. The first and last pieces of
        /// this file will be buffered before the stream is created if <paramref name="prebuffer"/> is
        /// set to true. Finally, this stream must be disposed before another stream can be created.
        /// </summary>
        /// <param name="file">The file to open</param>
        /// <param name="prebuffer">True if the first and last piece should be downloaded before the Stream is created.</param>
        /// <param name="token">The cancellation token.</param>
        /// <returns></returns>
        public async Task <Stream> CreateStreamAsync(TorrentFile file, bool prebuffer, CancellationToken token)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }
            if (!Manager.Torrent.Files.Contains(file))
            {
                throw new ArgumentException("The TorrentFile is not from this TorrentManager", nameof(file));
            }
            if (!Active)
            {
                throw new InvalidOperationException("You must call StartAsync before creating a stream.");
            }
            if (ActiveStream != null && !ActiveStream.Disposed)
            {
                throw new InvalidOperationException("You must Dispose the previous stream before creating a new one.");
            }

            Picker.SeekToPosition(file, 0);
            ActiveStream = new LocalStream(Manager, file, Picker);

            var tcs = CancellationTokenSource.CreateLinkedTokenSource(Cancellation.Token, token);

            if (prebuffer)
            {
                ActiveStream.Seek(ActiveStream.Length - 1, SeekOrigin.Begin);
                await ActiveStream.ReadAsync(new byte[1], 0, 1, tcs.Token);

                ActiveStream.Seek(0, SeekOrigin.Begin);
                await ActiveStream.ReadAsync(new byte[1], 0, 1, tcs.Token);
            }
            return(ActiveStream);
        }
Example #2
0
        /// <summary>
        /// Creates a <see cref="Stream"/> which can be used to access the given <see cref="TorrentFile"/>
        /// while it is downloading. This stream is seekable and readable. The first and last pieces of
        /// this file will be buffered before the stream is created if <paramref name="prebuffer"/> is
        /// set to true. Finally, this stream must be disposed before another stream can be created.
        /// </summary>
        /// <param name="file">The file to open</param>
        /// <param name="prebuffer">True if the first and last piece should be downloaded before the Stream is created.</param>
        /// <param name="token">The cancellation token.</param>
        /// <returns></returns>
        public async Task <Stream> CreateStreamAsync(ITorrentFileInfo file, bool prebuffer, CancellationToken token)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }
            if (Manager.Files == null)
            {
                throw new InvalidOperationException("The metadata for this torrent has not been downloaded. You must call WaitForMetadataAsync before creating a stream.");
            }
            if (Manager.State == TorrentState.Stopped || Manager.State == TorrentState.Stopping || Manager.State == TorrentState.Error)
            {
                throw new InvalidOperationException($"The torrent state was {Manager.State}. StreamProvider cannot be used unless the torrent manager has been successfully started.");
            }
            if (!Manager.Files.Contains(file))
            {
                throw new ArgumentException("The TorrentFile is not from this TorrentManager", nameof(file));
            }
            if (ActiveStream != null && !ActiveStream.Disposed)
            {
                throw new InvalidOperationException("You must Dispose the previous stream before creating a new one.");
            }

            ActiveStream = new LocalStream(Manager, file, PieceRequester);

            var tcs = CancellationTokenSource.CreateLinkedTokenSource(Cancellation.Token, token);

            if (prebuffer)
            {
                ActiveStream.Seek(ActiveStream.Length - Manager.PieceLength * 2, SeekOrigin.Begin);
                await ActiveStream.ReadAsync(new byte[1], 0, 1, tcs.Token);

                ActiveStream.Seek(0, SeekOrigin.Begin);
                await ActiveStream.ReadAsync(new byte[1], 0, 1, tcs.Token);
            }

            ActiveStream.Seek(0, SeekOrigin.Begin);
            return(ActiveStream);
        }