private void buttonExtract_Click(object sender, RoutedEventArgs e)
        {
            if (cmbTitleSet.SelectedItem == null)
            {
                return;
            }
            pid              = ((CUETools.Codecs.MPEG.MPLS.MPLSStream)cmbAudioTrack.SelectedItem).pid;
            chosenReader     = cmbTitleSet.SelectedItem as CUETools.Codecs.MPEG.MPLS.AudioDecoder;
            metaresult       = cmbMetadata.SelectedItem as CUEMetadataEntry;
            outputFolderPath = Path.Combine(textBoxDestination.Text, metaresult != null ?
                                            metaresult.metadata.Artist + " - " + metaresult.metadata.Year + " - " + metaresult.metadata.Title :
                                            Path.GetFileName(textBoxSource.Text) + "." + chosenReader.FileName + "." + pid.ToString());
            outputAudioPath = Path.Combine(outputFolderPath, metaresult != null ? metaresult.metadata.Artist + " - " + metaresult.metadata.Year + " - " + metaresult.metadata.Title + ".flac" : "image.flac");
            outputCuePath   = Path.ChangeExtension(outputAudioPath, "cue");

            pbStatus.Visibility = Visibility.Visible;
            pbStatus.Value      = 0.0;
            //pbStatus.IsIndeterminate = true;
            stackParams.IsEnabled    = false;
            buttonExtract.IsEnabled  = false;
            buttonExtract.Visibility = Visibility.Hidden;
            buttonStop.Visibility    = Visibility.Visible;
            buttonStop.IsEnabled     = true;

            workerExtract = new BackgroundWorker();
            workerExtract.WorkerSupportsCancellation = true;
            workerExtract.DoWork += workerExtract_DoWork;
            workerExtract.RunWorkerAsync();
        }
        private void textBoxSource_TextChanged(object sender, TextChangedEventArgs e)
        {
            var titleSets = new List <CUETools.Codecs.MPEG.MPLS.AudioDecoder>();
            IEnumerable <string> playlists = null;

            try
            {
                playlists = Directory.EnumerateFiles(Path.Combine(Path.Combine(textBoxSource.Text, "BDMV"), "PLAYLIST")).OrderBy(f => f);
            }
            catch
            {
            }
            if (playlists != null)
            {
                foreach (var playlist in playlists)
                {
                    var title = new CUETools.Codecs.MPEG.MPLS.AudioDecoder(new CUETools.Codecs.MPEG.MPLS.DecoderSettings(), playlist, null);
                    if (filterDups)
                    {
                        if (titleSets.Exists(title2 =>
                                             title.MPLSHeader.play_item.Count == title2.MPLSHeader.play_item.Count &&
                                             Enumerable.Range(0, title.MPLSHeader.play_item.Count).ToList().TrueForAll(i =>
                        {
                            var i1 = title.MPLSHeader.play_item[i];
                            var i2 = title2.MPLSHeader.play_item[i];
                            return(i1.clip_id == i2.clip_id && i1.in_time == i2.in_time && i1.out_time == i2.out_time);
                        })
                                             ))
                        {
                            continue;
                        }
                    }

                    if (filterRepeats > 1)
                    {
                        if (title.MPLSHeader.play_item.GroupBy(clip => clip.clip_id).Select(grp => grp.Count()).Max() > filterRepeats)
                        {
                            continue;
                        }
                    }

                    if (filterShort > 0)
                    {
                        if (title.Duration.TotalSeconds < filterShort)
                        {
                            continue;
                        }
                    }

                    titleSets.Add(title);
                }
            }
            cmbTitleSet.ItemsSource   = titleSets;
            cmbTitleSet.SelectedIndex = 0;
        }
        void workerExtract_DoWork(object sender, DoWorkEventArgs e)
        {
            CUETools.Codecs.MPEG.MPLS.AudioDecoder reader = null;
            try
            {
                reader = new CUETools.Codecs.MPEG.MPLS.AudioDecoder(chosenReader.Path, null, pid);
                Directory.CreateDirectory(outputFolderPath);
                if (File.Exists(outputCuePath))
                {
                    throw new Exception(string.Format("File \"{0}\" already exists", outputCuePath));
                }
                if (File.Exists(outputAudioPath))
                {
                    throw new Exception(string.Format("File \"{0}\" already exists", outputAudioPath));
                }
                AudioBuffer buff = new AudioBuffer(reader, 0x10000);
                CUETools.Codecs.Flake.EncoderSettings settings = new CUETools.Codecs.Flake.EncoderSettings()
                {
                    PCM         = reader.PCM,
                    Padding     = 16536,
                    EncoderMode = "5"
                };
                if (ctdb != null)
                {
                    using (StreamWriter cueWriter = new StreamWriter(outputCuePath, false, Encoding.UTF8))
                    {
                        cueWriter.WriteLine("REM COMMENT \"{0}\"", "Created by CUETools.eac3to");
                        if (metaresult != null && metaresult.metadata.Year != "")
                        {
                            cueWriter.WriteLine("REM DATE {0}", metaresult.metadata.Year);
                        }
                        else
                        {
                            cueWriter.WriteLine("REM DATE XXXX");
                        }
                        if (metaresult != null)
                        {
                            cueWriter.WriteLine("PERFORMER \"{0}\"", metaresult.metadata.Artist);
                            cueWriter.WriteLine("TITLE \"{0}\"", metaresult.metadata.Title);
                        }
                        else
                        {
                            cueWriter.WriteLine("PERFORMER \"\"");
                            cueWriter.WriteLine("TITLE \"\"");
                        }
                        cueWriter.WriteLine("FILE \"{0}\" WAVE", Path.GetFileName(outputAudioPath));
                        var toc = ctdb.TOC;
                        for (int track = 1; track <= toc.TrackCount; track++)
                        {
                            if (toc[track].IsAudio)
                            {
                                cueWriter.WriteLine("  TRACK {0:00} AUDIO", toc[track].Number);
                                if (metaresult != null && metaresult.metadata.Tracks.Count >= toc[track].Number)
                                {
                                    cueWriter.WriteLine("    TITLE \"{0}\"", metaresult.metadata.Tracks[(int)toc[track].Number - 1].Title);
                                    if (metaresult.metadata.Tracks[(int)toc[track].Number - 1].Artist != "")
                                    {
                                        cueWriter.WriteLine("    PERFORMER \"{0}\"", metaresult.metadata.Tracks[(int)toc[track].Number - 1].Artist);
                                    }
                                }
                                else
                                {
                                    cueWriter.WriteLine("    TITLE \"\"");
                                }
                                if (toc[track].ISRC != null)
                                {
                                    cueWriter.WriteLine("    ISRC {0}", toc[track].ISRC);
                                }
                                for (int index = toc[track].Pregap > 0 ? 0 : 1; index <= toc[track].LastIndex; index++)
                                {
                                    cueWriter.WriteLine("    INDEX {0:00} {1}", index, toc[track][index].MSF);
                                }
                            }
                        }
                    }
                }
                var      start     = DateTime.Now;
                TimeSpan lastPrint = TimeSpan.FromMilliseconds(0);
                var      writer    = new CUETools.Codecs.Flake.AudioEncoder(settings, outputAudioPath);
                try
                {
                    while (reader.Read(buff, -1) != 0)
                    {
                        writer.Write(buff);
                        TimeSpan elapsed = DateTime.Now - start;
                        if ((elapsed - lastPrint).TotalMilliseconds > 60)
                        {
                            long length = Math.Max((long)(reader.Duration.TotalSeconds * reader.PCM.SampleRate), Math.Max(reader.Position, 1));
                            this.Dispatcher.Invoke((Action)(() =>
                            {
                                pbStatus.Value = 100.0 * reader.Position / length;
                            }));
                            lastPrint = elapsed;
                        }
                        if (workerExtract.CancellationPending)
                        {
                            throw new Exception("aborted");
                        }
                    }
                }
                catch (Exception ex)
                {
                    writer.Delete();
                    try { File.Delete(outputCuePath); } catch (Exception) { }
                    throw ex;
                }
                writer.Close();
            }
            catch (Exception ex)
            {
                this.Dispatcher.Invoke((Action)(() =>
                {
                    MessageBox.Show(this, ex.Message, "Extraction failed");
                }));
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }

            this.Dispatcher.Invoke((Action)(() =>
            {
                pbStatus.Visibility = Visibility.Collapsed;
                //pbStatus.IsIndeterminate = false;
                stackParams.IsEnabled = true;
                buttonExtract.IsEnabled = true;
                buttonExtract.Visibility = Visibility.Visible;
                buttonStop.Visibility = Visibility.Hidden;
                buttonStop.IsEnabled = false;
            }));
        }