/// <summary> /// Download a movie /// </summary> /// <param name="movie">The movie to download</param> private async Task DownloadMovie(MovieFullDetails movie) { using (Session session = new Session()) { IsDownloadingMovie = true; // Inform subscribers we're actually loading a movie OnDownloadingMovie(new EventArgs()); // Listening to a port which is randomly between 6881 and 6889 session.ListenOn(6881, 6889); var addParams = new AddTorrentParams { // Where do we save the video file SavePath = Constants.MovieDownloads, // At this time, no quality selection is available in the interface, so we take the lowest Url = movie.Torrents.Aggregate((i1, i2) => (i1.SizeBytes < i2.SizeBytes ? i1 : i2)).Url }; TorrentHandle handle = session.AddTorrent(addParams); // We have to download sequentially, so that we're able to play the movie without waiting handle.SequentialDownload = true; bool alreadyBuffered = false; while (IsDownloadingMovie) { TorrentStatus status = handle.QueryStatus(); double progress = status.Progress*100.0; // Inform subscribers of our progress OnLoadingMovieProgress(new MovieLoadingProgressEventArgs(progress, status.DownloadRate/1024)); // We consider 2% of progress is enough to start playing if (progress >= Constants.MinimumBufferingBeforeMoviePlaying && !alreadyBuffered) { try { // We're looking for video file foreach (string directory in Directory.GetDirectories(Constants.MovieDownloads)) { foreach ( string filePath in Directory.GetFiles(directory, "*" + Constants.VideoFileExtension) ) { // Inform subscribers we have finished buffering the movie OnBufferedMovie(new MovieBufferedEventArgs(filePath)); alreadyBuffered = true; } } } catch (Exception e) { Console.WriteLine(e.Message); } } // Let sleep for a second before updating the torrent status await Task.Delay(1000, CancellationDownloadingToken.Token).ContinueWith(_ => { if (CancellationDownloadingToken.IsCancellationRequested && session != null) { OnStoppedDownloadingMovie(new EventArgs()); IsDownloadingMovie = false; session.RemoveTorrent(handle, true); } }).ConfigureAwait(false); } } }
/// <summary> /// Get the requested movie /// </summary> /// <param name="movieId">The movie ID</param> /// <param name="imdbCode">The IMDb code</param> private async Task LoadMovie(int movieId, string imdbCode) { Movie = new MovieFullDetails(); OnLoadingMovie(new EventArgs()); // Get the requested movie using the service Tuple<MovieFullDetails, IEnumerable<Exception>> movie = await ApiService.GetMovieAsync(movieId, CancellationLoadingToken).ConfigureAwait(false); // Check if we met any exception in the GetMoviesInfosAsync method if (HandleExceptions(movie.Item2)) { // Inform we loaded the requested movie OnLoadedMovie(new EventArgs()); return; } // Our loaded movie is here Movie = movie.Item1; // Inform we loaded the requested movie OnLoadedMovie(new EventArgs()); // Download the movie poster Tuple<string, IEnumerable<Exception>> moviePosterAsyncResults = await ApiService.DownloadMoviePosterAsync(Movie.ImdbCode, Movie.Images.LargeCoverImage, CancellationLoadingToken).ConfigureAwait(false); // Set the path to the poster image if no exception occured in the DownloadMoviePosterAsync method if (!HandleExceptions(moviePosterAsyncResults.Item2)) Movie.PosterImage = moviePosterAsyncResults.Item1; // For each director, we download its image foreach (Director director in Movie.Directors) { Tuple<string, IEnumerable<Exception>> directorsImagesAsyncResults = await ApiService.DownloadDirectorImageAsync(director.Name.Trim(), director.SmallImage, CancellationLoadingToken).ConfigureAwait(false); // Set the path to the director image if no exception occured in the DownloadDirectorImageAsync method if (!HandleExceptions(directorsImagesAsyncResults.Item2)) director.SmallImagePath = directorsImagesAsyncResults.Item1; } // For each actor, we download its image foreach (Actor actor in Movie.Actors) { Tuple<string, IEnumerable<Exception>> actorsImagesAsyncResults = await ApiService.DownloadActorImageAsync(actor.Name.Trim(), actor.SmallImage, CancellationLoadingToken).ConfigureAwait(false); // Set the path to the actor image if no exception occured in the DownloadActorImageAsync method if (!HandleExceptions(actorsImagesAsyncResults.Item2)) actor.SmallImagePath = actorsImagesAsyncResults.Item1; } Tuple<string, IEnumerable<Exception>> movieBackgroundImageResults = await ApiService.DownloadMovieBackgroundImageAsync(imdbCode, CancellationLoadingToken).ConfigureAwait(false); // Set the path to the poster image if no exception occured in the DownloadMoviePosterAsync method if (!HandleExceptions(movieBackgroundImageResults.Item2)) Movie.BackgroundImage = movieBackgroundImageResults.Item1; }