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;
}
}
}
}