Пример #1
0
        }// -----------------------------------------

        // --
        public override void start()
        {
            base.start();

            p = (RestoreParams)jobData;

            INPUT             = Path.Combine(p.tempDir, track.storedFileName);
            OUTPUT            = Path.Combine(p.tempDir, track.getFilenameRaw());
            track.workingFile = OUTPUT;     // Point to the new file

            // -
            var fileExt = Path.GetExtension(track.storedFileName);

            requirePostSizeFix = AudioMaster.isLossyByExt(fileExt);

            // --
            if (track.isData)
            {
                var ecm = new EcmTools(CDCRUSH.TOOLS_PATH);
                setupHandlers(ecm);
                ecm.unecm(INPUT);
            }
            else
            {
                // No need to convert back, end the task
                if (p.mode == 2)
                {
                    // Point to correct file
                    track.workingFile = INPUT;
                    complete();
                    return;
                }

                var ffmp = new FFmpeg(CDCRUSH.FFMPEG_PATH);

                if (fileExt.ToLower() == ".tak")
                {
                    var tak = new Tak(CDCRUSH.TOOLS_PATH);
                    setupHandlers(tak);

                    tak.decodeToStream(INPUT, (_out) => {
                        ffmp.convertWavStreamToPCM(OUTPUT, (_in) => {
                            _out.CopyTo(_in);
                            _in.Close();
                        });
                    });
                }
                else
                {
                    setupHandlers(ffmp);
                    ffmp.audioToPCM(INPUT, track.workingFile);
                }
            }

            log("Restoring track -" + track.storedFileName);
        }// -----------------------------------------
Пример #2
0
        }// -----------------------------------------

        // -
        public override void start()
        {
            RestoreParams p = jobData;

            LOG.line();
            LOG.log("=== RESTORING A CD with the following parameters :");
            LOG.log("- Input : {0}", p.inputFile);
            LOG.log("- Output Dir : {0}", p.outputDir);
            LOG.log("- Temp Dir : {0}", p.tempDir);
            LOG.log("- Force Single bin : {0}", p.flag_forceSingle);
            LOG.log("- Create subfolder : {0}", p.flag_folder);
            LOG.log("- Restore to encoded audio/.cue : {0}", p.flag_encCue);
            base.start();
        }// -----------------------------------------
Пример #3
0
        /// <summary>
        /// RESTORE An Archive file to target output folder
        /// </summary>
        /// <param name="_Input">Input file, Must be `.arc`</param>
        /// <param name="_Output">Output folder, If null, it will be same as input file folder</param>
        /// <param name="_Flag_Folder">Extract files to a subfolder of `_output`</param>
        /// <param name="_Mode">0: Normal, 1:Merge, 2:Restore To EncAudio</param>
        /// <param name="onComplete">(completeStatus)</param>
        /// <returns>Preliminary  Success</returns>
        public static bool startJob_RestoreCD(
            string _Input,
            string _Output,
            bool _Flag_Folder,
            int _Mode,
            Action <bool> onComplete)
        {
            // NOTE : JOB checks for input file
            if (LOCKED)
            {
                ERROR = "Engine is working"; return(false);
            }
            if (!FFMPEG_OK)
            {
                ERROR = "FFmpeg is not set"; return(false);
            }

            LOCKED = true;

            var par = new RestoreParams {
                inputFile      = _Input,                // Checked in the JOB
                outputDir      = _Output,               // Checked in the JOB
                flag_folder    = _Flag_Folder,
                mode           = _Mode,
                expectedTracks = HACK_CD_TRACKS
            };

            var j = new JobRestore(par);

            j.MAX_CONCURRENT = MAX_TASKS;
            j.onJobStatus    = jobStatusHandler;                        // For status and progress updates
            j.onComplete     = (s) =>
            {
                LOCKED = false;
                ERROR  = j.ERROR[1];
                onComplete(s);
            };

            j.start();

            return(true);
        }        // -----------------------------------------
