using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Net;
using System.Threading;
using System.Windows.Forms;
using CUEControls;
using CUETools.AccurateRip;
using CUETools.CTDB;
using CUETools.Processor;
using CUETools.Processor.Settings;
using CUETools.Ripper;
using Freedb;
using CUETools.Codecs;
using System.Xml;
using System.Xml.Serialization;
namespace CUERipper
{
public partial class frmCUERipper : Form
{
private Thread _workThread = null;
private StartStop _startStop;
private CUEConfig _config;
private CUERipperConfig cueRipperConfig;
private CUESheet cueSheet;
private DriveInfo selectedDriveInfo;
private string _pathOut;
private CUEControls.ShellIconMgr m_icon_mgr;
private bool testAndCopy = false;
internal CUERipperData data = new CUERipperData();
private bool initDone = false;
public readonly static XmlSerializerNamespaces xmlEmptyNamespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] { XmlQualifiedName.Empty });
public readonly static XmlWriterSettings xmlEmptySettings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true };
public frmCUERipper()
{
InitializeComponent();
_config = new CUEConfig();
_startStop = new StartStop();
cueRipperConfig = new CUERipperConfig();
m_icon_mgr = new CUEControls.ShellIconMgr();
m_icon_mgr.SetExtensionIcon(".flac", Properties.Resources.flac);
m_icon_mgr.SetExtensionIcon(".wv", Properties.Resources.wv);
m_icon_mgr.SetExtensionIcon(".ape", Properties.Resources.ape);
m_icon_mgr.SetExtensionIcon(".tta", Properties.Resources.tta);
m_icon_mgr.SetExtensionIcon(".wav", Properties.Resources.wave);
m_icon_mgr.SetExtensionIcon(".mp3", Properties.Resources.mp3);
m_icon_mgr.SetExtensionIcon(".m4a", Properties.Resources.ipod_sound);
m_icon_mgr.SetExtensionIcon(".ogg", Properties.Resources.ogg);
m_icon_mgr.SetExtensionIcon(".wma", Properties.Resources.wma);
}
string[] OutputPathUseTemplates = {
"%music%\\%artist%\\[%year% - ]%album%\\%artist% - %album%[ '('disc %discnumberandname%')'].cue",
"%music%\\%artist%\\[%year% - ]%album%[ '('disc %discnumberandname%')'][' ('%releasedateandlabel%')'][' ('%unique%')']\\%artist% - %album%.cue"
};
//// Calculate the graphics path that representing the figure in the bitmap
//// excluding the transparent color which is the top left pixel.
//private static GraphicsPath CalculateControlGraphicsPath(Bitmap bitmap, Color colorTransparent)
//{
// // Create GraphicsPath for our bitmap calculation
// GraphicsPath graphicsPath = new GraphicsPath();
// // Use the top left pixel as our transparent color
// colorTransparent = bitmap.GetPixel(0, 0);
// // This is to store the column value where an opaque pixel is first found.
// // This value will determine where we start scanning for trailing
// // opaque pixels.
// int colOpaquePixel = 0;
// // Go through all rows (Y axis)
// for (int row = 0; row < bitmap.Height; row++)
// {
// // Reset value
// colOpaquePixel = 0;
// // Go through all columns (X axis)
// for (int col = 0; col < bitmap.Width; col++)
// {
// // If this is an opaque pixel, mark it and search
// // for anymore trailing behind
// if (bitmap.GetPixel(col, row) != colorTransparent)
// {
// // Opaque pixel found, mark current position
// colOpaquePixel = col;
// // Create another variable to set the current pixel position
// int colNext = col;
// // Starting from current found opaque pixel, search for
// // anymore opaque pixels trailing behind, until a transparent
// // pixel is found or minimum width is reached
// for (colNext = colOpaquePixel; colNext < bitmap.Width; colNext++)
// if (bitmap.GetPixel(colNext, row) == colorTransparent)
// break;
// // Form a rectangle for line of opaque pixels found and
// // add it to our graphics path
// graphicsPath.AddRectangle(new Rectangle(colOpaquePixel,
// row, colNext - colOpaquePixel, 1));
// // No need to scan the line of opaque pixels just found
// col = colNext;
// }
// }
// }
// // Return calculated graphics path
// return graphicsPath;
//}
//private static void CreateControlRegion(Button button, Bitmap bitmap, Color colorTransparent)
//{
// // Return if control and bitmap are null
// if (button == null || bitmap == null)
// return;
// // Set our control's size to be the same as the bitmap
// button.Width = bitmap.Width;
// button.Height = bitmap.Height;
// // Do not show button text
// button.Text = "";
// // Change cursor to hand when over button
// button.Cursor = Cursors.Hand;
// // Set background image of button
// button.BackgroundImage = bitmap;
// // Calculate the graphics path based on the bitmap supplied
// GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap, colorTransparent);
// // Apply new region
// button.Region = new Region(graphicsPath);
//}
private void frmCUERipper_Load(object sender, EventArgs e)
{
//buttonTrackMetadata.Parent = listTracks;
//buttonTrackMetadata.ImageList = null;
//CreateControlRegion(buttonTrackMetadata, new Bitmap(imageListChecked.Images[0]), imageListChecked.TransparentColor);
//CreateControlRegion(buttonTrackMetadata, Properties.Resources.cdrepair, Color.White);
SettingsReader sr = new SettingsReader("CUERipper", "settings.txt", Application.ExecutablePath);
_config.Load(sr);
_config.CopyAlbumArt = false;
//_config.createEACLOG = sr.LoadBoolean("CreateEACLOG") ?? true;
//_config.preserveHTOA = sr.LoadBoolean("PreserveHTOA") ?? false;
//_config.createM3U = sr.LoadBoolean("CreateM3U") ?? true;
try
{
using (TextReader reader = new StringReader(sr.Load("CUERipper")))
cueRipperConfig = CUERipperConfig.serializer.Deserialize(reader) as CUERipperConfig;
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
bindingSourceCR.DataSource = data;
initDone = true;
bnComboBoxDrives.ImageList = m_icon_mgr.ImageList;
bnComboBoxFormat.ImageList = m_icon_mgr.ImageList;
SetupControls();
int iFormat, nFormats = sr.LoadInt32("OutputPathUseTemplates", 0, 10) ?? 0;
for (iFormat = 0; iFormat < OutputPathUseTemplates.Length; iFormat++)
bnComboBoxOutputFormat.Items.Add(OutputPathUseTemplates[iFormat]);
for (iFormat = nFormats - 1; iFormat >= 0; iFormat--)
bnComboBoxOutputFormat.Items.Add(sr.Load(string.Format("OutputPathUseTemplate{0}", iFormat)) ?? "");
bnComboBoxOutputFormat.Text = sr.Load("PathFormat") ?? "%music%\\%artist%\\[%year% - ]%album%\\%artist% - %album%.cue";
SelectedOutputAudioType = (AudioEncoderType?)sr.LoadInt32("OutputAudioType", null, null) ?? AudioEncoderType.Lossless;
bnComboBoxImage.SelectedIndex = sr.LoadInt32("ComboImage", 0, bnComboBoxImage.Items.Count - 1) ?? 0;
trackBarSecureMode.Value = sr.LoadInt32("SecureMode", 0, trackBarSecureMode.Maximum - 1) ?? 1;
trackBarSecureMode_Scroll(this, new EventArgs());
this.checkBoxTestAndCopy.Checked = this.testAndCopy = sr.LoadBoolean("TestAndCopy") ?? this.testAndCopy;
Size SizeIncrement = new Size(sr.LoadInt32("WidthIncrement", 0, null) ?? 0, sr.LoadInt32("HeightIncrement", 0, null) ?? 0);
Size = MinimumSize + SizeIncrement;
Left -= SizeIncrement.Width / 2;
Top -= SizeIncrement.Height / 2;
UpdateDrives();
}
#region private constants
///
/// The window message of interest, device change
///
const int WM_DEVICECHANGE = 0x0219;
const ushort DBT_DEVICEARRIVAL = 0x8000;
const ushort DBT_DEVICEREMOVECOMPLETE = 0x8004;
const ushort DBT_DEVNODES_CHANGED = 0x0007;
#endregion
///
/// This method is called when a window message is processed by the dotnet application
/// framework. We override this method and look for the WM_DEVICECHANGE message. All
/// messages are delivered to the base class for processing, but if the WM_DEVICECHANGE
/// method is seen, we also alert any BWGBURN programs that the media in the drive may
/// have changed.
///
/// the windows message being processed
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_DEVICECHANGE && _workThread == null)
{
int val = m.WParam.ToInt32();
if (val == DBT_DEVICEARRIVAL || val == DBT_DEVICEREMOVECOMPLETE)
UpdateDrive();
else if (val == DBT_DEVNODES_CHANGED)
{
if (_workThread == null)
UpdateDrives();
}
}
base.WndProc(ref m);
}
private void DrivesLookup(object o)
{
// Lookup
data.Drives.RaiseListChangedEvents = false;
foreach (char drive in CDDrivesList.DrivesAvailable())
{
this.BeginInvoke((MethodInvoker)(() =>
toolStripStatusLabel1.Text = Properties.Resources.DetectingDrives + ": " + drive + ":\\..."));
ICDRipper reader = Activator.CreateInstance(CUEProcessorPlugins.ripper) as ICDRipper;
try
{
reader.Open(drive);
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
reader.Close();
if (reader.ARName != null)
{
int driveOffset;
if (cueRipperConfig.DriveOffsets.ContainsKey(reader.ARName))
reader.DriveOffset = cueRipperConfig.DriveOffsets[reader.ARName];
else if (AccurateRipVerify.FindDriveReadOffset(reader.ARName, out driveOffset))
reader.DriveOffset = driveOffset;
else
reader.DriveOffset = 0;
}
data.Drives.Add(new DriveInfo(m_icon_mgr, drive + ":\\", reader));
}
this.BeginInvoke((MethodInvoker)delegate()
{
data.Drives.RaiseListChangedEvents = true;
data.Drives.ResetBindings();
for(int i = 0; i < bnComboBoxDrives.Items.Count; i++)
if ((bnComboBoxDrives.Items[i] as DriveInfo).Path == cueRipperConfig.DefaultDrive)
bnComboBoxDrives.SelectedIndex = i;
_workThread = null;
SetupControls();
if (data.Drives.Count == 0)
bnComboBoxDrives.Text = Properties.Resources.NoDrives;
else
UpdateDrive();
});
}
private void UpdateDrives()
{
buttonGo.Enabled = false;
foreach (DriveInfo driveInfo in data.Drives)
if (driveInfo.drive != null)
driveInfo.drive.Close();
data.Drives.Clear();
listTracks.Items.Clear();
data.Releases.Clear();
data.selectedRelease = null;
ResetAlbumArt();
selectedDriveInfo = null;
bnComboBoxRelease.Text = "";
if (CUEProcessorPlugins.ripper == null)
{
bnComboBoxDrives.Text = Properties.Resources.FailedToLoadRipperModule;
return;
}
_workThread = new Thread(DrivesLookup);
_workThread.Priority = ThreadPriority.BelowNormal;
_workThread.IsBackground = true;
SetupControls();
_workThread.Start(this);
}
bool outputFormatVisible = false;
private void SetupControls()
{
bool running = _workThread != null;
bnComboBoxOutputFormat.Visible = outputFormatVisible;
txtOutputPath.Visible = !outputFormatVisible;
txtOutputPath.Enabled = !running && !outputFormatVisible;
bnComboBoxRelease.Enabled = !running && data.Releases.Count > 0;
bnComboBoxDrives.Enabled = !running && data.Drives.Count > 0;
bnComboBoxOutputFormat.Enabled =
listTracks.Enabled =
listMetadata.Enabled =
groupBoxSettings.Enabled = !running;
buttonGo.Enabled = !running && data.selectedRelease != null;
buttonPause.Visible = buttonPause.Enabled = buttonAbort.Visible = buttonAbort.Enabled = running;
buttonGo.Visible = !running;
toolStripStatusLabel1.Text = String.Empty;
toolStripProgressBar1.Value = 0;
progressBarErrors.Value = 0;
progressBarCD.Value = 0;
buttonTracks.Enabled = data.selectedRelease != null && !running;
buttonMetadata.Enabled = data.selectedRelease != null && !running;
buttonFreedbSubmit.Enabled = data.selectedRelease != null && !running;
buttonVA.Enabled = data.selectedRelease != null && !running &&
data.selectedRelease.ImageKey == "freedb" && !data.selectedRelease.metadata.IsVarious() && (new CUEMetadata(data.selectedRelease.metadata)).FreedbToVarious();
buttonEncoding.Enabled = data.selectedRelease != null && !running &&
data.selectedRelease.ImageKey == "freedb" && (new CUEMetadata(data.selectedRelease.metadata)).FreedbToEncoding();
buttonReload.Enabled = data.selectedRelease != null && !running;
buttonEjectDisk.Enabled = selectedDriveInfo !=null && !running;
buttonSettings.Enabled = !running;
}
private void CheckStop()
{
lock (_startStop)
{
if (_startStop._stop)
{
_startStop._stop = false;
_startStop._pause = false;
throw new StopException();
}
if (_startStop._pause)
{
this.BeginInvoke((MethodInvoker)(()=> toolStripStatusLabel1.Text = Properties.Resources.PausedMessage + "..."));
Monitor.Wait(_startStop);
}
}
if (backgroundWorkerArtwork.IsBusy && backgroundWorkerArtwork.CancellationPending)
{
throw new StopException();
}
}
private void UploadProgress(object sender, Krystalware.UploadHelper.UploadProgressEventArgs e)
{
CheckStop();
this.BeginInvoke((MethodInvoker)delegate()
{
toolStripStatusLabel1.Text = e.uri;
toolStripProgressBar1.Value = Math.Max(0, Math.Min(100, (int)(e.percent * 100)));
});
}
private void CDReadProgress(object sender, ReadProgressArgs e)
{
CheckStop();
ICDRipper audioSource = sender as ICDRipper;
int processed = e.Position - e.PassStart;
TimeSpan elapsed = DateTime.Now - e.PassTime;
double speed = elapsed.TotalSeconds > 0 ? processed / elapsed.TotalSeconds / 75 : 1.0;
double percentTrck = (double)(e.Position - e.PassStart) / (e.PassEnd - e.PassStart);
string retry = e.Pass > 0 ? " (" + Properties.Resources.Retry + " " + e.Pass.ToString() + ")" : "";
string status = (elapsed.TotalSeconds > 0 && e.Pass >= 0) ?
string.Format("{0} @{1:00.00}x{2}...", e.Action, speed, retry) :
string.Format("{0}{1}...", e.Action, retry);
this.BeginInvoke((MethodInvoker)delegate()
{
toolStripStatusLabel1.Text = status;
toolStripProgressBar1.Value = Math.Max(0, Math.Min(100, (int)(percentTrck * 100)));
progressBarErrors.Value = Math.Min(progressBarErrors.Maximum, (int)(100 * Math.Log(e.ErrorsCount / 10.0 + 1) / Math.Log((e.PassEnd - e.PassStart) / 10.0 + 1)));
progressBarErrors.Enabled = e.Pass >= audioSource.CorrectionQuality;
progressBarCD.Maximum = (int) audioSource.TOC.AudioLength;
progressBarCD.Value = Math.Max(0, Math.Min(progressBarCD.Maximum, (int)e.PassStart + (e.PassEnd - e.PassStart) * (Math.Min(e.Pass, audioSource.CorrectionQuality) + 1) / (audioSource.CorrectionQuality + 1)));
});
}
private void Rip(object o)
{
ICDRipper audioSource = o as ICDRipper;
audioSource.ReadProgress += new EventHandler(CDReadProgress);
audioSource.DriveOffset = (int)numericWriteOffset.Value;
try
{
if (this.testAndCopy)
cueSheet.TestBeforeCopy();
else
cueSheet.ArTestVerify = null;
cueSheet.Go();
cueSheet.CTDB.Submit(
(int)cueSheet.ArVerify.WorstConfidence() + 1,
audioSource.CorrectionQuality == 0 ? 0 :
(int)(100 * (1.0 - Math.Log(audioSource.FailedSectors.PopulationCount() + 1) / Math.Log(audioSource.TOC.AudioLength + 1))),
cueSheet.Metadata.Artist,
cueSheet.Metadata.Title,
cueSheet.TOC.Barcode);
bool canFix = false;
if (cueSheet.CTDB.QueryExceptionStatus == WebExceptionStatus.Success && audioSource.FailedSectors.PopulationCount() != 0)
{
foreach (DBEntry entry in cueSheet.CTDB.Entries)
if (entry.hasErrors && entry.canRecover)
canFix = true;
}
this.Invoke((MethodInvoker)delegate()
{
DialogResult dlgRes = audioSource.FailedSectors.PopulationCount() != 0 ?
MessageBox.Show(this, cueSheet.GenerateVerifyStatus() + (canFix ? "\n" + Properties.Resources.DoneRippingRepair : "") + ".", Properties.Resources.DoneRippingErrors, MessageBoxButtons.OK, MessageBoxIcon.Error) :
MessageBox.Show(this, cueSheet.GenerateVerifyStatus() + ".", Properties.Resources.DoneRipping, MessageBoxButtons.OK, MessageBoxIcon.Information);
});
}
catch (StopException)
{
}
#if !DEBUG
catch (Exception ex)
{
this.Invoke((MethodInvoker)delegate()
{
string message = Properties.Resources.ExceptionMessage;
for (Exception e = ex; e != null; e = e.InnerException)
message += ": " + e.Message;
DialogResult dlgRes = MessageBox.Show(this, message, Properties.Resources.ExceptionMessage, MessageBoxButtons.OK, MessageBoxIcon.Error);
});
}
#endif
audioSource.ReadProgress -= new EventHandler(CDReadProgress);
try
{
audioSource.Close();
audioSource.Open(audioSource.Path[0]);
}
catch (Exception ex)
{
this.BeginInvoke((MethodInvoker)delegate()
{
data.Releases.Clear();
data.selectedRelease = null;
bnComboBoxRelease.Text = ex.Message;
});
}
_workThread = null;
this.BeginInvoke((MethodInvoker)delegate()
{
SetupControls();
UpdateOutputPath();
});
}
private void buttonGo_Click(object sender, EventArgs e)
{
if (selectedDriveInfo == null)
return;
if (!bnComboBoxOutputFormat.Items.Contains(bnComboBoxOutputFormat.Text) && bnComboBoxOutputFormat.Text.Contains("%"))
{
bnComboBoxOutputFormat.Items.Insert(OutputPathUseTemplates.Length, bnComboBoxOutputFormat.Text);
if (bnComboBoxOutputFormat.Items.Count > OutputPathUseTemplates.Length + 10)
bnComboBoxOutputFormat.Items.RemoveAt(OutputPathUseTemplates.Length + 10);
}
cueSheet.AlbumArt.Clear();
if (currentAlbumArt >= 0 && currentAlbumArt < albumArt.Count)
{
data.selectedRelease.metadata.AlbumArt.Clear();
data.selectedRelease.metadata.AlbumArt.Add(albumArt[currentAlbumArt].meta);
var blob = new TagLib.ByteVector(albumArt[currentAlbumArt].contents);
cueSheet.AlbumArt.Add(new TagLib.Picture(blob) { Type = TagLib.PictureType.FrontCover });
}
data.selectedRelease.metadata.Save();
cueSheet.CopyMetadata(data.selectedRelease.metadata);
cueSheet.OutputStyle = bnComboBoxImage.SelectedIndex == 0 ? CUEStyle.SingleFileWithCUE :
CUEStyle.GapsAppended;
_pathOut = cueSheet.GenerateUniqueOutputPath(bnComboBoxOutputFormat.Text,
cueSheet.OutputStyle == CUEStyle.SingleFileWithCUE ? "." + selectedFormat.ToString() : ".cue",
CUEAction.Encode, null);
if (_pathOut == "")
{
MessageBox.Show(this, "Output path generation failed", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (cueSheet.Metadata.Comment == "")
cueSheet.Metadata.Comment = selectedDriveInfo.drive.RipperVersion;
cueSheet.GenerateFilenames(SelectedOutputAudioType, selectedFormat.ToString(), _pathOut);
selectedDriveInfo.drive.CorrectionQuality = trackBarSecureMode.Value;
_workThread = new Thread(Rip);
_workThread.Priority = ThreadPriority.BelowNormal;
_workThread.IsBackground = true;
SetupControls();
_workThread.Start(selectedDriveInfo.drive);
}
private void buttonAbort_Click(object sender, EventArgs e)
{
_startStop.Stop();
}
private void buttonPause_Click(object sender, EventArgs e)
{
_startStop.Pause();
}
private void ResizeList(ListView list, ColumnHeader title)
{
int colSum = 0;
foreach (ColumnHeader col in list.Columns)
{
colSum += col.Width + SystemInformation.BorderSize.Width;
}
title.Width += list.Width - colSum - 2 * SystemInformation.BorderSize.Width - SystemInformation.VerticalScrollBarWidth;
}
private void UpdateRelease()
{
data.selectedRelease = bnComboBoxRelease.SelectedItem as CUEMetadataEntry;
UpdateOutputPath();
listTracks.BeginUpdate();
listMetadata.BeginUpdate();
listTracks.Items.Clear();
listMetadata.Items.Clear();
if (!data.metadataMode)
{
listTracks.Visible = true;
listMetadata.Visible = false;
if (data.selectedRelease != null)
{
columnHeaderArtist.Width = data.selectedRelease.metadata.IsVarious() ? 120 : 0;
for (int i = 1; i <= selectedDriveInfo.drive.TOC.TrackCount; i++)
{
string title = "Data track";
string artist = "";
if (selectedDriveInfo.drive.TOC[i].IsAudio)
{
title = data.selectedRelease.metadata.Tracks[i - selectedDriveInfo.drive.TOC.FirstAudio].Title;
artist = data.selectedRelease.metadata.Tracks[i - selectedDriveInfo.drive.TOC.FirstAudio].Artist;
}
listTracks.Items.Add(new ListViewItem(new string[] {
title,
selectedDriveInfo.drive.TOC[i].Number.ToString(),
artist,
selectedDriveInfo.drive.TOC[i].StartMSF,
selectedDriveInfo.drive.TOC[i].LengthMSF }));
}
}
}
else if (data.metadataTrack < 0)
{
listTracks.Visible = false;
listMetadata.Visible = true;
if (data.selectedRelease != null)
{
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(data.selectedRelease.metadata);
PropertyDescriptorCollection sortedprops = props.Sort(new string[] { "Artist", "Title", "Genre", "Year", "DiscNumber", "TotalDiscs", "DiscName", "Label", "LabelNo", "Country", "ReleaseDate" });
foreach (PropertyDescriptor p in sortedprops)
if (p.Name != "Tracks" && p.Name != "AlbumArt" && p.Name != "Id" && !p.Attributes.Contains(new System.Xml.Serialization.XmlIgnoreAttribute()))
listMetadata.Items.Add(new ListViewItem(new string[] { p.GetValue(data.selectedRelease.metadata).ToString(), p.Name }));
}
}
else
{
listTracks.Visible = false;
listMetadata.Visible = true;
if (data.selectedRelease != null)
{
CUETrackMetadata track = data.selectedRelease.metadata.Tracks[data.metadataTrack];
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(track);
props = props.Sort(new string[] { "ISRC", "Title", "Artist" });
ListViewItem lvItem = new ListViewItem(new string[] { (data.metadataTrack + 1).ToString(), "Number" });
lvItem.ForeColor = SystemColors.GrayText;
listMetadata.Items.Add(lvItem);
foreach (PropertyDescriptor p in props)
{
lvItem = new ListViewItem(new string[] { p.GetValue(track).ToString(), p.Name });
if (p.Name == "ISRC")
lvItem.ForeColor = SystemColors.GrayText;
listMetadata.Items.Add(lvItem);
}
}
}
ResizeList(listTracks, Title);
ResizeList(listMetadata, columnHeaderValue);
listTracks.EndUpdate();
listMetadata.EndUpdate();
SelectAlbumArt();
SetupControls();
}
//private void MusicBrainz_LookupProgress(object sender, XmlRequestEventArgs e)
//{
// CheckStop();
// //_progress.percentDisk = (1.0 + _progress.percentDisk) / 2;
// //_progress.input = e.Uri.ToString();
// this.BeginInvoke((MethodInvoker)delegate()
// {
// toolStripStatusLabel1.Text = Properties.Resources.LookingUpVia + " " + (e == null ? "FreeDB" : "MusicBrainz") + "...";
// toolStripProgressBar1.Value = (100 + 2 * toolStripProgressBar1.Value) / 3;
// });
//}
private void FreeDB_LookupProgress(object sender)
{
CheckStop();
//_progress.percentDisk = (1.0 + _progress.percentDisk) / 2;
//_progress.input = e.Uri.ToString();
string text = Properties.Resources.LookingUpVia + " FreeDB..." + (sender is string ? " " + (sender as string) : "");
this.BeginInvoke((MethodInvoker)delegate()
{
toolStripStatusLabel1.Text = text;
toolStripProgressBar1.Value = (100 + 2 * toolStripProgressBar1.Value) / 3;
});
}
private CUEMetadataEntry CreateCUESheet(ICDRipper audioSource, CTDBResponseMeta release)
{
CUEMetadataEntry entry = new CUEMetadataEntry(audioSource.TOC, release.source);
entry.metadata.FillFromCtdb(release, entry.TOC.FirstAudio - 1);
return entry;
}
//private CUEMetadataEntry CreateCUESheet(ICDRipper audioSource, Release release)
//{
// CUEMetadataEntry entry = new CUEMetadataEntry(audioSource.TOC, "musicbrainz");
// entry.metadata.FillFromMusicBrainz(release, entry.TOC.FirstAudio - 1);
// return entry;
//}
private CUEMetadataEntry CreateCUESheet(ICDRipper audioSource, CDEntry cdEntry)
{
CUEMetadataEntry entry = new CUEMetadataEntry(audioSource.TOC, "freedb");
entry.metadata.FillFromFreedb(cdEntry, entry.TOC.FirstAudio - 1);
return entry;
}
private CUEMetadataEntry CreateCUESheet(ICDRipper audioSource)
{
CUEMetadataEntry entry = new CUEMetadataEntry(audioSource.TOC, "local");
entry.metadata.Artist = "Unknown Artist";
entry.metadata.Title = "Unknown Title";
for (int i = 0; i < entry.TOC.AudioTracks; i++)
{
entry.metadata.Tracks[i].Title = string.Format("Track {0:00}", i + 1);
entry.metadata.Tracks[i].Artist = entry.metadata.Artist;
}
return entry;
}
private bool loadAllMetadata = false;
private void Lookup(object o)
{
ICDRipper audioSource = o as ICDRipper;
int mbresults_count = 0; // have to cache results.Count, because it sometimes hangs in it, and we don't want UI thread to hang.
string musicbrainzError = "";
data.Releases.RaiseListChangedEvents = false;
cueSheet = new CUESheet(_config);
cueSheet.OpenCD(audioSource);
cueSheet.Action = CUEAction.Encode;
this.BeginInvoke((MethodInvoker)delegate() { toolStripStatusLabel1.Text = Properties.Resources.LookingUpVia + " CTDB..."; });
cueSheet.UseCUEToolsDB("CUERipper " + CUESheet.CUEToolsVersion, selectedDriveInfo.drive.ARName, false, loadAllMetadata ? CTDBMetadataSearch.Extensive : _config.advanced.metadataSearch);
cueSheet.CTDB.UploadHelper.onProgress += new EventHandler(UploadProgress);
this.BeginInvoke((MethodInvoker)delegate() { toolStripStatusLabel1.Text = Properties.Resources.LookingUpVia + " AccurateRip..."; });
cueSheet.UseAccurateRip();
General.SetCUELine(cueSheet.Attributes, "REM", "DISCID", AccurateRipVerify.CalculateCDDBId(audioSource.TOC), false);
try
{
CUEMetadata cache = CUEMetadata.Load(audioSource.TOC.TOCID);
if (cache != null)
data.Releases.Add(new CUEMetadataEntry(cache, audioSource.TOC, "local"));
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
foreach (var ctdbMeta in cueSheet.CTDB.Metadata)
{
data.Releases.Add(CreateCUESheet(audioSource, ctdbMeta));
}
if (data.Releases.Count == 0 || loadAllMetadata)
{
loadAllMetadata = false;
//this.BeginInvoke((MethodInvoker)delegate() { toolStripStatusLabel1.Text = Properties.Resources.LookingUpVia + " MusicBrainz..."; });
//ReleaseQueryParameters p = new ReleaseQueryParameters();
//p.DiscId = audioSource.TOC.MusicBrainzId;
//Query results = Release.Query(p);
//MusicBrainzService.Proxy = _config.GetProxy();
//MusicBrainzService.XmlRequest += new EventHandler(MusicBrainz_LookupProgress);
//try
//{
// foreach (Release release in results)
// {
// release.GetEvents();
// release.GetTracks();
// data.Releases.Add(CreateCUESheet(audioSource, release));
// }
// mbresults_count = results.Count;
//}
//catch (Exception ex)
//{
// System.Diagnostics.Trace.WriteLine(ex.Message);
// if (!(ex is MusicBrainzNotFoundException))
// musicbrainzError = ex.Message;
//}
//MusicBrainzService.Proxy = null;
//MusicBrainzService.XmlRequest -= new EventHandler(MusicBrainz_LookupProgress);
this.BeginInvoke((MethodInvoker)delegate() { toolStripStatusLabel1.Text = Properties.Resources.LookingUpVia + " Freedb..."; });
FreedbHelper m_freedb = new FreedbHelper();
m_freedb.Proxy = _config.GetProxy();
m_freedb.UserName = _config.advanced.FreedbUser;
m_freedb.Hostname = _config.advanced.FreedbDomain;
m_freedb.ClientName = "CUERipper";
m_freedb.Version = CUESheet.CUEToolsVersion;
m_freedb.SetDefaultSiteAddress(Properties.Settings.Default.MAIN_FREEDB_SITEADDRESS);
QueryResult queryResult;
QueryResultCollection coll;
string code = string.Empty;
try
{
FreeDB_LookupProgress(this);
code = m_freedb.Query(AccurateRipVerify.CalculateCDDBQuery(audioSource.TOC), out queryResult, out coll);
if (code == FreedbHelper.ResponseCodes.CODE_200)
{
bool duplicate = false;
foreach (var ctdbMeta in cueSheet.CTDB.Metadata)
if (ctdbMeta.source == "freedb" && ctdbMeta.id == queryResult.Category + "/" + queryResult.Discid)
duplicate = true;
if (!duplicate)
{
FreeDB_LookupProgress(queryResult.Category + "/" + queryResult.Discid);
CDEntry cdEntry;
code = m_freedb.Read(queryResult, out cdEntry);
if (code == FreedbHelper.ResponseCodes.CODE_210)
{
CUEMetadataEntry r = CreateCUESheet(audioSource, cdEntry);
data.Releases.Add(r);
}
}
}
else
if (code == FreedbHelper.ResponseCodes.CODE_210 ||
code == FreedbHelper.ResponseCodes.CODE_211)
{
foreach (QueryResult qr in coll)
{
bool duplicate = false;
foreach (var ctdbMeta in cueSheet.CTDB.Metadata)
if (ctdbMeta.source == "freedb" && ctdbMeta.id == qr.Category + "/" + qr.Discid)
duplicate = true;
if (!duplicate)
{
CDEntry cdEntry;
FreeDB_LookupProgress(qr.Category + "/" + qr.Discid);
code = m_freedb.Read(qr, out cdEntry);
if (code == FreedbHelper.ResponseCodes.CODE_210)
{
CUEMetadataEntry r = CreateCUESheet(audioSource, cdEntry);
data.Releases.Add(r);
}
}
}
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
if (data.Releases.Count == 0)
{
data.Releases.Add(CreateCUESheet(audioSource));
}
_workThread = null;
if (musicbrainzError != "")
musicbrainzError = musicbrainzError + ": ";
while (backgroundWorkerArtwork.IsBusy)
{
Thread.Sleep(100);
}
this.BeginInvoke((MethodInvoker)delegate()
{
SetupControls();
data.Releases.RaiseListChangedEvents = true;
data.Releases.ResetBindings();
//bnComboBoxRelease.SelectedIndex = 0;
toolStripStatusAr.Enabled = cueSheet.ArVerify.ARStatus == null;
toolStripStatusAr.Text = cueSheet.ArVerify.ARStatus == null ? cueSheet.ArVerify.WorstTotal().ToString() : "";
toolStripStatusAr.ToolTipText = "AccurateRip: " + (cueSheet.ArVerify.ARStatus ?? "found") + ".";
toolStripStatusCTDB.Enabled = cueSheet.CTDB.DBStatus == null;
toolStripStatusCTDB.Text = cueSheet.CTDB.DBStatus == null ? cueSheet.CTDB.Total.ToString() : "";
toolStripStatusCTDB.ToolTipText = "CUETools DB: " + (cueSheet.CTDB.DBStatus ?? "found") + ".";
toolStripStatusLabelMusicBrainz.Enabled = true;
toolStripStatusLabelMusicBrainz.BorderStyle = mbresults_count > 0 ? Border3DStyle.SunkenInner : Border3DStyle.RaisedInner;
toolStripStatusLabelMusicBrainz.Text = mbresults_count > 0 ? mbresults_count.ToString() : "";
toolStripStatusLabelMusicBrainz.ToolTipText = "Musicbrainz: " + (mbresults_count > 0 ? mbresults_count.ToString() + " entries found." : (musicbrainzError + "click to submit."));
if (_config.advanced.coversSearch != CUEConfigAdvanced.CTDBCoversSearch.None)
backgroundWorkerArtwork.RunWorkerAsync(new BackgroundWorkerArtworkArgs() { cueSheet = cueSheet, meta = data.selectedRelease });
});
}
private void UpdateDrive()
{
if (bnComboBoxDrives.SelectedItem as DriveInfo == null)
return;
if (selectedDriveInfo != null)
selectedDriveInfo.drive.Close();
selectedDriveInfo = bnComboBoxDrives.SelectedItem as DriveInfo;
cueRipperConfig.DefaultDrive = selectedDriveInfo.Path;
toolStripStatusAr.Enabled = false;
toolStripStatusAr.Text = "";
toolStripStatusAr.ToolTipText = "";
toolStripStatusCTDB.Enabled = false;
toolStripStatusCTDB.Text = "";
toolStripStatusCTDB.ToolTipText = "";
toolStripStatusLabelMusicBrainz.Enabled = false;
toolStripStatusLabelMusicBrainz.Text = "";
toolStripStatusLabelMusicBrainz.ToolTipText = "";
listTracks.Items.Clear();
data.Releases.Clear();
data.selectedRelease = null;
ResetAlbumArt();
bnComboBoxRelease.Enabled = false;
bnComboBoxRelease.Text = "";
if (selectedDriveInfo == null)
{
SetupControls();
return;
}
if (cueSheet != null)
{
cueSheet.Close();
cueSheet = null;
}
numericWriteOffset.Value = selectedDriveInfo.drive.DriveOffset;
try
{
selectedDriveInfo.drive.Open(selectedDriveInfo.drive.Path[0]);
}
catch (Exception ex)
{
selectedDriveInfo.drive.Close();
bnComboBoxRelease.Text = ex.Message;
SetupControls();
return;
}
// cannot use data.Drives.ResetItem(bnComboBoxDrives.SelectedIndex); - causes recursion
UpdateRelease();
_workThread = new Thread(Lookup);
_workThread.Priority = ThreadPriority.BelowNormal;
_workThread.IsBackground = true;
SetupControls();
_workThread.Start(selectedDriveInfo.drive);
}
private void listTracks_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F2)
{
listTracks.FocusedItem.BeginEdit();
}
}
private void listTracks_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (listTracks.FocusedItem != null && listTracks.FocusedItem.Index + 1 < listTracks.Items.Count)// && e.Label != null)
{
listTracks.FocusedItem.Selected = false;
listTracks.FocusedItem = listTracks.Items[listTracks.FocusedItem.Index + 1];
listTracks.FocusedItem.Selected = true;
listTracks.FocusedItem.BeginEdit();
}
}
}
private void listTracks_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
if (data.selectedRelease == null) return;
if (e.Label != null && selectedDriveInfo.drive.TOC[e.Item + 1].IsAudio)
data.selectedRelease.metadata.Tracks[e.Item].Title = e.Label;
else
e.CancelEdit = true;
}
private void frmCUERipper_FormClosed(object sender, FormClosedEventArgs e)
{
SettingsWriter sw = new SettingsWriter("CUERipper", "settings.txt", Application.ExecutablePath);
_config.Save(sw);
//sw.Save("CreateEACLOG", _config.createEACLOG);
//sw.Save("PreserveHTOA", _config.preserveHTOA);
//sw.Save("CreateM3U", _config.createM3U);
sw.Save("OutputAudioType", (int)SelectedOutputAudioType);
sw.Save("ComboImage", bnComboBoxImage.SelectedIndex);
sw.Save("PathFormat", bnComboBoxOutputFormat.Text);
sw.Save("SecureMode", trackBarSecureMode.Value);
sw.Save("OutputPathUseTemplates", bnComboBoxOutputFormat.Items.Count - OutputPathUseTemplates.Length);
sw.Save("TestAndCopy", this.testAndCopy);
var SizeIncrement = Size - MinimumSize;
sw.Save("WidthIncrement", SizeIncrement.Width);
sw.Save("HeightIncrement", SizeIncrement.Height);
for (int iFormat = bnComboBoxOutputFormat.Items.Count - 1; iFormat >= OutputPathUseTemplates.Length; iFormat--)
sw.Save(string.Format("OutputPathUseTemplate{0}", iFormat - OutputPathUseTemplates.Length), bnComboBoxOutputFormat.Items[iFormat].ToString());
using (TextWriter tw = new StringWriter())
using (XmlWriter xw = XmlTextWriter.Create(tw, xmlEmptySettings))
{
CUERipperConfig.serializer.Serialize(xw, cueRipperConfig, xmlEmptyNamespaces);
sw.SaveText("CUERipper", tw.ToString());
}
sw.Close();
}
private void listTracks_BeforeLabelEdit(object sender, LabelEditEventArgs e)
{
if (!selectedDriveInfo.drive.TOC[e.Item + 1].IsAudio)
e.CancelEdit = true;
}
private string SelectedOutputAudioFormat
{
get
{
return selectedFormat == null ? "dummy" : selectedFormat.ToString();
}
set
{
foreach (CUEToolsFormat fmt in data.Formats)
if (fmt.ToString() == value)
bnComboBoxFormat.SelectedItem = fmt;
}
}
private CUEToolsFormat SelectedOutputAudioFmt
{
get
{
return selectedFormat;
}
}
private AudioEncoderType SelectedOutputAudioType
{
get
{
return (bnComboBoxLosslessOrNot.SelectedItem as ImgComboBoxItem).Value;
}
set
{
foreach (ImgComboBoxItem item in data.LosslessOrNot)
if (value == item.Value)
{
bnComboBoxLosslessOrNot.SelectedItem = item;
return;
}
throw new Exception("invalid value");
}
}
private void resetEncoderModes(CUEToolsUDC encoder)
{
encoder.settings.PCM = AudioPCMConfig.RedBook;
buttonEncoderSettings.Enabled = encoder.settings.HasBrowsableAttributes();
string[] modes = encoder.SupportedModes;
if (modes == null || modes.Length < 2)
{
trackBarEncoderMode.Visible = false;
labelEncoderMode.Visible = false;
labelEncoderMinMode.Visible = false;
labelEncoderMaxMode.Visible = false;
}
else
{
if (encoder.EncoderModeIndex == -1)
{
string defaultMode;
encoder.settings.GetSupportedModes(out defaultMode);
encoder.settings.EncoderMode = defaultMode;
}
trackBarEncoderMode.Maximum = modes.Length - 1;
trackBarEncoderMode.Value = encoder.EncoderModeIndex == -1 ? modes.Length - 1 : encoder.EncoderModeIndex;
labelEncoderMode.Text = encoder.settings.EncoderMode;
labelEncoderMinMode.Text = modes[0];
labelEncoderMaxMode.Text = modes[modes.Length - 1];
trackBarEncoderMode.Visible = true;
labelEncoderMode.Visible = true;
labelEncoderMinMode.Visible = true;
labelEncoderMaxMode.Visible = true;
}
}
private void bnComboBoxEncoder_SelectedValueChanged(object sender, EventArgs e)
{
if (SelectedOutputAudioFormat == null)
return;
CUEToolsUDC encoder = bnComboBoxEncoder.SelectedItem as CUEToolsUDC;
if (encoder == null)
return;
if (SelectedOutputAudioType == AudioEncoderType.Lossless)
SelectedOutputAudioFmt.encoderLossless = encoder;
else
SelectedOutputAudioFmt.encoderLossy = encoder;
resetEncoderModes(encoder);
}
private void trackBarEncoderMode_Scroll(object sender, EventArgs e)
{
CUEToolsUDC encoder = bnComboBoxEncoder.SelectedItem as CUEToolsUDC;
string[] modes = encoder.SupportedModes;
encoder.settings.EncoderMode = modes[trackBarEncoderMode.Value];
labelEncoderMode.Text = encoder.settings.EncoderMode;
}
private void trackBarSecureMode_Scroll(object sender, EventArgs e)
{
string[] modes = new string[] { "Burst", "Secure", "Paranoid" };
labelSecureMode.Text = modes[trackBarSecureMode.Value];
}
private void toolStripStatusLabelMusicBrainz_Click(object sender, EventArgs e)
{
if (selectedDriveInfo == null)
return;
System.Diagnostics.Process.Start("http://musicbrainz.org/bare/cdlookup.html?toc=" + selectedDriveInfo.drive.TOC.MusicBrainzTOC);
}
private void frmCUERipper_KeyDown(object sender, KeyEventArgs e)
{
if (_workThread == null && e.KeyCode == Keys.F5)
{
loadAllMetadata = true;
UpdateDrives();
}
}
private void UpdateOutputPath()
{
if (selectedFormat == null) return;
if (data.selectedRelease == null)
{
txtOutputPath.Text = "";
return;
}
CUEStyle style = bnComboBoxImage.SelectedIndex == 0 ? CUEStyle.SingleFileWithCUE : CUEStyle.GapsAppended;
CUESheet sheet = new CUESheet(_config);
sheet.TOC = selectedDriveInfo.drive.TOC;
sheet.CopyMetadata(data.selectedRelease.metadata);
txtOutputPath.Text = sheet.GenerateUniqueOutputPath(bnComboBoxOutputFormat.Text,
style == CUEStyle.SingleFileWithCUE ? "." + selectedFormat.ToString() : ".cue", CUEAction.Encode, null);
}
private void bnComboBoxRelease_SelectedValueChanged(object sender, EventArgs e)
{
UpdateRelease();
}
private void bnComboBoxDrives_SelectedIndexChanged(object sender, EventArgs e)
{
if (_workThread == null)
UpdateDrive();
}
private CUEToolsFormat selectedFormat;
private void bnComboBoxFormat_SelectedValueChanged(object sender, EventArgs e)
{
selectedFormat = bnComboBoxFormat.SelectedItem as CUEToolsFormat;
data.Encoders.Clear();
if (SelectedOutputAudioFmt == null)
return;
if (initDone)
{
switch (SelectedOutputAudioType)
{
case AudioEncoderType.Lossless:
cueRipperConfig.DefaultLosslessFormat = SelectedOutputAudioFormat;
break;
case AudioEncoderType.Lossy:
cueRipperConfig.DefaultLossyFormat = SelectedOutputAudioFormat;
break;
case AudioEncoderType.Hybrid:
cueRipperConfig.DefaultHybridFormat = SelectedOutputAudioFormat;
break;
}
}
data.Encoders.RaiseListChangedEvents = false;
foreach (CUEToolsUDC encoder in _config.encoders)
if (encoder.extension == SelectedOutputAudioFmt.extension)
{
if (SelectedOutputAudioType == AudioEncoderType.Lossless && !encoder.lossless)
continue;
if (SelectedOutputAudioType == AudioEncoderType.Lossy && encoder.lossless)
continue;
data.Encoders.Add(encoder);
}
CUEToolsUDC select = SelectedOutputAudioType == AudioEncoderType.Lossless ? SelectedOutputAudioFmt.encoderLossless
: SelectedOutputAudioFmt.encoderLossy;
data.Encoders.RaiseListChangedEvents = true;
data.Encoders.ResetBindings();
bnComboBoxEncoder.SelectedItem = select;
UpdateOutputPath();
}
private void bnComboBoxImage_SelectedValueChanged(object sender, EventArgs e)
{
UpdateOutputPath();
}
private void bnComboBoxLosslessOrNot_SelectedValueChanged(object sender, EventArgs e)
{
if (bnComboBoxLosslessOrNot.SelectedItem == null) return;
data.Formats.Clear();
data.Formats.RaiseListChangedEvents = false;
foreach (KeyValuePair format in _config.formats)
{
if (SelectedOutputAudioType == AudioEncoderType.Lossless && !format.Value.allowLossless)
continue;
if (SelectedOutputAudioType == AudioEncoderType.Hybrid) // && format.Key != "wv") TODO!!!!!
continue;
if (SelectedOutputAudioType == AudioEncoderType.Lossy && !format.Value.allowLossy)
continue;
data.Formats.Add(format.Value);
}
string select = null;
switch (SelectedOutputAudioType)
{
case AudioEncoderType.Lossless:
select = cueRipperConfig.DefaultLosslessFormat;
break;
case AudioEncoderType.Lossy:
select = cueRipperConfig.DefaultLossyFormat;
break;
case AudioEncoderType.Hybrid:
select = cueRipperConfig.DefaultHybridFormat;
break;
}
data.Formats.RaiseListChangedEvents = true;
data.Formats.ResetBindings();
SelectedOutputAudioFormat = select;
}
private void bnComboBoxOutputFormat_TextChanged(object sender, EventArgs e)
{
UpdateOutputPath();
}
private void txtOutputPath_Enter(object sender, EventArgs e)
{
if (outputFormatVisible)
return;
txtOutputPath.Enabled = false;
txtOutputPath.Visible = false;
outputFormatVisible = true;
bnComboBoxOutputFormat.Visible = true;
bnComboBoxOutputFormat.Focus();
}
private void bnComboBoxOutputFormat_MouseLeave(object sender, EventArgs e)
{
//if (!outputFormatVisible)
// return;
//outputFormatVisible = false;
//bnComboBoxOutputFormat.Visible = false;
//txtOutputPath.Enabled = true;
//txtOutputPath.Visible = true;
}
private void bnComboBoxOutputFormat_DroppedDown(object sender, EventArgs e)
{
if (!outputFormatVisible || bnComboBoxOutputFormat.DroppedDown || ActiveControl == bnComboBoxOutputFormat)
return;
outputFormatVisible = false;
bnComboBoxOutputFormat.Visible = false;
txtOutputPath.Enabled = true;
txtOutputPath.Visible = true;
}
private void bnComboBoxOutputFormat_Leave(object sender, EventArgs e)
{
bnComboBoxOutputFormat_DroppedDown(sender, e);
}
private void listMetadata_Click(object sender, EventArgs e)
{
listMetadata.FocusedItem.BeginEdit();
}
private void listMetadata_BeforeLabelEdit(object sender, LabelEditEventArgs e)
{
if (data.selectedRelease == null || !data.metadataMode)
{
e.CancelEdit = true;
}
else if (data.metadataTrack < 0)
{
}
else
{
if (listMetadata.Items[e.Item].SubItems[1].Text == "ISRC" ||
listMetadata.Items[e.Item].SubItems[1].Text == "Number")
{
e.CancelEdit = true;
}
}
}
private void listMetadata_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
if (data.selectedRelease == null || e.Label == null || !data.metadataMode)
{
e.CancelEdit = true;
}
else if (data.metadataTrack < 0)
{
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(data.selectedRelease.metadata);
PropertyDescriptor prop = props[listMetadata.Items[e.Item].SubItems[1].Text];
if (prop.Name == "Artist")
data.selectedRelease.metadata.UpdateArtist(e.Label);
else
prop.SetValue(data.selectedRelease.metadata, e.Label);
data.Releases.ResetItem(bnComboBoxRelease.SelectedIndex);
}
else
{
CUETrackMetadata track = data.selectedRelease.metadata.Tracks[data.metadataTrack];
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(track);
props[listMetadata.Items[e.Item].SubItems[1].Text].SetValue(track, e.Label);
//data.Tracks.ResetItem(data.metadataTrack);
}
}
private void buttonMetadata_Click(object sender, EventArgs e)
{
buttonTracks.Visible = true;
buttonTracks.Focus();
buttonMetadata.Visible = false;
data.metadataTrack = -1;
data.metadataMode = true;
UpdateRelease();
}
private void buttonTracks_Click(object sender, EventArgs e)
{
buttonMetadata.Visible = true;
buttonMetadata.Focus();
buttonTracks.Visible = false;
data.metadataMode = false;
UpdateRelease();
}
private void buttonReload_Click(object sender, EventArgs e)
{
loadAllMetadata = true;
data.Releases.Clear();
data.selectedRelease = null;
ResetAlbumArt();
UpdateRelease();
_workThread = new Thread(Lookup);
_workThread.Priority = ThreadPriority.BelowNormal;
_workThread.IsBackground = true;
SetupControls();
_workThread.Start(selectedDriveInfo.drive);
}
private void buttonVA_Click(object sender, EventArgs e)
{
if (data.selectedRelease == null) return;
data.selectedRelease.metadata.FreedbToVarious();
UpdateRelease();
data.Releases.ResetItem(bnComboBoxRelease.SelectedIndex);
SetupControls();
}
private void buttonEncoding_Click(object sender, EventArgs e)
{
if (data.selectedRelease == null) return;
data.selectedRelease.metadata.FreedbToEncoding();
UpdateRelease();
data.Releases.ResetItem(bnComboBoxRelease.SelectedIndex);
UpdateOutputPath();
SetupControls();
}
private void listTracks_Click(object sender, EventArgs e)
{
Point p = listTracks.PointToClient(MousePosition);
ListViewItem lvItem = listTracks.GetItemAt(p.X, p.Y);
if (lvItem != null)
{
ListViewItem.ListViewSubItem a = lvItem.GetSubItemAt(p.X, p.Y);
if (a != null)
{
int track = lvItem.Index + 1 - selectedDriveInfo.drive.TOC.FirstAudio;
if (a == lvItem.SubItems[0])
lvItem.BeginEdit();
else if (/*a == lvItem.SubItems[2] &&*/ track >= 0 && track < selectedDriveInfo.drive.TOC.AudioTracks)
{
buttonTracks.Visible = true;
buttonTracks.Focus();
buttonMetadata.Visible = false;
data.metadataTrack = track;
data.metadataMode = true;
UpdateRelease();
}
}
}
}
private void FreedbSubmit(object o)
{
StringCollection tmp = new StringCollection();
tmp.Add("DTITLE=");
CDEntry entry = new CDEntry(tmp);
entry.Artist = data.selectedRelease.metadata.Artist;
entry.Title = data.selectedRelease.metadata.Title;
entry.Year = data.selectedRelease.metadata.Year;
entry.Genre = data.selectedRelease.metadata.Genre;
int i = 1;
for (i = 1; i <= selectedDriveInfo.drive.TOC.TrackCount; i++)
{
Freedb.Track tt = new Freedb.Track();
if (i >= selectedDriveInfo.drive.TOC.FirstAudio && i < selectedDriveInfo.drive.TOC.FirstAudio + selectedDriveInfo.drive.TOC.AudioTracks)
{
CUETrackMetadata t = data.selectedRelease.metadata.Tracks[i - selectedDriveInfo.drive.TOC.FirstAudio];
if (t.Artist != "" && t.Artist != entry.Artist)
tt.Title = t.Artist + " / " + t.Title;
else
tt.Title = t.Title;
} else
tt.Title = "Data track";
tt.FrameOffset = 150 + (int)selectedDriveInfo.drive.TOC[i].Start;
entry.Tracks.Add(tt);
}
FreedbHelper m_freedb = new FreedbHelper();
frmFreedbSubmit frm = new frmFreedbSubmit();
foreach (string c in m_freedb.ValidCategories)
frm.Data.Categories.Add(c);
frm.Data.User = _config.advanced.FreedbUser;
frm.Data.Domain = _config.advanced.FreedbDomain;
frm.Data.Category = "misc";
DialogResult dlgRes = DialogResult.Cancel;
this.Invoke((MethodInvoker)delegate() { dlgRes = frm.ShowDialog(); });
if (dlgRes == DialogResult.Cancel)
{
_workThread = null;
this.BeginInvoke((MethodInvoker)delegate() { SetupControls(); });
return;
}
data.selectedRelease.metadata.Save();
_config.advanced.FreedbUser = frm.Data.User;
_config.advanced.FreedbDomain = frm.Data.Domain;
m_freedb.Proxy = _config.GetProxy();
m_freedb.UserName = _config.advanced.FreedbUser;
m_freedb.Hostname = _config.advanced.FreedbDomain;
m_freedb.ClientName = "CUERipper";
m_freedb.Version = CUESheet.CUEToolsVersion;
//try
//{
// string code = m_freedb.GetCategories(out tmp);
// if (code == FreedbHelper.ResponseCodes.CODE_210)
// m_freedb.ValidCategories = tmp;
//}
//catch
//{
//}
uint length = selectedDriveInfo.drive.TOC.Length / 75 + 2;
try
{
string res = m_freedb.Submit(entry, (int)length, AccurateRipVerify.CalculateCDDBId(selectedDriveInfo.drive.TOC), frm.Data.Category, false);
this.BeginInvoke((MethodInvoker)delegate()
{
dlgRes = MessageBox.Show(this, res, "Submit result", MessageBoxButtons.OK, MessageBoxIcon.Information);
});
}
catch (Exception ex)
{
this.BeginInvoke((MethodInvoker)delegate()
{
dlgRes = MessageBox.Show(this, ex.Message, "Submit result", MessageBoxButtons.OK, MessageBoxIcon.Error);
});
}
_workThread = null;
this.BeginInvoke((MethodInvoker)delegate() { SetupControls(); });
}
private void buttonFreedbSubmit_Click(object sender, EventArgs e)
{
_workThread = new Thread(FreedbSubmit);
_workThread.Priority = ThreadPriority.BelowNormal;
_workThread.IsBackground = true;
SetupControls();
_workThread.Start();
}
List albumArt = new List();
int currentAlbumArt = 0;//, frontAlbumArt = -1;
private void ResetAlbumArt()
{
if (this.cueSheet != null)
{
this.cueSheet.CTDB.CancelRequest();
}
lock (albumArt)
{
if (backgroundWorkerArtwork.IsBusy)
backgroundWorkerArtwork.CancelAsync();
albumArt.Clear();
}
currentAlbumArt = 0;
resetPictureBox(null);
}
private void SelectAlbumArt()
{
if (data.selectedRelease != null && data.selectedRelease.metadata.AlbumArt.Count > 0)
{
for (int i = 0; i < albumArt.Count; i++)
{
foreach (var aa in data.selectedRelease.metadata.AlbumArt)
{
if (aa.uri == albumArt[i].meta.uri)
{
currentAlbumArt = i;
break;
}
}
}
}
resetPictureBox(null);
}
private void backgroundWorkerArtwork_DoWork(object sender, DoWorkEventArgs e)
{
var args = e.Argument as BackgroundWorkerArtworkArgs;
var cueSheet = args.cueSheet;
albumArt.Clear();
currentAlbumArt = 0;
//frontAlbumArt = -1;
var knownUrls = new List();
var firstUrls = new List();
if (args.meta != null && args.meta.metadata.AlbumArt.Count > 0)
foreach (var aa in args.meta.metadata.AlbumArt)
firstUrls.Add(aa.uri);
for (int i = 0; i < 2; i++)
{
foreach (var metadata in cueSheet.CTDB.Metadata)
{
if (metadata.coverart == null)
continue;
foreach (var coverart in metadata.coverart)
{
var uri = _config.advanced.coversSearch == CUEConfigAdvanced.CTDBCoversSearch.Large ?
coverart.uri : coverart.uri150 ?? coverart.uri;
if (knownUrls.Contains(uri) || !coverart.primary)
continue;
if (i == 0 && !firstUrls.Contains(coverart.uri))
continue;
var ms = new MemoryStream();
if (!cueSheet.CTDB.FetchFile(uri, ms))
continue;
lock (this.albumArt)
{
if (backgroundWorkerArtwork.CancellationPending)
{
e.Cancel = true;
return;
}
this.albumArt.Add(new AlbumArt(coverart, ms.ToArray()));
}
knownUrls.Add(uri);
backgroundWorkerArtwork.ReportProgress(0);
}
}
}
}
private void backgroundWorkerArtwork_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
SelectAlbumArt();
}
private void backgroundWorkerArtwork_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
toolStripStatusLabel1.Text = "";
toolStripProgressBar1.Value = 0;
}
private void buttonSettings_Click(object sender, EventArgs e)
{
var form = new Options(new CUERipperSettings(this._config));
form.ShowDialog(this);
}
private void checkBoxTestAndCopy_Click(object sender, EventArgs e)
{
this.testAndCopy = checkBoxTestAndCopy.Checked;
}
private void frmCUERipper_ClientSizeChanged(object sender, EventArgs e)
{
ResizeList(listTracks, Title);
ResizeList(listMetadata, columnHeaderValue);
}
private void numericWriteOffset_ValueChanged(object sender, EventArgs e)
{
if (selectedDriveInfo != null && selectedDriveInfo.drive.ARName != null)
{
cueRipperConfig.DriveOffsets[selectedDriveInfo.drive.ARName] = (int)numericWriteOffset.Value;
}
}
private void buttonEncoderSettings_Click(object sender, EventArgs e)
{
CUEToolsUDC encoder = bnComboBoxEncoder.SelectedItem as CUEToolsUDC;
if (encoder == null)
return;
var form = new Options(encoder.settings);
form.propertyGrid1.HelpVisible = true;
form.ShowDialog(this);
resetEncoderModes(encoder);
}
private static Bitmap cropImage(Image imgToResize, Size boxSize, RectangleF srcRect)
{
Bitmap b = new Bitmap(boxSize.Width, boxSize.Height);
//area.Width / 2 - area.X, area.Height /2 - area.Y, area.Width, area.Height
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, new Rectangle(0, 0, boxSize.Width, boxSize.Height), srcRect, GraphicsUnit.Pixel);
g.Dispose();
return b;
}
private void resetPictureBox(MouseEventArgs e)
{
if (currentAlbumArt < 0 || currentAlbumArt >= albumArt.Count)
{
pictureBox1.Image = null;
toolStripStatusLabel1.Text = "";
return;
}
toolStripStatusLabel1.Text = albumArt[currentAlbumArt].meta.uri;
if (e == null || e.Button != System.Windows.Forms.MouseButtons.Right || _config.advanced.coversSearch != CUEConfigAdvanced.CTDBCoversSearch.Large)
{
pictureBox1.Image = albumArt[currentAlbumArt].image;
return;
}
var isz = new RectangleF(0.0f, 0.0f, albumArt[currentAlbumArt].image.Width, albumArt[currentAlbumArt].image.Height);
//float ratio = Math.Min(isz.Width / pictureBox1.ClientSize.Width, isz.Height / pictureBox1.ClientSize.Height);
//ratio = Math.Min(ratio, 1.0f);
float ratio = 1.0f;
var rf = new RectangleF(
Math.Min(pictureBox1.ClientSize.Width, Math.Max(0, e.Location.X)) * (isz.Width / pictureBox1.ClientSize.Width - ratio),
Math.Min(pictureBox1.ClientSize.Height, Math.Max(0, e.Location.Y)) * (isz.Height / pictureBox1.ClientSize.Height - ratio),
pictureBox1.ClientSize.Width * ratio,
pictureBox1.ClientSize.Height * ratio);
pictureBox1.Image = cropImage(albumArt[currentAlbumArt].image, pictureBox1.ClientSize, rf);
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
if (++currentAlbumArt > albumArt.Count)
currentAlbumArt = 0;
resetPictureBox(null);
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
resetPictureBox(e);
if (currentAlbumArt < 0 || currentAlbumArt >= albumArt.Count)
{
toolStripStatusLabel1.Text = "";
return;
}
toolStripStatusLabel1.Text = albumArt[currentAlbumArt].meta.uri;
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
resetPictureBox(null);
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
toolStripStatusLabel1.Text = null;
}
private void buttonEjectDisk_Click(object sender, EventArgs e)
{
if (selectedDriveInfo != null)
selectedDriveInfo.drive.EjectDisk();
}
}
internal class BackgroundWorkerArtworkArgs
{
public CUESheet cueSheet;
public CUEMetadataEntry meta;
}
internal class AlbumArt
{
public CTDBResponseMetaImage meta;
public byte[] contents;
public Image image;
public AlbumArt(CTDBResponseMetaImage meta, byte[] contents)
{
this.meta = meta;
this.contents = contents;
using (MemoryStream imageStream = new MemoryStream(contents))
try { this.image = Image.FromStream(imageStream); }
catch { }
}
}
public class StartStop
{
public bool _stop, _pause;
public StartStop()
{
_stop = false;
_pause = false;
}
public void Stop()
{
lock (this)
{
if (_pause)
{
_pause = false;
Monitor.Pulse(this);
}
_stop = true;
}
}
public void Pause()
{
lock (this)
{
if (_pause)
{
_pause = false;
Monitor.Pulse(this);
}
else
{
_pause = true;
}
}
}
}
public class DriveInfo
{
public ICDRipper drive;
DirectoryInfo di;
CUEControls.IIconManager iconMgr;
public string Path
{
get
{
return di.FullName;
}
}
public int ImageKey
{
get
{
return iconMgr.GetIconIndex(di, true);
}
}
public DriveInfo(CUEControls.IIconManager iconMgr, string path, ICDRipper drive)
{
this.iconMgr = iconMgr;
this.di = new DirectoryInfo(path);
this.drive = drive;
}
public override string ToString()
{
return drive.Path;
}
}
internal class CUERipperData
{
public CUERipperData()
{
}
private BindingList cueStyles = new BindingList { "image", "tracks" };
//private BindingList losslessOrNot = new BindingList { "lossless", "lossy" };
private BindingList> losslessOrNot = new BindingList> {
new ImgComboBoxItem("lossless", "checked", AudioEncoderType.Lossless),
new ImgComboBoxItem("lossy", "unchecked", AudioEncoderType.Lossy)
};
private BindingList releases = new BindingList();
private BindingList drives = new BindingList();
private BindingList formats = new BindingList();
private BindingList encoders = new BindingList();
public CUEMetadataEntry selectedRelease { get; set; }
public bool metadataMode { get; set; }
public int metadataTrack { get; set; }
public BindingList CUEStyles
{
get
{
return cueStyles;
}
}
public BindingList> LosslessOrNot
{
get
{
return losslessOrNot;
}
}
public BindingList Releases
{
get
{
return releases;
}
}
public BindingList Drives
{
get
{
return drives;
}
}
public BindingList Formats
{
get
{
return formats;
}
}
public BindingList Encoders
{
get
{
return encoders;
}
}
}
}