From 16ed2f95953f74fa2c4459786a05bc0e0150cc1f Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 13 Sep 2023 16:36:51 -0400 Subject: [PATCH] Migrate to Nuget package for cuesheets --- CHANGELIST.md | 1 + MPF.CueSheets/CueFile.cs | 238 --------- MPF.CueSheets/CueIndex.cs | 163 ------ MPF.CueSheets/CueSheet.cs | 250 ---------- MPF.CueSheets/CueTrack.cs | 554 --------------------- MPF.CueSheets/MPF.CueSheets.csproj | 31 -- MPF.CueSheets/PostGap.cs | 139 ------ MPF.CueSheets/PreGap.cs | 140 ------ MPF.Modules/Aaru/Parameters.cs | 52 +- MPF.Modules/DiscImageCreator/Parameters.cs | 2 - MPF.Modules/MPF.Modules.csproj | 2 +- MPF.sln | 7 - 12 files changed, 40 insertions(+), 1539 deletions(-) delete mode 100644 MPF.CueSheets/CueFile.cs delete mode 100644 MPF.CueSheets/CueIndex.cs delete mode 100644 MPF.CueSheets/CueSheet.cs delete mode 100644 MPF.CueSheets/CueTrack.cs delete mode 100644 MPF.CueSheets/MPF.CueSheets.csproj delete mode 100644 MPF.CueSheets/PostGap.cs delete mode 100644 MPF.CueSheets/PreGap.cs 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}