diff --git a/CUETools.Processor/CUETools.Processor.csproj b/CUETools.Processor/CUETools.Processor.csproj
index 28c52e9..d1dfd50 100644
--- a/CUETools.Processor/CUETools.Processor.csproj
+++ b/CUETools.Processor/CUETools.Processor.csproj
@@ -98,6 +98,7 @@
+
diff --git a/CUETools.Processor/Processor.cs b/CUETools.Processor/Processor.cs
index c3a2a24..16a72b4 100644
--- a/CUETools.Processor/Processor.cs
+++ b/CUETools.Processor/Processor.cs
@@ -61,6 +61,7 @@ namespace CUETools.Processor
{
None,
Verify,
+ VerifyPlusCRCs,
VerifyThenConvert,
VerifyAndConvert
}
@@ -479,9 +480,23 @@ namespace CUETools.Processor
public bool ContinueOperation = true;
}
+ public class CUEToolsSourceFile
+ {
+ public string path;
+ public string contents;
+ public bool isEAC;
+
+ public CUEToolsSourceFile(string _path, StreamReader reader)
+ {
+ path = _path;
+ contents = reader.ReadToEnd();
+ reader.Close();
+ }
+ }
+
public class CUEToolsSelectionEventArgs
{
- public string[] choices;
+ public object[] choices;
public int selection = -1;
}
@@ -740,22 +755,13 @@ namespace CUETools.Processor
cueSheet = CUESheet.CreateDummyCUESheet(pathIn, "*." + _config.udc1Extension);
if (cueSheet == null)
throw new Exception("Input directory doesn't contain supported audio files.");
- sr = new StringReader(cueSheet);
- if (CUEToolsSelection != null)
- {
- CUEToolsSelectionEventArgs e = new CUEToolsSelectionEventArgs();
- e.choices = Directory.GetFiles(pathIn, "*.log");
- if (e.choices.Length > 0)
- {
- CUEToolsSelection(this, e);
- if (e.selection != -1)
- {
- StreamReader logReader = new StreamReader(e.choices[e.selection], CUESheet.Encoding);
- _eacLog = logReader.ReadToEnd();
- logReader.Close();
- }
- }
- }
+ sr = new StringReader(cueSheet);
+
+ List logFiles = new List();
+ foreach (string logPath in Directory.GetFiles(pathIn, "*.log"))
+ logFiles.Add(new CUEToolsSourceFile(logPath, new StreamReader(logPath, CUESheet.Encoding)));
+ CUEToolsSourceFile selectedLogFile = ChooseFile(logFiles, null, false);
+ _eacLog = selectedLogFile != null ? selectedLogFile.contents : null;
}
else if (Path.GetExtension(pathIn).ToLower() == ".zip" || Path.GetExtension(pathIn).ToLower() == ".rar")
{
@@ -795,64 +801,28 @@ namespace CUETools.Processor
}
}
- string cueName = null, cueText = null, logName = null;
- List cueNames = new List();
- List logNames = new List();
-
+ List logFiles = new List();
+ List cueFiles = new List();
foreach (string s in _archiveContents)
{
- if (Path.GetExtension(s).ToLower() == ".cue")
- cueNames.Add(s);
- if (Path.GetExtension(s).ToLower() == ".log")
- logNames.Add(s);
+ if (Path.GetExtension(s).ToLower() == ".cue" || Path.GetExtension(s).ToLower() == ".log")
+ {
+ Stream archiveStream = OpenArchive(s, false);
+ CUEToolsSourceFile sourceFile = new CUEToolsSourceFile(s, new StreamReader(archiveStream, CUESheet.Encoding));
+ archiveStream.Close();
+ if (Path.GetExtension(s).ToLower() == ".cue")
+ cueFiles.Add(sourceFile);
+ else
+ logFiles.Add(sourceFile);
+ }
}
- if (cueNames.Count == 0)
- throw new Exception("Input archive doesn't contain a cue sheet.");
- if (cueNames.Count == 1)
- cueName = cueNames[0];
- if (cueName == null && CUEToolsSelection != null)
- {
- CUEToolsSelectionEventArgs e = new CUEToolsSelectionEventArgs();
- e.choices = cueNames.ToArray();
- CUEToolsSelection(this, e);
- if (e.selection != -1)
- cueName = e.choices[e.selection];
- }
- if (cueName == null)
- throw new Exception("Input archive contains several cue sheets.");
-
- if (logNames.Contains(Path.ChangeExtension(cueName, ".log")))
- logName = Path.ChangeExtension(cueName, ".log");
- if (logName == null && CUEToolsSelection != null && logNames.Count > 0)
- {
- CUEToolsSelectionEventArgs e = new CUEToolsSelectionEventArgs();
- e.choices = logNames.ToArray();
- CUEToolsSelection(this, e);
- if (e.selection != -1)
- logName = e.choices[e.selection];
- }
-
- if (cueName != null)
- {
- Stream archiveStream = OpenArchive(cueName, false);
- StreamReader cueReader = new StreamReader(archiveStream, CUESheet.Encoding);
- cueText = cueReader.ReadToEnd();
- cueReader.Close();
- archiveStream.Close();
- if (cueText == "")
- throw new Exception("Empty cue sheet.");
- }
- if (cueText == null)
- throw new Exception("Input archive doesn't contain a cue sheet.");
- if (logName != null)
- {
- Stream archiveStream = OpenArchive(logName, false);
- StreamReader logReader = new StreamReader(archiveStream, CUESheet.Encoding);
- _eacLog = logReader.ReadToEnd();
- logReader.Close();
- archiveStream.Close();
- }
- _archiveCUEpath = Path.GetDirectoryName(cueName);
+ CUEToolsSourceFile selectedCUEFile = ChooseFile(cueFiles, null, true);
+ if (selectedCUEFile == null || selectedCUEFile.contents == "")
+ throw new Exception("Input archive doesn't contain a usable cue sheet.");
+ CUEToolsSourceFile selectedLogFile = ChooseFile(logFiles, Path.GetFileNameWithoutExtension(selectedCUEFile.path), true);
+ _eacLog = selectedLogFile != null ? selectedLogFile.contents : null;
+ _archiveCUEpath = Path.GetDirectoryName(selectedCUEFile.path);
+ string cueText = selectedCUEFile.contents;
if (_config.autoCorrectFilenames)
cueText = CorrectAudioFilenames(_archiveCUEpath, cueText, false, _archiveContents);
sr = new StringReader(cueText);
@@ -864,29 +834,13 @@ namespace CUETools.Processor
else
sr = new StreamReader (pathIn, CUESheet.Encoding);
- string logPath = Path.ChangeExtension(pathIn, ".log");
- if (System.IO.File.Exists(logPath))
- {
- StreamReader logReader = new StreamReader(logPath, CUESheet.Encoding);
- _eacLog = logReader.ReadToEnd();
- logReader.Close();
- }
- else if (CUEToolsSelection != null)
- {
- CUEToolsSelectionEventArgs e = new CUEToolsSelectionEventArgs();
- e.choices = Directory.GetFiles(cueDir == "" ? "." : cueDir, "*.log");
- if (e.choices.Length > 0)
- {
- CUEToolsSelection(this, e);
- if (e.selection != -1)
- {
- StreamReader logReader = new StreamReader(e.choices[e.selection], CUESheet.Encoding);
- _eacLog = logReader.ReadToEnd();
- logReader.Close();
- }
- }
- }
- } else
+ List logFiles = new List();
+ foreach (string logPath in Directory.GetFiles(cueDir == "" ? "." : cueDir, "*.log"))
+ logFiles.Add(new CUEToolsSourceFile(logPath, new StreamReader(logPath, CUESheet.Encoding)));
+ CUEToolsSourceFile selectedLogFile = ChooseFile(logFiles, Path.GetFileNameWithoutExtension(pathIn), false);
+ _eacLog = selectedLogFile != null ? selectedLogFile.contents : null;
+ }
+ else
{
string cuesheetTag = null;
TagLib.File fileInfo;
@@ -1332,6 +1286,43 @@ namespace CUETools.Processor
}
}
+ internal CUEToolsSourceFile ChooseFile(List sourceFiles, string defaultFileName, bool quietIfSingle)
+ {
+ if (sourceFiles.Count <= 0)
+ return null;
+
+ if (defaultFileName != null)
+ {
+ CUEToolsSourceFile defaultFile = null;
+ foreach (CUEToolsSourceFile file in sourceFiles)
+ if (Path.GetFileNameWithoutExtension(file.path).ToLower() == defaultFileName.ToLower())
+ {
+ if (defaultFile != null)
+ {
+ defaultFile = null;
+ break;
+ }
+ defaultFile = file;
+ }
+ if (defaultFile != null)
+ return defaultFile;
+ }
+
+ if (quietIfSingle && sourceFiles.Count == 1)
+ return sourceFiles[0];
+
+ if (CUEToolsSelection == null)
+ return null;
+
+ CUEToolsSelectionEventArgs e = new CUEToolsSelectionEventArgs();
+ e.choices = sourceFiles.ToArray();
+ CUEToolsSelection(this, e);
+ if (e.selection == -1)
+ return null;
+
+ return sourceFiles[e.selection];
+ }
+
internal Stream OpenArchive(string fileName, bool showProgress)
{
#if !MONO
@@ -1347,9 +1338,9 @@ namespace CUETools.Processor
if (Path.GetExtension(_archivePath).ToLower() == ".zip")
{
SeekableZipStream zipStream = new SeekableZipStream(_archivePath, fileName);
- zipStream.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired);
+ zipStream.PasswordRequired += new ZipPasswordRequiredHandler(unzip_PasswordRequired);
if (showProgress)
- zipStream.ExtractionProgress += new ExtractionProgressHandler(unrar_ExtractionProgress);
+ zipStream.ExtractionProgress += new ZipExtractionProgressHandler(unzip_ExtractionProgress);
return zipStream;
}
throw new Exception("Unknown archive type.");
@@ -1370,16 +1361,7 @@ namespace CUETools.Processor
#if !MONO
private void CDReadProgress(object sender, ReadProgressArgs e)
{
- lock (this)
- {
- if (_stop)
- throw new StopException();
- if (_pause)
- {
- ShowProgress("Paused...", 0, 0, null, null);
- Monitor.Wait(this);
- }
- }
+ CheckStop();
if (this.CUEToolsProgress == null)
return;
CDDriveReader audioSource = (CDDriveReader)sender;
@@ -1406,6 +1388,7 @@ namespace CUETools.Processor
private void unrar_ExtractionProgress(object sender, ExtractionProgressEventArgs e)
{
+ CheckStop();
if (this.CUEToolsProgress == null)
return;
_progress.percentTrck = e.PercentComplete/100;
@@ -1436,6 +1419,38 @@ namespace CUETools.Processor
}
#endif
+ private void unzip_ExtractionProgress(object sender, ZipExtractionProgressEventArgs e)
+ {
+ CheckStop();
+ if (this.CUEToolsProgress == null)
+ return;
+ _progress.percentTrck = e.PercentComplete / 100;
+ this.CUEToolsProgress(this, _progress);
+ }
+
+ private void unzip_PasswordRequired(object sender, ZipPasswordRequiredEventArgs e)
+ {
+ if (_archivePassword != null)
+ {
+ e.ContinueOperation = true;
+ e.Password = _archivePassword;
+ return;
+ }
+ if (this.PasswordRequired != null)
+ {
+ ArchivePasswordRequiredEventArgs e1 = new ArchivePasswordRequiredEventArgs();
+ this.PasswordRequired(this, e1);
+ if (e1.ContinueOperation && e1.Password != "")
+ {
+ _archivePassword = e1.Password;
+ e.ContinueOperation = true;
+ e.Password = e1.Password;
+ return;
+ }
+ }
+ throw new IOException("Password is required for extraction.");
+ }
+
public delegate string GetStringTagProvider(TagLib.File file);
public string GetCommonTag(GetStringTagProvider provider)
@@ -1943,7 +1958,7 @@ namespace CUETools.Processor
}
}
- if (_accurateRipMode != AccurateRipMode.Verify)
+ if (_accurateRipMode != AccurateRipMode.Verify && _accurateRipMode != AccurateRipMode.VerifyPlusCRCs)
for (int i = 0; i < destPaths.Length; i++)
for (int j = 0; j < _sourcePaths.Count; j++)
if (destPaths[i].ToLower() == _sourcePaths[j].ToLower())
@@ -1972,17 +1987,10 @@ namespace CUETools.Processor
break;
}
ShowProgress((string)"Contacting AccurateRip database...", 0, (dtl - minDTL) / 75.0, null, null);
+ CheckStop();
lock (this)
{
- if (_stop)
- throw new StopException();
- if (_pause)
- {
- ShowProgress("Paused...", 0, 0, null, null);
- Monitor.Wait(this);
- }
- else
- Monitor.Wait(this, 1000);
+ Monitor.Wait(this, 1000);
}
}
if (_arVerify.AccResult != HttpStatusCode.OK)
@@ -1993,6 +2001,23 @@ namespace CUETools.Processor
else
_arVerify.ContactAccurateRip(_accurateRipId);
+ if (_accurateRipMode == AccurateRipMode.Verify)
+ {
+ if (_arVerify.AccResult != HttpStatusCode.OK)
+ {
+ if (_config.writeArLogOnVerify)
+ {
+ if (!Directory.Exists(dir))
+ Directory.CreateDirectory(dir);
+ StreamWriter sw = new StreamWriter(Path.ChangeExtension(_cuePath, ".accurip"),
+ false, CUESheet.Encoding);
+ GenerateAccurateRipLog(sw);
+ sw.Close();
+ }
+ return;
+ }
+ }
+
if (_accurateRipMode == AccurateRipMode.VerifyThenConvert)
{
if (_arVerify.AccResult != HttpStatusCode.OK && !_isCD)
@@ -2047,16 +2072,16 @@ namespace CUETools.Processor
if (!SkipOutput)
{
- if (_accurateRipMode != AccurateRipMode.Verify)
+ if (_accurateRipMode != AccurateRipMode.Verify && _accurateRipMode != AccurateRipMode.VerifyPlusCRCs)
{
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
}
if (_isCD)
destLengths = CalculateAudioFileLengths(style); // need to recalc, might have changed after scanning the CD
- if (_outputFormat != OutputAudioFormat.NoAudio || _accurateRipMode == AccurateRipMode.Verify)
- WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, _accurateRipMode == AccurateRipMode.Verify);
- if (_accurateRipMode != AccurateRipMode.Verify)
+ if (_outputFormat != OutputAudioFormat.NoAudio || _accurateRipMode == AccurateRipMode.Verify || _accurateRipMode == AccurateRipMode.VerifyPlusCRCs)
+ WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, _accurateRipMode == AccurateRipMode.Verify || _accurateRipMode == AccurateRipMode.VerifyPlusCRCs);
+ if (_accurateRipMode != AccurateRipMode.Verify && _accurateRipMode != AccurateRipMode.VerifyPlusCRCs)
{
string logContents = LOGContents();
string cueContents = CUESheetContents(style);
@@ -2140,11 +2165,12 @@ namespace CUETools.Processor
}
}
- if (_accurateRipMode == AccurateRipMode.Verify ||
+ if (_accurateRipMode == AccurateRipMode.Verify ||
+ _accurateRipMode == AccurateRipMode.VerifyPlusCRCs ||
(_accurateRipMode != AccurateRipMode.None && _outputFormat != OutputAudioFormat.NoAudio))
{
ShowProgress((string)"Generating AccurateRip report...", 0, 0, null, null);
- if (_accurateRipMode == AccurateRipMode.Verify && _config.writeArTagsOnVerify && _writeOffset == 0 && !_isArchive && !_isCD)
+ if ((_accurateRipMode == AccurateRipMode.Verify || _accurateRipMode == AccurateRipMode.VerifyPlusCRCs) && _config.writeArTagsOnVerify && _writeOffset == 0 && !_isArchive && !_isCD)
{
uint tracksMatch;
int bestOffset;
@@ -2174,8 +2200,8 @@ namespace CUETools.Processor
}
}
- if ((_accurateRipMode != AccurateRipMode.Verify && _config.writeArLogOnConvert) ||
- (_accurateRipMode == AccurateRipMode.Verify && _config.writeArLogOnVerify))
+ if ((_accurateRipMode != AccurateRipMode.Verify && _accurateRipMode != AccurateRipMode.VerifyPlusCRCs && _config.writeArLogOnConvert) ||
+ ((_accurateRipMode == AccurateRipMode.Verify || _accurateRipMode == AccurateRipMode.VerifyPlusCRCs) && _config.writeArLogOnVerify))
{
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
@@ -2525,16 +2551,7 @@ namespace CUETools.Processor
samplesRemIndex -= copyCount;
samplesRemSource -= copyCount;
- lock (this)
- {
- if (_stop)
- throw new StopException();
- if (_pause)
- {
- ShowProgress("Paused...", 0, 0, null, null);
- Monitor.Wait(this);
- }
- }
+ CheckStop();
}
}
}
@@ -2734,6 +2751,20 @@ namespace CUETools.Processor
return fileLengths;
}
+ private void CheckStop()
+ {
+ lock (this)
+ {
+ if (_stop)
+ throw new StopException();
+ if (_pause)
+ {
+ ShowProgress("Paused...", 0, 0, null, null);
+ Monitor.Wait(this);
+ }
+ }
+ }
+
public void Stop() {
lock (this) {
if (_pause)
@@ -2766,6 +2797,14 @@ namespace CUETools.Processor
}
}
+ public CDImageLayout TOC
+ {
+ get
+ {
+ return _toc;
+ }
+ }
+
private IAudioDest GetAudioDest(string path, int finalSampleCount, int bps, bool noOutput)
{
if (noOutput)
@@ -3007,123 +3046,6 @@ namespace CUETools.Processor
}
}
- public class SeekableZipStream : Stream
- {
- ZipFile zipFile;
- ZipEntry zipEntry;
- Stream zipStream;
- long position;
- byte[] temp;
-
- public SeekableZipStream(string path, string fileName)
- {
- zipFile = new ZipFile(path);
- zipEntry = zipFile.GetEntry(fileName);
- if (zipEntry == null)
- throw new Exception("Archive entry not found.");
- zipStream = zipFile.GetInputStream(zipEntry);
- temp = new byte[65536];
- position = 0;
- }
- public override bool CanRead
- {
- get { return true; }
- }
- public override bool CanSeek
- {
- get { return true; }
- }
- public override bool CanWrite
- {
- get { return false; }
- }
- public override long Length
- {
- get
- {
- return zipEntry.Size;
- }
- }
- public override long Position
- {
- get { return position; }
- set { Seek(value, SeekOrigin.Begin); }
- }
- public override void Close()
- {
- zipStream.Close();
- zipEntry = null;
- zipFile.Close();
- }
- public override void Flush()
- {
- throw new NotSupportedException();
- }
- public override void SetLength(long value)
- {
- throw new NotSupportedException();
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- if (position == 0 && zipEntry.IsCrypted && ((ZipInputStream)zipStream).Password == null && PasswordRequired != null)
- {
- PasswordRequiredEventArgs e = new PasswordRequiredEventArgs();
- PasswordRequired(this, e);
- if (e.ContinueOperation && e.Password.Length > 0)
- ((ZipInputStream)zipStream).Password = e.Password;
- }
- // TODO: always save to a local temp circular buffer for optimization of the backwards seek.
- int total = zipStream.Read(buffer, offset, count);
- position += total;
- if (ExtractionProgress != null)
- {
- ExtractionProgressEventArgs e = new ExtractionProgressEventArgs();
- e.BytesExtracted = position;
- e.FileName = zipEntry.Name;
- e.FileSize = zipEntry.Size;
- e.PercentComplete = 100.0 * position / zipEntry.Size;
- ExtractionProgress(this, e);
- }
- return total;
- }
- public override long Seek(long offset, SeekOrigin origin)
- {
- long seek_to;
- switch (origin)
- {
- case SeekOrigin.Begin:
- seek_to = offset;
- break;
- case SeekOrigin.Current:
- seek_to = Position + offset;
- break;
- case SeekOrigin.End:
- seek_to = Length + offset;
- break;
- default:
- throw new NotSupportedException();
- }
- if (seek_to < 0 || seek_to > Length)
- throw new IOException("Invalid seek");
- if (seek_to < position)
- {
- zipStream.Close();
- zipStream = zipFile.GetInputStream(zipEntry);
- position = 0;
- }
- while (seek_to > position)
- if (Read(temp, 0, (int) Math.Min(seek_to - position, (long) temp.Length)) <= 0)
- throw new IOException("Invalid seek");
- return position;
- }
- public override void Write(byte[] array, int offset, int count)
- {
- throw new NotSupportedException();
- }
- public event PasswordRequiredHandler PasswordRequired;
- public event ExtractionProgressHandler ExtractionProgress;
- }
-
public class ArchiveFileAbstraction : TagLib.File.IFileAbstraction
{
private string name;
diff --git a/CUETools.Processor/SeekableZipStream.cs b/CUETools.Processor/SeekableZipStream.cs
new file mode 100644
index 0000000..4346ff9
--- /dev/null
+++ b/CUETools.Processor/SeekableZipStream.cs
@@ -0,0 +1,167 @@
+using System;
+using System.IO;
+using ICSharpCode.SharpZipLib.Zip;
+
+namespace CUETools.Processor
+{
+ #region Event Delegate Definitions
+
+ ///
+ /// Represents the method that will handle extraction progress events
+ ///
+ public delegate void ZipExtractionProgressHandler(object sender, ZipExtractionProgressEventArgs e);
+ ///
+ /// Represents the method that will handle password required events
+ ///
+ public delegate void ZipPasswordRequiredHandler(object sender, ZipPasswordRequiredEventArgs e);
+
+ #endregion
+
+ public class SeekableZipStream : Stream
+ {
+ ZipFile zipFile;
+ ZipEntry zipEntry;
+ Stream zipStream;
+ long position;
+ byte[] temp;
+
+ public SeekableZipStream(string path, string fileName)
+ {
+ zipFile = new ZipFile(path);
+ zipEntry = zipFile.GetEntry(fileName);
+ if (zipEntry == null)
+ throw new Exception("Archive entry not found.");
+ zipStream = zipFile.GetInputStream(zipEntry);
+ temp = new byte[65536];
+ position = 0;
+ }
+
+ public override bool CanRead
+ {
+ get { return true; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return true; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override long Length
+ {
+ get
+ {
+ return zipEntry.Size;
+ }
+ }
+
+ public override long Position
+ {
+ get { return position; }
+ set { Seek(value, SeekOrigin.Begin); }
+ }
+
+ public override void Close()
+ {
+ zipStream.Close();
+ zipEntry = null;
+ zipFile.Close();
+ }
+
+ public override void Flush()
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (position == 0 && zipEntry.IsCrypted && ((ZipInputStream)zipStream).Password == null && PasswordRequired != null)
+ {
+ ZipPasswordRequiredEventArgs e = new ZipPasswordRequiredEventArgs();
+ PasswordRequired(this, e);
+ if (e.ContinueOperation && e.Password.Length > 0)
+ ((ZipInputStream)zipStream).Password = e.Password;
+ }
+ // TODO: always save to a local temp circular buffer for optimization of the backwards seek.
+ int total = zipStream.Read(buffer, offset, count);
+ position += total;
+ if (ExtractionProgress != null)
+ {
+ ZipExtractionProgressEventArgs e = new ZipExtractionProgressEventArgs();
+ e.BytesExtracted = position;
+ e.FileName = zipEntry.Name;
+ e.FileSize = zipEntry.Size;
+ e.PercentComplete = 100.0 * position / zipEntry.Size;
+ ExtractionProgress(this, e);
+ }
+ return total;
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ long seek_to;
+ switch (origin)
+ {
+ case SeekOrigin.Begin:
+ seek_to = offset;
+ break;
+ case SeekOrigin.Current:
+ seek_to = Position + offset;
+ break;
+ case SeekOrigin.End:
+ seek_to = Length + offset;
+ break;
+ default:
+ throw new NotSupportedException();
+ }
+ if (seek_to < 0 || seek_to > Length)
+ throw new IOException("Invalid seek");
+ if (seek_to < position)
+ {
+ zipStream.Close();
+ zipStream = zipFile.GetInputStream(zipEntry);
+ position = 0;
+ }
+ while (seek_to > position)
+ if (Read(temp, 0, (int)Math.Min(seek_to - position, (long)temp.Length)) <= 0)
+ throw new IOException("Invalid seek");
+ return position;
+ }
+
+ public override void Write(byte[] array, int offset, int count)
+ {
+ throw new NotSupportedException();
+ }
+
+ public event ZipPasswordRequiredHandler PasswordRequired;
+ public event ZipExtractionProgressHandler ExtractionProgress;
+ }
+
+ #region Event Argument Classes
+
+ public class ZipPasswordRequiredEventArgs
+ {
+ public string Password = string.Empty;
+ public bool ContinueOperation = true;
+ }
+
+ public class ZipExtractionProgressEventArgs
+ {
+ public string FileName;
+ public long FileSize;
+ public long BytesExtracted;
+ public double PercentComplete;
+ public bool ContinueOperation = true;
+ }
+
+ #endregion
+}
diff --git a/CUETools.Processor/Tagging.cs b/CUETools.Processor/Tagging.cs
index a3ef447..e762d96 100644
--- a/CUETools.Processor/Tagging.cs
+++ b/CUETools.Processor/Tagging.cs
@@ -18,6 +18,8 @@ namespace CUETools.Processor
xiph.SetField(tag, tags.GetValues(tag));
return true;
}
+ if (fileInfo is TagLib.Mpeg4.File)
+ return true;
if (fileInfo is TagLib.UserDefined.File && !(fileInfo as TagLib.UserDefined.File).SupportsAPEv2)
{
if (!(fileInfo as TagLib.UserDefined.File).SupportsID3v2)
diff --git a/CUETools.Processor/UserDefined.cs b/CUETools.Processor/UserDefined.cs
index 2a1a061..98ffc70 100644
--- a/CUETools.Processor/UserDefined.cs
+++ b/CUETools.Processor/UserDefined.cs
@@ -1,80 +1,80 @@
-//
-// File.cs: Provides tagging and properties support for WavPack files.
-//
-// Author:
-// Brian Nickel (brian.nickel@gmail.com)
-//
-// Original Source:
-// wvfile.cpp from libtunepimp
-//
-// Copyright (C) 2006-2007 Brian Nickel
-// Copyright (C) 2006 by Lukáš Lalinský (Original Implementation)
-// Copyright (C) 2004 by Allan Sandfeld Jensen (Original Implementation)
-//
-// This library is free software; you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License version
-// 2.1 as published by the Free Software Foundation.
-//
-// This library is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-// USA
-//
-
-using System;
-using TagLib;
-
-namespace TagLib.UserDefined {
- ///
- /// This class extends to
- /// provide tagging and properties support for user defined format files.
- ///
- ///
- /// A will be added automatically to
- /// any file that doesn't contain one. This change does not effect
- /// the file and can be reversed using the following method:
- /// file.RemoveTags (file.TagTypes & ~file.TagTypesOnDisk);
- ///
- [SupportedMimeType("taglib/misc", "misc")]
- public class File : TagLib.NonContainer.File
- {
- #region Private Fields
-
+//
+// File.cs: Provides tagging and properties support for WavPack files.
+//
+// Author:
+// Brian Nickel (brian.nickel@gmail.com)
+//
+// Original Source:
+// wvfile.cpp from libtunepimp
+//
+// Copyright (C) 2006-2007 Brian Nickel
+// Copyright (C) 2006 by Lukáš Lalinský (Original Implementation)
+// Copyright (C) 2004 by Allan Sandfeld Jensen (Original Implementation)
+//
+// This library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License version
+// 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA
+//
+
+using System;
+using TagLib;
+
+namespace TagLib.UserDefined {
+ ///
+ /// This class extends to
+ /// provide tagging and properties support for user defined format files.
+ ///
+ ///
+ /// A will be added automatically to
+ /// any file that doesn't contain one. This change does not effect
+ /// the file and can be reversed using the following method:
+ /// file.RemoveTags (file.TagTypes & ~file.TagTypesOnDisk);
+ ///
+ [SupportedMimeType("taglib/misc", "misc")]
+ public class File : TagLib.NonContainer.File
+ {
+ #region Private Fields
+
private bool _supportsAPEv2 = true;
- private bool _supportsID3v2 = true;
-
- #endregion
-
-
-
- #region Constructors
-
- ///
- /// Constructs and initializes a new instance of for a specified path in the local file
- /// system and specified read style.
- ///
- ///
- /// A object containing the path of the
- /// file to use in the new instance.
- ///
- ///
- /// A value specifying at what level
- /// of accuracy to read the media properties, or to ignore the properties.
- ///
- ///
- /// is .
- ///
- public File (string path, ReadStyle propertiesStyle, bool supportsAPEv2, bool supportsID3v2)
- : base (path, propertiesStyle)
- {
+ private bool _supportsID3v2 = true;
+
+ #endregion
+
+
+
+ #region Constructors
+
+ ///
+ /// Constructs and initializes a new instance of for a specified path in the local file
+ /// system and specified read style.
+ ///
+ ///
+ /// A object containing the path of the
+ /// file to use in the new instance.
+ ///
+ ///
+ /// A value specifying at what level
+ /// of accuracy to read the media properties, or to ignore the properties.
+ ///
+ ///
+ /// is .
+ ///
+ public File (string path, ReadStyle propertiesStyle, bool supportsAPEv2, bool supportsID3v2)
+ : base (path, propertiesStyle)
+ {
_supportsAPEv2 = supportsAPEv2;
_supportsID3v2 = supportsID3v2;
// Make sure we have an APE tag.
@@ -83,23 +83,23 @@ namespace TagLib.UserDefined {
else
if (_supportsID3v2)
GetTag(TagTypes.Id3v2, true);
- }
-
- ///
- /// Constructs and initializes a new instance of for a specified path in the local file
- /// system with an average read style.
- ///
- ///
- /// A object containing the path of the
- /// file to use in the new instance.
- ///
- ///
- /// is .
+ }
+
+ ///
+ /// Constructs and initializes a new instance of for a specified path in the local file
+ /// system with an average read style.
+ ///
+ ///
+ /// A object containing the path of the
+ /// file to use in the new instance.
+ ///
+ ///
+ /// is .
///
public File(string path, bool supportsAPEv2, bool supportsID3v2)
- : base(path)
- {
+ : base(path)
+ {
_supportsAPEv2 = supportsAPEv2;
_supportsID3v2 = supportsID3v2;
// Make sure we have an APE tag.
@@ -108,56 +108,30 @@ namespace TagLib.UserDefined {
else
if (_supportsID3v2)
GetTag(TagTypes.Id3v2, true);
- }
-
- ///
- /// Constructs and initializes a new instance of for a specified file abstraction and
- /// specified read style.
- ///
- ///
- /// A object to use when
- /// reading from and writing to the file.
- ///
- ///
- /// A value specifying at what level
- /// of accuracy to read the media properties, or to ignore the properties.
- ///
- ///
- /// is .
- ///
- public File (File.IFileAbstraction abstraction,
- ReadStyle propertiesStyle, bool supportsAPEv2, bool supportsID3v2)
- : base (abstraction, propertiesStyle)
- {
- _supportsAPEv2 = supportsAPEv2;
- _supportsID3v2 = supportsID3v2;
- // Make sure we have an APE tag.
- if (_supportsAPEv2)
- GetTag(TagTypes.Ape, true);
- else
- if (_supportsID3v2)
- GetTag(TagTypes.Id3v2, true);
- }
-
- ///
- /// Constructs and initializes a new instance of for a specified file abstraction with an
- /// average read style.
- ///
- ///
- /// A object to use when
- /// reading from and writing to the file.
- ///
- ///
- /// is .
+ }
+
+ ///
+ /// Constructs and initializes a new instance of for a specified file abstraction and
+ /// specified read style.
+ ///
+ ///
+ /// A object to use when
+ /// reading from and writing to the file.
+ ///
+ ///
+ /// A value specifying at what level
+ /// of accuracy to read the media properties, or to ignore the properties.
+ ///
+ ///
+ /// is .
///
- public File(File.IFileAbstraction abstraction, bool supportsAPEv2, bool supportsID3v2)
- : base (abstraction)
- {
+ public File (File.IFileAbstraction abstraction,
+ ReadStyle propertiesStyle, bool supportsAPEv2, bool supportsID3v2)
+ : base (abstraction, propertiesStyle)
+ {
_supportsAPEv2 = supportsAPEv2;
_supportsID3v2 = supportsID3v2;
// Make sure we have an APE tag.
@@ -166,20 +140,46 @@ namespace TagLib.UserDefined {
else
if (_supportsID3v2)
GetTag(TagTypes.Id3v2, true);
- }
-
- #endregion
-
-
-
- #region Public Methods
-
- public bool SupportsAPEv2
- {
- get
- {
- return _supportsAPEv2;
- }
+ }
+
+ ///
+ /// Constructs and initializes a new instance of for a specified file abstraction with an
+ /// average read style.
+ ///
+ ///
+ /// A object to use when
+ /// reading from and writing to the file.
+ ///
+ ///
+ /// is .
+ ///
+ public File(File.IFileAbstraction abstraction, bool supportsAPEv2, bool supportsID3v2)
+ : base (abstraction)
+ {
+ _supportsAPEv2 = supportsAPEv2;
+ _supportsID3v2 = supportsID3v2;
+ // Make sure we have an APE tag.
+ if (_supportsAPEv2)
+ GetTag(TagTypes.Ape, true);
+ else
+ if (_supportsID3v2)
+ GetTag(TagTypes.Id3v2, true);
+ }
+
+ #endregion
+
+
+
+ #region Public Methods
+
+ public bool SupportsAPEv2
+ {
+ get
+ {
+ return _supportsAPEv2;
+ }
}
public bool SupportsID3v2
@@ -188,133 +188,133 @@ namespace TagLib.UserDefined {
{
return _supportsID3v2;
}
- }
-
-
- ///
- /// Gets a tag of a specified type from the current instance,
- /// optionally creating a new tag if possible.
- ///
- ///
- /// A value indicating the
- /// type of tag to read.
- ///
- ///
- /// A value specifying whether or not to
- /// try and create the tag if one is not found.
- ///
- ///
- /// A object containing the tag that was
- /// found in or added to the current instance. If no
- /// matching tag was found and none was created, is returned.
- ///
- ///
- /// If a is added to the
- /// current instance, it will be placed at the start of the
- /// file. On the other hand,
- /// will be added to the end of
- /// the file. All other tag types will be ignored.
- ///
- public override TagLib.Tag GetTag (TagTypes type, bool create)
- {
- Tag t = (Tag as TagLib.NonContainer.Tag).GetTag (type);
-
- if (t != null || !create)
- return t;
-
- switch (type)
- {
- case TagTypes.Id3v1:
- return EndTag.AddTag (type, Tag);
-
- case TagTypes.Id3v2:
- return StartTag.AddTag (type, Tag);
-
- case TagTypes.Ape:
- return EndTag.AddTag (type, Tag);
-
- default:
- return null;
- }
- }
-
- #endregion
-
-
-
- #region Protected Methods
-
- ///
- /// Reads format specific information at the start of the
- /// file.
- ///
- ///
- /// A value containing the seek position
- /// at which the tags end and the media data begins.
- ///
- ///
- /// A value specifying at what level
- /// of accuracy to read the media properties, or to ignore the properties.
- ///
- protected override void ReadStart (long start,
- ReadStyle propertiesStyle)
- {
- }
-
- ///
- /// Reads format specific information at the end of the
- /// file.
- ///
- ///
- /// A value containing the seek position
- /// at which the media data ends and the tags begin.
- ///
- ///
- /// A value specifying at what level
- /// of accuracy to read the media properties, or to ignore the properties.
- ///
- protected override void ReadEnd (long end,
- ReadStyle propertiesStyle)
- {
- }
-
- ///
- /// Reads the audio properties from the file represented by
- /// the current instance.
- ///
- ///
- /// A value containing the seek position
- /// at which the tags end and the media data begins.
- ///
- ///
- /// A value containing the seek position
- /// at which the media data ends and the tags begin.
- ///
- ///
- /// A value specifying at what level
- /// of accuracy to read the media properties, or to ignore the properties.
- ///
- ///
- /// A object describing the
- /// media properties of the file represented by the current
- /// instance.
- ///
- protected override Properties ReadProperties (long start,
- long end,
- ReadStyle propertiesStyle)
- {
- return new Properties ();
- }
-
- #endregion
- }
-
- public static class AdditionalFileTypes
- {
+ }
+
+
+ ///
+ /// Gets a tag of a specified type from the current instance,
+ /// optionally creating a new tag if possible.
+ ///
+ ///
+ /// A value indicating the
+ /// type of tag to read.
+ ///
+ ///
+ /// A value specifying whether or not to
+ /// try and create the tag if one is not found.
+ ///
+ ///
+ /// A object containing the tag that was
+ /// found in or added to the current instance. If no
+ /// matching tag was found and none was created, is returned.
+ ///
+ ///
+ /// If a is added to the
+ /// current instance, it will be placed at the start of the
+ /// file. On the other hand,
+ /// will be added to the end of
+ /// the file. All other tag types will be ignored.
+ ///
+ public override TagLib.Tag GetTag (TagTypes type, bool create)
+ {
+ Tag t = (Tag as TagLib.NonContainer.Tag).GetTag (type);
+
+ if (t != null || !create)
+ return t;
+
+ switch (type)
+ {
+ case TagTypes.Id3v1:
+ return EndTag.AddTag (type, Tag);
+
+ case TagTypes.Id3v2:
+ return StartTag.AddTag (type, Tag);
+
+ case TagTypes.Ape:
+ return EndTag.AddTag (type, Tag);
+
+ default:
+ return null;
+ }
+ }
+
+ #endregion
+
+
+
+ #region Protected Methods
+
+ ///
+ /// Reads format specific information at the start of the
+ /// file.
+ ///
+ ///
+ /// A value containing the seek position
+ /// at which the tags end and the media data begins.
+ ///
+ ///
+ /// A value specifying at what level
+ /// of accuracy to read the media properties, or to ignore the properties.
+ ///
+ protected override void ReadStart (long start,
+ ReadStyle propertiesStyle)
+ {
+ }
+
+ ///
+ /// Reads format specific information at the end of the
+ /// file.
+ ///
+ ///
+ /// A value containing the seek position
+ /// at which the media data ends and the tags begin.
+ ///
+ ///
+ /// A value specifying at what level
+ /// of accuracy to read the media properties, or to ignore the properties.
+ ///
+ protected override void ReadEnd (long end,
+ ReadStyle propertiesStyle)
+ {
+ }
+
+ ///
+ /// Reads the audio properties from the file represented by
+ /// the current instance.
+ ///
+ ///
+ /// A value containing the seek position
+ /// at which the tags end and the media data begins.
+ ///
+ ///
+ /// A value containing the seek position
+ /// at which the media data ends and the tags begin.
+ ///
+ ///
+ /// A value specifying at what level
+ /// of accuracy to read the media properties, or to ignore the properties.
+ ///
+ ///
+ /// A object describing the
+ /// media properties of the file represented by the current
+ /// instance.
+ ///
+ protected override Properties ReadProperties (long start,
+ long end,
+ ReadStyle propertiesStyle)
+ {
+ return new Properties ();
+ }
+
+ #endregion
+ }
+
+ public static class AdditionalFileTypes
+ {
private static bool inited = false;
private static CUETools.Processor.CUEConfig _config;
@@ -329,27 +329,27 @@ namespace TagLib.UserDefined {
private static TagLib.File UserDefinedResolver(TagLib.File.IFileAbstraction abstraction, string mimetype, TagLib.ReadStyle style)
{
- if (mimetype == "taglib/flac" || mimetype == "taglib/wv" || mimetype == "taglib/ape" || mimetype == "taglib/wav" || mimetype == "taglib/ogg")
+ if (mimetype == "taglib/flac" || mimetype == "taglib/wv" || mimetype == "taglib/ape" || mimetype == "taglib/wav" || mimetype == "taglib/ogg" || mimetype == "taglib/m4a")
return null;
if (mimetype == "taglib/tta")
return new File(abstraction, style, true, false);
if (mimetype == "taglib/" + _config.udc1Extension)
- return new File(abstraction, style, _config.udc1APEv2, _config.udc1ID3v2);
+ return new File(abstraction, style, _config.udc1APEv2, _config.udc1ID3v2);
return null;
}
-
- static AdditionalFileTypes ()
- {
- Init();
- }
-
- internal static void Init()
- {
- if (inited)
+
+ static AdditionalFileTypes ()
+ {
+ Init();
+ }
+
+ internal static void Init()
+ {
+ if (inited)
return;
TagLib.File.AddFileTypeResolver(new TagLib.File.FileTypeResolver(UserDefinedResolver));
- //FileTypes.Register(typeof(TagLib.NonContainer.File));
- inited = true;
- }
- }
-}
+ //FileTypes.Register(typeof(TagLib.NonContainer.File));
+ inited = true;
+ }
+ }
+}
diff --git a/CUETools/CUETools.csproj b/CUETools/CUETools.csproj
index 6cdf581..49be309 100644
--- a/CUETools/CUETools.csproj
+++ b/CUETools/CUETools.csproj
@@ -9,6 +9,7 @@
Properties
JDP
CUETools
+ Resources\cue.ico
true
@@ -203,6 +204,10 @@
+
+ {1DD41038-D885-46C5-8DDE-E0B82F066584}
+ CUETools.CDImage
+
{4911BD82-49EF-4858-8B51-5394F86739A4}
CUETools.Processor
@@ -222,6 +227,10 @@
+
+
+
+