Пример #4
0
        }// -----------------------------------------

        /// <summary>
        /// Called on FAIL / COMPLETE / PROGRAM EXIT
        /// Clean up temporary files
        /// </summary>
        protected override void kill()
        {
            base.kill();

            if (CDCRUSH.FLAG_KEEP_TEMP)
            {
                return;
            }

            RestoreParams p = jobData;

            if (p.tempDir != p.outputDir)      // NOTE: This is always a subdir of the master temp dir
            {
                try {
                    Directory.Delete(p.tempDir, true);
                }catch (IOException) {
                    // do nothing
                }
            }    // --
        }// -----------------------------------------
Пример #5
0
        }        // -----------------------------------------

        /// <summary>
        /// RESTORE an arc file to target output folder
        /// </summary>
        /// <param name="_Input">Input file, Must be `.arc`</param>
        /// <param name="_Output">Output folder, If null, it will be same as input file folder</param>
        /// <param name="onComplete">(completeStatus)</param>
        /// <returns></returns>
        public static bool restoreARC(string _Input, string _Output,
                                      bool flag_folder, bool flag_forceSingle, Action <bool> onComplete)
        {
            // NOTE : JOB checks for input file
            if (LOCKED)
            {
                ERROR = "Engine is working"; return(false);
            }
            if (!FFMPEG_OK)
            {
                ERROR = "FFmpeg is not set"; return(false);
            }

            LOCKED = true;

            var par = new RestoreParams {
                inputFile        = _Input,              // Checked in the JOB
                outputDir        = _Output,             // Checked in the JOB
                flag_folder      = flag_folder,
                flag_forceSingle = flag_forceSingle     // SINGLE FILE
            };

            var j = new JobRestore(par);

            j.MAX_CONCURRENT = MAX_TASKS;
            j.onComplete     = (s) =>
            {
                LOCKED = false;
                ERROR  = j.ERROR[1];
                onComplete(s);
            };

            j.onJobStatus = jobStatusHandler;                           // For status and progress updates
            j.start();

            return(true);
        }        // -----------------------------------------
Пример #6
0
        }// -----------------------------------------

        // --
        public override void start()
        {
            base.start();

            p = (RestoreParams)jobData;

            log("Restoring track -" + track.storedFileName);

            // --
            crushedTrackPath = Path.Combine(p.tempDir, track.storedFileName);
            // Set the final track pathname now, I need this for later.
            track.workingFile = Path.Combine(p.tempDir, track.getFilenameRaw());

            // --
            if (track.isData)
            {
                var ecm = new EcmTools(CDCRUSH.TOOLS_PATH);
                ecm.onComplete = (s) => {
                    if (s)
                    {
                        deleteOldFile();
                        if (!checkTrackMD5())
                        {
                            fail(msg: "MD5 checksum is wrong!");
                            return;
                        }
                        complete();
                    }
                    else
                    {
                        fail(msg: ecm.ERROR);
                    }
                };
                ecm.unecm(crushedTrackPath);
                killExtra = () => ecm.kill();
            }
            else
            {
                if (Path.GetExtension(track.storedFileName) == ".ogg")
                {
                    isOgg = true;
                }
                else
                {
                    isFlac = true;             // must be flac
                }

                var ffmp = new FFmpeg(CDCRUSH.FFMPEG_PATH);
                ffmp.onComplete = (s) => {
                    if (s)
                    {
                        deleteOldFile();                 // Don't need it
                        if (isOgg)
                        {
                            correctPCMSize();
                        }
                        if (isFlac)
                        {
                            if (!checkTrackMD5())
                            {
                                fail(msg: "MD5 checksum is wrong!");
                                return;
                            }
                        }
                        complete();
                    }
                    else
                    {
                        fail(msg: ffmp.ERROR);
                    }
                };

                ffmp.audioToPCM(crushedTrackPath);
                killExtra = () => ffmp.kill();
            }
        }// -----------------------------------------
