diff --git a/ChartTools/IO/Chart/ChartFile.cs b/ChartTools/IO/Chart/ChartFile.cs
index a1fbf848..c23f2cfe 100644
--- a/ChartTools/IO/Chart/ChartFile.cs
+++ b/ChartTools/IO/Chart/ChartFile.cs
@@ -5,6 +5,7 @@
using ChartTools.IO.Chart.Configuration.Sessions;
using ChartTools.IO.Chart.Parsing;
using ChartTools.IO.Chart.Serializing;
+using ChartTools.IO.Components;
using ChartTools.IO.Configuration;
using ChartTools.IO.Formatting;
using ChartTools.Lyrics;
@@ -43,36 +44,6 @@ public static class ChartFile
#region Reading
#region Song
- ///
- /// Creates a for parsing a section based on the header.
- ///
- ///
- private static ChartParser GetSongParser(string header, ChartReadingSession session)
- {
- switch (header)
- {
- case ChartFormatting.MetadataHeader:
- return new MetadataParser();
- case ChartFormatting.GlobalEventHeader:
- return new GlobalEventParser(session);
- case ChartFormatting.SyncTrackHeader:
- return new SyncTrackParser(session);
- default:
- if (drumsTrackHeaders.TryGetValue(header, out Difficulty diff))
- return new DrumsTrackParser(diff, session, header);
- else if (ghlTrackHeaders.TryGetValue(header, out (Difficulty, GHLInstrumentIdentity) ghlTuple))
- return new GHLTrackParser(ghlTuple.Item1, ghlTuple.Item2, session, header);
- else if (standardTrackHeaders.TryGetValue(header, out (Difficulty, StandardInstrumentIdentity) standardTuple))
- return new StandardTrackParser(standardTuple.Item1, standardTuple.Item2, session, header);
- else
- {
- return session.Configuration.UnknownSectionPolicy == UnknownSectionPolicy.ThrowException
- ? throw new Exception($"Unknown section with header \"{header}\". Consider using {UnknownSectionPolicy.Store} to avoid this error.")
- : new UnknownSectionParser(session, header);
- }
- }
- }
-
///
/// Combines the results from the parsers of a into a .
///
@@ -92,72 +63,124 @@ private static Song CreateSongFromReader(ChartFileReader reader)
///
public static Song ReadSong(string path, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
{
- var session = new ChartReadingSession(config, formatting ?? new());
- var reader = new ChartFileReader(path, header => GetSongParser(header, session));
+ var session = new ChartReadingSession(ComponentList.Full(), config, formatting);
+ var reader = new ChartFileReader(path, session);
reader.Read();
return CreateSongFromReader(reader);
}
- ///
- ///
- ///
- ///
public static async Task ReadSongAsync(string path, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
{
- var session = new ChartReadingSession(config, formatting ?? new());
- var reader = new ChartFileReader(path, header => GetSongParser(header, session));
+ var session = new ChartReadingSession(ComponentList.Full(), config, formatting);
+ var reader = new ChartFileReader(path, session);
+
+ await reader.ReadAsync(cancellationToken);
+ return CreateSongFromReader(reader);
+ }
+
+ public static Song ReadComponents(string path, ComponentList components, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
+ {
+
+ var session = new ChartReadingSession(components, config, formatting);
+ var reader = new ChartFileReader(path, session);
+
+ reader.Read();
+ return CreateSongFromReader(reader);
+ }
+
+ public static async Task ReadComponentsAsync(string path, ComponentList components, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
+ {
+
+ var session = new ChartReadingSession(components, config, formatting);
+ var reader = new ChartFileReader(path, session);
await reader.ReadAsync(cancellationToken);
return CreateSongFromReader(reader);
}
#endregion
+
#region Instruments
- ///
- /// Combines the results from the parsers in a into an instrument.
- ///
- private static TInst? CreateInstrumentFromReader(ChartFileReader reader) where TInst : Instrument, new() where TChord : IChord, new()
+ private static InstrumentSet CreateInstrumentSetFromReader(ChartFileReader reader)
{
- TInst? output = null;
+ var instruments = new InstrumentSet();
foreach (var parser in reader.Parsers)
- (output ??= new()).SetTrack(((TrackParser)parser).Result!);
+ switch (parser)
+ {
+ case DrumsTrackParser drumsParser:
+ instruments.Drums ??= new();
+ drumsParser.ApplyToInstrument(instruments.Drums);
+ break;
+ case StandardTrackParser standardParser:
+ var standardInst = instruments.Get(standardParser.Instrument);
+
+ if (standardInst is null)
+ {
+ standardInst = new StandardInstrument(standardParser.Instrument);
+ instruments.Set(standardInst);
+ }
+
+ standardParser.ApplyToInstrument(standardInst);
+ break;
+ case GHLTrackParser ghlParser:
+ var ghlInst = instruments.Get(ghlParser.Instrument);
+
+ if (ghlInst is null)
+ {
+ ghlInst = new GHLInstrument(ghlParser.Instrument);
+ instruments.Set(ghlInst);
+ }
+
+ ghlParser.ApplyToInstrument(ghlInst);
+ break;
+ }
- return output;
+ return instruments;
}
- ///
- /// Reads an instrument from a chart file.
- ///
- /// Instance of containing all data about the given instrument
- /// if the file contains no data for the given instrument
- ///
- /// Path of the file to read
- /// Instrument to read
- ///
- ///
- ///
- ///
- public static Instrument? ReadInstrument(string path, InstrumentIdentity instrument, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
+ public static InstrumentSet ReadInstruments(string path, InstrumentComponentList components, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
+ {
+ var session = new ChartReadingSession(new() { Instruments = components }, config, formatting);
+ var reader = new ChartFileReader(path, session);
+
+ reader.Read();
+ return CreateInstrumentSetFromReader(reader);
+ }
+
+ public static async Task ReadInstrumentsAsync(string path, InstrumentComponentList components, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
+ {
+ var session = new ChartReadingSession(new() { Instruments = components }, config, formatting);
+ var reader = new ChartFileReader(path, session);
+
+ await reader.ReadAsync(cancellationToken);
+ return CreateInstrumentSetFromReader(reader);
+ }
+
+ [Obsolete($"Use {nameof(ReadInstruments)} with a component list.")]
+ public static Instrument? ReadInstrument(string path, InstrumentIdentity instrument, DifficultySet difficulties = DifficultySet.All, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
{
if (instrument == InstrumentIdentity.Drums)
- return ReadDrums(path, config, formatting);
+ return ReadDrums(path, difficulties, config, formatting);
if (Enum.IsDefined((GHLInstrumentIdentity)instrument))
- return ReadInstrument(path, (GHLInstrumentIdentity)instrument, config, formatting);
+ return ReadInstrument(path, (GHLInstrumentIdentity)instrument, difficulties, config, formatting);
return Enum.IsDefined((StandardInstrumentIdentity)instrument)
- ? ReadInstrument(path, (StandardInstrumentIdentity)instrument, config, formatting)
+ ? ReadInstrument(path, (StandardInstrumentIdentity)instrument, difficulties, config, formatting)
: throw new UndefinedEnumException(instrument);
}
- public static async Task ReadInstrumentAsync(string path, InstrumentIdentity instrument, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
+
+ [Obsolete($"Use {nameof(ReadInstrumentsAsync)} with a component list.")]
+ public static async Task ReadInstrumentAsync(string path, InstrumentIdentity instrument, DifficultySet difficulties = DifficultySet.All, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
{
if (instrument == InstrumentIdentity.Drums)
- return await ReadDrumsAsync(path, config, formatting, cancellationToken);
+ return await ReadDrumsAsync(path, difficulties, config, formatting, cancellationToken);
if (Enum.IsDefined((GHLInstrumentIdentity)instrument))
- return await ReadInstrumentAsync(path, (GHLInstrumentIdentity)instrument, config, formatting, cancellationToken);
+ return await ReadInstrumentAsync(path, (GHLInstrumentIdentity)instrument, difficulties, config, formatting, cancellationToken);
return Enum.IsDefined((StandardInstrumentIdentity)instrument)
- ? await ReadInstrumentAsync(path, (StandardInstrumentIdentity)instrument, config, formatting, cancellationToken)
+ ? await ReadInstrumentAsync(path, (StandardInstrumentIdentity)instrument, difficulties, config, formatting, cancellationToken)
: throw new UndefinedEnumException(instrument);
}
+
#region Vocals
///
/// Reads vocals from the global events in a chart file.
@@ -167,8 +190,10 @@ public static async Task ReadSongAsync(string path, ChartReadingConfigurat
///
/// Path of the file to read
public static Vocals? ReadVocals(string path) => BuildVocals(ReadGlobalEvents(path));
+
public static async Task ReadVocalsAsync(string path, CancellationToken cancellationToken = default) => BuildVocals(await ReadGlobalEventsAsync(path, cancellationToken));
- private static Vocals? BuildVocals(List events)
+
+ private static Vocals? BuildVocals(IList events)
{
var lyrics = events.GetLyrics().ToArray();
@@ -186,323 +211,116 @@ public static async Task ReadSongAsync(string path, ChartReadingConfigurat
return instument;
}
#endregion
- #region Drums
- private static DrumsTrackParser? GetAnyDrumsTrackParser(string header, ChartReadingSession session) => drumsTrackHeaders.TryGetValue(header, out Difficulty difficulty)
- ? new(difficulty, session, header)
- : null;
- ///
- /// Reads drums from a chart file.
- ///
- /// Instance of where TChord is containing all drums data
- /// if the file contains no drums data
- ///
- /// Path of the file to read
- ///
- ///
- public static Drums? ReadDrums(string path, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
- {
- var session = new ChartReadingSession(config, formatting ?? new());
- var reader = new ChartFileReader(path, header => GetAnyDrumsTrackParser(header, session));
- reader.Read();
- return CreateInstrumentFromReader(reader);
- }
- public static async Task ReadDrumsAsync(string path, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
- {
- var session = new ChartReadingSession(config, formatting ?? new());
- var reader = new ChartFileReader(path, header => GetAnyDrumsTrackParser(header, session));
+ #region Drums
+ [Obsolete($"Use {nameof(ReadInstruments)} with a component list.")]
+ public static Drums? ReadDrums(string path, DifficultySet difficulties = DifficultySet.All, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
+ => ReadInstruments(path, new(InstrumentIdentity.Drums), config, formatting).Drums;
- await reader.ReadAsync(cancellationToken);
- return CreateInstrumentFromReader(reader);
- }
+ [Obsolete($"Use {nameof(ReadInstrumentsAsync)} with a component list.")]
+ public static async Task ReadDrumsAsync(string path, DifficultySet difficulties = DifficultySet.All, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
+ => (await ReadInstrumentsAsync(path, new(InstrumentIdentity.Drums), config, formatting)).Drums;
#endregion
- #region GHL
- private static GHLTrackParser? GetAnyGHLTrackParser(string header, GHLInstrumentIdentity instrument, ChartReadingSession session) => ghlTrackHeaders.TryGetValue(header, out (Difficulty, GHLInstrumentIdentity) tuple) && tuple.Item2 == instrument
- ? new(tuple.Item1, tuple.Item2, session, header)
- : null;
- ///
- /// Reads a Guitar Hero Live instrument from a chart file.
- ///
- /// Instance of where TChord is containing all data about the given instrument
- /// if the file has no data for the given instrument
- ///
- /// Path of the file to read
- ///
- public static GHLInstrument? ReadInstrument(string path, GHLInstrumentIdentity instrument, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
- {
- Validator.ValidateEnum(instrument);
-
- var session = new ChartReadingSession(config, formatting ?? new());
- var reader = new ChartFileReader(path, header => GetAnyGHLTrackParser(header, instrument, session));
-
- reader.Read();
- return CreateInstrumentFromReader(reader);
- }
- public static async Task ReadInstrumentAsync(string path, GHLInstrumentIdentity instrument, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
- {
- Validator.ValidateEnum(instrument);
- var session = new ChartReadingSession(config, formatting ?? new());
- var reader = new ChartFileReader(path, header => GetAnyGHLTrackParser(header, instrument, session));
+ #region GHL
+ [Obsolete($"Use {nameof(ReadInstruments)} with a component list.")]
+ public static GHLInstrument? ReadInstrument(string path, GHLInstrumentIdentity instrument, DifficultySet difficulties = DifficultySet.All, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
+ => ReadInstruments(path, new(instrument, difficulties), config, formatting).Get(instrument);
- await reader.ReadAsync(cancellationToken);
- return CreateInstrumentFromReader(reader);
- }
+ [Obsolete($"Use {nameof(ReadInstrumentsAsync)} with a component list.")]
+ public static async Task ReadInstrumentAsync(string path, GHLInstrumentIdentity instrument, DifficultySet difficulties = DifficultySet.All, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
+ => (await ReadInstrumentsAsync(path, new(instrument, difficulties), config, formatting, cancellationToken)).Get(instrument);
#endregion
- #region Standard
- private static StandardTrackParser? GetAnyStandardTrackParser(string header, StandardInstrumentIdentity instrument, ChartReadingSession session) => standardTrackHeaders.TryGetValue(header, out (Difficulty, StandardInstrumentIdentity) tuple) && tuple.Item2 == instrument
- ? new(tuple.Item1, tuple.Item2, session, header)
- : null;
- ///
- ///
- ///
- ///
- public static StandardInstrument? ReadInstrument(string path, StandardInstrumentIdentity instrument, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
- {
- Validator.ValidateEnum(instrument);
- var session = new ChartReadingSession(config, formatting ?? new());
- var reader = new ChartFileReader(path, header => GetAnyStandardTrackParser(header, instrument, session));
-
- reader.Read();
- return CreateInstrumentFromReader(reader);
- }
- ///
- ///
- ///
- ///
- ///
- public static async Task ReadInstrumentAsync(string path, StandardInstrumentIdentity instrument, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
- {
- Validator.ValidateEnum(instrument);
-
- var session = new ChartReadingSession(config, formatting ?? new());
- var reader = new ChartFileReader(path, header => GetAnyStandardTrackParser(header, instrument, session));
+ #region Standard
+ [Obsolete($"Use {nameof(ReadInstruments)} with a component list.")]
+ public static StandardInstrument? ReadInstrument(string path, StandardInstrumentIdentity instrument, DifficultySet difficulties = DifficultySet.All, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
+ => ReadInstruments(path, new(instrument, difficulties), config, formatting).Get(instrument);
- await reader.ReadAsync(cancellationToken);
- return CreateInstrumentFromReader(reader);
- }
+ [Obsolete($"Use {nameof(ReadInstrumentsAsync)} with a component list.")]
+ public static async Task ReadInstrumentAsync(string path, StandardInstrumentIdentity instrument, DifficultySet difficulties = DifficultySet.All, ChartReadingConfiguration? config = default, FormattingRules? formatting = default, CancellationToken cancellationToken = default)
+ => (await ReadInstrumentsAsync(path, new(instrument, difficulties), config, formatting, cancellationToken)).Get(instrument);
#endregion
#endregion
+
#region Tracks
- ///
- ///
- ///
- ///
- ///
- public static Track ReadTrack(string path, InstrumentIdentity instrument, Difficulty difficulty, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
- {
- if (instrument == InstrumentIdentity.Drums)
- return ReadDrumsTrack(path, difficulty, config, formatting);
- if (Enum.IsDefined((GHLInstrumentIdentity)instrument))
- return ReadTrack(path, (GHLInstrumentIdentity)instrument, difficulty, config, formatting);
- if (Enum.IsDefined((StandardInstrumentIdentity)instrument))
- return ReadTrack(path, (StandardInstrumentIdentity)instrument, difficulty, config, formatting);
+ [Obsolete($"Use {nameof(ReadInstruments)} with a component list.")]
+ public static Track? ReadTrack(string path, InstrumentIdentity instrument, Difficulty difficulty, ChartReadingConfiguration? config = default, FormattingRules? formatting = default)
+ => ReadInstrument(path, instrument, difficulty.ToSet(), config, formatting)?.GetTrack(difficulty);
- throw new UndefinedEnumException(instrument);
- }
- ///
- ///
- ///
- ///
- ///
- ///
- public static async Task