diff --git a/CHANGELIST.md b/CHANGELIST.md
index 834e0d18..93c15965 100644
--- a/CHANGELIST.md
+++ b/CHANGELIST.md
@@ -11,6 +11,7 @@
- Migrate to Nuget package for Redump
- Remove dd for Windows
- Migrate to Nuget package for XMID
+- Migrate to Nuget package for cuesheets
### 2.6.3 (2023-08-15)
diff --git a/MPF.CueSheets/CueFile.cs b/MPF.CueSheets/CueFile.cs
deleted file mode 100644
index afa8d2d2..00000000
--- a/MPF.CueSheets/CueFile.cs
+++ /dev/null
@@ -1,238 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-
-///
-/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
-///
-namespace MPF.CueSheets
-{
- ///
- /// The audio or data file’s filetype
- ///
- public enum CueFileType
- {
- ///
- /// Intel binary file (least significant byte first). Use for data files.
- ///
- BINARY,
-
- ///
- /// Motorola binary file (most significant byte first). Use for data files.
- ///
- MOTOROLA,
-
- ///
- /// Audio AIFF file (44.1KHz 16-bit stereo)
- ///
- AIFF,
-
- ///
- /// Audio WAVE file (44.1KHz 16-bit stereo)
- ///
- WAVE,
-
- ///
- /// Audio MP3 file (44.1KHz 16-bit stereo)
- ///
- MP3,
- }
-
- ///
- /// Represents a single FILE in a cuesheet
- ///
- public class CueFile
- {
- ///
- /// filename
- ///
- public string FileName { get; set; }
-
- ///
- /// filetype
- ///
- public CueFileType FileType { get; set; }
-
- ///
- /// List of TRACK in FILE
- ///
- public List Tracks { get; set; }
-
- ///
- /// Create an empty FILE
- ///
- public CueFile()
- {
- }
-
- ///
- /// Fill a FILE from an array of lines
- ///
- /// File name to set
- /// File type to set
- /// Lines array to pull from
- /// Reference to index in array
- /// True if errors throw an exception, false otherwise
- public CueFile(string fileName, string fileType, string[] cueLines, ref int i, bool throwOnError = false)
- {
- if (cueLines == null)
- {
- if (throwOnError)
- throw new ArgumentNullException(nameof(cueLines));
-
- return;
- }
- else if (i < 0 || i > cueLines.Length)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException();
-
- return;
- }
-
- // Set the current fields
- this.FileName = fileName.Trim('"');
- this.FileType = GetFileType(fileType);
-
- // Increment to start
- i++;
-
- for (; i < cueLines.Length; i++)
- {
- string line = cueLines[i].Trim();
- string[] splitLine = line.Split(' ');
-
- // If we have an empty line, we skip
- if (string.IsNullOrWhiteSpace(line))
- continue;
-
- switch (splitLine[0])
- {
- // Read comments
- case "REM":
- // We ignore all comments for now
- break;
-
- // Read track information
- case "TRACK":
- if (splitLine.Length < 3)
- {
- if (throwOnError)
- throw new FormatException($"TRACK line malformed: {line}");
-
- continue;
- }
-
- if (this.Tracks == null)
- this.Tracks = new List();
-
- var track = new CueTrack(splitLine[1], splitLine[2], cueLines, ref i);
- if (track == default)
- {
- if (throwOnError)
- throw new FormatException($"TRACK line malformed: {line}");
-
- continue;
- }
-
- this.Tracks.Add(track);
- break;
-
- // Default means return
- default:
- i--;
- return;
- }
- }
- }
-
- ///
- /// Write the FILE out to a stream
- ///
- /// StreamWriter to write to
- /// True if errors throw an exception, false otherwise
- public void Write(StreamWriter sw, bool throwOnError = false)
- {
- // If we don't have any tracks, it's invalid
- if (this.Tracks == null)
- {
- if (throwOnError)
- throw new ArgumentNullException(nameof(this.Tracks));
-
- return;
- }
- else if (this.Tracks.Count == 0)
- {
- if (throwOnError)
- throw new ArgumentException("No tracks provided to write");
-
- return;
- }
-
- sw.WriteLine($"FILE \"{this.FileName}\" {FromFileType(this.FileType)}");
-
- foreach (var track in Tracks)
- {
- track.Write(sw);
- }
- }
-
- ///
- /// Get the file type from a given string
- ///
- /// String to get value from
- /// CueFileType, if possible
- private CueFileType GetFileType(string fileType)
- {
- switch (fileType.ToLowerInvariant())
- {
- case "binary":
- return CueFileType.BINARY;
-
- case "motorola":
- return CueFileType.MOTOROLA;
-
- case "aiff":
- return CueFileType.AIFF;
-
- case "wave":
- return CueFileType.WAVE;
-
- case "mp3":
- return CueFileType.MP3;
-
- default:
- return CueFileType.BINARY;
- }
- }
-
- ///
- /// Get the string from a given file type
- ///
- /// CueFileType to get value from
- /// String, if possible (default BINARY)
- private string FromFileType(CueFileType fileType)
- {
- switch (fileType)
- {
- case CueFileType.BINARY:
- return "BINARY";
-
- case CueFileType.MOTOROLA:
- return "MOTOROLA";
-
- case CueFileType.AIFF:
- return "AIFF";
-
- case CueFileType.WAVE:
- return "WAVE";
-
- case CueFileType.MP3:
- return "MP3";
-
- default:
- return string.Empty;
- }
- }
- }
-}
diff --git a/MPF.CueSheets/CueIndex.cs b/MPF.CueSheets/CueIndex.cs
deleted file mode 100644
index 8a6a52d9..00000000
--- a/MPF.CueSheets/CueIndex.cs
+++ /dev/null
@@ -1,163 +0,0 @@
-using System;
-using System.IO;
-using System.Linq;
-
-///
-/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
-///
-namespace MPF.CueSheets
-{
- ///
- /// Represents a single INDEX in a TRACK
- ///
- public class CueIndex
- {
- ///
- /// INDEX number, between 0 and 99
- ///
- public int Index { get; set; }
-
- ///
- /// Starting time of INDEX in minutes
- ///
- public int Minutes { get; set; }
-
- ///
- /// Starting time of INDEX in seconds
- ///
- /// There are 60 seconds in a minute
- public int Seconds { get; set; }
-
- ///
- /// Starting time of INDEX in frames.
- ///
- /// There are 75 frames per second
- public int Frames { get; set; }
-
- ///
- /// Create an empty INDEX
- ///
- public CueIndex()
- {
- }
-
- ///
- /// Fill a INDEX from an array of lines
- ///
- /// Index to set
- /// Start time to set
- /// True if errors throw an exception, false otherwise
- public CueIndex(string index, string startTime, bool throwOnError = false)
- {
- // Set the current fields
- if (!int.TryParse(index, out int parsedIndex))
- {
- if (throwOnError)
- throw new ArgumentException($"Index was not a number: {index}");
-
- return;
- }
- else if (parsedIndex < 0 || parsedIndex > 99)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Index must be between 0 and 99: {parsedIndex}");
-
- return;
- }
-
- // Ignore empty lines
- if (string.IsNullOrWhiteSpace(startTime))
- {
- if (throwOnError)
- throw new ArgumentException("Start time was null or whitespace");
-
- return;
- }
-
- // Ignore lines that don't contain the correct information
- if (startTime.Length != 8 || startTime.Count(c => c == ':') != 2)
- {
- if (throwOnError)
- throw new FormatException($"Start time was not in a recognized format: {startTime}");
-
- return;
- }
-
- // Split the line
- string[] splitTime = startTime.Split(':');
- if (splitTime.Length != 3)
- {
- if (throwOnError)
- throw new FormatException($"Start time was not in a recognized format: {startTime}");
-
- return;
- }
-
- // Parse the lengths
- int[] lengthSegments = new int[3];
-
- // Minutes
- if (!int.TryParse(splitTime[0], out lengthSegments[0]))
- {
- if (throwOnError)
- throw new FormatException($"Minutes segment was not a number: {splitTime[0]}");
-
- return;
- }
- else if (lengthSegments[0] < 0)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Minutes segment must be 0 or greater: {lengthSegments[0]}");
-
- return;
- }
-
- // Seconds
- if (!int.TryParse(splitTime[1], out lengthSegments[1]))
- {
- if (throwOnError)
- throw new FormatException($"Seconds segment was not a number: {splitTime[1]}");
-
- return;
- }
- else if (lengthSegments[1] < 0 || lengthSegments[1] > 60)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Seconds segment must be between 0 and 60: {lengthSegments[1]}");
-
- return;
- }
-
- // Frames
- if (!int.TryParse(splitTime[2], out lengthSegments[2]))
- {
- if (throwOnError)
- throw new FormatException($"Frames segment was not a number: {splitTime[2]}");
-
- return;
- }
- else if (lengthSegments[2] < 0 || lengthSegments[2] > 75)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Frames segment must be between 0 and 75: {lengthSegments[2]}");
-
- return;
- }
-
- // Set the values
- this.Index = parsedIndex;
- this.Minutes = lengthSegments[0];
- this.Seconds = lengthSegments[1];
- this.Frames = lengthSegments[2];
- }
-
- ///
- /// Write the INDEX out to a stream
- ///
- /// StreamWriter to write to
- public void Write(StreamWriter sw)
- {
- sw.WriteLine($" INDEX {this.Index:D2} {this.Minutes:D2}:{this.Seconds:D2}:{this.Frames:D2}");
- }
- }
-}
diff --git a/MPF.CueSheets/CueSheet.cs b/MPF.CueSheets/CueSheet.cs
deleted file mode 100644
index 4df49700..00000000
--- a/MPF.CueSheets/CueSheet.cs
+++ /dev/null
@@ -1,250 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-
-///
-/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
-///
-namespace MPF.CueSheets
-{
- ///
- /// Represents a single cuesheet
- ///
- public class CueSheet
- {
- ///
- /// CATALOG
- ///
- public string Catalog { get; set; }
-
- ///
- /// CDTEXTFILE
- ///
- public string CdTextFile { get; set; }
-
- ///
- /// PERFORMER
- ///
- public string Performer { get; set; }
-
- ///
- /// SONGWRITER
- ///
- public string Songwriter { get; set; }
-
- ///
- /// TITLE
- ///
- public string Title { get; set; }
-
- ///
- /// List of FILE in cuesheet
- ///
- public List Files { get; set; }
-
- ///
- /// Create an empty cuesheet
- ///
- public CueSheet()
- {
- }
-
- ///
- /// Create a cuesheet from a file, if possible
- ///
- ///
- /// True if errors throw an exception, false otherwise
- public CueSheet(string filename, bool throwOnError = false)
- {
- // Check that the file exists
- if (!File.Exists(filename))
- return;
-
- // Check the extension
- string ext = Path.GetExtension(filename).TrimStart('.');
- if (!string.Equals(ext, "cue", StringComparison.OrdinalIgnoreCase)
- && !string.Equals(ext, "txt", StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
-
- // Open the file and begin reading
- string[] cueLines = File.ReadAllLines(filename);
- for (int i = 0; i < cueLines.Length; i++)
- {
- string line = cueLines[i].Trim();
-
- // http://stackoverflow.com/questions/554013/regular-expression-to-split-on-spaces-unless-in-quotes
- string[] splitLine = Regex
- .Matches(line, @"[^\s""]+|""[^""]*""")
- .Cast()
- .Select(m => m.Groups[0].Value)
- .ToArray();
-
- // If we have an empty line, we skip
- if (string.IsNullOrWhiteSpace(line))
- continue;
-
- switch (splitLine[0])
- {
- // Read comments
- case "REM":
- // We ignore all comments for now
- break;
-
- // Read MCN
- case "CATALOG":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"CATALOG line malformed: {line}");
-
- continue;
- }
-
- this.Catalog = splitLine[1];
- break;
-
- // Read external CD-Text file path
- case "CDTEXTFILE":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"CDTEXTFILE line malformed: {line}");
-
- continue;
- }
-
- this.CdTextFile = splitLine[1];
- break;
-
- // Read CD-Text enhanced performer
- case "PERFORMER":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"PERFORMER line malformed: {line}");
-
- continue;
- }
-
- this.Performer = splitLine[1];
- break;
-
- // Read CD-Text enhanced songwriter
- case "SONGWRITER":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"SONGWRITER line malformed: {line}");
-
- continue;
- }
-
- this.Songwriter = splitLine[1];
- break;
-
- // Read CD-Text enhanced title
- case "TITLE":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"TITLE line malformed: {line}");
-
- continue;
- }
-
- this.Title = splitLine[1];
- break;
-
- // Read file information
- case "FILE":
- if (splitLine.Length < 3)
- {
- if (throwOnError)
- throw new FormatException($"FILE line malformed: {line}");
-
- continue;
- }
-
- if (this.Files == null)
- this.Files = new List();
-
- var file = new CueFile(splitLine[1], splitLine[2], cueLines, ref i);
- if (file == default)
- {
- if (throwOnError)
- throw new FormatException($"FILE line malformed: {line}");
-
- continue;
- }
-
- this.Files.Add(file);
- break;
- }
- }
- }
-
- ///
- /// Write the cuesheet out to a file
- ///
- /// File path to write to
- public void Write(string filename)
- {
- using (var fs = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
- {
- Write(fs);
- }
- }
-
- ///
- /// Write the cuesheet out to a stream
- ///
- /// Stream to write to
- /// True if errors throw an exception, false otherwise
- public void Write(Stream stream, bool throwOnError = false)
- {
- // If we don't have any files, it's invalid
- if (this.Files == null)
- {
- if (throwOnError)
- throw new ArgumentNullException(nameof(this.Files));
-
- return;
- }
- else if (this.Files.Count == 0)
- {
- if (throwOnError)
- throw new ArgumentException("No files provided to write");
-
- return;
- }
-
- using (var sw = new StreamWriter(stream, Encoding.ASCII, 1024, true))
- {
- if (!string.IsNullOrEmpty(this.Catalog))
- sw.WriteLine($"CATALOG {this.Catalog}");
-
- if (!string.IsNullOrEmpty(this.CdTextFile))
- sw.WriteLine($"CDTEXTFILE {this.CdTextFile}");
-
- if (!string.IsNullOrEmpty(this.Performer))
- sw.WriteLine($"PERFORMER {this.Performer}");
-
- if (!string.IsNullOrEmpty(this.Songwriter))
- sw.WriteLine($"SONGWRITER {this.Songwriter}");
-
- if (!string.IsNullOrEmpty(this.Title))
- sw.WriteLine($"TITLE {this.Title}");
-
- foreach (var file in Files)
- {
- file.Write(sw);
- }
- }
- }
- }
-}
diff --git a/MPF.CueSheets/CueTrack.cs b/MPF.CueSheets/CueTrack.cs
deleted file mode 100644
index 9414ab49..00000000
--- a/MPF.CueSheets/CueTrack.cs
+++ /dev/null
@@ -1,554 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-
-///
-/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
-///
-namespace MPF.CueSheets
-{
- ///
- /// Track datatype
- ///
- public enum CueTrackDataType
- {
- ///
- /// AUDIO, Audio/Music (2352)
- ///
- AUDIO,
-
- ///
- /// CDG, Karaoke CD+G (2448)
- ///
- CDG,
-
- ///
- /// MODE1/2048, CD-ROM Mode1 Data (cooked)
- ///
- MODE1_2048,
-
- ///
- /// MODE1/2352 CD-ROM Mode1 Data (raw)
- ///
- MODE1_2352,
-
- ///
- /// MODE2/2336, CD-ROM XA Mode2 Data
- ///
- MODE2_2336,
-
- ///
- /// MODE2/2352, CD-ROM XA Mode2 Data
- ///
- MODE2_2352,
-
- ///
- /// CDI/2336, CD-I Mode2 Data
- ///
- CDI_2336,
-
- ///
- /// CDI/2352, CD-I Mode2 Data
- ///
- CDI_2352,
- }
-
- ///
- /// Special subcode flags within a track
- ///
- [Flags]
- public enum CueTrackFlag
- {
- ///
- /// DCP, Digital copy permitted
- ///
- DCP = 1 << 0,
-
- ///
- /// 4CH, Four channel audio
- ///
- FourCH = 1 << 1,
-
- ///
- /// PRE, Pre-emphasis enabled (audio tracks only)
- ///
- PRE = 1 << 2,
-
- ///
- /// SCMS, Serial Copy Management System (not supported by all recorders)
- ///
- SCMS = 1 << 3,
-
- ///
- /// DATA, set for data files. This flag is set automatically based on the track’s filetype
- ///
- DATA = 1 << 4,
- }
-
- ///
- /// Represents a single TRACK in a FILE
- ///
- public class CueTrack
- {
- ///
- /// Track number. The range is 1 to 99.
- ///
- public int Number { get; set; }
-
- ///
- /// Track datatype
- ///
- public CueTrackDataType DataType { get; set; }
-
- ///
- /// FLAGS
- ///
- public CueTrackFlag Flags { get; set; }
-
- ///
- /// ISRC
- ///
- /// 12 characters in length
- public string ISRC { get; set; }
-
- ///
- /// PERFORMER
- ///
- public string Performer { get; set; }
-
- ///
- /// SONGWRITER
- ///
- public string Songwriter { get; set; }
-
- ///
- /// TITLE
- ///
- public string Title { get; set; }
-
- ///
- /// PREGAP
- ///
- public PreGap PreGap { get; set; }
-
- ///
- /// List of INDEX in TRACK
- ///
- /// Must start with 0 or 1 and then sequential
- public List Indices { get; set; }
-
- ///
- /// POSTGAP
- ///
- public PostGap PostGap { get; set; }
-
- ///
- /// Create an empty TRACK
- ///
- public CueTrack()
- {
- }
-
- ///
- /// Fill a TRACK from an array of lines
- ///
- /// Number to set
- /// Data type to set
- /// Lines array to pull from
- /// Reference to index in array
- /// True if errors throw an exception, false otherwise
- public CueTrack(string number, string dataType, string[] cueLines, ref int i, bool throwOnError = false)
- {
- if (cueLines == null)
- {
- if (throwOnError)
- throw new ArgumentNullException(nameof(cueLines));
-
- return;
- }
- else if (i < 0 || i > cueLines.Length)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException();
-
- return;
- }
-
- // Set the current fields
- if (!int.TryParse(number, out int parsedNumber))
- {
- if (throwOnError)
- throw new ArgumentException($"Number was not a number: {number}");
-
- return;
- }
- else if (parsedNumber < 1 || parsedNumber > 99)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Index must be between 1 and 99: {parsedNumber}");
-
- return;
- }
-
- this.Number = parsedNumber;
- this.DataType = GetDataType(dataType);
-
- // Increment to start
- i++;
-
- for (; i < cueLines.Length; i++)
- {
- string line = cueLines[i].Trim();
- string[] splitLine = line.Split(' ');
-
- // If we have an empty line, we skip
- if (string.IsNullOrWhiteSpace(line))
- continue;
-
- switch (splitLine[0])
- {
- // Read comments
- case "REM":
- // We ignore all comments for now
- break;
-
- // Read flag information
- case "FLAGS":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"FLAGS line malformed: {line}");
-
- continue;
- }
-
- this.Flags = GetFlags(splitLine);
- break;
-
- // Read International Standard Recording Code
- case "ISRC":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"ISRC line malformed: {line}");
-
- continue;
- }
-
- this.ISRC = splitLine[1];
- break;
-
- // Read CD-Text enhanced performer
- case "PERFORMER":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"PERFORMER line malformed: {line}");
-
- continue;
- }
-
- this.Performer = splitLine[1];
- break;
-
- // Read CD-Text enhanced songwriter
- case "SONGWRITER":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"SONGWRITER line malformed: {line}");
-
- continue;
- }
-
- this.Songwriter = splitLine[1];
- break;
-
- // Read CD-Text enhanced title
- case "TITLE":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"TITLE line malformed: {line}");
-
- continue;
- }
-
- this.Title = splitLine[1];
- break;
-
- // Read pregap information
- case "PREGAP":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"PREGAP line malformed: {line}");
-
- continue;
- }
-
- var pregap = new PreGap(splitLine[1]);
- if (pregap == default)
- {
- if (throwOnError)
- throw new FormatException($"PREGAP line malformed: {line}");
-
- continue;
- }
-
- this.PreGap = pregap;
- break;
-
- // Read index information
- case "INDEX":
- if (splitLine.Length < 3)
- {
- if (throwOnError)
- throw new FormatException($"INDEX line malformed: {line}");
-
- continue;
- }
-
- if (this.Indices == null)
- this.Indices = new List();
-
- var index = new CueIndex(splitLine[1], splitLine[2]);
- if (index == default)
- {
- if (throwOnError)
- throw new FormatException($"INDEX line malformed: {line}");
-
- continue;
- }
-
- this.Indices.Add(index);
- break;
-
- // Read postgap information
- case "POSTGAP":
- if (splitLine.Length < 2)
- {
- if (throwOnError)
- throw new FormatException($"POSTGAP line malformed: {line}");
-
- continue;
- }
-
- var postgap = new PostGap(splitLine[1]);
- if (postgap == default)
- {
- if (throwOnError)
- throw new FormatException($"POSTGAP line malformed: {line}");
-
- continue;
- }
-
- this.PostGap = postgap;
- break;
-
- // Default means return
- default:
- i--;
- return;
- }
- }
- }
-
- ///
- /// Write the TRACK out to a stream
- ///
- /// StreamWriter to write toTrue if errors throw an exception, false otherwise
- public void Write(StreamWriter sw, bool throwOnError = false)
- {
- // If we don't have any indices, it's invalid
- if (this.Indices == null)
- {
- if (throwOnError)
- throw new ArgumentNullException(nameof(this.Indices));
-
- return;
- }
- else if (this.Indices.Count == 0)
- {
- if (throwOnError)
- throw new ArgumentException("No indices provided to write");
-
- return;
- }
-
- sw.WriteLine($" TRACK {this.Number:D2} {FromDataType(this.DataType)}");
-
- if (this.Flags != 0)
- sw.WriteLine($" FLAGS {FromFlags(this.Flags)}");
-
- if (!string.IsNullOrEmpty(this.ISRC))
- sw.WriteLine($"ISRC {this.ISRC}");
-
- if (!string.IsNullOrEmpty(this.Performer))
- sw.WriteLine($"PERFORMER {this.Performer}");
-
- if (!string.IsNullOrEmpty(this.Songwriter))
- sw.WriteLine($"SONGWRITER {this.Songwriter}");
-
- if (!string.IsNullOrEmpty(this.Title))
- sw.WriteLine($"TITLE {this.Title}");
-
- if (this.PreGap != null)
- this.PreGap.Write(sw);
-
- foreach (var index in Indices)
- {
- index.Write(sw);
- }
-
- if (this.PostGap != null)
- this.PostGap.Write(sw);
- }
-
- ///
- /// Get the data type from a given string
- ///
- /// String to get value from
- /// CueTrackDataType, if possible (default AUDIO)
- private CueTrackDataType GetDataType(string dataType)
- {
- switch (dataType.ToLowerInvariant())
- {
- case "audio":
- return CueTrackDataType.AUDIO;
-
- case "cdg":
- return CueTrackDataType.CDG;
-
- case "mode1/2048":
- return CueTrackDataType.MODE1_2048;
-
- case "mode1/2352":
- return CueTrackDataType.MODE1_2352;
-
- case "mode2/2336":
- return CueTrackDataType.MODE2_2336;
-
- case "mode2/2352":
- return CueTrackDataType.MODE2_2352;
-
- case "cdi/2336":
- return CueTrackDataType.CDI_2336;
-
- case "cdi/2352":
- return CueTrackDataType.CDI_2352;
-
- default:
- return CueTrackDataType.AUDIO;
- }
- }
-
- ///
- /// Get the string from a given data type
- ///
- /// CueTrackDataType to get value from
- /// string, if possible
- private string FromDataType(CueTrackDataType dataType)
- {
- switch (dataType)
- {
- case CueTrackDataType.AUDIO:
- return "AUDIO";
-
- case CueTrackDataType.CDG:
- return "CDG";
-
- case CueTrackDataType.MODE1_2048:
- return "MODE1/2048";
-
- case CueTrackDataType.MODE1_2352:
- return "MODE1/2352";
-
- case CueTrackDataType.MODE2_2336:
- return "MODE2/2336";
-
- case CueTrackDataType.MODE2_2352:
- return "MODE2/2352";
-
- case CueTrackDataType.CDI_2336:
- return "CDI/2336";
-
- case CueTrackDataType.CDI_2352:
- return "CDI/2352";
-
- default:
- return string.Empty;
- }
- }
-
- ///
- /// Get the flag value for an array of strings
- ///
- /// Possible flags as strings
- /// CueTrackFlag value representing the strings, if possible
- private CueTrackFlag GetFlags(string[] flagStrings)
- {
- CueTrackFlag flag = 0;
-
- foreach (string flagString in flagStrings)
- {
- switch (flagString.ToLowerInvariant())
- {
- case "flags":
- // No-op since this is the start of the line
- break;
-
- case "dcp":
- flag |= CueTrackFlag.DCP;
- break;
-
- case "4ch":
- flag |= CueTrackFlag.FourCH;
- break;
-
- case "pre":
- flag |= CueTrackFlag.PRE;
- break;
-
- case "scms":
- flag |= CueTrackFlag.SCMS;
- break;
-
- case "data":
- flag |= CueTrackFlag.DATA;
- break;
- }
- }
-
- return flag;
- }
-
- ///
- /// Get the string value for a set of track flags
- ///
- /// CueTrackFlag to get value from
- /// String value representing the CueTrackFlag, if possible
- private string FromFlags(CueTrackFlag flags)
- {
- string outputFlagString = string.Empty;
-
- if (flags.HasFlag(CueTrackFlag.DCP))
- outputFlagString += "DCP ";
-
- if (flags.HasFlag(CueTrackFlag.FourCH))
- outputFlagString += "4CH ";
-
- if (flags.HasFlag(CueTrackFlag.PRE))
- outputFlagString += "PRE ";
-
- if (flags.HasFlag(CueTrackFlag.SCMS))
- outputFlagString += "SCMS ";
-
- if (flags.HasFlag(CueTrackFlag.DATA))
- outputFlagString += "DATA ";
-
- return outputFlagString.Trim();
- }
- }
-}
diff --git a/MPF.CueSheets/MPF.CueSheets.csproj b/MPF.CueSheets/MPF.CueSheets.csproj
deleted file mode 100644
index c4d877d4..00000000
--- a/MPF.CueSheets/MPF.CueSheets.csproj
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
- net48;net6.0
- win7-x64;win8-x64;win81-x64;win10-x64;linux-x64;osx-x64
- Matt Nadareski;ReignStumble;Jakz
- Copyright (c)2019-2023
- https://github.com/SabreTools/MPF
- 2.6.3
- $(Version)
- $(Version)
- true
- true
- true
-
-
-
- $(Version)-{chash:8}
- true
- false
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
diff --git a/MPF.CueSheets/PostGap.cs b/MPF.CueSheets/PostGap.cs
deleted file mode 100644
index c0e9b7c1..00000000
--- a/MPF.CueSheets/PostGap.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-using System;
-using System.IO;
-using System.Linq;
-
-///
-/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
-///
-namespace MPF.CueSheets
-{
- ///
- /// Represents POSTGAP information of a track
- ///
- public class PostGap
- {
- ///
- /// Length of POSTGAP in minutes
- ///
- public int Minutes { get; set; }
-
- ///
- /// Length of POSTGAP in seconds
- ///
- /// There are 60 seconds in a minute
- public int Seconds { get; set; }
-
- ///
- /// Length of POSTGAP in frames.
- ///
- /// There are 75 frames per second
- public int Frames { get; set; }
-
- /// Create an empty POSTGAP
- ///
- public PostGap()
- {
- }
-
- ///
- /// Create a POSTGAP from a mm:ss:ff length
- ///
- /// String to get length information from
- /// True if errors throw an exception, false otherwise
- public PostGap(string length, bool throwOnError = false)
- {
- // Ignore empty lines
- if (string.IsNullOrWhiteSpace(length))
- {
- if (throwOnError)
- throw new ArgumentException("Length was null or whitespace");
-
- return;
- }
-
- // Ignore lines that don't contain the correct information
- if (length.Length != 8 || length.Count(c => c == ':') != 2)
- {
- if (throwOnError)
- throw new FormatException($"Length was not in a recognized format: {length}");
-
- return;
- }
-
- // Split the line
- string[] splitLength = length.Split(':');
- if (splitLength.Length != 3)
- {
- if (throwOnError)
- throw new FormatException($"Length was not in a recognized format: {length}");
-
- return;
- }
-
- // Parse the lengths
- int[] lengthSegments = new int[3];
-
- // Minutes
- if (!int.TryParse(splitLength[0], out lengthSegments[0]))
- {
- if (throwOnError)
- throw new FormatException($"Minutes segment was not a number: {splitLength[0]}");
-
- return;
- }
- else if (lengthSegments[0] < 0)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Minutes segment must be 0 or greater: {lengthSegments[0]}");
-
- return;
- }
-
- // Seconds
- if (!int.TryParse(splitLength[1], out lengthSegments[1]))
- {
- if (throwOnError)
- throw new FormatException($"Seconds segment was not a number: {splitLength[1]}");
-
- return;
- }
- else if (lengthSegments[1] < 0 || lengthSegments[1] > 60)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Seconds segment must be between 0 and 60: {lengthSegments[1]}");
-
- return;
- }
-
- // Frames
- if (!int.TryParse(splitLength[2], out lengthSegments[2]))
- {
- if (throwOnError)
- throw new FormatException($"Frames segment was not a number: {splitLength[2]}");
-
- return;
- }
- else if (lengthSegments[2] < 0 || lengthSegments[2] > 75)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Frames segment must be between 0 and 75: {lengthSegments[2]}");
-
- return;
- }
-
- // Set the values
- this.Minutes = lengthSegments[0];
- this.Seconds = lengthSegments[1];
- this.Frames = lengthSegments[2];
- }
-
- ///
- /// Write the POSTGAP out to a stream
- ///
- /// StreamWriter to write to
- public void Write(StreamWriter sw)
- {
- sw.WriteLine($" POSTGAP {this.Minutes:D2}:{this.Seconds:D2}:{this.Frames:D2}");
- }
- }
-}
diff --git a/MPF.CueSheets/PreGap.cs b/MPF.CueSheets/PreGap.cs
deleted file mode 100644
index 803bc5c5..00000000
--- a/MPF.CueSheets/PreGap.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-using System;
-using System.IO;
-using System.Linq;
-
-///
-/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
-///
-namespace MPF.CueSheets
-{
- ///
- /// Represents PREGAP information of a track
- ///
- public class PreGap
- {
- ///
- /// Length of PREGAP in minutes
- ///
- public int Minutes { get; set; }
-
- ///
- /// Length of PREGAP in seconds
- ///
- /// There are 60 seconds in a minute
- public int Seconds { get; set; }
-
- ///
- /// Length of PREGAP in frames.
- ///
- /// There are 75 frames per second
- public int Frames { get; set; }
-
- ///
- /// Create an empty PREGAP
- ///
- public PreGap()
- {
- }
-
- ///
- /// Create a PREGAP from a mm:ss:ff length
- ///
- /// String to get length information from
- /// True if errors throw an exception, false otherwise
- public PreGap(string length, bool throwOnError = false)
- {
- // Ignore empty lines
- if (string.IsNullOrWhiteSpace(length))
- {
- if (throwOnError)
- throw new ArgumentException("Length was null or whitespace");
-
- return;
- }
-
- // Ignore lines that don't contain the correct information
- if (length.Length != 8 || length.Count(c => c == ':') != 2)
- {
- if (throwOnError)
- throw new FormatException($"Length was not in a recognized format: {length}");
-
- return;
- }
-
- // Split the line
- string[] splitLength = length.Split(':');
- if (splitLength.Length != 3)
- {
- if (throwOnError)
- throw new FormatException($"Length was not in a recognized format: {length}");
-
- return;
- }
-
- // Parse the lengths
- int[] lengthSegments = new int[3];
-
- // Minutes
- if (!int.TryParse(splitLength[0], out lengthSegments[0]))
- {
- if (throwOnError)
- throw new FormatException($"Minutes segment was not a number: {splitLength[0]}");
-
- return;
- }
- else if (lengthSegments[0] < 0)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Minutes segment must be 0 or greater: {lengthSegments[0]}");
-
- return;
- }
-
- // Seconds
- if (!int.TryParse(splitLength[1], out lengthSegments[1]))
- {
- if (throwOnError)
- throw new FormatException($"Seconds segment was not a number: {splitLength[1]}");
-
- return;
- }
- else if (lengthSegments[1] < 0 || lengthSegments[1] > 60)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Seconds segment must be between 0 and 60: {lengthSegments[1]}");
-
- return;
- }
-
- // Frames
- if (!int.TryParse(splitLength[2], out lengthSegments[2]))
- {
- if (throwOnError)
- throw new FormatException($"Frames segment was not a number: {splitLength[2]}");
-
- return;
- }
- else if (lengthSegments[2] < 0 || lengthSegments[2] > 75)
- {
- if (throwOnError)
- throw new IndexOutOfRangeException($"Frames segment must be between 0 and 75: {lengthSegments[2]}");
-
- return;
- }
-
- // Set the values
- this.Minutes = lengthSegments[0];
- this.Seconds = lengthSegments[1];
- this.Frames = lengthSegments[2];
- }
-
- ///
- /// Write the PREGAP out to a stream
- ///
- /// StreamWriter to write to
- public void Write(StreamWriter sw)
- {
- sw.WriteLine($" PREGAP {this.Minutes:D2}:{this.Seconds:D2}:{this.Frames:D2}");
- }
- }
-}
diff --git a/MPF.Modules/Aaru/Parameters.cs b/MPF.Modules/Aaru/Parameters.cs
index 4dcf56c0..2293a871 100644
--- a/MPF.Modules/Aaru/Parameters.cs
+++ b/MPF.Modules/Aaru/Parameters.cs
@@ -9,7 +9,7 @@ using System.Xml.Schema;
using System.Xml.Serialization;
using MPF.Core.Converters;
using MPF.Core.Data;
-using MPF.CueSheets;
+using SabreTools.Models.CueSheets;
using SabreTools.RedumpLib.Data;
using Schemas;
@@ -2441,10 +2441,10 @@ namespace MPF.Modules.Aaru
// Required variables
uint totalTracks = 0;
- CueSheet cueSheet = new CueSheet
+ var cueFiles = new List();
+ var cueSheet = new CueSheet
{
Performer = string.Join(", ", cicmSidecar.Performer ?? new string[0]),
- Files = new List(),
};
// Only care about OpticalDisc types
@@ -2482,13 +2482,13 @@ namespace MPF.Modules.Aaru
{
FileName = GenerateTrackName(basePath, (int)totalTracks, cueTrack.Number, opticalDisc.DiscType),
FileType = CueFileType.BINARY,
- Tracks = new List(),
};
// Add index data
+ var cueTracks = new List();
if (track.Indexes != null && track.Indexes.Length > 0)
{
- cueTrack.Indices = new List();
+ var cueIndicies = new List();
// Loop through each index
foreach (TrackIndexType trackIndex in track.Indexes)
@@ -2502,36 +2502,60 @@ namespace MPF.Modules.Aaru
// Pregap information
if (trackIndex.Value < 0)
- cueTrack.PreGap = new PreGap(timeString);
+ {
+ string[] timeStringSplit = timeString.Split(':');
+ cueTrack.PreGap = new PreGap
+ {
+ Minutes = int.Parse(timeStringSplit[0]),
+ Seconds = int.Parse(timeStringSplit[1]),
+ Frames = int.Parse(timeStringSplit[2]),
+ };
+ }
// Individual indexes
else
- cueTrack.Indices.Add(new CueIndex(trackIndex.index.ToString(), timeString));
+ {
+ string[] timeStringSplit = timeString.Split(':');
+ cueIndicies.Add(new CueIndex
+ {
+ Index = trackIndex.index,
+ Minutes = int.Parse(timeStringSplit[0]),
+ Seconds = int.Parse(timeStringSplit[1]),
+ Frames = int.Parse(timeStringSplit[2]),
+ });
+ }
}
+
+ cueTrack.Indices = cueIndicies.ToArray();
}
else
{
// Default if index data missing from sidecar
- cueTrack.Indices = new List()
+ cueTrack.Indices = new CueIndex[]
{
- new CueIndex("01", "00:00:00"),
+ new CueIndex
+ {
+ Index = 1,
+ Minutes = 0,
+ Seconds = 0,
+ Frames = 0,
+ },
};
}
// Add the track to the file
- cueFile.Tracks.Add(cueTrack);
+ cueTracks.Add(cueTrack);
// Add the file to the cuesheet
- cueSheet.Files.Add(cueFile);
+ cueFiles.Add(cueFile);
}
}
// If we have a cuesheet to write out, do so
+ cueSheet.Files = cueFiles.ToArray();
if (cueSheet != null && cueSheet != default)
{
- MemoryStream ms = new MemoryStream();
- cueSheet.Write(ms);
- ms.Position = 0;
+ var ms = new SabreTools.Serialization.Streams.CueSheet().Serialize(cueSheet);
using (var sr = new StreamReader(ms))
{
return sr.ReadToEnd();
diff --git a/MPF.Modules/DiscImageCreator/Parameters.cs b/MPF.Modules/DiscImageCreator/Parameters.cs
index 7fc5194a..9ced2d5e 100644
--- a/MPF.Modules/DiscImageCreator/Parameters.cs
+++ b/MPF.Modules/DiscImageCreator/Parameters.cs
@@ -2,12 +2,10 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Text;
using System.Text.RegularExpressions;
using MPF.Core.Converters;
using MPF.Core.Data;
using MPF.Core.Utilities;
-using MPF.CueSheets;
using SabreTools.RedumpLib.Data;
namespace MPF.Modules.DiscImageCreator
diff --git a/MPF.Modules/MPF.Modules.csproj b/MPF.Modules/MPF.Modules.csproj
index 5deb9774..3c1bdefb 100644
--- a/MPF.Modules/MPF.Modules.csproj
+++ b/MPF.Modules/MPF.Modules.csproj
@@ -22,12 +22,12 @@
-
+
diff --git a/MPF.sln b/MPF.sln
index b91a1966..7bd30432 100644
--- a/MPF.sln
+++ b/MPF.sln
@@ -23,8 +23,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
publish-win.bat = publish-win.bat
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MPF.CueSheets", "MPF.CueSheets\MPF.CueSheets.csproj", "{F2C12798-DF53-4D4C-A55B-F5A77F29D6B1}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MPF.Core", "MPF.Core\MPF.Core.csproj", "{70B1265D-FE49-472A-A83D-0B462152D37A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MPF.Modules", "MPF.Modules\MPF.Modules.csproj", "{8A4254BD-552F-4238-B8EB-D59AACD768B9}"
@@ -55,10 +53,6 @@ Global
{8CFDE289-E171-4D49-A40D-5293265C1253}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CFDE289-E171-4D49-A40D-5293265C1253}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CFDE289-E171-4D49-A40D-5293265C1253}.Release|Any CPU.Build.0 = Release|Any CPU
- {F2C12798-DF53-4D4C-A55B-F5A77F29D6B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F2C12798-DF53-4D4C-A55B-F5A77F29D6B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F2C12798-DF53-4D4C-A55B-F5A77F29D6B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F2C12798-DF53-4D4C-A55B-F5A77F29D6B1}.Release|Any CPU.Build.0 = Release|Any CPU
{70B1265D-FE49-472A-A83D-0B462152D37A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70B1265D-FE49-472A-A83D-0B462152D37A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70B1265D-FE49-472A-A83D-0B462152D37A}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -80,7 +74,6 @@ Global
{7CC064D2-38AB-4A05-8519-28660DE4562A} = {4160167D-681D-480B-ABC6-06AC869E5769}
{51AB0928-13F9-44BF-A407-B6957A43A056} = {4160167D-681D-480B-ABC6-06AC869E5769}
{8CFDE289-E171-4D49-A40D-5293265C1253} = {4160167D-681D-480B-ABC6-06AC869E5769}
- {F2C12798-DF53-4D4C-A55B-F5A77F29D6B1} = {4160167D-681D-480B-ABC6-06AC869E5769}
{70B1265D-FE49-472A-A83D-0B462152D37A} = {4160167D-681D-480B-ABC6-06AC869E5769}
{8A4254BD-552F-4238-B8EB-D59AACD768B9} = {4160167D-681D-480B-ABC6-06AC869E5769}
{EA3768DB-694A-4653-82E4-9FF71B8963F3} = {4160167D-681D-480B-ABC6-06AC869E5769}