Пример #7
0
        // --
        public JobRestore(RestoreParams p) : base("Restore CD")
        {
            // Check for input files
            // --------------------

            if (!CDCRUSH.check_file_(p.inputFile, CDCRUSH.CDCRUSH_EXTENSION))
            {
                fail(msg: CDCRUSH.ERROR);
                return;
            }

            if (string.IsNullOrEmpty(p.outputDir))
            {
                p.outputDir = Path.GetDirectoryName(p.inputFile);
            }

            // -- Output folder check
            if (p.flag_folder)
            {
                p.outputDir = CDCRUSH.checkCreateUniqueOutput(p.outputDir, Path.GetFileNameWithoutExtension(p.inputFile));
                if (p.outputDir == null)
                {
                    fail("Output Dir Error " + p.outputDir);
                    return;
                }
            }
            else
            {
                if (!FileTools.createDirectory(p.outputDir))
                {
                    fail(msg: "Can't create Output Dir " + p.outputDir);
                    return;
                }
            }

            // --
            p.tempDir = Path.Combine(CDCRUSH.TEMP_FOLDER, Guid.NewGuid().ToString().Substring(0, 12));
            if (!FileTools.createDirectory(p.tempDir))
            {
                fail(msg: "Can't create TEMP dir");
                return;
            }

            // Safeguard, even if the GUI doesn't allow it
            if (p.flag_encCue)
            {
                p.flag_forceSingle = false;
            }

            // IMPORTANT!! sharedData gets set by value, NOT A POINTER, do not make changes to p after this
            jobData = p;

            // --
            hack_setExpectedProgTracks(p.expectedTracks + 3);

            // - Extract the Archive
            // -----------------------
            add(new CTask((t) => {
                var arc = new FreeArc(CDCRUSH.TOOLS_PATH);
                t.handleCliReport(arc);
                arc.extractAll(p.inputFile, p.tempDir);
                arc.onProgress = (pr) => t.PROGRESS = pr;
                // In case the operation is aborted
                t.killExtra = () => {
                    arc.kill();
                };
            }, "Extracting", "Extracting the archive to temp folder"));

            //  - Read JSON data
            //  - Restore tracks
            //  - JOIN if it has to
            // -----------------------
            add(new CTask((t) => {
                var cd = new CueReader(); jobData.cd = cd;

                // --
                if (!cd.loadJson(Path.Combine(p.tempDir, CDCRUSH.CDCRUSH_SETTINGS)))
                {
                    t.fail(msg: cd.ERROR);
                    return;
                }

                LOG.log("== Detailed CD INFOS ==");
                LOG.log(cd.getDetailedInfo());

                // - Push TASK RESTORE tasks right after this one
                foreach (CueTrack tr in cd.tracks)
                {
                    addNextAsync(new TaskRestoreTrack(tr)); // Note: Task will take care of encoded cue case
                }                                           //--

                t.complete();
            }, "-Preparing to Restore", "Reading stored CD info and preparing track restore tasks"));



            // - Join Tracks, but only when not creating .Cue/Enc Audio
            // -----------------------
            if (!p.flag_encCue)
            {
                add(new CTask((t) => {
                    CueReader cd = jobData.cd;
                    // -- Join tracks
                    if (p.flag_forceSingle || !cd.MULTIFILE)
                    {
                        // The task will read data from the shared job data var
                        // Will join all tracks in place into track01.bin
                        // Note: Sets track.workingFile to null to moved track
                        addNext(new TaskJoinTrackFiles());
                    }    //--

                    t.complete();
                }, "-Preparing to Join"));
            }


            // - Prepare tracks `trackfile` which is the track written to the CUE
            // - Convert tracks
            // - Move files to final destination
            // - Create CUE files
            // - Delete Temp Files
            // -----------------------
            add(new CTask((t) => {
                CueReader cd = jobData.cd;

                int progressStep = (int)Math.Round(100.0f / cd.tracks.Count);
                // --
                foreach (var track in cd.tracks)
                {
                    if (p.flag_encCue)
                    {
                        string ext = Path.GetExtension(track.workingFile);
                        if (cd.tracks.Count == 1)
                        {
                            track.trackFile = $"{cd.CD_TITLE}{ext}";
                        }
                        else
                        {
                            track.trackFile = $"{cd.CD_TITLE} (track {track.trackNo}){ext}";
                        }
                        if (!cd.MULTIFILE)
                        {
                            track.setNewTimesReset();                               // :: CONVERTS SINGLE TO MULTI
                        }
                    }
                    else
                    {
                        if (p.flag_forceSingle && cd.MULTIFILE)                // :: CONVERT MULTI TO SINGLE
                        {
                            track.setNewTimesBasedOnSector();
                        }

                        if (cd.MULTIFILE && !p.flag_forceSingle)
                        {
                            track.trackFile = cd.CD_TITLE + " " + track.getFilenameRaw();
                        }

                        if (!cd.MULTIFILE || p.flag_forceSingle)
                        {
                            if (track.trackNo == 1)
                            {
                                track.trackFile = cd.CD_TITLE + ".bin";
                            }
                            else
                            {
                                track.trackFile = null;
                            }
                        }
                    }
                    // --
                    // Move ALL files to final output folder
                    // NULL workingFile means that is has been deleted
                    if (track.workingFile != null)
                    {
                        FileTools.tryMove(track.workingFile, Path.Combine(p.outputDir, track.trackFile));
                        t.PROGRESS += progressStep;
                    }
                }        // -- end track processing

                // --
                // Create CUE File
                if (!cd.saveCUE(Path.Combine(p.outputDir, cd.CD_TITLE + ".cue")))
                {
                    t.fail(cd.ERROR); return;
                }

                t.complete();
            }, "Moving, Finalizing", "Calculating track data and creating .CUE"));

            // - Complete -
        }// -----------------------------------------
