diff --git a/ChartTools.Generator/ChartTools.Generator.csproj b/ChartTools.Generator/ChartTools.Generator.csproj
new file mode 100644
index 00000000..21818594
--- /dev/null
+++ b/ChartTools.Generator/ChartTools.Generator.csproj
@@ -0,0 +1,12 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
diff --git a/ChartTools/Events/GlobalEvent.cs b/ChartTools/Events/GlobalEvent.cs
index e2f8b537..83f8313d 100644
--- a/ChartTools/Events/GlobalEvent.cs
+++ b/ChartTools/Events/GlobalEvent.cs
@@ -46,7 +46,7 @@ public bool IsKeyboardMovementEvent
/// The event stores text for a syllable of lyrics for karaoke when no vocal track is present
///
public bool IsLyricEvent
- => IsPhraseEvent || EventType == EventTypeHelper.Global.Lyric;
+ => IsPhraseEvent || EventType is EventTypeHelper.Global.Lyric;
///
/// The event represents the start or end of a lyric phrase when no vocal track is present
diff --git a/ChartTools/Extensions/Collections/Delayed/DelayedEnumerator.cs b/ChartTools/Extensions/Collections/Delayed/DelayedEnumerator.cs
index 89f0b9a2..31ea01f2 100644
--- a/ChartTools/Extensions/Collections/Delayed/DelayedEnumerator.cs
+++ b/ChartTools/Extensions/Collections/Delayed/DelayedEnumerator.cs
@@ -30,7 +30,8 @@ public bool MoveNext()
return true;
}
- void IEnumerator.Reset() => throw new InvalidOperationException();
+ void IEnumerator.Reset()
+ => throw new InvalidOperationException();
void IDisposable.Dispose() { }
}
diff --git a/ChartTools/Extensions/Linq/CollectionExtensions.cs b/ChartTools/Extensions/Linq/CollectionExtensions.cs
index fe1b1ec9..c919646a 100644
--- a/ChartTools/Extensions/Linq/CollectionExtensions.cs
+++ b/ChartTools/Extensions/Linq/CollectionExtensions.cs
@@ -3,7 +3,7 @@
public static class CollectionExtensions
{
public static int BinarySearchIndex(this IList source, TKey target, Func keySelector, out bool exactMatch)
- where TKey : notnull, IComparable
+ where TKey : notnull, IComparable
{
int
left = 0,
diff --git a/ChartTools/IO/Chart/ChartFile.cs b/ChartTools/IO/Chart/ChartFile.cs
index e2919e33..1ccf1a98 100644
--- a/ChartTools/IO/Chart/ChartFile.cs
+++ b/ChartTools/IO/Chart/ChartFile.cs
@@ -10,6 +10,7 @@
using ChartTools.IO.Formatting;
using ChartTools.IO.Sources;
using ChartTools.Lyrics;
+using ChartTools.Meta;
namespace ChartTools.IO.Chart;
@@ -516,7 +517,7 @@ private static ChartFileWriter GetMetadataWriter(WritingDataSource source, Metad
=> new(source, null, new MetadataSerializer(metadata));
///
- /// Replaces the in a chart target.
+ /// Replaces the in a chart target.
///
/// File path or stream to write to
/// Metadata to write
@@ -527,7 +528,7 @@ public static void ReplaceMetadata(WritingDataSource source, Metadata metadata)
}
///
- /// Replaces the in a chart target asynchronously.
+ /// Replaces the in a chart target asynchronously.
///
/// File path or stream to write to
/// Metadata to write
diff --git a/ChartTools/IO/Chart/ChartFileReader.cs b/ChartTools/IO/Chart/ChartFileReader.cs
index 10b7800a..0daf223f 100644
--- a/ChartTools/IO/Chart/ChartFileReader.cs
+++ b/ChartTools/IO/Chart/ChartFileReader.cs
@@ -3,6 +3,7 @@
using ChartTools.IO.Components;
using ChartTools.IO.Configuration;
using ChartTools.IO.Sources;
+using ChartTools.Meta;
namespace ChartTools.IO.Chart;
diff --git a/ChartTools/IO/Chart/Parsing/MetadataParser.cs b/ChartTools/IO/Chart/Parsing/MetadataParser.cs
index c06360ce..6c07520b 100644
--- a/ChartTools/IO/Chart/Parsing/MetadataParser.cs
+++ b/ChartTools/IO/Chart/Parsing/MetadataParser.cs
@@ -1,4 +1,5 @@
-namespace ChartTools.IO.Chart.Parsing;
+using ChartTools.Meta;
+using ChartTools.Meta.Mapping;
internal class MetadataParser(Metadata? existing = null)
: ChartParser(null! /* Session not used */, ChartFormatting.MetadataHeader.AsMemory())
diff --git a/ChartTools/IO/Chart/Serializing/MetadataSerializer.cs b/ChartTools/IO/Chart/Serializing/MetadataSerializer.cs
index 803bee71..14d9104b 100644
--- a/ChartTools/IO/Chart/Serializing/MetadataSerializer.cs
+++ b/ChartTools/IO/Chart/Serializing/MetadataSerializer.cs
@@ -1,4 +1,6 @@
-namespace ChartTools.IO.Chart.Serializing;
+using ChartTools.Meta;
+
+namespace ChartTools.IO.Chart.Serializing;
internal class MetadataSerializer(Metadata content) : Serializer(ChartFormatting.MetadataHeader, content)
{
@@ -19,7 +21,7 @@ public override IEnumerable Serialize()
if (Content.Year is not null)
yield return ChartFormatting.Line("Year", $"\", {Content.Year}\"");
- foreach (UnidentifiedMetadata data in Content.UnidentifiedData.Where(d => d.Origin == FileType.Chart))
+ foreach (UnidentifiedMetadata data in Content.UnidentifiedData.Where(d => d.Origin is FileType.Chart))
yield return ChartFormatting.Line(data.Key, data.Value);
}
}
diff --git a/ChartTools/IO/Chart/Serializing/TrackSerializer.cs b/ChartTools/IO/Chart/Serializing/TrackSerializer.cs
index 8bca0779..d58a1b6e 100644
--- a/ChartTools/IO/Chart/Serializing/TrackSerializer.cs
+++ b/ChartTools/IO/Chart/Serializing/TrackSerializer.cs
@@ -22,7 +22,7 @@ protected override IEnumerable[] LaunchProviders()
// Convert solo and soloend events into star power
if (Session.Configuration.SoloNoStarPowerPolicy is SoloNoStarPowerPolicy.Convert &&
- Content.SpecialPhrases.Count == 0 && Content.LocalEvents is not null)
+ Content.SpecialPhrases.Count is 0 && Content.LocalEvents is not null)
{
TrackSpecialPhrase? starPower = null;
diff --git a/ChartTools/IO/Components/ComponentList.cs b/ChartTools/IO/Components/ComponentList.cs
index 4db7ce25..2fd60018 100644
--- a/ChartTools/IO/Components/ComponentList.cs
+++ b/ChartTools/IO/Components/ComponentList.cs
@@ -28,7 +28,7 @@ public record ComponentList()
};
///
- /// Include the
+ /// Include the
///
public bool Metadata { get; set; }
diff --git a/ChartTools/IO/DirectoryHandler.cs b/ChartTools/IO/DirectoryHandler.cs
index ac4487cb..fc72d865 100644
--- a/ChartTools/IO/DirectoryHandler.cs
+++ b/ChartTools/IO/DirectoryHandler.cs
@@ -1,5 +1,6 @@
using ChartTools.IO.Formatting;
using ChartTools.IO.Ini;
+using ChartTools.Meta;
namespace ChartTools.IO;
diff --git a/ChartTools/IO/Formatting/FormattingEnums.cs b/ChartTools/IO/Formatting/FormattingEnums.cs
index f987aee2..fc42436c 100644
--- a/ChartTools/IO/Formatting/FormattingEnums.cs
+++ b/ChartTools/IO/Formatting/FormattingEnums.cs
@@ -1,7 +1,7 @@
namespace ChartTools.IO.Formatting;
///
-/// Key used to serialize
+/// Key used to serialize
///
[Flags]
public enum AlbumTrackKey : byte
diff --git a/ChartTools/IO/Ini/IniFile.cs b/ChartTools/IO/Ini/IniFile.cs
index 490b56e9..a0f9463a 100644
--- a/ChartTools/IO/Ini/IniFile.cs
+++ b/ChartTools/IO/Ini/IniFile.cs
@@ -1,5 +1,6 @@
using ChartTools.Extensions.Linq;
using ChartTools.IO.Sources;
+using ChartTools.Meta;
namespace ChartTools.IO.Ini;
diff --git a/ChartTools/IO/Ini/IniFileReader.cs b/ChartTools/IO/Ini/IniFileReader.cs
index b27db68c..27c17880 100644
--- a/ChartTools/IO/Ini/IniFileReader.cs
+++ b/ChartTools/IO/Ini/IniFileReader.cs
@@ -1,5 +1,6 @@
using ChartTools.IO.Parsing;
using ChartTools.IO.Sources;
+using ChartTools.Meta;
namespace ChartTools.IO.Ini;
diff --git a/ChartTools/IO/Ini/IniFormatting.cs b/ChartTools/IO/Ini/IniFormatting.cs
index c4d6b69b..78c9123f 100644
--- a/ChartTools/IO/Ini/IniFormatting.cs
+++ b/ChartTools/IO/Ini/IniFormatting.cs
@@ -11,59 +11,59 @@ public static class IniFormatting
public const string Header = "[song]";
///
- /// Value of
+ /// Value of
///
public const string Title = "name";
///
- /// Value of
+ /// Value of
///
public const string Artist = "artist";
///
- /// Value of
+ /// Value of
///
public const string Album = "album";
///
- /// Value of
+ /// Value of
///
/// Alternate key to
public const string AlbumTrack = "album_track";
///
- /// Value of
+ /// Value of
///
/// Alternate key to
public const string Track = "track";
///
- /// Value of
+ /// Value of
///
public const string Playlist = "playlist";
///
- /// Value of
+ /// Value of
///
public const string SubPlaylist = "sub_playlist";
///
- /// Value of
+ /// Value of
///
public const string PlaylistTrack = "playlist_track";
///
- /// Value of
+ /// Value of
///
public const string Genre = "genre";
///
- /// Value of
+ /// Value of
///
public const string Explicit = "explicit_lyrics";
///
- /// Value of
+ /// Value of
///
public const string Year = "year";
diff --git a/ChartTools/IO/Ini/IniParser.cs b/ChartTools/IO/Ini/IniParser.cs
index 081feac7..f2a44028 100644
--- a/ChartTools/IO/Ini/IniParser.cs
+++ b/ChartTools/IO/Ini/IniParser.cs
@@ -1,5 +1,6 @@
using ChartTools.IO.Formatting;
using ChartTools.IO.Parsing;
+using ChartTools.Meta;
using ChartTools.Tools;
namespace ChartTools.IO.Ini;
diff --git a/ChartTools/IO/Ini/IniSerializer.cs b/ChartTools/IO/Ini/IniSerializer.cs
index 715f1d7b..b0ca532b 100644
--- a/ChartTools/IO/Ini/IniSerializer.cs
+++ b/ChartTools/IO/Ini/IniSerializer.cs
@@ -1,4 +1,5 @@
using ChartTools.IO.Formatting;
+using ChartTools.Meta;
namespace ChartTools.IO.Ini;
diff --git a/ChartTools/IO/Parsers/TextParser.cs b/ChartTools/IO/Parsers/TextParser.cs
index 6c98be35..34ece946 100644
--- a/ChartTools/IO/Parsers/TextParser.cs
+++ b/ChartTools/IO/Parsers/TextParser.cs
@@ -1,4 +1,4 @@
-namespace ChartTools.IO.Parsing;
+using System.Reflection.PortableExecutable;
internal abstract class TextParser(in ReadOnlyMemory header)
: FileParser>
diff --git a/ChartTools/Metadata/Charter.cs b/ChartTools/Meta/Charter.cs
similarity index 95%
rename from ChartTools/Metadata/Charter.cs
rename to ChartTools/Meta/Charter.cs
index 71dbf94b..acd335c4 100644
--- a/ChartTools/Metadata/Charter.cs
+++ b/ChartTools/Meta/Charter.cs
@@ -2,7 +2,7 @@
using ChartTools.IO.Chart.Serializing;
using ChartTools.IO.Ini;
-namespace ChartTools;
+namespace ChartTools.Meta;
///
/// Creator of the chart
diff --git a/ChartTools/Metadata/InstrumentDifficultySet.cs b/ChartTools/Meta/InstrumentDifficultySet.cs
similarity index 99%
rename from ChartTools/Metadata/InstrumentDifficultySet.cs
rename to ChartTools/Meta/InstrumentDifficultySet.cs
index 3323e5ed..1f735879 100644
--- a/ChartTools/Metadata/InstrumentDifficultySet.cs
+++ b/ChartTools/Meta/InstrumentDifficultySet.cs
@@ -1,6 +1,6 @@
using ChartTools.IO.Ini;
-namespace ChartTools;
+namespace ChartTools.Meta;
///
/// Stores the estimated difficulties for instruments
diff --git a/ChartTools/Meta/Mapping/IMetadataMapper.cs b/ChartTools/Meta/Mapping/IMetadataMapper.cs
new file mode 100644
index 00000000..3b2a01d6
--- /dev/null
+++ b/ChartTools/Meta/Mapping/IMetadataMapper.cs
@@ -0,0 +1,104 @@
+using ChartTools.IO;
+using ChartTools.IO.Chart;
+
+namespace ChartTools.Meta.Mapping;
+
+internal interface IMetadataMapper
+{
+ public static abstract FileType FileType { get; }
+
+ public static abstract string? Get(Metadata metadata, in ReadOnlySpan key);
+
+ public static abstract void Set(Metadata metadata, in ReadOnlySpan key, in ReadOnlySpan value);
+
+ public static abstract void Remove(Metadata metadata, in ReadOnlySpan key);
+
+ protected static string? FindUndentified(Metadata metadata, FileType fileType, in ReadOnlySpan key)
+ => metadata.UnidentifiedData.TryGetValue(new()
+ {
+ Key = key.ToString(),
+ Origin = fileType
+ }, out UnidentifiedMetadata found)
+ ? found.Value
+ : null;
+
+ protected static void Remove(Metadata metadata, FileType fileType, in ReadOnlySpan key)
+ {
+ switch (key)
+ {
+ case ChartFormatting.Title:
+ metadata.Title = null;
+ break;
+ case ChartFormatting.Artist:
+ metadata.Artist = null;
+ break;
+ case ChartFormatting.Charter:
+ metadata.Charter.Name = null;
+ break;
+ case ChartFormatting.Album:
+ metadata.Album = null;
+ break;
+ case ChartFormatting.Year:
+ metadata.Year = null;
+ break;
+ case ChartFormatting.AudioOffset:
+ metadata.AudioOffset = null;
+ break;
+ case ChartFormatting.Difficulty:
+ metadata.Difficulty = null;
+ break;
+ case ChartFormatting.PreviewStart:
+ metadata.PreviewStart = null;
+ break;
+ case ChartFormatting.PreviewEnd:
+ metadata.PreviewEnd = null;
+ break;
+ case ChartFormatting.Genre:
+ metadata.Genre = null;
+ break;
+ case ChartFormatting.MediaType:
+ metadata.MediaType = null;
+ break;
+ case ChartFormatting.MusicStream:
+ metadata.Streams.Music = null;
+ break;
+ case ChartFormatting.GuitarStream:
+ metadata.Streams.Guitar = null;
+ break;
+ case ChartFormatting.BassStream:
+ metadata.Streams.Bass = null;
+ break;
+ case ChartFormatting.RhythmStream:
+ metadata.Streams.Rhythm = null;
+ break;
+ case ChartFormatting.KeysStream:
+ metadata.Streams.Keys = null;
+ break;
+ case ChartFormatting.DrumStream:
+ metadata.Streams.Drum = null;
+ break;
+ case ChartFormatting.Drum2Stream:
+ metadata.Streams.Drum2 = null;
+ break;
+ case ChartFormatting.Drum3Stream:
+ metadata.Streams.Drum3 = null;
+ break;
+ case ChartFormatting.Drum4Stream:
+ metadata.Streams.Drum4 = null;
+ break;
+ case ChartFormatting.VocalStream:
+ metadata.Streams.Vocals = null;
+ break;
+ case ChartFormatting.CrowdStream:
+ metadata.Streams.Crowd = null;
+ break;
+ default:
+ metadata.UnidentifiedData.Remove(new()
+ {
+ Key = key.ToString(),
+ Origin = FileType.Chart
+ });
+ break;
+ }
+ }
+}
diff --git a/ChartTools/Meta/Mapping/MetadataChartMapper.cs b/ChartTools/Meta/Mapping/MetadataChartMapper.cs
new file mode 100644
index 00000000..c513b19d
--- /dev/null
+++ b/ChartTools/Meta/Mapping/MetadataChartMapper.cs
@@ -0,0 +1,123 @@
+using ChartTools.IO;
+using ChartTools.IO.Chart;
+
+namespace ChartTools.Meta.Mapping;
+
+internal class MetadataChartMapper : IMetadataMapper
+{
+ public static FileType FileType => FileType.Chart;
+
+ public static string? Get(Metadata metadata, in ReadOnlySpan key)
+ => key switch
+ {
+ ChartFormatting.Title => metadata.Title,
+ ChartFormatting.Artist => metadata.Artist,
+ ChartFormatting.Charter => metadata.Charter.Name,
+ ChartFormatting.Album => metadata.Album,
+ ChartFormatting.Year => metadata.Year is null ? null : $"\", {metadata.Year}\"",
+ ChartFormatting.AudioOffset => metadata.AudioOffset?.TotalMilliseconds.ToString(),
+ ChartFormatting.Difficulty => metadata.Difficulty?.ToString(),
+ ChartFormatting.PreviewStart => metadata.PreviewStart?.ToString(),
+ ChartFormatting.PreviewEnd => metadata.PreviewEnd?.ToString(),
+ ChartFormatting.Genre => metadata.Genre,
+ ChartFormatting.MediaType => metadata.MediaType,
+ ChartFormatting.MusicStream => metadata.Streams.Music,
+ ChartFormatting.GuitarStream => metadata.Streams.Guitar,
+ ChartFormatting.BassStream => metadata.Streams.Bass,
+ ChartFormatting.RhythmStream => metadata.Streams.Rhythm,
+ ChartFormatting.KeysStream => metadata.Streams.Keys,
+ ChartFormatting.DrumStream => metadata.Streams.Drum,
+ ChartFormatting.Drum2Stream => metadata.Streams.Drum2,
+ ChartFormatting.Drum3Stream => metadata.Streams.Drum3,
+ ChartFormatting.Drum4Stream => metadata.Streams.Drum4,
+ ChartFormatting.VocalStream => metadata.Streams.Vocals,
+ ChartFormatting.CrowdStream => metadata.Streams.Crowd,
+ _ => IMetadataMapper.FindUndentified(metadata, FileType.Chart, key)
+ };
+
+ public static void Set(Metadata metadata, in ReadOnlySpan key, in ReadOnlySpan value)
+ {
+ switch (key)
+ {
+ case ChartFormatting.Title:
+ metadata.Title = value.ToString();
+ break;
+ case ChartFormatting.Artist:
+ metadata.Artist = value.ToString();
+ break;
+ case ChartFormatting.Charter:
+ metadata.Charter.Name = value.ToString();
+ break;
+ case ChartFormatting.Album:
+ metadata.Album = value.ToString();
+ break;
+ case ChartFormatting.Year:
+ metadata.Year = ValueParser.Parse(value.TrimStart(','), "year");
+ break;
+ case ChartFormatting.AudioOffset:
+ metadata.AudioOffset = TimeSpan.FromMilliseconds(ValueParser.Parse(value, "audio offset") * 1000);
+ break;
+ case ChartFormatting.Difficulty:
+ metadata.Difficulty = ValueParser.Parse(value, "difficulty");
+ break;
+ case ChartFormatting.PreviewStart:
+ metadata.PreviewStart = ValueParser.Parse(value, "preview start");
+ break;
+ case ChartFormatting.PreviewEnd:
+ metadata.PreviewEnd = ValueParser.Parse(value, "preview end");
+ break;
+ case ChartFormatting.Genre:
+ metadata.Genre = value.ToString();
+ break;
+ case ChartFormatting.MediaType:
+ metadata.MediaType = value.ToString();
+ break;
+ case ChartFormatting.MusicStream:
+ metadata.Streams.Music = value.ToString();
+ break;
+ case ChartFormatting.GuitarStream:
+ metadata.Streams.Guitar = value.ToString();
+ break;
+ case ChartFormatting.BassStream:
+ metadata.Streams.Bass = value.ToString();
+ break;
+ case ChartFormatting.RhythmStream:
+ metadata.Streams.Rhythm = value.ToString();
+ break;
+ case ChartFormatting.KeysStream:
+ metadata.Streams.Keys = value.ToString();
+ break;
+ case ChartFormatting.DrumStream:
+ metadata.Streams.Drum = value.ToString();
+ break;
+ case ChartFormatting.Drum2Stream:
+ metadata.Streams.Drum2 = value.ToString();
+ break;
+ case ChartFormatting.Drum3Stream:
+ metadata.Streams.Drum3 = value.ToString();
+ break;
+ case ChartFormatting.Drum4Stream:
+ metadata.Streams.Drum4 = value.ToString();
+ break;
+ case ChartFormatting.VocalStream:
+ metadata.Streams.Vocals = value.ToString();
+ break;
+ case ChartFormatting.CrowdStream:
+ metadata.Streams.Crowd = value.ToString();
+ break;
+ default:
+ metadata.UnidentifiedData.Add(new()
+ {
+ Key = key.ToString(),
+ Value = value.ToString(),
+ Origin = FileType.Chart
+ });
+ break;
+ }
+ }
+
+ public static void Remove(Metadata metadata, in ReadOnlySpan key)
+ => IMetadataMapper.Remove(metadata, FileType.Chart, in key);
+
+ private MetadataChartMapper() { }
+}
diff --git a/ChartTools/Meta/Mapping/MetadataIniMapper.cs b/ChartTools/Meta/Mapping/MetadataIniMapper.cs
new file mode 100644
index 00000000..d05520e1
--- /dev/null
+++ b/ChartTools/Meta/Mapping/MetadataIniMapper.cs
@@ -0,0 +1,61 @@
+using ChartTools.IO;
+using ChartTools.IO.Chart;
+using ChartTools.IO.Ini;
+
+namespace ChartTools.Meta.Mapping;
+
+internal class MetadataIniMapper : IMetadataMapper
+{
+ public static FileType FileType => FileType.Ini;
+
+ public static string? Get(Metadata metadata, in ReadOnlySpan key)
+ => key switch
+ {
+ IniFormatting.Title => metadata.Title,
+ IniFormatting.Artist => metadata.Artist,
+ IniFormatting.Album => metadata.Charter.Name,
+ IniFormatting.AlbumTrack => metadata.AlbumTrack?.ToString(),
+ IniFormatting.Track => metadata.AlbumTrack?.ToString(),
+ IniFormatting.Playlist => metadata.Playlist,
+ IniFormatting.SubPlaylist => metadata.SubPlaylist,
+ IniFormatting.PlaylistTrack => metadata.PlaylistTrack?.ToString(),
+ IniFormatting.Year => metadata.Year?.ToString(),
+ IniFormatting.Genre => metadata.Genre,
+ IniFormatting.Charter => metadata.Charter.Name,
+ IniFormatting.Frets => metadata.Charter.Name,
+ IniFormatting.Icon => metadata.Charter.Icon,
+ IniFormatting.PreviewStart => metadata.PreviewStart?.ToString(),
+ IniFormatting.PreviewEnd => metadata.PreviewEnd?.ToString(),
+ IniFormatting.AudioOffset => metadata.AudioOffset?.TotalMilliseconds.ToString(),
+ IniFormatting.VideoOffset => metadata.VideoOffset?.TotalMilliseconds.ToString(),
+ IniFormatting.Length => metadata.Length?.ToString(),
+ IniFormatting.LoadingText => metadata.LoadingText,
+ IniFormatting.Modchart => metadata.IsModchart.HasValue ? (metadata.IsModchart.Value ? "1" : "0") : null,
+ IniFormatting.Explicit => metadata.Explicit?.ToString(),
+ IniFormatting.Difficulties.Global => metadata.Difficulty?.ToString(),
+ IniFormatting.Difficulties.StandardLeadGuitar => metadata.InstrumentDifficulties.StandardLeadGuitar?.ToString(),
+ IniFormatting.Difficulties.StandardRhythmGuitar => metadata.InstrumentDifficulties.StandardRhythmGuitar?.ToString(),
+ IniFormatting.Difficulties.StandardCoopGuitar => metadata.InstrumentDifficulties.StandardCoopGuitar?.ToString(),
+ IniFormatting.Difficulties.StandardBass => metadata.InstrumentDifficulties.StandardBass?.ToString(),
+ IniFormatting.Difficulties.Drums => metadata.InstrumentDifficulties.Drums?.ToString(),
+ IniFormatting.Difficulties.StandardKeys => metadata.InstrumentDifficulties.StandardKeys?.ToString(),
+ IniFormatting.Difficulties.GHLLeadGuitar => metadata.InstrumentDifficulties.GHLLeadGuitar?.ToString(),
+ IniFormatting.Difficulties.GHLRhythmGuitar => metadata.InstrumentDifficulties.GHLRhythmGuitar?.ToString(),
+ IniFormatting.Difficulties.GHLCoopGuitar => metadata.InstrumentDifficulties.GHLCoopGuitar?.ToString(),
+ IniFormatting.Difficulties.GHLBass => metadata.InstrumentDifficulties.GHLBass?.ToString(),
+ IniFormatting.SustainCutoff => metadata.Formatting.SustainCutoff?.ToString(),
+ IniFormatting.HopoFrequency => metadata.Formatting.HopoFrequency?.ToString(),
+ _ => IMetadataMapper.FindUndentified(metadata, FileType.Ini, key)
+ };
+
+ public static void Set(Metadata metadata, in ReadOnlySpan key, in ReadOnlySpan value)
+ {
+ // TODO Implement with source generation
+ throw new NotImplementedException();
+ }
+
+ public static void Remove(Metadata metadata, in ReadOnlySpan key)
+ => IMetadataMapper.Remove(metadata, FileType.Ini, in key);
+
+ private MetadataIniMapper() { }
+}
diff --git a/ChartTools/Metadata/Metadata.cs b/ChartTools/Meta/Metadata.cs
similarity index 84%
rename from ChartTools/Metadata/Metadata.cs
rename to ChartTools/Meta/Metadata.cs
index 5fde4a37..07d8a8d5 100644
--- a/ChartTools/Metadata/Metadata.cs
+++ b/ChartTools/Meta/Metadata.cs
@@ -4,8 +4,9 @@
using ChartTools.IO.Chart.Serializing;
using ChartTools.IO.Formatting;
using ChartTools.IO.Ini;
+using ChartTools.Meta.Mapping;
-namespace ChartTools;
+namespace ChartTools.Meta;
///
/// Set of miscellaneous information about a
@@ -75,10 +76,13 @@ public class Metadata
///
public Charter Charter
{
- get => m_charter;
- set => m_charter = value ?? throw new ArgumentNullException(nameof(value));
- }
- private Charter m_charter = new();
+ get;
+ set
+ {
+ ArgumentNullException.ThrowIfNull(value);
+ field = value;
+ }
+ } = new();
///
/// The song contains explicit lyrics
@@ -124,10 +128,13 @@ public uint PreviewLength
///
public InstrumentDifficultySet InstrumentDifficulties
{
- get => m_instrumentDifficulties;
- set => m_instrumentDifficulties = value ?? throw new ArgumentNullException(nameof(value));
- }
- private InstrumentDifficultySet m_instrumentDifficulties = new();
+ get;
+ set
+ {
+ ArgumentNullException.ThrowIfNull(value);
+ field = value;
+ }
+ } = new();
///
/// Type of media the audio track comes from
@@ -147,10 +154,13 @@ public InstrumentDifficultySet InstrumentDifficulties
///
public StreamCollection Streams
{
- get => m_streams;
- set => m_streams = value ?? throw new ArgumentNullException(nameof(value));
- }
- private StreamCollection m_streams = new();
+ get;
+ set
+ {
+ ArgumentNullException.ThrowIfNull(value);
+ field = value;
+ }
+ } = new();
///
/// Offset of the background video. A higher value makes the video start sooner.
@@ -173,16 +183,14 @@ public StreamCollection Streams
/// The song is a modchart
///
[IniKeySerializable(IniFormatting.Modchart)]
- public bool IsModchart { get; set; }
+ public bool? IsModchart { get; set; }
-
- private FormattingRules m_formatting = new();
///
public FormattingRules Formatting
{
- get => m_formatting;
- set => m_formatting = value ?? throw new ArgumentNullException(nameof(value));
- }
+ get;
+ set => field = value ?? throw new ArgumentNullException(nameof(value));
+ } = new();
///
/// Unrecognized metadata
@@ -193,6 +201,38 @@ public FormattingRules Formatting
static (a, b) => a.Key == b.Key && a.Origin == b.Origin));
#endregion
+ public string? Get(FileType fileType, string key)
+ => fileType switch
+ {
+ FileType.Chart => MetadataChartMapper.Get(this, key),
+ FileType.Ini => MetadataIniMapper.Get(this, key)
+ };
+
+ public void Set(FileType fileType, string key, string value)
+ {
+ switch (fileType)
+ {
+ case FileType.Chart:
+ MetadataChartMapper.Set(this, key, value);
+ break;
+ case FileType.Ini:
+ MetadataIniMapper.Set(this, key, value);
+ break;
+ }
+ }
+
+ public void Remove(FileType fileType, string key)
+ {
+ switch (fileType)
+ {
+ case FileType.Chart:
+ MetadataChartMapper.Remove(this, key);
+ break;
+ case FileType.Ini:
+ throw new NotImplementedException();
+ }
+ }
+
///
/// Appends the metadata from another file.
///
diff --git a/ChartTools/Metadata/StreamCollection.cs b/ChartTools/Meta/StreamCollection.cs
similarity index 98%
rename from ChartTools/Metadata/StreamCollection.cs
rename to ChartTools/Meta/StreamCollection.cs
index 7e2cb55d..f514a072 100644
--- a/ChartTools/Metadata/StreamCollection.cs
+++ b/ChartTools/Meta/StreamCollection.cs
@@ -1,7 +1,7 @@
using ChartTools.IO.Chart;
using ChartTools.IO.Chart.Serializing;
-namespace ChartTools;
+namespace ChartTools.Meta;
///
/// Set of audio files to play and mute during gameplay
diff --git a/ChartTools/Metadata/UnidentifiedMetadata.cs b/ChartTools/Meta/UnidentifiedMetadata.cs
similarity index 83%
rename from ChartTools/Metadata/UnidentifiedMetadata.cs
rename to ChartTools/Meta/UnidentifiedMetadata.cs
index 43367b6d..61eb57df 100644
--- a/ChartTools/Metadata/UnidentifiedMetadata.cs
+++ b/ChartTools/Meta/UnidentifiedMetadata.cs
@@ -1,4 +1,4 @@
-namespace ChartTools;
+namespace ChartTools.Meta;
public struct UnidentifiedMetadata
{
diff --git a/ChartTools/Song.cs b/ChartTools/Song.cs
index bd2c5064..5252283a 100644
--- a/ChartTools/Song.cs
+++ b/ChartTools/Song.cs
@@ -6,6 +6,7 @@
using ChartTools.IO.Formatting;
using ChartTools.IO.Ini;
using ChartTools.Lyrics;
+using ChartTools.Meta;
using ChartTools.Tools;
namespace ChartTools;
diff --git a/ChartTools/Sync/TempoMap.cs b/ChartTools/Sync/TempoMap.cs
index dc0d8aa9..1fba6ab6 100644
--- a/ChartTools/Sync/TempoMap.cs
+++ b/ChartTools/Sync/TempoMap.cs
@@ -159,8 +159,9 @@ public void Synchronize(uint resolution, bool desyncedPreOrdered = false)
if (Synchronized)
return;
- List synced = [];
- List desynced = [];
+ List
+ synced = [],
+ desynced = [];
// Split synced and desynced. Sync 0 anchors.
foreach (Tempo tempo in m_items)