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<Krystalware.UploadHelper.UploadProgressEventArgs>(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<Release> results = Release.Query(p);
                //MusicBrainzService.Proxy = _config.GetProxy();
                //MusicBrainzService.XmlRequest += new EventHandler<XmlRequestEventArgs>(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<XmlRequestEventArgs>(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 });
            });
        }
        public List<object> LookupAlbumInfo(bool useCache, bool useCUE, bool useCTDB, CTDBMetadataSearch metadataSearch)
        {
            List<object> Releases = new List<object>();

            CUEMetadata dbmeta = null;

            if (useCache && _localDB != null)
            {
                List<string> fullAudioPaths = this.SourcePaths.ConvertAll(p => CUEToolsLocalDBEntry.NormalizePath(p));
                var myEntry = _localDB.Find(e => e.Equals(this.TOC, fullAudioPaths));
                if (myEntry != null)
                    dbmeta = myEntry.Metadata;
            }

            if (dbmeta != null)
                Releases.Add(new CUEMetadataEntry(dbmeta, TOC, "local"));

            //if (useCache)
            //{
            //    try
            //    {
            //        CUEMetadata cache = CUEMetadata.Load(TOC.TOCID);
            //        if (cache != null)
            //            Releases.Add(new CUEMetadataEntry(cache, TOC, "local"));
            //    }
            //    catch (Exception ex)
            //    {
            //        System.Diagnostics.Trace.WriteLine(ex.Message);
            //    }
            //}

            if (useCUE)
            {
                if (dbmeta == null || !dbmeta.Contains(cueMetadata))
                {
                    if (cueMetadata.Contains(taglibMetadata) || !taglibMetadata.Contains(cueMetadata))
                        Releases.Add(new CUEMetadataEntry(new CUEMetadata(cueMetadata), TOC, "cue"));
                }
                if (dbmeta == null || !dbmeta.Contains(taglibMetadata))
                {
                    if (!cueMetadata.Contains(taglibMetadata))
                        Releases.Add(new CUEMetadataEntry(new CUEMetadata(taglibMetadata), TOC, "tags"));
                }
            }

            if (useCache && _localDB != null)
            {
                foreach (var entry in _localDB)
                    if (entry.DiscID == TOC.TOCID && entry.Metadata != null && (dbmeta == null || !dbmeta.Contains(entry.Metadata)))
                        Releases.Add(new CUEMetadataEntry(entry.Metadata, TOC, "local"));
            }

            bool ctdbFound = false;
            if (useCTDB)
            {
                ShowProgress("Looking up album via CTDB...", 0.0, null, null);
                var ctdb = new CUEToolsDB(TOC, proxy);
                ctdb.ContactDB(_config.advanced.CTDBServer, "CUETools " + CUEToolsVersion, null, false, false, metadataSearch);
                foreach (var meta in ctdb.Metadata)
                {
                    CUEMetadata metadata = new CUEMetadata(TOC.TOCID, (int)TOC.AudioTracks);
                    metadata.FillFromCtdb(meta, TOC.FirstAudio - 1);
                    CDImageLayout toc = TOC; //  TocFromCDEntry(meta);
                    Releases.Add(new CUEMetadataEntry(metadata, toc, meta.source));
                    ctdbFound = true;
                }
            }

            if (!ctdbFound && metadataSearch == CTDBMetadataSearch.Extensive)
            {
                ShowProgress("Looking up album via Freedb...", 0.0, null, null);

                FreedbHelper m_freedb = new FreedbHelper();
                m_freedb.Proxy = proxy;
                m_freedb.UserName = _config.advanced.FreedbUser;
                m_freedb.Hostname = _config.advanced.FreedbDomain;
                m_freedb.ClientName = "CUETools";
                m_freedb.Version = CUEToolsVersion;
                m_freedb.SetDefaultSiteAddress("freedb.org");

                QueryResult queryResult;
                QueryResultCollection coll;
                string code = string.Empty;
                try
                {
                    CDEntry cdEntry = null;
                    code = m_freedb.Query(AccurateRipVerify.CalculateCDDBQuery(_toc), out queryResult, out coll);
                    if (code == FreedbHelper.ResponseCodes.CODE_200)
                    {
                        ShowProgress("Looking up album via Freedb... " + queryResult.Discid, 0.5, null, null);
                        code = m_freedb.Read(queryResult, out cdEntry);
                        if (code == FreedbHelper.ResponseCodes.CODE_210)
                        {
                            CUEMetadata metadata = new CUEMetadata(TOC.TOCID, (int)TOC.AudioTracks);
                            metadata.FillFromFreedb(cdEntry, TOC.FirstAudio - 1);
                            CDImageLayout toc = TocFromCDEntry(cdEntry);
                            Releases.Add(new CUEMetadataEntry(metadata, toc, "freedb"));
                        }
                    }
                    else
                        if (code == FreedbHelper.ResponseCodes.CODE_210 ||
                            code == FreedbHelper.ResponseCodes.CODE_211)
                        {
                            int i = 0;
                            foreach (QueryResult qr in coll)
                            {
                                ShowProgress("Looking up album via freedb... " + qr.Discid, (++i + 0.0) / coll.Count, null, null);
                                CheckStop();
                                code = m_freedb.Read(qr, out cdEntry);
                                if (code == FreedbHelper.ResponseCodes.CODE_210)
                                {
                                    CUEMetadata metadata = new CUEMetadata(TOC.TOCID, (int)TOC.AudioTracks);
                                    metadata.FillFromFreedb(cdEntry, TOC.FirstAudio - 1);
                                    CDImageLayout toc = TocFromCDEntry(cdEntry);
                                    Releases.Add(new CUEMetadataEntry(metadata, toc, "freedb"));
                                }
                            }
                        }
                }
                catch (Exception ex)
                {
                    if (ex is StopException)
                        throw ex;
                }
            }

            ShowProgress("", 0, null, null);
            return Releases;
        }
		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);
            }
            /*
			foreach (CUETrackMetadata t in data.selectedRelease.metadata.Tracks)
			{
				Freedb.Track tt = new Freedb.Track();
				if (t.Artist != "" && t.Artist != entry.Artist)
					tt.Title = t.Artist + " / " + t.Title;
				else
					tt.Title = t.Title;
				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(); });
		}