private static List <SmkFileInfo> SmkFilesIn(ExtractionPaths paths, BinaryReader reader)
        {
            reader.ReadBytes(4); // Magic word MFF
            uint headerCount = reader.ReadUInt32();

            var files = new List <SmkFileInfo>();

            for (int i = 0; i < headerCount; ++i)
            {
                string originalPath = DataExtractor.ReadString(reader.ReadBytes(256));
                uint   offset       = reader.ReadUInt32();

                reader.ReadBytes(4); // unknown data

                string outputPath = Path.Combine(
                    paths.OutputDirectory,
                    paths.OriginalFileName,
                    Path.GetDirectoryName(originalPath)
                    );

                files.Add(new SmkFileInfo()
                {
                    Offset       = offset,
                    OriginalPath = originalPath,
                    TempSmkPath  = Path.Combine(paths.TempDirectory, originalPath),
                    OutputPath   = outputPath
                });
            }

            return(files);
        }
        private static void ExportTableToTsv(
            ExtractionPaths path, OleDbConnection mdbConnection, string tableName)
        {
            string outputFileName = GenerateOutputPath(path, tableName);

            Directory.CreateDirectory(Path.GetDirectoryName(outputFileName));

            using (StreamWriter streamWriter = new StreamWriter(outputFileName))
            {
                string query = string.Format("Select * from [{0}]", tableName);
                using (OleDbCommand cmd = new OleDbCommand(query, mdbConnection))
                {
                    cmd.CommandType = CommandType.Text;

                    using (var dataReader = cmd.ExecuteReader())
                    {
                        var csvWriter = new CsvWriter(streamWriter, GetCsvConfig());
                        csvWriter.WriteFullRecord(GetHeaderValues(dataReader));

                        while (dataReader.Read())
                        {
                            csvWriter.WriteFullRecord(GetRowValues(dataReader));
                        }
                    }
                }
            }
        }
        public void Extract(ExtractionPaths paths, ProgressReporter progress = null)
        {
            using (var file = File.OpenRead(paths.OriginalFilePath))
                using (BinaryReader reader = new BinaryReader(file, Encoding.ASCII))
                {
                    var smkFiles = SmkFilesIn(paths, reader);

                    int extractionProgress = 0;

                    foreach (var smkFile in smkFiles)
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(smkFile.TempSmkPath));

                        ExtractSmkFile(file, reader, smkFile.Offset, smkFile.TempSmkPath);

                        progress?.Report(50 * (++extractionProgress + 1) / smkFiles.Count);
                    }

                    Parallel.ForEach(smkFiles, smkFile =>
                    {
                        m_smkExtractor.Extract(new ExtractionPaths
                        {
                            OriginalFilePath = smkFile.TempSmkPath,
                            OriginalFileName = Path.GetFileName(smkFile.OriginalPath),
                            OutputDirectory  = smkFile.OutputPath,
                            TempDirectory    = paths.TempDirectory,
                        });

                        progress?.Report(50 * (Interlocked.Increment(ref extractionProgress) + 1) / smkFiles.Count);
                    });
                }
        }
        public void Extract(ExtractionPaths path, ProgressReporter progress = null)
        {
            using (OleDbConnection mdbConnection = ConnectToMdbFile(path.OriginalFilePath))
            {
                var tables = GetTableNames(mdbConnection).ToList();
                for (int i = 0; i < tables.Count; i++)
                {
                    ExportTableToTsv(path, mdbConnection, tables[i]);

                    progress?.Report(100 * (i + 1) / tables.Count);
                }
            }
        }
        public void Extract(ExtractionPaths path, ProgressReporter progress = null)
        {
            using (var stream = File.OpenRead(path.OriginalFilePath))
                using (ZipArchive archive = new ZipArchive(stream))
                {
                    Directory.CreateDirectory(path.TempDirectory);

                    for (int i = 0; i < archive.Entries.Count; i++)
                    {
                        Extract(path, archive.Entries[i]);

                        progress?.Report(100 * (i + 1) / archive.Entries.Count);
                    }
                }
        }
        private void Extract(ExtractionPaths path, ZipArchiveEntry entry)
        {
            if (!entry.Name.Contains(".mdb", CompareOptions.IgnoreCase))
            {
                Console.WriteLine($"Ignoring {path.OriginalFileName}/{entry.Name}");
                return;
            }

            string mdbTempFilePath = Path.Combine(path.TempDirectory, entry.Name);

            entry.ExtractToFile(mdbTempFilePath);

            m_mdbExtractor.Extract(new ExtractionPaths
            {
                OriginalFilePath = mdbTempFilePath,
                OriginalFileName = entry.Name,
                OutputDirectory  = Path.Combine(path.OutputDirectory, path.OriginalFileName),
                TempDirectory    = path.TempDirectory,
            });
        }
        private void ReadAudioTrack(
            int track, ExtractionPaths paths, ProgressReporter progress)
        {
            Directory.CreateDirectory(paths.OutputDirectory);

            string     outputPath = GenerateOutputPath(paths, track - 1);
            ID3TagData metadata   = GenerateTrackMetadata(track - 1);

            using (var mp3Writer = new LameMP3FileWriter(
                       outputPath, new WaveFormat(), LAMEPreset.STANDARD, metadata))
            {
                CdDataReadEventHandler     onDataRead = (x, y) => OnDataRead(x, y, mp3Writer);
                CdReadProgressEventHandler onProgress = (x, y) => OnTrackProgress(x, y, progress);

                if (m_drive.ReadTrack(track, onDataRead, onProgress) == 0)
                {
                    throw new InvalidOperationException($"Cannot read track {track}");
                }
            }
        }
        public void Extract(ExtractionPaths paths, ProgressReporter progress = null)
        {
            char driveLetter = Path.GetFullPath(paths.OriginalFilePath)[0];

            if (!m_drive.Open(driveLetter))
            {
                throw new InvalidOperationException($"Cannot open drive {driveLetter}");
            }

            if (!m_drive.Refresh())
            {
                throw new InvalidOperationException($"Cannot refresh drive {driveLetter}");
            }

            var audioTracks = GetAudioTracks().ToList();

            progress?.AddSubProgress(audioTracks.Count);

            for (int i = 0; i < audioTracks.Count; i++)
            {
                ReadAudioTrack(audioTracks[i], paths, progress?[i]);
            }
        }
 private static string GenerateOutputPath(ExtractionPaths paths, string tableName)
 {
     return(Path.Combine(paths.OutputDirectory, paths.OriginalFileName, $"{tableName}.tsv"));
 }
        public unsafe void Extract(ExtractionPaths path, ProgressReporter progress = null)
        {
            AVFormatContext* formatContext = CreateFormatContext(path.OriginalFilePath);
            AVStream* stream = GetStream(formatContext);

            var destinationPixelFormat = AVPixelFormat.AV_PIX_FMT_BGR24;

            fixed (byte* convertedFrameBuffer = new byte[GetFrameSize(stream, destinationPixelFormat)])
            {
                var dstData = new byte_ptrArray4();
                var dstLinesize = new int_array4();

                ffmpeg.av_image_fill_arrays(ref dstData, ref dstLinesize, convertedFrameBuffer,
                    destinationPixelFormat, stream->codec->width, stream->codec->height, 1);

                OpenCodec(stream->codec);

                var decodedFrame = ffmpeg.av_frame_alloc();

                var packet = new AVPacket();
                ffmpeg.av_init_packet(&packet);

                SwsContext* convertContext = CreateConversionContext(stream, destinationPixelFormat);

                using (var bitmap = CreateBitmap(stream, PixelFormat.Format24bppRgb))
                {
                    Directory.CreateDirectory(Path.Combine(path.OutputDirectory, path.OriginalFileName));

                    long frameCount = stream->nb_frames;
                    for (int frame = 0; frame < frameCount || frameCount == 0; ++frame)
                    {
                        try
                        {
                            if (ffmpeg.av_read_frame(formatContext, &packet) < 0)
                            {
                                Console.WriteLine(@"Could not read frame");
                                break;
                            }

                            if (!DecodeFrame(stream, &packet, decodedFrame, frame))
                            {
                                continue;
                            }

                            ffmpeg.sws_scale(convertContext, decodedFrame->data,
                                decodedFrame->linesize, 0, stream->codec->height, dstData, dstLinesize);

                            SaveFrame(bitmap, GenerateOutputPath(path, frame),
                                dstLinesize[0], (IntPtr)convertedFrameBuffer);
                        }
                        finally
                        {
                            ffmpeg.av_packet_unref(&packet);
                            ffmpeg.av_frame_unref(decodedFrame);
                        }
                    }
                }

                ffmpeg.sws_freeContext(convertContext);

                ffmpeg.av_free(decodedFrame);
                ffmpeg.avcodec_close(stream->codec);
                ffmpeg.avformat_close_input(&formatContext);

                progress?.Report(100);
            }
        }
 private static string GenerateOutputPath(ExtractionPaths path, int frame)
 {
     return Path.Combine(path.OutputDirectory, path.OriginalFileName, $"{frame}.png");
 }
 private string GenerateOutputPath(ExtractionPaths paths, int track)
 {
     return(Path.Combine(paths.OutputDirectory, GetTrackName(track) + ".mp3"));
 }