prevent the UI from freezing by not doing any essential work in the main thread;

save AccurateRip tags in output files in convert-and-verify mode;
This commit is contained in:
chudov
2008-12-02 00:06:16 +00:00
parent 687cd5062c
commit e4e1d3ebde
2 changed files with 290 additions and 230 deletions

View File

@@ -216,22 +216,15 @@ namespace JDP {
CUEConfig _config; CUEConfig _config;
private void StartConvert() { private void StartConvert() {
string pathIn, pathOut, outDir; try
CUESheet cueSheet; {
CUEStyle cueStyle;
try {
_workThread = null; _workThread = null;
if (_batchPaths.Count != 0) { if (_batchPaths.Count != 0)
{
txtInputPath.Text = _batchPaths[0]; txtInputPath.Text = _batchPaths[0];
} }
pathIn = txtInputPath.Text;
cueStyle = SelectedCUEStyle;
AccurateRipMode accurateRip = SelectedAccurateRipMode;
bool outputAudio = !rbNoAudio.Checked && accurateRip != AccurateRipMode.Verify;
bool outputCUE = cueStyle != CUEStyle.SingleFileWithCUE && accurateRip != AccurateRipMode.Verify;
string pathIn = txtInputPath.Text;
if (!File.Exists(pathIn)) if (!File.Exists(pathIn))
{ {
if (!Directory.Exists(pathIn)) if (!Directory.Exists(pathIn))
@@ -243,89 +236,38 @@ namespace JDP {
} }
} }
cueSheet = new CUESheet(_config); CUESheet cueSheet = new CUESheet(_config);
cueSheet.PasswordRequired += new ArchivePasswordRequiredHandler(PasswordRequired); cueSheet.PasswordRequired += new ArchivePasswordRequiredHandler(PasswordRequired);
cueSheet.CUEToolsProgress += new CUEToolsProgressHandler(SetStatus);
cueSheet.WriteOffset = _writeOffset; cueSheet.WriteOffset = _writeOffset;
cueSheet.Open(pathIn, chkLossyWAV.Checked);
UpdateOutputPath(cueSheet.Artist != "" ? cueSheet.Artist : "Unknown Artist", cueSheet.Title != "" ? cueSheet.Title : "Unknown Title"); object[] p = new object[6];
pathOut = txtOutputPath.Text;
cueSheet.GenerateFilenames(SelectedOutputAudioFormat, pathOut);
outDir = Path.GetDirectoryName(pathOut);
if (cueStyle == CUEStyle.SingleFileWithCUE)
cueSheet.SingleFilename = Path.GetFileName (pathOut);
bool outputExists = false;
if (outputCUE)
outputExists = File.Exists(pathOut);
if (outputAudio) {
if (cueStyle == CUEStyle.SingleFile || cueStyle == CUEStyle.SingleFileWithCUE) {
outputExists |= File.Exists(Path.Combine(outDir, cueSheet.SingleFilename));
}
else {
if ((cueStyle == CUEStyle.GapsAppended) && _config.preserveHTOA) {
outputExists |= File.Exists(Path.Combine(outDir, cueSheet.HTOAFilename));
}
for (int i = 0; i < cueSheet.TrackCount; i++) {
outputExists |= File.Exists(Path.Combine(outDir, cueSheet.TrackFilenames[i]));
}
}
}
if (outputExists) {
DialogResult dlgRes = MessageBox.Show("One or more output file already exists, " +
"do you want to overwrite?", "Overwrite?", (_batchPaths.Count == 0) ?
MessageBoxButtons.YesNo : MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (dlgRes == DialogResult.Cancel) {
_batchPaths.Clear();
}
if (dlgRes != DialogResult.Yes) {
goto SkipConversion;
}
}
cueSheet.UsePregapForFirstTrackInSingleFile = _usePregapForFirstTrackInSingleFile && !outputAudio;
cueSheet.AccurateRip = accurateRip;
if (accurateRip != AccurateRipMode.None)
cueSheet.DataTrackLength = txtDataTrackLength.Text;
if (outputAudio || accurateRip != AccurateRipMode.None)
{
object[] p = new object[3];
_workThread = new Thread(WriteAudioFilesThread); _workThread = new Thread(WriteAudioFilesThread);
_workClass = cueSheet; _workClass = cueSheet;
p[0] = cueSheet; p[0] = cueSheet;
p[1] = outDir; p[1] = pathIn;
p[2] = cueStyle; p[2] = SelectedCUEStyle;
p[3] = SelectedAccurateRipMode;
p[4] = SelectedOutputAudioFormat;
p[5] = chkLossyWAV.Checked;
SetupControls(true); SetupControls(true);
_workThread.Priority = ThreadPriority.BelowNormal; _workThread.Priority = ThreadPriority.BelowNormal;
_workThread.IsBackground = true; _workThread.IsBackground = true;
_workThread.Start(p); _workThread.Start(p);
} }
else { catch (Exception ex)
if (!Directory.Exists(outDir)) {
Directory.CreateDirectory(outDir); if (!ShowErrorMessage(ex))
if (outputCUE)
cueSheet.WriteText(pathOut, cueSheet.CUESheetContents(cueStyle));
ShowFinishedMessage(cueSheet.PaddedToFrame);
}
}
catch (Exception ex) {
if (!ShowErrorMessage(ex)) {
_batchPaths.Clear(); _batchPaths.Clear();
} if ((_workThread == null) && (_batchPaths.Count != 0))
} {
SkipConversion:
if ((_workThread == null) && (_batchPaths.Count != 0)) {
_batchPaths.RemoveAt(0); _batchPaths.RemoveAt(0);
if (_batchPaths.Count == 0) { if (_batchPaths.Count == 0)
ShowBatchDoneMessage(); ShowBatchDoneMessage();
} else
else {
StartConvert(); StartConvert();
} }
} }
@@ -333,10 +275,8 @@ namespace JDP {
private void PasswordRequired(object sender, ArchivePasswordRequiredEventArgs e) private void PasswordRequired(object sender, ArchivePasswordRequiredEventArgs e)
{ {
//if (this.InvokeRequired) this.Invoke((MethodInvoker)delegate()
// this.Invoke(this.PasswordRequired, sender, e); {
//this.Invoke((MethodInvoker)delegate()
//{
frmPassword dlg = new frmPassword(); frmPassword dlg = new frmPassword();
if (dlg.ShowDialog() == DialogResult.OK) if (dlg.ShowDialog() == DialogResult.OK)
{ {
@@ -344,26 +284,89 @@ namespace JDP {
e.ContinueOperation = true; e.ContinueOperation = true;
} else } else
e.ContinueOperation = false; e.ContinueOperation = false;
//}); });
} }
private void WriteAudioFilesThread(object o) { private void WriteAudioFilesThread(object o) {
object[] p = (object[])o; object[] p = (object[])o;
CUESheet cueSheet = (CUESheet)p[0]; CUESheet cueSheet = (CUESheet)p[0];
string outDir = (string)p[1]; string pathIn = (string)p[1];
CUEStyle cueStyle = (CUEStyle)p[2]; CUEStyle cueStyle = (CUEStyle)p[2];
AccurateRipMode accurateRip = (AccurateRipMode)p[3];
OutputAudioFormat outputFormat = (OutputAudioFormat)p[4];
bool lossyWAV = (bool)p[5];
try
{
bool outputAudio = outputFormat != OutputAudioFormat.NoAudio && accurateRip != AccurateRipMode.Verify;
bool outputCUE = cueStyle != CUEStyle.SingleFileWithCUE && accurateRip != AccurateRipMode.Verify;
string pathOut = null;
cueSheet.Open(pathIn, lossyWAV);
this.Invoke((MethodInvoker)delegate()
{
UpdateOutputPath(cueSheet.Artist != "" ? cueSheet.Artist : "Unknown Artist", cueSheet.Title != "" ? cueSheet.Title : "Unknown Title");
pathOut = txtOutputPath.Text;
});
cueSheet.GenerateFilenames(outputFormat, pathOut);
string outDir = Path.GetDirectoryName(pathOut);
if (cueStyle == CUEStyle.SingleFileWithCUE)
cueSheet.SingleFilename = Path.GetFileName(pathOut);
bool outputExists = false;
if (outputCUE)
outputExists = File.Exists(pathOut);
if (outputAudio)
{
if (cueStyle == CUEStyle.SingleFile || cueStyle == CUEStyle.SingleFileWithCUE)
outputExists |= File.Exists(Path.Combine(outDir, cueSheet.SingleFilename));
else
{
if (cueStyle == CUEStyle.GapsAppended && _config.preserveHTOA)
outputExists |= File.Exists(Path.Combine(outDir, cueSheet.HTOAFilename));
for (int i = 0; i < cueSheet.TrackCount; i++)
outputExists |= File.Exists(Path.Combine(outDir, cueSheet.TrackFilenames[i]));
}
}
DialogResult dlgRes = DialogResult.Cancel;
if (outputExists)
{
this.Invoke((MethodInvoker)delegate()
{
dlgRes = MessageBox.Show("One or more output file already exists, " +
"do you want to overwrite?", "Overwrite?", (_batchPaths.Count == 0) ?
MessageBoxButtons.YesNo : MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
});
if (dlgRes == DialogResult.Yes)
outputExists = false;
else if (dlgRes == DialogResult.Cancel || _batchPaths.Count == 0)
{
_batchPaths.Clear();
SetupControls(false);
return;
}
}
if (!outputExists)
{
cueSheet.UsePregapForFirstTrackInSingleFile = _usePregapForFirstTrackInSingleFile && !outputAudio;
cueSheet.AccurateRip = accurateRip;
if (accurateRip != AccurateRipMode.None)
cueSheet.DataTrackLength = txtDataTrackLength.Text;
try {
cueSheet.CUEToolsProgress += new CUEToolsProgressHandler(SetStatus);
cueSheet.WriteAudioFiles(outDir, cueStyle); cueSheet.WriteAudioFiles(outDir, cueStyle);
this.Invoke((MethodInvoker)delegate() { }
this.Invoke((MethodInvoker)delegate()
{
if (_batchPaths.Count == 0) if (_batchPaths.Count == 0)
{ {
if (cueSheet.AccurateRip != AccurateRipMode.None) if (cueSheet.AccurateRip != AccurateRipMode.None)
{ {
using (frmReport reportForm = new frmReport()) frmReport reportForm = new frmReport();
{
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
cueSheet.GenerateAccurateRipLog(sw); cueSheet.GenerateAccurateRipLog(sw);
reportForm.Message = sw.ToString(); reportForm.Message = sw.ToString();
@@ -371,26 +374,30 @@ namespace JDP {
CenterSubForm(reportForm); CenterSubForm(reportForm);
reportForm.ShowDialog(this); reportForm.ShowDialog(this);
} }
}
else else
ShowFinishedMessage(cueSheet.PaddedToFrame); ShowFinishedMessage(cueSheet.PaddedToFrame);
SetupControls(false); SetupControls(false);
} }
}); });
} }
catch (StopException) { catch (StopException)
{
_batchPaths.Clear(); _batchPaths.Clear();
this.Invoke((MethodInvoker)delegate() { this.Invoke((MethodInvoker)delegate()
{
SetupControls(false); SetupControls(false);
MessageBox.Show("Conversion was stopped.", "Stopped", MessageBoxButtons.OK, MessageBox.Show("Conversion was stopped.", "Stopped", MessageBoxButtons.OK,
MessageBoxIcon.Exclamation); MessageBoxIcon.Exclamation);
}); });
} }
#if !DEBUG #if !DEBUG
catch (Exception ex) { catch (Exception ex)
this.Invoke((MethodInvoker)delegate() { {
this.Invoke((MethodInvoker)delegate()
{
if (_batchPaths.Count == 0) SetupControls(false); if (_batchPaths.Count == 0) SetupControls(false);
if (!ShowErrorMessage(ex)) { if (!ShowErrorMessage(ex))
{
_batchPaths.Clear(); _batchPaths.Clear();
SetupControls(false); SetupControls(false);
} }

View File

@@ -818,8 +818,8 @@ namespace CUETools.Processor
if (indexes[i].Index == 1 && (i == 0 || indexes[i - 1].Index != 0)) if (indexes[i].Index == 1 && (i == 0 || indexes[i - 1].Index != 0))
_toc[indexes[i].Track].AddIndex(new CDTrackIndex(0U, (uint)indexes[i].Time)); _toc[indexes[i].Track].AddIndex(new CDTrackIndex(0U, (uint)indexes[i].Time));
_toc[indexes[i].Track].AddIndex(new CDTrackIndex((uint)indexes[i].Index, (uint)indexes[i].Time)); _toc[indexes[i].Track].AddIndex(new CDTrackIndex((uint)indexes[i].Index, (uint)indexes[i].Time));
//_toc[indexes[i].Track].AddIndex(new CDTrackIndex((uint)indexes[i].Index, (uint)indexes[i].Time, (uint)length));
} }
// Calculate the length of each track // Calculate the length of each track
for (int iTrack = 1; iTrack <= TrackCount; iTrack++) for (int iTrack = 1; iTrack <= TrackCount; iTrack++)
{ {
@@ -1449,9 +1449,11 @@ namespace CUETools.Processor
bool htoaToFile = ((style == CUEStyle.GapsAppended) && _config.preserveHTOA && bool htoaToFile = ((style == CUEStyle.GapsAppended) && _config.preserveHTOA &&
(_toc.Pregap != 0)); (_toc.Pregap != 0));
if (_usePregapForFirstTrackInSingleFile) { if (_isCD && (style == CUEStyle.GapsLeftOut || style == CUEStyle.GapsPrepended) && (_accurateRipMode == AccurateRipMode.None || _accurateRipMode == AccurateRipMode.VerifyAndConvert))
throw new Exception("When ripping a CD, gaps Left Out/Gaps prepended modes can only be used in verify-then-convert mode");
if (_usePregapForFirstTrackInSingleFile)
throw new Exception("UsePregapForFirstTrackInSingleFile is not supported for writing audio files."); throw new Exception("UsePregapForFirstTrackInSingleFile is not supported for writing audio files.");
}
if (style == CUEStyle.SingleFile || style == CUEStyle.SingleFileWithCUE) { if (style == CUEStyle.SingleFile || style == CUEStyle.SingleFileWithCUE) {
destPaths = new string[1]; destPaths = new string[1];
@@ -1540,6 +1542,11 @@ namespace CUETools.Processor
} }
return; return;
} }
if (_accurateRipMode == AccurateRipMode.VerifyThenConvert && _isCD)
{
_writeOffset = 0;
WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, true);
}
} }
else if (_accurateRipMode == AccurateRipMode.VerifyThenConvert) else if (_accurateRipMode == AccurateRipMode.VerifyThenConvert)
{ {
@@ -1572,6 +1579,8 @@ namespace CUETools.Processor
if (!Directory.Exists(dir)) if (!Directory.Exists(dir))
Directory.CreateDirectory(dir); Directory.CreateDirectory(dir);
} }
if (_isCD)
destLengths = CalculateAudioFileLengths(style); // need to recalc, might have changed after scanning the CD
WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, _accurateRipMode == AccurateRipMode.Verify); WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, _accurateRipMode == AccurateRipMode.Verify);
if (_accurateRipMode != AccurateRipMode.Verify) if (_accurateRipMode != AccurateRipMode.Verify)
{ {
@@ -1581,18 +1590,40 @@ namespace CUETools.Processor
if (logContents != null) if (logContents != null)
WriteText(Path.ChangeExtension(_cuePath, ".log"), logContents); WriteText(Path.ChangeExtension(_cuePath, ".log"), logContents);
if (style != CUEStyle.SingleFileWithCUE) if (style != CUEStyle.SingleFileWithCUE)
{
WriteText(_cuePath, cueContents); WriteText(_cuePath, cueContents);
#if !MONO
if (_accurateRipMode == AccurateRipMode.VerifyAndConvert &&
_config.writeArTagsOnConvert &&
_arVerify.AccResult == HttpStatusCode.OK)
{
uint tracksMatch;
int bestOffset;
FindBestOffset(1, true, out tracksMatch, out bestOffset);
for (int iTrack = 0; iTrack < TrackCount; iTrack++)
{
IAudioSource audioSource = AudioReadWrite.GetAudioSource(destPaths[iTrack + (htoaToFile ? 1 : 0)], null);
CleanupTags(audioSource.Tags, "ACCURATERIP");
GenerateAccurateRipTags(audioSource.Tags, 0, bestOffset, iTrack);
audioSource.UpdateTags(false);
audioSource.Close();
audioSource = null;
}
}
#endif
}
else else
{ {
if (_config.createCUEFileWhenEmbedded) if (_config.createCUEFileWhenEmbedded)
WriteText(Path.ChangeExtension(_cuePath, ".cue"), cueContents); WriteText(Path.ChangeExtension(_cuePath, ".cue"), cueContents);
#if !MONO #if !MONO
if (_accurateRipMode == AccurateRipMode.VerifyAndConvert || if ((_accurateRipMode == AccurateRipMode.VerifyAndConvert &&
(_accurateRipMode != AccurateRipMode.VerifyThenConvert && _isCD)) _config.writeArTagsOnConvert &&
_arVerify.AccResult == HttpStatusCode.OK) ||
(_accurateRipMode != AccurateRipMode.VerifyThenConvert &&
_isCD))
{ {
IAudioSource audioSource = AudioReadWrite.GetAudioSource(destPaths[0], null); IAudioSource audioSource = AudioReadWrite.GetAudioSource(destPaths[0], null);
if (audioSource is FLACReader)
{
if (_isCD) if (_isCD)
{ {
audioSource.Tags.Add("CUESHEET", cueContents); audioSource.Tags.Add("CUESHEET", cueContents);
@@ -1601,13 +1632,16 @@ namespace CUETools.Processor
uint tracksMatch; uint tracksMatch;
int bestOffset; int bestOffset;
FindBestOffset(1, true, out tracksMatch, out bestOffset); FindBestOffset(1, true, out tracksMatch, out bestOffset);
if (_accurateRipMode == AccurateRipMode.VerifyAndConvert && _arVerify.AccResult == HttpStatusCode.OK) if (_accurateRipMode == AccurateRipMode.VerifyAndConvert &&
_config.writeArTagsOnConvert &&
_arVerify.AccResult == HttpStatusCode.OK)
{
CleanupTags(audioSource.Tags, "ACCURATERIP");
GenerateAccurateRipTags(audioSource.Tags, 0, bestOffset, -1); GenerateAccurateRipTags(audioSource.Tags, 0, bestOffset, -1);
else
audioSource.Tags.Add("ACCURATERIPID", _accurateRipId);
audioSource.UpdateTags(false);
} }
audioSource.UpdateTags(false);
audioSource.Close(); audioSource.Close();
audioSource = null;
} }
#endif #endif
} }
@@ -1870,10 +1904,14 @@ namespace CUETools.Processor
ShowProgress(String.Format("{2} track {0:00} ({1:00}%)...", 0, 0, noOutput ? "Verifying" : "Writing"), 0, 0.0, null, null); ShowProgress(String.Format("{2} track {0:00} ({1:00}%)...", 0, 0, noOutput ? "Verifying" : "Writing"), 0, 0.0, null, null);
for (iTrack = 0; iTrack < TrackCount; iTrack++) { try
{
for (iTrack = 0; iTrack < TrackCount; iTrack++)
{
track = _tracks[iTrack]; track = _tracks[iTrack];
if ((style == CUEStyle.GapsPrepended) || (style == CUEStyle.GapsLeftOut)) { if ((style == CUEStyle.GapsPrepended) || (style == CUEStyle.GapsLeftOut))
{
iDest++; iDest++;
if (hdcdDecoder != null) if (hdcdDecoder != null)
hdcdDecoder.AudioDest = null; hdcdDecoder.AudioDest = null;
@@ -1884,8 +1922,9 @@ namespace CUETools.Processor
SetTrackTags(audioDest, iTrack, bestOffset); SetTrackTags(audioDest, iTrack, bestOffset);
} }
for (iIndex = 0; iIndex <= _toc[iTrack+1].LastIndex; iIndex++) { for (iIndex = 0; iIndex <= _toc[iTrack + 1].LastIndex; iIndex++)
uint trackPercent= 0, lastTrackPercent= 101; {
uint trackPercent = 0, lastTrackPercent = 101;
uint samplesRemIndex = _toc.IndexLength(iTrack + 1, iIndex) * 588; uint samplesRemIndex = _toc.IndexLength(iTrack + 1, iIndex) * 588;
if (iIndex == 1) if (iIndex == 1)
@@ -1907,34 +1946,40 @@ namespace CUETools.Processor
SetTrackTags(audioDest, iTrack, bestOffset); SetTrackTags(audioDest, iTrack, bestOffset);
} }
if ((style == CUEStyle.GapsAppended) && (iIndex == 0) && (iTrack == 0)) { if ((style == CUEStyle.GapsAppended) && (iIndex == 0) && (iTrack == 0))
{
discardOutput = !htoaToFile; discardOutput = !htoaToFile;
if (htoaToFile) { if (htoaToFile)
{
iDest++; iDest++;
audioDest = GetAudioDest(destPaths[iDest], destLengths[iDest], noOutput); audioDest = GetAudioDest(destPaths[iDest], destLengths[iDest], noOutput);
} }
} }
else if ((style == CUEStyle.GapsLeftOut) && (iIndex == 0)) { else if ((style == CUEStyle.GapsLeftOut) && (iIndex == 0))
{
discardOutput = true; discardOutput = true;
} }
else { else
{
discardOutput = false; discardOutput = false;
} }
while (samplesRemIndex != 0) { while (samplesRemIndex != 0)
if (samplesRemSource == 0) { {
if (samplesRemSource == 0)
{
#if !MONO #if !MONO
if (_isCD && audioSource != null && audioSource is CDDriveReader) if (_isCD && audioSource != null && audioSource is CDDriveReader)
updatedTOC = ((CDDriveReader)audioSource).TOC; updatedTOC = ((CDDriveReader)audioSource).TOC;
#endif #endif
if (audioSource != null) audioSource.Close(); if (audioSource != null) audioSource.Close();
audioSource = GetAudioSource(++iSource); audioSource = GetAudioSource(++iSource);
samplesRemSource = (uint) _sources[iSource].Length; samplesRemSource = (uint)_sources[iSource].Length;
} }
uint copyCount = (uint) Math.Min(Math.Min(samplesRemIndex, samplesRemSource), buffLen); uint copyCount = (uint)Math.Min(Math.Min(samplesRemIndex, samplesRemSource), buffLen);
if ( trackLength > 0 ) if (trackLength > 0)
{ {
trackPercent = (uint)(currentOffset / 0.01 / trackLength); trackPercent = (uint)(currentOffset / 0.01 / trackLength);
double diskPercent = ((float)diskOffset) / diskLength; double diskPercent = ((float)diskOffset) / diskLength;
@@ -1980,16 +2025,10 @@ namespace CUETools.Processor
samplesRemIndex -= copyCount; samplesRemIndex -= copyCount;
samplesRemSource -= copyCount; samplesRemSource -= copyCount;
lock (this) { lock (this)
if (_stop) { {
if (hdcdDecoder != null) if (_stop)
hdcdDecoder.AudioDest = null;
audioSource.Close();
try {
if (audioDest != null) audioDest.Close();
} catch { }
throw new StopException(); throw new StopException();
}
if (_pause) if (_pause)
{ {
ShowProgress("Paused...", 0, 0, null, null); ShowProgress("Paused...", 0, 0, null, null);
@@ -1999,6 +2038,20 @@ namespace CUETools.Processor
} }
} }
} }
}
catch (Exception ex)
{
if (hdcdDecoder != null)
hdcdDecoder.AudioDest = null;
hdcdDecoder = null;
try { if (audioSource != null) audioSource.Close(); }
catch { }
audioSource = null;
try { if (audioDest != null) audioDest.Close(); }
catch { }
audioDest = null;
throw ex;
}
#if !MONO #if !MONO
if (_isCD && audioSource != null && audioSource is CDDriveReader) if (_isCD && audioSource != null && audioSource is CDDriveReader)