/// <summary> /// Downloads a beatmap. /// This will post notifications tracking progress. /// </summary> /// <param name="beatmapSetInfo">The <see cref="BeatmapSetInfo"/> to be downloaded.</param> /// <param name="noVideo">Whether the beatmap should be downloaded without video. Defaults to false.</param> /// <returns>Downloading can happen</returns> public bool Download(BeatmapSetInfo beatmapSetInfo, bool noVideo = false) { var existing = GetExistingDownload(beatmapSetInfo); if (existing != null || api == null) { return(false); } if (!api.LocalUser.Value.IsSupporter) { PostNotification?.Invoke(new SimpleNotification { Icon = FontAwesome.fa_superpowers, Text = "You gotta be an osu!supporter to download for now 'yo" }); return(false); } var downloadNotification = new DownloadNotification { CompletionText = $"Imported {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}!", Text = $"Downloading {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}", }; var request = new DownloadBeatmapSetRequest(beatmapSetInfo, noVideo); request.DownloadProgressed += progress => { downloadNotification.State = ProgressNotificationState.Active; downloadNotification.Progress = progress; }; request.Success += data => { downloadNotification.Text = $"Importing {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}"; Task.Factory.StartNew(() => { BeatmapSetInfo importedBeatmap; // This gets scheduled back to the update thread, but we want the import to run in the background. using (var stream = new MemoryStream(data)) using (var archive = new ZipArchiveReader(stream, beatmapSetInfo.ToString())) importedBeatmap = Import(archive); downloadNotification.CompletionClickAction = () => { PresentCompletedImport(importedBeatmap.Yield()); return(true); }; downloadNotification.State = ProgressNotificationState.Completed; currentDownloads.Remove(request); }, TaskCreationOptions.LongRunning); }; request.Failure += error => { BeatmapDownloadFailed?.Invoke(request); if (error is OperationCanceledException) { return; } downloadNotification.State = ProgressNotificationState.Cancelled; Logger.Error(error, "Beatmap download failed!"); currentDownloads.Remove(request); }; downloadNotification.CancelRequested += () => { request.Cancel(); currentDownloads.Remove(request); downloadNotification.State = ProgressNotificationState.Cancelled; return(true); }; currentDownloads.Add(request); PostNotification?.Invoke(downloadNotification); // don't run in the main api queue as this is a long-running task. Task.Factory.StartNew(() => request.Perform(api), TaskCreationOptions.LongRunning); BeatmapDownloadBegan?.Invoke(request); return(true); }
/// <summary> /// Downloads a beatmap. /// This will post notifications tracking progress. /// </summary> /// <param name="beatmapSetInfo">The <see cref="BeatmapSetInfo"/> to be downloaded.</param> /// <param name="noVideo">Whether the beatmap should be downloaded without video. Defaults to false.</param> /// <returns>Downloading can happen</returns> public bool Download(BeatmapSetInfo beatmapSetInfo, bool noVideo = false) { var existing = GetExistingDownload(beatmapSetInfo); if (existing != null || api == null) { return(false); } var downloadNotification = new DownloadNotification { Text = $"Downloading {beatmapSetInfo}", }; var request = new DownloadBeatmapSetRequest(beatmapSetInfo, noVideo); request.DownloadProgressed += progress => { downloadNotification.State = ProgressNotificationState.Active; downloadNotification.Progress = progress; }; request.Success += filename => { Task.Factory.StartNew(() => { // This gets scheduled back to the update thread, but we want the import to run in the background. Import(downloadNotification, filename); currentDownloads.Remove(request); }, TaskCreationOptions.LongRunning); }; request.Failure += error => { BeatmapDownloadFailed?.Invoke(request); if (error is OperationCanceledException) { return; } downloadNotification.State = ProgressNotificationState.Cancelled; Logger.Error(error, "Beatmap download failed!"); currentDownloads.Remove(request); }; downloadNotification.CancelRequested += () => { request.Cancel(); currentDownloads.Remove(request); downloadNotification.State = ProgressNotificationState.Cancelled; return(true); }; currentDownloads.Add(request); PostNotification?.Invoke(downloadNotification); // don't run in the main api queue as this is a long-running task. Task.Factory.StartNew(() => { try { request.Perform(api); } catch { // no need to handle here as exceptions will filter down to request.Failure above. } }, TaskCreationOptions.LongRunning); BeatmapDownloadBegan?.Invoke(request); return(true); }
/// <summary> /// Downloads a beatmap. /// This will post notifications tracking progress. /// </summary> /// <param name="beatmapSetInfo">The <see cref="BeatmapSetInfo"/> to be downloaded.</param> /// <param name="noVideo">Whether the beatmap should be downloaded without video. Defaults to false.</param> /// <returns>Downloading can happen</returns> public bool Download(BeatmapSetInfo beatmapSetInfo, bool noVideo = false) { var existing = GetExistingDownload(beatmapSetInfo); if (existing != null || api == null) { return(false); } var downloadNotification = new DownloadNotification { CompletionText = $"Imported {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}!", Text = $"Downloading {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}", }; var request = new DownloadBeatmapSetRequest(beatmapSetInfo, noVideo); request.DownloadProgressed += progress => { downloadNotification.State = ProgressNotificationState.Active; downloadNotification.Progress = progress; }; request.Success += filename => { downloadNotification.Text = $"Importing {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}"; Task.Factory.StartNew(() => { // This gets scheduled back to the update thread, but we want the import to run in the background. var importedBeatmap = Import(filename); downloadNotification.CompletionClickAction = () => { PresentCompletedImport(importedBeatmap.Yield()); return(true); }; downloadNotification.State = ProgressNotificationState.Completed; currentDownloads.Remove(request); }, TaskCreationOptions.LongRunning); }; request.Failure += error => { BeatmapDownloadFailed?.Invoke(request); if (error is OperationCanceledException) { return; } downloadNotification.State = ProgressNotificationState.Cancelled; Logger.Error(error, "Beatmap download failed!"); currentDownloads.Remove(request); }; downloadNotification.CancelRequested += () => { request.Cancel(); currentDownloads.Remove(request); downloadNotification.State = ProgressNotificationState.Cancelled; return(true); }; currentDownloads.Add(request); PostNotification?.Invoke(downloadNotification); // don't run in the main api queue as this is a long-running task. Task.Factory.StartNew(() => request.Perform(api), TaskCreationOptions.LongRunning); BeatmapDownloadBegan?.Invoke(request); return(true); }