/// <summary> /// Add a <see cref="BeatmapSetInfo"/> to the database. /// </summary> /// <param name="beatmapSet">The beatmap to add.</param> public void Add(BeatmapSetInfo beatmapSet) { var context = GetContext(); foreach (var beatmap in beatmapSet.Beatmaps.Where(b => b.Metadata != null)) { // If we detect a new metadata object it'll be attached to the current context so it can be reused // to prevent duplicate entries when persisting. To accomplish this we look in the cache (.Local) // of the corresponding table (.Set<BeatmapMetadata>()) for matching entries to our criteria. var contextMetadata = context.Set <BeatmapMetadata>().Local.SingleOrDefault(e => e.Equals(beatmap.Metadata)); if (contextMetadata != null) { beatmap.Metadata = contextMetadata; } else { context.BeatmapMetadata.Attach(beatmap.Metadata); } } context.BeatmapSetInfo.Attach(beatmapSet); context.SaveChanges(); BeatmapSetAdded?.Invoke(beatmapSet); }
/// <summary> /// Add a <see cref="BeatmapSetInfo"/> to the database. /// </summary> /// <param name="beatmapSet">The beatmap to add.</param> public void Add(BeatmapSetInfo beatmapSet) { Connection.RunInTransaction(() => { Connection.InsertOrReplaceWithChildren(beatmapSet, true); }); BeatmapSetAdded?.Invoke(beatmapSet); }
/// <summary> /// Update a <see cref="BeatmapSetInfo"/> in the database. TODO: This only supports very basic updates currently. /// </summary> /// <param name="beatmapSet">The beatmap to update.</param> public void Update(BeatmapSetInfo beatmapSet) { BeatmapSetRemoved?.Invoke(beatmapSet); using (var usage = ContextFactory.GetForWrite()) usage.Context.BeatmapSetInfo.Update(beatmapSet); BeatmapSetAdded?.Invoke(beatmapSet); }
/// <summary> /// Add a <see cref="BeatmapSetInfo"/> to the database. /// </summary> /// <param name="beatmapSet">The beatmap to add.</param> public void Add(BeatmapSetInfo beatmapSet) { var context = GetContext(); context.BeatmapSetInfo.Attach(beatmapSet); context.SaveChanges(); BeatmapSetAdded?.Invoke(beatmapSet); }
private BeatmapStore createBeatmapStore(Func <OsuDbContext> context) { var store = new BeatmapStore(context); store.BeatmapSetAdded += s => BeatmapSetAdded?.Invoke(s); store.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s); store.BeatmapHidden += b => BeatmapHidden?.Invoke(b); store.BeatmapRestored += b => BeatmapRestored?.Invoke(b); return(store); }
public void Import(IEnumerable <BeatmapSetInfo> beatmapSets) { connection.BeginTransaction(); foreach (var s in beatmapSets) { connection.InsertWithChildren(s, true); BeatmapSetAdded?.Invoke(s); } connection.Commit(); }
/// <summary> /// Restore a previously deleted <see cref="BeatmapSetInfo"/>. /// </summary> /// <param name="beatmapSet">The beatmap to restore.</param> /// <returns>Whether the beatmap's <see cref="BeatmapSetInfo.DeletePending"/> was changed.</returns> public bool Undelete(BeatmapSetInfo beatmapSet) { if (!beatmapSet.DeletePending) { return(false); } beatmapSet.DeletePending = false; Connection.Update(beatmapSet); BeatmapSetAdded?.Invoke(beatmapSet); return(true); }
public BeatmapManager(Storage storage, FileStore files, SQLiteConnection connection, RulesetStore rulesets, IIpcHost importHost = null) { beatmaps = new BeatmapStore(connection); beatmaps.BeatmapSetAdded += s => BeatmapSetAdded?.Invoke(s); beatmaps.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s); this.storage = storage; this.files = files; this.rulesets = rulesets; if (importHost != null) { ipc = new BeatmapIPCChannel(importHost, this); } }
/// <summary> /// Restore a previously deleted <see cref="BeatmapSetInfo"/>. /// </summary> /// <param name="beatmapSet">The beatmap to restore.</param> /// <returns>Whether the beatmap's <see cref="BeatmapSetInfo.DeletePending"/> was changed.</returns> public bool Undelete(BeatmapSetInfo beatmapSet) { var context = GetContext(); Refresh(ref beatmapSet, BeatmapSets); if (!beatmapSet.DeletePending) { return(false); } beatmapSet.DeletePending = false; context.SaveChanges(); BeatmapSetAdded?.Invoke(beatmapSet); return(true); }
/// <summary> /// Restore a previously deleted <see cref="BeatmapSetInfo"/>. /// </summary> /// <param name="beatmapSet">The beatmap to restore.</param> /// <returns>Whether the beatmap's <see cref="BeatmapSetInfo.DeletePending"/> was changed.</returns> public bool Undelete(BeatmapSetInfo beatmapSet) { using (ContextFactory.GetForWrite()) { Refresh(ref beatmapSet, BeatmapSets); if (!beatmapSet.DeletePending) { return(false); } beatmapSet.DeletePending = false; } BeatmapSetAdded?.Invoke(beatmapSet); return(true); }
public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, IIpcHost importHost = null) { this.contextFactory = contextFactory; beatmaps = new BeatmapStore(contextFactory); beatmaps.BeatmapSetAdded += s => BeatmapSetAdded?.Invoke(s); beatmaps.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s); beatmaps.BeatmapHidden += b => BeatmapHidden?.Invoke(b); beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b); files = new FileStore(contextFactory, storage); this.rulesets = rulesets; this.api = api; if (importHost != null) { ipc = new BeatmapIPCChannel(importHost, this); } beatmaps.Cleanup(); }
/// <summary> /// Duplicates content from <paramref name="path"/> to storage and returns a representing <see cref="BeatmapSetInfo"/>. /// </summary> /// <param name="path">Content location</param> /// <returns><see cref="BeatmapSetInfo"/></returns> private BeatmapSetInfo getBeatmapSet(string path) { string hash = null; BeatmapMetadata metadata; using (var reader = ArchiveReader.GetReader(storage, path)) metadata = reader.ReadMetadata(); if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader { using (var input = storage.GetStream(path)) { hash = input.GetMd5Hash(); input.Seek(0, SeekOrigin.Begin); path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash); if (!storage.Exists(path)) { using (var output = storage.GetStream(path, FileAccess.Write)) input.CopyTo(output); } } } var existing = connection.Table <BeatmapSetInfo>().FirstOrDefault(b => b.Hash == hash); if (existing != null) { if (existing.DeletePending) { existing.DeletePending = false; Update(existing, false); BeatmapSetAdded?.Invoke(existing); } return(existing); } var beatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = metadata.OnlineBeatmapSetID, Beatmaps = new List <BeatmapInfo>(), Path = path, Hash = hash, Metadata = metadata }; using (var archive = ArchiveReader.GetReader(storage, path)) { string[] mapNames = archive.BeatmapFilenames; foreach (var name in mapNames) { using (var raw = archive.GetStream(name)) using (var ms = new MemoryStream()) //we need a memory stream so we can seek and shit using (var sr = new StreamReader(ms)) { raw.CopyTo(ms); ms.Position = 0; var decoder = BeatmapDecoder.GetDecoder(sr); Beatmap beatmap = decoder.Decode(sr); beatmap.BeatmapInfo.Path = name; beatmap.BeatmapInfo.Hash = ms.GetMd5Hash(); // TODO: Diff beatmap metadata with set metadata and leave it here if necessary beatmap.BeatmapInfo.Metadata = null; beatmap.BeatmapInfo.StarDifficulty = beatmap.CalculateStarDifficulty(); beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } } beatmapSet.StoryboardFile = archive.StoryboardFilename; } return(beatmapSet); }
/// <summary> /// Duplicates content from <paramref name="path"/> to storage and returns a representing <see cref="BeatmapSetInfo"/>. /// </summary> /// <param name="path">Content location</param> /// <returns><see cref="BeatmapSetInfo"/></returns> private BeatmapSetInfo getBeatmapSet(string path) { string hash = null; BeatmapMetadata metadata; using (var reader = ArchiveReader.GetReader(storage, path)) metadata = reader.ReadMetadata(); if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader { using (var md5 = MD5.Create()) using (var input = storage.GetStream(path)) { hash = BitConverter.ToString(md5.ComputeHash(input)).Replace("-", "").ToLowerInvariant(); input.Seek(0, SeekOrigin.Begin); path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash); if (!storage.Exists(path)) { using (var output = storage.GetStream(path, FileAccess.Write)) input.CopyTo(output); } } } var existing = connection.Table <BeatmapSetInfo>().FirstOrDefault(b => b.Hash == hash); if (existing != null) { if (existing.DeletePending) { existing.DeletePending = false; Update(existing, false); BeatmapSetAdded?.Invoke(existing); } return(existing); } var beatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = metadata.OnlineBeatmapSetID, Beatmaps = new List <BeatmapInfo>(), Path = path, Hash = hash, Metadata = metadata }; using (var reader = ArchiveReader.GetReader(storage, path)) { string[] mapNames = reader.BeatmapFilenames; foreach (var name in mapNames) { using (var stream = new StreamReader(reader.GetStream(name))) { var decoder = BeatmapDecoder.GetDecoder(stream); Beatmap beatmap = decoder.Decode(stream); beatmap.BeatmapInfo.Path = name; // TODO: Diff beatmap metadata with set metadata and leave it here if necessary beatmap.BeatmapInfo.Metadata = null; beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } } beatmapSet.StoryboardFile = reader.StoryboardFilename; } return(beatmapSet); }
private BeatmapSetInfo getBeatmapSet(ArchiveReader archiveReader) { BeatmapMetadata metadata; using (var stream = new StreamReader(archiveReader.GetStream(archiveReader.BeatmapFilenames[0]))) metadata = BeatmapDecoder.GetDecoder(stream).Decode(stream).Metadata; string hash; string path; using (var input = archiveReader.GetUnderlyingStream()) { hash = input.GetMd5Hash(); input.Seek(0, SeekOrigin.Begin); path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash); if (!Storage.Exists(path)) { using (var output = Storage.GetStream(path, FileAccess.Write)) input.CopyTo(output); } } var existing = Connection.Table <BeatmapSetInfo>().FirstOrDefault(b => b.Hash == hash); if (existing != null) { GetChildren(existing); if (existing.DeletePending) { existing.DeletePending = false; Update(existing, false); BeatmapSetAdded?.Invoke(existing); } return(existing); } var beatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = metadata.OnlineBeatmapSetID, Beatmaps = new List <BeatmapInfo>(), Path = path, Hash = hash, Metadata = metadata }; using (var archive = ArchiveReader.GetReader(Storage, path)) { string[] mapNames = archive.BeatmapFilenames; foreach (var name in mapNames) { using (var raw = archive.GetStream(name)) using (var ms = new MemoryStream()) //we need a memory stream so we can seek and shit using (var sr = new StreamReader(ms)) { raw.CopyTo(ms); ms.Position = 0; var decoder = BeatmapDecoder.GetDecoder(sr); Beatmap beatmap = decoder.Decode(sr); beatmap.BeatmapInfo.Path = name; beatmap.BeatmapInfo.Hash = ms.GetMd5Hash(); // TODO: Diff beatmap metadata with set metadata and leave it here if necessary beatmap.BeatmapInfo.Metadata = null; // TODO: this should be done in a better place once we actually need to dynamically update it. beatmap.BeatmapInfo.Ruleset = rulesets.Query <RulesetInfo>().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID); beatmap.BeatmapInfo.StarDifficulty = rulesets.Query <RulesetInfo>().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID)?.CreateInstance()?.CreateDifficultyCalculator(beatmap).Calculate() ?? 0; beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } } beatmapSet.StoryboardFile = archive.StoryboardFilename; } return(beatmapSet); }