private void WriteAudioFilesThread(object o) { object[] p = (object[])o; CUESheet cueSheet = (CUESheet)p[0]; string pathIn = (string)p[1]; CUEStyle cueStyle = (CUEStyle)p[2]; CUEAction action = (CUEAction)p[3]; string outputFormat = (string)p[4]; AudioEncoderType audioEncoderType = (AudioEncoderType)p[5]; CUEToolsScript script = (CUEToolsScript)p[6]; DialogResult dlgRes = DialogResult.OK; string status = null; bool outputAudio = action == CUEAction.Encode && audioEncoderType != AudioEncoderType.NoAudio; bool useAR = action == CUEAction.Verify || (outputAudio && checkBoxUseAccurateRip.Checked); bool useCUEToolsDB = action == CUEAction.Verify && checkBoxVerifyUseCDRepair.Checked; bool useLocalDB = action != CUEAction.Verify || checkBoxVerifyUseLocal.Checked; bool skipRecent = action == CUEAction.Verify && checkBoxSkipRecent.Checked; try { if (_profile._config.checkForUpdates && DateTime.UtcNow - lastMOTD > TimeSpan.FromDays(1) && _batchReport.Length == 0) { this.Invoke((MethodInvoker)(() => toolStripStatusLabel1.Text = "Checking for updates...")); IWebProxy proxy = _profile._config.GetProxy(); HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://cuetools.net/motd/motd.jpg"); req.Proxy = proxy; req.Method = "GET"; try { using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) if (resp.StatusCode == HttpStatusCode.OK) { using (Stream respStream = resp.GetResponseStream()) using (FileStream motd = new FileStream(MOTDImagePath, FileMode.Create, FileAccess.Write)) { byte[] buff = new byte[0x8000]; do { int count = respStream.Read(buff, 0, buff.Length); if (count == 0) break; motd.Write(buff, 0, count); } while (true); } } else { File.Delete(MOTDImagePath); } lastMOTD = DateTime.UtcNow; } catch (WebException ex) { if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null && ex.Response is HttpWebResponse) { HttpWebResponse resp = (HttpWebResponse)ex.Response; if (resp.StatusCode == HttpStatusCode.NotFound) { File.Delete(MOTDImagePath); lastMOTD = DateTime.UtcNow; } } } motdImage = null; if (File.Exists(MOTDImagePath)) using (FileStream imageStream = new FileStream(MOTDImagePath, FileMode.Open, FileAccess.Read)) try { motdImage = Image.FromStream(imageStream); } catch { } req = (HttpWebRequest)WebRequest.Create("http://cuetools.net/motd/motd.txt"); req.Proxy = proxy; req.Method = "GET"; try { using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) { if (resp.StatusCode == HttpStatusCode.OK) { using (Stream respStream = resp.GetResponseStream()) using (FileStream motd = new FileStream(MOTDTextPath, FileMode.Create, FileAccess.Write)) using (StreamReader sr = new StreamReader(respStream, Encoding.UTF8)) using (StreamWriter sw = new StreamWriter(motd, Encoding.UTF8)) { string motdText = sr.ReadToEnd(); sw.Write(motdText); } } else { File.Delete(MOTDTextPath); } } lastMOTD = DateTime.UtcNow; } catch { } if (File.Exists(MOTDTextPath)) try { using (StreamReader sr = new StreamReader(MOTDTextPath, Encoding.UTF8)) { string version = sr.ReadLine(); if (version != MOTDVersion) { string motd = sr.ReadToEnd(); _batchReport.Append(motd); } } } catch { } } if (action == CUEAction.CreateDummyCUE) { if (Directory.Exists(pathIn)) { if (_batchPaths.Count == 0) throw new Exception("is a directory"); List<FileGroupInfo> fileGroups = CUESheet.ScanFolder(_profile._config, pathIn); int directoriesFound = 0, cueSheetsFound = 0; foreach (FileGroupInfo fileGroup in fileGroups) if (fileGroup.type == FileGroupInfoType.Folder) _batchPaths.Insert(++directoriesFound, fileGroup.main.FullName); foreach (FileGroupInfo fileGroup in fileGroups) if (fileGroup.type == FileGroupInfoType.CUESheetFile) throw new Exception("already contains a cue sheet"); foreach (FileGroupInfo fileGroup in fileGroups) if (fileGroup.type == FileGroupInfoType.TrackFiles || fileGroup.type == FileGroupInfoType.FileWithCUE || fileGroup.type == FileGroupInfoType.M3UFile) _batchPaths.Insert(directoriesFound + (++cueSheetsFound), fileGroup.main.FullName); } else if (File.Exists(pathIn)) { pathIn = Path.GetFullPath(pathIn); List<FileGroupInfo> fileGroups = CUESheet.ScanFolder(_profile._config, Path.GetDirectoryName(pathIn)); FileGroupInfo fileGroup = fileGroups.Find(f => f.type == FileGroupInfoType.TrackFiles && f.Contains(pathIn)) ?? fileGroups.Find(f => f.type == FileGroupInfoType.FileWithCUE && f.Contains(pathIn)) ?? fileGroups.Find(f => f.type == FileGroupInfoType.M3UFile && f.Contains(pathIn)); if (fileGroup == null) throw new Exception("doesn't seem to be part of an album"); string cueSheetContents; if (_batchPaths.Count == 0) { cueSheet.Open(fileGroup.main.FullName); cueSheetContents = cueSheet.GetCUESheetContents(); cueSheet.Close(); } else cueSheetContents = CUESheet.CreateDummyCUESheet(_profile._config, fileGroup); string fullCueName; if (fileGroup.type == FileGroupInfoType.FileWithCUE) fullCueName = Path.ChangeExtension(fileGroup.main.FullName, ".cue"); else { string cueName = Path.GetFileName(Path.GetDirectoryName(pathIn)) + (fileGroup.discNo != 1 ? ".cd" + fileGroup.discNo.ToString() : "") + ".cuetools" + Path.GetExtension(pathIn) + ".cue"; fullCueName = Path.Combine(Path.GetDirectoryName(pathIn), cueName); } if (File.Exists(fullCueName)) throw new Exception("file already exists"); bool utf8Required = CUESheet.Encoding.GetString(CUESheet.Encoding.GetBytes(cueSheetContents)) != cueSheetContents; StreamWriter sw1 = new StreamWriter(fullCueName, false, utf8Required ? Encoding.UTF8 : CUESheet.Encoding); sw1.Write(cueSheetContents); sw1.Close(); BatchLog("created ok.", fullCueName); } else { //if (_batchPaths.Count > 0) //BatchLog("invalid path", pathIn); throw new Exception("invalid path"); } } else if (action == CUEAction.CorrectFilenames) { if (Directory.Exists(pathIn)) { if (_batchPaths.Count == 0) throw new Exception("is a directory"); string[] cues = Directory.GetFiles(pathIn, "*.cue", SearchOption.AllDirectories); if (cues.Length == 0) BatchLog("no cue files.", pathIn); else _batchPaths.InsertRange(1, cues); } else if (File.Exists(pathIn)) { if (Path.GetExtension(pathIn).ToLower() != ".cue") throw new Exception("is not a .cue file"); string cue = null; using (StreamReader sr = new StreamReader(pathIn, CUESheet.Encoding)) cue = sr.ReadToEnd(); string extension; string fixedCue; if (CorrectorMode == CorrectorModeEnum.Locate) fixedCue = CUESheet.CorrectAudioFilenames(_profile._config, Path.GetDirectoryName(pathIn), cue, true, null, out extension); else { extension = toolStripDropDownButtonCorrectorFormat.Text; using (StringReader sr = new StringReader(cue)) { using (StringWriter sw = new StringWriter()) { string lineStr; while ((lineStr = sr.ReadLine()) != null) { CUELine line = new CUELine(lineStr); if (line.Params.Count == 3 && line.Params[0].ToUpper() == "FILE" && (line.Params[2].ToUpper() != "BINARY" && line.Params[2].ToUpper() != "MOTOROLA") ) sw.WriteLine("FILE \"" + Path.ChangeExtension(line.Params[1], "." + extension) + "\" WAVE"); else sw.WriteLine(lineStr); } fixedCue = sw.ToString(); } } } if (fixedCue != cue) { if (toolStripButtonCorrectorOverwrite.Checked) { using (StreamWriter sw = new StreamWriter(pathIn, false, CUESheet.Encoding)) sw.Write(fixedCue); BatchLog("corrected ({0}).", pathIn, extension); } else { string pathFixed = Path.ChangeExtension(pathIn, extension + ".cue"); if (File.Exists(pathFixed)) BatchLog("corrected cue already exists.", pathIn); else { using (StreamWriter sw = new StreamWriter(pathFixed, false, CUESheet.Encoding)) sw.Write(fixedCue); BatchLog("corrected ({0}).", pathIn, extension); } } } else BatchLog("no changes.", pathIn); } else throw new Exception("invalid path"); } else { if (Directory.Exists(pathIn) && !IsCDROM(pathIn)) { if (_batchPaths.Count == 0) throw new Exception("is a directory"); List<FileGroupInfo> fileGroups = CUESheet.ScanFolder(_profile._config, pathIn); int directoriesFound = 0, cueSheetsFound = 0; foreach (FileGroupInfo fileGroup in fileGroups) if (fileGroup.type == FileGroupInfoType.Folder) _batchPaths.Insert(++directoriesFound, fileGroup.main.FullName); foreach (FileGroupInfo fileGroup in fileGroups) if (fileGroup.type == FileGroupInfoType.FileWithCUE) _batchPaths.Insert(directoriesFound + (++cueSheetsFound), fileGroup.main.FullName); foreach (FileGroupInfo fileGroup in fileGroups) if (fileGroup.type == FileGroupInfoType.CUESheetFile) { string cue; using (TextReader tr = new StreamReader(fileGroup.main.FullName)) cue = tr.ReadToEnd(); foreach (FileGroupInfo fileGroup2 in fileGroups) if (fileGroup2.type == FileGroupInfoType.FileWithCUE && fileGroup2.TOC != null) { CDImageLayout toc = CUESheet.CUE2TOC(cue, (int)fileGroup2.TOC.AudioLength); if (toc != null && toc.TrackOffsets == fileGroup2.TOC.TrackOffsets) { cue = null; break; } } if (cue != null) _batchPaths.Insert(directoriesFound + (++cueSheetsFound), fileGroup.main.FullName); } if (cueSheetsFound == 0) foreach (FileGroupInfo fileGroup in fileGroups) if (fileGroup.type == FileGroupInfoType.TrackFiles) _batchPaths.Insert(directoriesFound + (++cueSheetsFound), fileGroup.main.FullName); } else if (File.Exists(pathIn) || IsCDROM(pathIn)) { string pathOut = null; if (Directory.Exists(pathIn) && !pathIn.EndsWith(new string(Path.DirectorySeparatorChar, 1))) pathIn = pathIn + Path.DirectorySeparatorChar; var fullInputPath = CUEToolsLocalDBEntry.NormalizePath(pathIn); var recentEntry = skipRecent ? _localDB.Find(item => item.HasPath(fullInputPath) && item.VerificationDate != DateTime.MinValue && item.Status != null && item.VerificationDate.AddDays(30) > DateTime.Now) : null; if (recentEntry != null) throw new Exception("recently verified: " + recentEntry.Status); cueSheet.Action = action; cueSheet.OutputStyle = cueStyle; cueSheet.Open(pathIn); cueSheet.PreGapLengthMSF = txtPreGapLength.Text; if (useAR || useCUEToolsDB) cueSheet.DataTrackLengthMSF = txtDataTrackLength.Text; if (useLocalDB) cueSheet.UseLocalDB(_localDB); if (useCUEToolsDB) cueSheet.UseCUEToolsDB("CUETools " + CUESheet.CUEToolsVersion, null, true, CTDBMetadataSearch.None); if (useAR) cueSheet.UseAccurateRip(); List<string> fullAudioPaths = cueSheet.SourcePaths.ConvertAll(sp => CUEToolsLocalDBEntry.NormalizePath(sp)); recentEntry = skipRecent ? _localDB.Find(item => item.Equals(cueSheet.TOC, fullAudioPaths) && item.VerificationDate != null && item.Status != null && item.VerificationDate.AddDays(30) > DateTime.Now) : null; if (recentEntry != null) { if (useLocalDB) { _localDB.Dirty = true; if (recentEntry.InputPaths == null) recentEntry.InputPaths = new List<string>(); if (!recentEntry.InputPaths.Contains(fullInputPath)) recentEntry.InputPaths.Add(fullInputPath); } throw new Exception("recently verified: " + recentEntry.Status); } this.Invoke((MethodInvoker)delegate() { toolStripStatusLabelAR.Visible = useAR; toolStripStatusLabelCTDB.Visible = useCUEToolsDB; if (_batchPaths.Count == 0 && action == CUEAction.Encode && (checkBoxUseFreeDb.Checked || checkBoxUseMusicBrainz.Checked)) { frmChoice dlg = new frmChoice(); if (_choiceWidth != 0 && _choiceHeight != 0) dlg.Size = new Size(_choiceWidth, _choiceHeight); if (_choiceMaxed) dlg.WindowState = FormWindowState.Maximized; dlg.CUE = cueSheet; dlg.LookupAlbumInfo(_profile._config.advanced.CacheMetadata, true, true, CTDBMetadataSearch.Default); dlgRes = dlg.ShowDialog(this); _choiceMaxed = dlg.WindowState == FormWindowState.Maximized; if (!_choiceMaxed) { _choiceHeight = dlg.Height; _choiceWidth = dlg.Width; } if (dlgRes == DialogResult.Cancel) { cueSheet.Close(); SetupControls(false); } else if (_profile._config.advanced.CacheMetadata && dlg.ChosenRelease != null) { var entry = cueSheet.OpenLocalDBEntry(); if (entry != null) { _localDB.Dirty = true; entry.Metadata.CopyMetadata(dlg.ChosenRelease.metadata); } } dlg.Close(); } else if (_profile._config.advanced.CacheMetadata) { recentEntry = _localDB.Find(item => item.Equals(cueSheet.TOC, fullAudioPaths)); if (recentEntry != null) cueSheet.CopyMetadata(recentEntry.Metadata); } UpdateOutputPath(pathIn, cueSheet); pathOut = txtOutputPath.Text; if (dlgRes != DialogResult.Cancel && cueSheet.AlbumArt.Count != 0) pictureBoxMotd.Image = cueSheet.Cover; else pictureBoxMotd.Image = motdImage; }); if (dlgRes == DialogResult.Cancel) return; cueSheet.GenerateFilenames(audioEncoderType, outputFormat, pathOut); List<string> outputExists = cueSheet.OutputExists(); dlgRes = DialogResult.Cancel; if (outputExists.Count > 0) { this.Invoke((MethodInvoker)delegate() { if (overwriteResult == DialogResult.None) { using (frmOverwrite frm = new frmOverwrite()) { outputExists.ForEach(path => frm.textFiles.AppendText(path + "\n")); dlgRes = frm.ShowDialog(this); if (frm.checkBoxRemember.Checked) overwriteResult = dlgRes; } } else dlgRes = overwriteResult; if (dlgRes == DialogResult.Yes) outputExists.Clear(); else if (_batchPaths.Count == 0) SetupControls(false); }); if (outputExists.Count > 0 && _batchPaths.Count == 0) { cueSheet.Close(); return; } } if (outputExists.Count == 0) { cueSheet.UsePregapForFirstTrackInSingleFile = _usePregapForFirstTrackInSingleFile && !outputAudio; if (script == null || (script.builtin && script.name == "default")) { status = cueSheet.Go(); if (cueSheet.Config.advanced.CTDBSubmit && useAR && useCUEToolsDB && cueSheet.ArVerify.ARStatus == null && cueSheet.ArVerify.WorstConfidence() >= 2 && (cueSheet.AccurateRipId == null || AccurateRipVerify.CalculateAccurateRipId(cueSheet.TOC) == cueSheet.AccurateRipId) && cueSheet.CTDB.MatchingEntries.Count == 0 && (cueSheet.CTDB.QueryExceptionStatus == WebExceptionStatus.Success || (cueSheet.CTDB.QueryExceptionStatus == WebExceptionStatus.ProtocolError && cueSheet.CTDB.QueryResponseStatus == HttpStatusCode.NotFound) ) ) { DialogResult res = DialogResult.OK; if (cueSheet.Config.advanced.CTDBAsk) { bool remember = true; this.Invoke((MethodInvoker)delegate() { var confirm = new frmSubmit(); res = confirm.ShowDialog(this); remember = confirm.checkBoxRemember.Checked; }); if (remember) { cueSheet.Config.advanced.CTDBSubmit = res == DialogResult.OK; cueSheet.Config.advanced.CTDBAsk = false; } } if (res == DialogResult.OK) { cueSheet.CTDB.Submit( (int)cueSheet.ArVerify.WorstConfidence(), 100, cueSheet.Metadata.Artist, cueSheet.Metadata.Title + (cueSheet.Metadata.Title != "" && cueSheet.Metadata.DiscNumberAndName != "" ? " (disc " + cueSheet.Metadata.DiscNumberAndName + ")" : ""), cueSheet.Metadata.Barcode); if (cueSheet.CTDB.SubStatus != null) status += ", submit: " + cueSheet.CTDB.SubStatus; } } } else status = cueSheet.ExecuteScript(script); if (_batchPaths.Count > 0) { _batchProcessed++; BatchLog("{0}.", pathIn, status); } cueSheet.CheckStop(); } } else throw new Exception("invalid path"); } this.Invoke((MethodInvoker)delegate() { if (_batchPaths.Count == 0) { if (cueSheet.IsCD) { frmReport reportForm = new frmReport(); reportForm.Message = cueSheet.LOGContents; reportForm.ShowDialog(this); } else if (action == CUEAction.CreateDummyCUE || action == CUEAction.CorrectFilenames) { ReportState = true; //frmReport reportForm = new frmReport(); //reportForm.Message = _batchReport.ToString(); //reportForm.ShowDialog(this); } else if (useAR && cueSheet.Processed) { _batchReport.Append(CUESheetLogWriter.GetAccurateRipLog(cueSheet)); ReportState = true; //frmReport reportForm = new frmReport(); //StringWriter sw = new StringWriter(); //cueSheet.GenerateAccurateRipLog(sw); //if (status != null) // reportForm.Text += ": " + status; //reportForm.Message = sw.ToString(); //_batchReport.Append(sw.ToString()); //sw.Close(); //reportForm.ShowDialog(this); } else ShowFinishedMessage(cueSheet.PaddedToFrame, status); SetupControls(false); } }); } catch (StopException) { } #if !DEBUG catch (Exception ex) { if (_batchPaths.Count == 0) { this.Invoke((MethodInvoker)delegate() { SetupControls(false); ShowErrorMessage(ex); }); } else { _batchProcessed++; String msg = ""; for (Exception e = ex; e != null; e = e.InnerException) msg += ": " + e.Message; BatchLog("{0}.", pathIn, msg.Substring(2)); } } #endif try { cueSheet.CheckStop(); } catch (StopException) { _batchPaths.Clear(); this.Invoke((MethodInvoker)delegate() { SetupControls(false); MessageBox.Show(this, "Conversion was stopped.", "Stopped", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); }); } cueSheet.Close(); if (_batchPaths.Count != 0) { _batchPaths.RemoveAt(0); if (_batchPaths.Count == 0) { SaveDatabase(); } this.BeginInvoke((MethodInvoker)delegate() { if (_batchPaths.Count == 0) { SetupControls(false); ReportState = true; //frmReport reportForm = new frmReport(); //reportForm.Message = _batchReport.ToString(); //reportForm.ShowDialog(this); //ShowBatchDoneMessage(); } else { StartConvert(); } }); } }
private void StartConvert() { try { _workThread = null; _workClass = null; if (_batchPaths.Count != 0) { InputPath = _batchPaths[0]; txtInputPath.SelectAll(); } string pathIn = InputPath; //if (!File.Exists(pathIn) && !Directory.Exists(pathIn) && !IsCDROM(pathIn)) // throw new Exception("Invalid input path."); //if (Directory.Exists(pathIn) && !pathIn.EndsWith(new string(Path.DirectorySeparatorChar, 1))) //{ // pathIn = pathIn + Path.DirectorySeparatorChar; // InputPath = pathIn; //} CUESheet cueSheet = new CUESheet(_profile._config); cueSheet.PasswordRequired += new EventHandler<CompressionPasswordRequiredEventArgs>(PasswordRequired); cueSheet.CUEToolsProgress += new EventHandler<CUEToolsProgressEventArgs>(SetStatus); cueSheet.CUEToolsSelection += new EventHandler<CUEToolsSelectionEventArgs>(MakeSelection); cueSheet.WriteOffset = (int)numericWriteOffset.Value; object[] p = new object[7]; _workThread = new Thread(WriteAudioFilesThread); _workClass = cueSheet; p[0] = cueSheet; p[1] = pathIn; p[2] = SelectedCUEStyle; p[3] = SelectedAction; p[4] = SelectedOutputAudioFormat; p[5] = SelectedOutputAudioType; p[6] = comboBoxScript.SelectedItem; SetupControls(true); _workThread.Priority = ThreadPriority.BelowNormal; _workThread.IsBackground = true; _workThread.Start(p); } catch (Exception ex) { if (!ShowErrorMessage(ex)) _batchPaths.Clear(); if ((_workThread == null) && (_batchPaths.Count != 0)) { _batchPaths.RemoveAt(0); if (_batchPaths.Count == 0) { frmReport reportForm = new frmReport(); reportForm.Message = _batchReport.ToString(); reportForm.ShowDialog(this); //ShowBatchDoneMessage(); } else StartConvert(); } } }