private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            _midi = new Midi();

            _midi.OutputDevicesEnumerated += _midi_OutputDevicesEnumerated;
            _midi.InputDevicesEnumerated  += _midi_InputDevicesEnumerated;

            _midi.Initialize();
        }
        protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pExtractMidiStruct, DoWorkEventArgs e)
        {
            long headerOffset = 0;

            using (FileStream fs = File.OpenRead(pPath))
            {
                while ((headerOffset = ParseFile.GetNextOffset(fs, headerOffset, Midi.ASCII_SIGNATURE_MTHD)) > -1)
                {
                    Midi midiFile = new Midi();
                    midiFile.Initialize(fs, pPath, headerOffset);
                    midiFile.ExtractToFile(fs, Path.Combine(Path.GetDirectoryName(pPath), Path.GetFileNameWithoutExtension(pPath)));
                    headerOffset += 1;
                }
            }
        }
        protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pPspSeqDataFinderStruct, DoWorkEventArgs e)
        {
            PspSeqDataFinderStruct pspStruct = (PspSeqDataFinderStruct)pPspSeqDataFinderStruct;

            long offset;

            int        phdNumber = 0;
            PphdStruct phdObject;
            ArrayList  phdArrayList = new ArrayList();

            string midName;
            int    midNumber = 0;

            Psf.ProbableItemStruct midEntry;
            ArrayList midFiles = new ArrayList();
            bool      midNamingMessageDisplayed = false;
            Midi      midiFile = new Midi();

            Psf.ProbableItemStruct   potentialPbd;
            Psf.ProbableItemStruct[] potentialPbdList;
            byte[]    pbdRow       = new byte[Psf.SONY_ADPCM_ROW_SIZE];
            ArrayList emptyRowList = new ArrayList();

            // display file name
            this.progressStruct.Clear();
            this.progressStruct.GenericMessage = String.Format("[{0}]{1}", pPath, Environment.NewLine);
            this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct);

            // open file
            using (FileStream fs = File.OpenRead(pPath))
            {
                string destinationFolder = Path.Combine(Path.GetDirectoryName(pPath), Path.GetFileNameWithoutExtension(pPath));

                // get PHD files
                #region PHD EXTRACT
                this.progressStruct.Clear();
                this.progressStruct.GenericMessage = String.Format("  Extracting PHD{0}", Environment.NewLine);
                this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct);

                offset = 0;

                while ((offset = ParseFile.GetNextOffset(fs, offset, PPHD_SIGNATURE)) > -1)
                {
                    try
                    {
                        // get PPHD data
                        phdObject          = GetPphdData(fs, offset);
                        phdObject.FileName = String.Format("{0}_{1}.PHD", Path.GetFileNameWithoutExtension(pPath), phdNumber++.ToString("X4"));

                        // extract the file
                        ParseFile.ExtractChunkToFile(fs, offset, (int)phdObject.length,
                                                     Path.Combine(destinationFolder, phdObject.FileName), true, true);

                        // add to array
                        phdArrayList.Add(phdObject);
                    }
                    catch (Exception pphdEx)
                    {
                        this.progressStruct.Clear();
                        this.progressStruct.ErrorMessage = String.Format("      Error extracting PPHD at offset 0x{0}: {1}{2}", offset.ToString("X8"), pphdEx.Message, Environment.NewLine);
                        ReportProgress(progress, this.progressStruct);
                    }

                    // increment offset
                    offset += 1;
                }

                #endregion

                // get MID Files
                #region MID EXTRACT
                this.progressStruct.Clear();
                this.progressStruct.GenericMessage = String.Format("  Extracting MID{0}", Environment.NewLine);
                this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct);

                midEntry = new Psf.ProbableItemStruct();
                offset   = 0;

                // build file list
                while ((offset = ParseFile.GetNextOffset(fs, offset, Midi.ASCII_SIGNATURE_MTHD)) > -1)
                {
                    midiFile.Initialize(fs, pPath, offset);
                    midEntry.offset = midiFile.FileStartOffset;
                    midEntry.length = (uint)midiFile.TotalFileLength;
                    midFiles.Add(midEntry);

                    offset += 1;
                }

                foreach (Psf.ProbableItemStruct mid in midFiles)
                {
                    if (pspStruct.ReorderMidFiles)
                    {
                        if (phdArrayList.Count < midFiles.Count)
                        {
                            if (!midNamingMessageDisplayed)
                            {
                                this.progressStruct.Clear();
                                this.progressStruct.ErrorMessage = String.Format(
                                    "Warning, cannot reorder MID files, there are less PHD files than MID files.{0}", Environment.NewLine);
                                this.ReportProgress(this.progress, this.progressStruct);
                                midNamingMessageDisplayed = true;
                            }

                            midName = String.Format("{0}_{1}.MID", Path.GetFileNameWithoutExtension(pPath), midNumber++.ToString("X4"));
                        }
                        else
                        {
                            phdObject = (PphdStruct)phdArrayList[phdArrayList.Count - midFiles.Count + midNumber++];
                            midName   = Path.ChangeExtension(phdObject.FileName, ".MID");
                        }
                    }
                    else
                    {
                        midName = String.Format("{0}_{1}.MID", Path.GetFileNameWithoutExtension(pPath), midNumber++.ToString("X4"));
                    }

                    ParseFile.ExtractChunkToFile(fs, mid.offset, (int)mid.length,
                                                 Path.Combine(destinationFolder, midName), true, true);
                }
                #endregion

                // get PBD files
                #region PBD EXTRACT
                this.progressStruct.Clear();
                this.progressStruct.GenericMessage = String.Format("  Extracting PBD...WARNING, THIS CAN TAKE A LONG TIME...{0}", Environment.NewLine);
                this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct);

                offset = 0;

                // build list of potential adpcm start indexes
                potentialPbd = new Psf.ProbableItemStruct();

                // build list of potential adpcm start indexes
                while ((offset = ParseFile.GetNextOffset(fs, offset, Psf.VB_START_BYTES, pspStruct.UseZeroOffsetForPbd, 0x10L, 0x00L, true)) > -1)
                {
                    try
                    {
                        pbdRow = ParseFile.ParseSimpleOffset(fs, offset, pbdRow.Length);

                        if (Psf.IsPotentialAdpcm(fs, offset + 0x10, Psf.MIN_ADPCM_ROW_COUNT, false))
                        {
                            potentialPbd.offset = offset;
                            emptyRowList.Add(potentialPbd);
                        }
                    }
                    catch (Exception pbdEx)
                    {
                        this.progressStruct.Clear();
                        this.progressStruct.ErrorMessage = String.Format(" ERROR finding BD for <{0}> at Offset 0x{1}: {2}{3}", pPath, offset.ToString("X8"), pbdEx.Message, Environment.NewLine);
                        this.ReportProgress(this.progress, this.progressStruct);
                    }

                    offset += 1;
                }

                potentialPbdList = (Psf.ProbableItemStruct[])emptyRowList.ToArray(typeof(Psf.ProbableItemStruct));

                // set probable lengths
                for (int i = 0; i < potentialPbdList.Length; i++)
                {
                    if (i > 0)
                    {
                        potentialPbdList[i - 1].length = (uint)(potentialPbdList[i].offset - potentialPbdList[i - 1].offset);
                    }
                }

                // compare PHD sample sizes to potential adpcm sizes/indexes
                phdObject.startingOffset    = 0;
                phdObject.length            = 0;
                phdObject.pbdStartingOffset = 0;
                phdObject.pbdLength         = 0;

                string   pbdName;
                string   newFileName;
                string[] dupeFileNames;

                for (int i = 0; i < phdArrayList.Count; i++)
                {
                    phdObject = (PphdStruct)phdArrayList[i];
                    if (phdObject.vagLengths.Length < 1)
                    {
                        this.progressStruct.Clear();
                        this.progressStruct.ErrorMessage = String.Format(" ERROR building PBD for <{0}>: {1} refers to a single VAG, cannot determine proper PBD.  Skipping...{2}", pPath, phdObject.FileName, Environment.NewLine);
                        this.ReportProgress(this.progress, this.progressStruct);
                    }
                    else
                    {
                        for (int j = 0; j < potentialPbdList.Length; j++)
                        {
                            // we have a potential match or are at the last item.
                            if ((phdObject.vagLengths[0] <= potentialPbdList[j].length) ||
                                (potentialPbdList[j].length == 0))
                            {
                                try
                                {
                                    phdObject = PopulatePbdOffsetLength(fs, potentialPbdList, j, phdObject);

                                    if (phdObject.pbdLength > 0)
                                    {
                                        // check for other BD files that matched and rename accordingly
                                        dupeFileNames = Directory.GetFiles(destinationFolder, Path.GetFileNameWithoutExtension(phdObject.FileName) + "*.PBD");

                                        if (dupeFileNames.Length >= 1)
                                        {
                                            pbdName = String.Format("{0}_{1}.PBD", Path.GetFileNameWithoutExtension(phdObject.FileName), (dupeFileNames.Length).ToString("X4"));

                                            if (dupeFileNames.Length == 1)
                                            {
                                                // rename existing
                                                newFileName = String.Format("{0}_{1}.PBD", Path.GetFileNameWithoutExtension(phdObject.FileName), (dupeFileNames.Length - 1).ToString("X4"));
                                                File.Move(dupeFileNames[0], Path.Combine(Path.GetDirectoryName(dupeFileNames[0]), newFileName));
                                            }
                                        }
                                        else
                                        {
                                            pbdName = Path.ChangeExtension(phdObject.FileName, ".PBD");
                                        }


                                        ParseFile.ExtractChunkToFile(fs, phdObject.pbdStartingOffset, phdObject.pbdLength,
                                                                     Path.Combine(destinationFolder, pbdName), true, true);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    this.progressStruct.Clear();
                                    this.progressStruct.ErrorMessage = String.Format("     ERROR building BD for <{0}>: {1}{2}", pPath, ex.Message, Environment.NewLine);
                                    this.ReportProgress(this.progress, this.progressStruct);
                                }
                            }
                        }
                    }
                }

                #endregion
            }
        }