Пример #8
0
        }// -----------------------------------------

        // --
        public override void start()
        {
            base.start();

            p = (RestoreParams)jobData;

            // --
            crushedTrackPath = Path.Combine(p.tempDir, track.storedFileName);
            // Set the final track pathname now, I need this for later.
            track.workingFile = Path.Combine(p.tempDir, track.getFilenameRaw());

            // --
            if (track.isData)
            {
                var ecm = new EcmTools(CDCRUSH.TOOLS_PATH);
                ecm.onComplete = (s) => {
                    ecm.onProgress = handleProgress;
                    if (s)
                    {
                        deleteOldFile();
                        if (!checkTrackMD5())
                        {
                            fail(msg: "MD5 checksum is wrong!");
                            return;
                        }
                        complete();
                    }
                    else
                    {
                        fail(msg: ecm.ERROR);
                    }
                };
                ecm.unecm(crushedTrackPath);
                killExtra = () => ecm.kill();
            }
            else
            {
                // No need to convert back
                if (p.flag_encCue)
                {
                    // Fix current file
                    track.workingFile = crushedTrackPath;
                    complete();
                    return;
                }

                // --
                isFlac = (Path.GetExtension(track.storedFileName) == ".flac");

                var ffmp = new FFmpeg(CDCRUSH.FFMPEG_PATH);
                ffmp.onProgress = handleProgress;
                ffmp.onComplete = (s) => {
                    if (s)
                    {
                        deleteOldFile();                 // Don't need it
                        if (!isFlac)
                        {
                            // OGG and MP3 don't restore to the exact byte length
                            correctPCMSize();
                        }
                        else
                        {
                            // FLAC restores to exact bytes
                            if (!checkTrackMD5())
                            {
                                fail(msg: "MD5 checksum is wrong!");
                                return;
                            }
                        }
                        complete();
                    }
                    else
                    {
                        fail(msg: ffmp.ERROR);
                    }
                };

                ffmp.audioToPCM(crushedTrackPath);
                killExtra = () => ffmp.kill();
            }

            log("Restoring track -" + track.storedFileName);
        }// -----------------------------------------
Пример #9
0
        // --
        public JobRestore(RestoreParams p) : base("Restore CD")
        {
            // Check for input files
            // :: --------------------

            if (!CDCRUSH.check_file_(p.inputFile, CDCRUSH.CDCRUSH_EXTENSION))
            {
                fail(msg: CDCRUSH.ERROR);
                return;
            }

            if (string.IsNullOrEmpty(p.outputDir))
            {
                p.outputDir = Path.GetDirectoryName(p.inputFile);
            }

            if (p.flag_folder)
            {
                try {
                    p.outputDir = Path.Combine(p.outputDir, Path.GetFileNameWithoutExtension(p.inputFile));
                }
                catch (ArgumentException) {
                    fail("Output Dir Error " + p.outputDir);
                    return;
                }
            }

            if (!FileTools.createDirectory(p.outputDir))
            {
                fail(msg: "Can't create Output Dir " + p.outputDir);
                return;
            }

            p.tempDir = Path.Combine(CDCRUSH.TEMP_FOLDER, Guid.NewGuid().ToString().Substring(0, 12));
            if (!FileTools.createDirectory(p.tempDir))
            {
                fail(msg: "Can't create TEMP dir");
                return;
            }

            // IMPORTANT!! sharedData gets set by value, NOT A POINTER, do not make changes to p after this
            jobData = p;

            // - Extract the Archive
            // -----------------------
            add(new CTask((t) => {
                var arc = new FreeArc(CDCRUSH.TOOLS_PATH);
                t.handleCliReport(arc);
                arc.extractAll(p.inputFile, p.tempDir);
                // In case the operation is aborted
                t.killExtra = () => {
                    arc.kill();
                };
            }, "Extracting", true));

            //  - Read JSON data
            //  - Restore tracks
            //  - JOIN if it has to
            // -----------------------
            add(new CTask((t) => {
                var cd     = new CueReader();
                jobData.cd = cd;
                // This runs in sync:
                if (!cd.loadJson(Path.Combine(p.tempDir, CDCRUSH.CDCRUSH_SETTINGS)))
                {
                    t.fail(msg: cd.ERROR);
                    return;
                }        //--

                        #if DEBUG
                cd.debugInfo();
                        #endif

                // - Push TASK RESTORE tasks right after this one
                foreach (CueTrack tr in cd.tracks)
                {
                    addNextAsync(new TaskRestoreTrack(tr));
                }        //--

                t.complete();
            }, "Preparing to Restore"));



            // - Join Tracks
            // -----------------------
            add(new CTask((t) => {
                CueReader cd = jobData.cd;
                // -- Join tracks
                if (p.flag_forceSingle || !cd.MULTIFILE)
                {
                    // The task will read data from the shared job data var
                    // Will join all tracks in place into track01.bin
                    // Note: Sets track.workingFile to null to moved track
                    addNext(new TaskJoinTrackFiles());
                }        //--

                t.complete();
            }, "Preparing to Join"));


            // - Prepare tracks `trackfile` which is the track written to the CUE
            // - Convert tracks
            // - Move files to final destination
            // - Create CUE files
            // - Delete Temp Files
            // -----------------------
            add(new CTask((t) => {
                CueReader cd = jobData.cd;

                // --
                foreach (var track in cd.tracks)
                {
                    if (p.flag_forceSingle && cd.MULTIFILE)            // :: CONVERT MULTI TO SINGLE
                    {
                        track.setNewTimesBasedOnSector();
                    }

                    if (cd.MULTIFILE && !p.flag_forceSingle)
                    {
                        track.trackFile = cd.CD_TITLE + " " + track.getFilenameRaw();
                    }

                    if (!cd.MULTIFILE || p.flag_forceSingle)
                    {
                        if (track.trackNo == 1)
                        {
                            track.trackFile = cd.CD_TITLE + ".bin";
                        }
                        else
                        {
                            track.trackFile = null;
                        }
                    }

                    // --
                    // Move ALL files to final output folder
                    // NULL workingFile means that is has been deleted
                    if (track.workingFile != null)
                    {
                        FileTools.tryMove(track.workingFile, Path.Combine(p.outputDir, track.trackFile));
                    }
                }        // -- end track processing

                // --
                // Create CUE File
                if (!cd.saveCUE(Path.Combine(p.outputDir, cd.CD_TITLE + ".cue")))
                {
                    t.fail(cd.ERROR); return;
                }

                t.complete();
            }, "Moving, Finalizing"));

            // - Complete -
        }// -----------------------------------------
Пример #10
0
        // --
        public JobRestore(RestoreParams par) : base("Restore CD")
        {
            p = par;

            // --
            hack_setExpectedProgTracks(p.expectedTracks + 3);

            // - Extract the Archive
            // -----------------------
            add(new CTask((t) => {
                var arc = ArchiveMaster.getArchiver(p.inputFile);
                t.handleProcessStatus(arc);
                arc.extract(p.inputFile, p.tempDir);
                arc.onProgress = (pr) => t.PROGRESS = pr;
                // In case the operation is aborted
                t.killExtra = () => {
                    arc.kill();
                };
            }, "Extracting", "Extracting the archive to temp folder"));

            //  - Read JSON data
            //  - Restore tracks
            //  - JOIN if it has to
            // -----------------------
            add(new CTask((t) =>
            {
                p.cd = new cd.CDInfos();

                try{
                    p.cd.jsonLoad(Path.Combine(p.tempDir, CDCRUSH.CDCRUSH_SETTINGS));
                }catch (haxe.lang.HaxeException e) {
                    t.fail(msg: e.Message); return;
                }

                jobData = p;

                LOG.log("== Detailed CD INFOS ==");
                LOG.log(p.cd.getDetailedInfo());

                for (int i = 0; i < p.cd.tracks.length; i++)
                {
                    // Push TASK RESTORE tasks right after this one
                    // Note: Task will take care of encoded cue case
                    addNextAsync(new TaskRestoreTrack(p.cd.tracks[i] as cd.CDTrack));
                }        //--

                t.complete();
            }, "-Preparing to Restore", "Reading stored CD info and preparing track restore tasks"));



            // - Join all Tracks together
            // -------------------------
            if (p.mode < 2)
            {
                add(new CTask((t) =>
                {
                    // -- Join tracks
                    if (p.mode == 1 || !p.cd.MULTIFILE)
                    {
                        // The task will read data from the shared job data var
                        // Will join all tracks in place into track01.bin
                        // Note: Sets track.workingFile to null to moved track
                        addNext(new TaskJoinTrackFiles());
                    }    //--

                    t.complete();
                }, "-Preparing to Join"));
            }


            // - Prepare tracks `trackfile` which is the track written to the CUE
            // - Convert tracks
            // - Move files to final destination
            // - Create CUE files
            // - Delete Temp Files
            // -----------------------
            add(new CTask((t) =>
            {
                cd.CDInfos CD = p.cd;

                int progressStep = (int)Math.Round(100.0f / CD.tracks.length);
                // --
                for (int i = 0; i < CD.tracks.length; i++)
                {
                    cd.CDTrack track = CD.tracks[i] as cd.CDTrack;
                    string ext       = Path.GetExtension(track.workingFile);

                    if (p.mode == 2)          // Restore to encoded audio
                    {
                        if (CD.tracks.length == 1)
                        {
                            track.trackFile = $"{CD.CD_TITLE}{ext}";
                        }
                        else
                        {
                            track.trackFile = $"{CD.CD_TITLE} (track {track.trackNo}){ext}";
                        }
                        if (!CD.MULTIFILE)
                        {
                            track.rewriteIndexes_forMultiFile();                               // :: CONVERTS SINGLE TO MULTI
                        }
                    }
                    else
                    {
                        if (p.mode == 1 && CD.MULTIFILE)              // :: CONVERT MULTI TO SINGLE
                        {
                            track.rewriteIndexes_forSingleFile();
                        }

                        if (CD.MULTIFILE && p.mode != 1)
                        {
                            track.trackFile = $"{CD.CD_TITLE} (track {track.trackNo}){ext}";
                        }

                        if (!CD.MULTIFILE || p.mode == 1)
                        {
                            if (track.trackNo == 1)
                            {
                                track.trackFile = CD.CD_TITLE + ".bin";
                            }
                            else
                            {
                                track.trackFile = null;
                            }
                        }
                    }

                    // --
                    // Move ALL files to final output folder
                    // NULL workingFile means that is has been deleted
                    if (track.workingFile != null)
                    {
                        FileTools.tryMove(track.workingFile, Path.Combine(p.outputDir, track.trackFile));
                        t.PROGRESS += progressStep;
                    }
                }        // -- end track processing

                // --
                // Create CUE File
                try{
                    CD.cueSave(
                        Path.Combine(p.outputDir, CD.CD_TITLE + ".cue"),
                        new haxe.root.Array <object>(new [] {
                        "CDCRUSH (dotNet) version : " + CDCRUSH.PROGRAM_VERSION,
                        CDCRUSH.LINK_SOURCE
                    }));
                }catch (haxe.lang.HaxeException e) {
                    t.fail(msg: e.Message); return;
                }

                t.complete();
            }, "Moving, Finalizing", "Calculating track data and creating .CUE"));

            // - Complete -
        }// -----------------------------------------