Beispiel #1
0
        }        // -----------------------------------------

        /// <summary>
        /// Quickly load a CUE file, read it, check for validity and report back.
        /// Returns a customized object with some info
        /// </summary>
        /// <param name="cueFile"></param>
        /// <param name="onComplete"></param>
        /// <returns>null on ERROR, A valid info object otherwise</returns>
        public static object loadQuickCUE(string cueFile)
        {
            if (LOCKED)
            {
                ERROR = "LOCKED";
                return(null);
            }

            if (!check_file_(cueFile, ".cue"))
            {
                return(false);
            }

            // Load the CUE file and try to parse it
            var cd = new cd.CDInfos();

            try {
                cd.cueLoad(cueFile);
            }catch (haxe.lang.HaxeException e) {
                ERROR = e.Message; return(null);
            }

            LOG.log("= QuickLoaded `{0}' - [OK]", cueFile);

            var info = new
            {
                title  = cd.CD_TITLE,
                size1  = cd.CD_TOTAL_SIZE,
                tracks = cd.tracks.length
            };

            return(info);
        }        // -----------------------------------------
Beispiel #2
0
        }// -----------------------------------------

        // =============================================
        // FORM INTERACTION
        // =============================================


        // --
        // Show a popup with some CD infos like checksums
        public void form_showCdInfo(cd.CDInfos cd)
        {
            if (FormChecksums.ISOPEN)
            {
                return;
            }
            var f = new FormChecksums(cd);

            f.Show();
        }// -----------------------------------------
Beispiel #3
0
        }// -----------------------------------------

        // ==========================================
        // FORM ACTIONS
        // ==========================================


        /// <summary>
        /// Clear CD Infos and Locks
        /// </summary>
        private void form_prepare_init()
        {
            form_lockSection("action", true);
            form_set_cover(null);       // Empty it out
            form_set_cd_info(null);
            form_set_crushed_size();    // Empty it out
            loadedCuePath  = null;
            postCdInfo     = null;
            numberOfTracks = 0;
        }// -----------------------------------------
Beispiel #4
0
        }// --

        // --
        private void PanelRestore_Load(object sender, EventArgs e)
        {
            FormTools.fileLoadDialogPrepare("arc", "ARC files (*.arc)|*.arc");
            form_lockSection("action", true);
            form_setCdInfo(null);
            form_setCoverImage(null);
            loadedArcPath = null;
            loadedCDInfo  = null;
            combo_method.SelectedIndex = 0;
        }// -----------------------------------------
Beispiel #5
0
        }// -----------------------------------------

        // --
        // Gets called regardless of number of tracks:
        public override void start()
        {
            base.start();

            // Get the global cd object
            cd.CDInfos CD = jobData.cd;
            input = (CD.tracks[0] as cd.CDTrack).workingFile;

            // No need to cut an already cut CD
            // Multifiles `workingfile` is already set to proper
            if (CD.MULTIFILE)
            {
                complete();
                return;
            }

            // No need to copy the bytes to the temp folder, just work from the source
            if (CD.tracks.length == 1)
            {
                complete();
                return;
            }


            int progressStep = (int)Math.Round((double)(100 / CD.tracks.length));

            // -- Cut the tracks ::

            FileStream inStr = new FileStream(input, FileMode.Open, FileAccess.Read);

            for (int i = 0; i < CD.tracks.length; i++)
            {
                cd.CDTrack track = (CD.tracks[i] as cd.CDTrack);

                int byteStart = track.sectorStart * CD.SECTOR_SIZE;
                int byteLen   = track.sectorSize * CD.SECTOR_SIZE;

                // New filename for the tracks
                track.workingFile = Path.Combine(jobData.tempDir, track.getFilenameRaw());
                FileStream outStr = new FileStream(track.workingFile, FileMode.CreateNew, FileAccess.Write);
                copyStream(inStr, outStr, byteStart, byteLen);
                outStr.Dispose();
                PROGRESS += progressStep;
            }    // --

            inStr.Dispose();

            complete();
        }// -----------------------------------------
Beispiel #6
0
        }// -----------------------------------------

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

            cd.CDInfos CD = jobData.cd;

            // --
            if (CD.tracks.length == 1)
            {
                complete();
                return;
            }

            // --
            inputs = new string[CD.tracks.length - 1];
            for (int i = 1; i < CD.tracks.length; i++)
            {
                inputs[i - 1] = (CD.tracks[i] as cd.CDTrack).workingFile;
                (CD.tracks[i] as cd.CDTrack).workingFile = null;                // Used later when moving, null files won't be moved
            }

            output = (CD.tracks[0] as cd.CDTrack).workingFile;

            int progressStep = (int)Math.Round((double)(100.0f / inputs.Length));

            // NOTE:
            // If I didn't use FileMode.Append , the file would be overwritten
            // It is compatible with new files also.
            FileStream streamWrite = new FileStream(output, FileMode.Append, FileAccess.Write);

            for (int i = 0; i < inputs.Length; i++)
            {
                using (FileStream streamRead = File.OpenRead(inputs[i]))
                {
                    streamRead.CopyTo(streamWrite);
                }

                if (!CDCRUSH.FLAG_KEEP_TEMP)
                {
                    FileTools.tryDelete(inputs[i]);
                }
                PROGRESS += progressStep;
            }

            streamWrite.Close();
            complete();
        } // -----------------------------------------
Beispiel #7
0
        }// -----------------------------------------

        /// <summary>
        /// Set form infos from a CueReader object
        /// - Called when quickloading a CD
        /// - Called to clear fields
        /// </summary>
        /// <param name="cdInfo">Object CDCURSH,loadQuickInfo() sends</param>
        void form_setCdInfo(dynamic cdInfo = null)
        {
            if (cdInfo == null)
            {
                // set all to none
                info_cdtitle.Text = "";
                info_size0.Text   = "";         // Small
                info_size1.Text   = "";         // Full
                info_tracks.Text  = "";
                info_audio.Text   = "";
                btn_chksm.Enabled = false;
                loadedCDInfo      = null;
                return;
            }

            loadedCDInfo      = cdInfo.cd;
            btn_chksm.Enabled = true;

            int numberOfTracks = loadedCDInfo.tracks.length;

            info_cdtitle.Text = loadedCDInfo.CD_TITLE;
            info_size0.Text   = String.Format("{0}MB", FormTools.bytesToMB(cdInfo.sizeArc));
            info_size1.Text   = String.Format("{0}MB", FormTools.bytesToMB(loadedCDInfo.CD_TOTAL_SIZE));
            info_audio.Text   = loadedCDInfo.CD_AUDIO_QUALITY;
            info_tracks.Text  = numberOfTracks.ToString();

            /// TODO: Alter the combobox -->

            //// Init some controls dependant on track count
            //toggle_merged.Enabled = (numberOfTracks>1);
            //toggle_cueaudio.Enabled = (numberOfTracks>1);

            //if(numberOfTracks==1)
            //{
            //	toggle_merged.Checked = false;
            //	toggle_cueaudio.Checked = false;
            //}
        }// -----------------------------------------
Beispiel #8
0
 // --
 public FormChecksums(cd.CDInfos _cd)
 {
     cd = _cd;
     InitializeComponent();
 }        // -----------------------------------------
Beispiel #9
0
        }        // -----------------------------------------

        /// <summary>
        /// Take a crushed archive and extract only the info file, Returns a customized object with some info
        /// </summary>
        /// <param name="arcFile"></param>
        /// <param name="onComplete">(null) on error,
        ///		OBJECT =
        ///			cd:CueReader,
        ///			cover:Path of image cover or null
        ///			sizeArc:Size of ARC in bytes
        ///
        ///	</param>
        /// <returns>Success</returns>
        public static bool loadQuickInfo(string arcFile, Action <Object> onComplete)
        {
            if (LOCKED)
            {
                ERROR = "LOCKED";
                return(false);
            }

            if (!check_file_(arcFile, CDCRUSH_EXTENSIONS))
            {
                ERROR = "Invalid file extension. Supported  = (" + string.Join(" ", CDCRUSH.CDCRUSH_EXTENSIONS) + ")";
                return(false);
            }


            LOCKED = true;

            // Delete old files from previous quickInfos, IF ANY
            FileTools.tryDelete(Path.Combine(TEMP_FOLDER, CDCRUSH_SETTINGS));
            FileTools.tryDelete(Path.Combine(TEMP_FOLDER, CDCRUSH_COVER));

            var arc = ArchiveMaster.getArchiver(arcFile);

            // --
            arc.onComplete = (success) =>
            {
                LOCKED = false;

                if (success)                // OK
                {
                    // Continue
                    var cd = new cd.CDInfos();
                    try{
                        cd.jsonLoad(Path.Combine(TEMP_FOLDER, CDCRUSH_SETTINGS));
                    }catch (haxe.lang.HaxeException e) {
                        ERROR = "Not a valid CDCRUSH Archive.";
                        onComplete(null);
                        return;
                    }

                    // This is the object with the info returned to user
                    var info = new
                    {
                        cd,
                        sizeArc = (int)new FileInfo(arcFile).Length,
                        cover   = Path.Combine(TEMP_FOLDER, CDCRUSH_COVER)
                    };

                    LOG.log("= QuickLoaded `{0}` - [OK]", arcFile);
                    onComplete(info);
                }
                else
                {
                    ERROR = arc.ERROR;
                    onComplete(null);
                }
            };


            // TODO: Make sure ARCHIVE contains proper files
            // : Actually extract
            arc.extract(arcFile, TEMP_FOLDER, new [] { CDCRUSH_SETTINGS, CDCRUSH_COVER });

            return(true);
        }        // -----------------------------------------
Beispiel #10
0
        // --
        public JobCrush(CrushParams par) : base("Compress CD")
        {
            p = par;

            // Hack to fix progress
            hack_setExpectedProgTracks(p.expectedTracks + 3);

            // - Read CUE and some init
            // ---------------------------
            add(new CTask((t) => {
                var cd = new cd.CDInfos();

                p.cd = cd;

                try{
                    cd.cueLoad(p.inputFile);
                }catch (haxe.lang.HaxeException e) {
                    t.fail(msg: e.Message); return;
                }

                // Meaning the tracks are going to be CUT in the temp folder, so they are safe to be removed
                p.flag_sourceTracksOnTemp = (!cd.MULTIFILE && cd.tracks.length > 1);

                // In case user named the CD, otherwise it's going to be the same
                if (!string.IsNullOrWhiteSpace(p.cdTitle))
                {
                    cd.CD_TITLE = FileTools.sanitizeFilename(p.cdTitle);
                }

                // Real quality to string name
                cd.CD_AUDIO_QUALITY = AudioMaster.getCodecSettingsInfo(p.audioQuality);

                if (p.mode != 1)      // Convert only does not require an archive
                {
                    // Generate the final ARCHIVE path now that I have the CD TITLE
                    p.finalArcPath = Path.Combine(p.outputDir, cd.CD_TITLE + p.archiver_ext);

                    // Try to create a new archive in case it exists?
                    while (File.Exists(p.finalArcPath))
                    {
                        LOG.log("{0} already exists, adding (_) until unique", p.finalArcPath);
                        // S is entire path without (.ext)
                        string S       = p.finalArcPath.Substring(0, p.finalArcPath.Length - p.archiver_ext.Length);
                        p.finalArcPath = S + "_" + p.archiver_ext;
                    }

                    LOG.log("- Destination Archive : {0}", p.finalArcPath);
                }

                if (p.mode == 1)
                {
                    // : ALWAYS Create a subfolder (when converting) to avoid overwriting the source files
                    p.outputDir = CDCRUSH.checkCreateUniqueOutput(p.outputDir, p.cdTitle + CDCRUSH.RESTORED_FOLDER_SUFFIX);
                    if (p.outputDir == null)
                    {
                        fail("Output Dir Error " + p.outputDir);
                        return;
                    }
                }

                jobData = p;         // Some TASKS read jobData
                t.complete();
            }, "-Reading", "Reading CUE data and preparing"));

            // - Cut tracks
            // ---------------------------
            add(new TaskCutTrackFiles());

            // - Encode tracks
            // ---------------------
            add(new CTask((t) =>
            {
                for (int i = 0; i < p.cd.tracks.length; i++)
                {
                    cd.CDTrack tr = p.cd.tracks[i] as cd.CDTrack;

                    // Do not encode DATA TRACKS to ECM when converting.
                    if (p.mode > 0 && tr.isData)
                    {
                        continue;
                    }

                    addNextAsync(new TaskCompressTrack(tr));
                }

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



            // - Prepare Tracks on CONVERT modes
            // - Needed for the new .CUE to be created
            // - if CONVERT MODE, move all files to output
            if (p.mode > 0)
            {
                add(new CTask((t) =>
                {
                    // DEV: So far :
                    // track.trackFile is UNSET. cd.saveCue needs it to be set.
                    // track.workingFile points to a valid file, some might be in TEMP folder and some in input folder (data tracks)

                    int stepProgress = (int)Math.Round(100.0f / p.cd.tracks.length);

                    // -- Move files to output folder
                    for (int i = 0; i < p.cd.tracks.length; i++)
                    {
                        cd.CDTrack track = p.cd.tracks[i] as cd.CDTrack;

                        if (!p.cd.MULTIFILE)
                        {
                            // Fix the index times to start with 00:00:00
                            track.rewriteIndexes_forMultiFile();
                        }

                        string ext = Path.GetExtension(track.workingFile);

                        // This tells what the files should be named in the `.cue` file:
                        track.trackFile = $"{p.cd.CD_TITLE} (track {track.trackNo}){ext}";

                        // Data track was not cut or encoded.
                        // It's in the input folder, don't move it
                        if (track.isData && (p.cd.MULTIFILE || p.cd.tracks.length == 1))
                        {
                            if (p.mode == 1)
                            {
                                FileTools.tryCopy(track.workingFile, Path.Combine(p.outputDir, track.trackFile));
                                track.workingFile = Path.Combine(p.outputDir, track.trackFile);
                            }
                            else
                            {
                                // I need to copy all files to TEMP, so that they can be renamed and archived
                                FileTools.tryCopy(track.workingFile, Path.Combine(p.tempDir, track.trackFile));
                                track.workingFile = Path.Combine(p.tempDir, track.trackFile);
                            }
                        }
                        else         // encoded file that is on TEMP or OUTPUT
                        {
                            if (p.mode == 1)
                            {
                                // TaskCompress already put the audio files on the output folder
                                // But it's no big deal calling it again
                                // This is for the data tracks that are on the temp folder
                                FileTools.tryMove(track.workingFile, Path.Combine(p.outputDir, track.trackFile));
                                track.workingFile = Path.Combine(p.outputDir, track.trackFile);
                            }
                            else
                            {
                                // Track that has been encoded and is on TEMP
                                // It is currently named as "track_xx.xx" so rename it
                                FileTools.tryMove(track.workingFile, Path.Combine(p.tempDir, track.trackFile));
                                track.workingFile = Path.Combine(p.tempDir, track.trackFile);
                            }
                        }

                        t.PROGRESS += stepProgress;
                    }     // -- end processing tracks


                    if (p.mode == 1)
                    {
                        p.new_cue_path = Path.Combine(p.outputDir, p.cd.CD_TITLE + ".cue");
                    }
                    else
                    {
                        p.new_cue_path = Path.Combine(p.tempDir, p.cd.CD_TITLE + ".cue");
                    }

                    //. Create the new CUE file
                    try{
                        p.cd.cueSave(
                            p.new_cue_path,
                            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();
                }, "Converting"));
            }


            // - Create an Archive
            // Add all tracks to the final archive
            // ---------------------
            if (p.mode != 1)
            {
                add(new CTask((t) =>
                {
                    // -- Get list of files to compress
                    // . Tracks
                    System.Collections.ArrayList files = new System.Collections.ArrayList();
                    for (var i = 0; i < p.cd.tracks.length; i++)
                    {
                        files.Add((p.cd.tracks[i] as cd.CDTrack).workingFile);         // Working file is valid, was set earlier
                    }

                    if (p.mode == 0)  // Only on CDCRUSH add cover and json data
                    {
                        // . Settings
                        string path_settings = Path.Combine(p.tempDir, CDCRUSH.CDCRUSH_SETTINGS);
                        try{
                            p.cd.jsonSave(path_settings);
                            files.Add(path_settings);
                        }catch (haxe.lang.HaxeException e) {
                            t.fail(msg: e.Message); return;
                        }

                        // . Cover Image
                        string path_cover;
                        if (p.cover != null)
                        {
                            path_cover = Path.Combine(p.tempDir, CDCRUSH.CDCRUSH_COVER);
                            File.Copy(p.cover, path_cover);
                            files.Add(path_cover);
                        }
                        else
                        {
                            path_cover = null;
                        }
                    }
                    else
                    {
                        // It must be CONVERT + ARCHIVE
                        files.Add(p.new_cue_path);
                    }

                    // -. Compress whatever files are on
                    var arc = ArchiveMaster.getArchiver(p.finalArcPath);

                    string arcStr = ArchiveMaster.getCompressionSettings(p.archiveSettingsInd).Item2;

                    arc.compress((string[])files.ToArray(typeof(string)), jobData.finalArcPath, -1, arcStr);
                    arc.onProgress = (pr) => t.PROGRESS = pr;
                    arc.onComplete = (s) => {
                        if (s)
                        {
                            // NOTE: This var is autowritten whenever a compress operation is complete
                            p.crushedSize = (int)arc.COMPRESSED_SIZE;
                            // IMPORTANT to write to jobdata, because it is not a pointer and this needs to be read externally
                            jobData = p;
                            t.complete();
                        }
                        else
                        {
                            fail(arc.ERROR);
                        }
                    };

                    t.killExtra = () => arc.kill();
                }, "Compressing", "Compressing everything into an archive"));
            }


            // -- COMPLETE --

            add(new CTask((t) =>
            {
                LOG.log("== Detailed CD INFOS ==");
                LOG.log(p.cd.getDetailedInfo());
                t.complete();
            }, "-complete"));
        }// -----------------------------------------
Beispiel #11
0
        }// -----------------------------------------

        // --
        // Event Clicked Compressed Button
        private void btn_CRUSH_Click(object sender, EventArgs e)
        {
            // Common callback for all job types
            Action <bool, CrushParams> jobCallback = (complete, jobdata) =>
            {
                FormTools.invoke(this, () =>
                {
                    form_lockSection("all", false);
                    form_set_crushed_size(jobdata.crushedSize);
                    postCdInfo = jobdata.cd;                    // Either null or full info

                    if (complete)
                    {
                        FormMain.sendMessage("Complete", 2);
                        btn_chksm.Enabled = true;
                    }
                    else
                    {
                        FormMain.sendProgress(0);
                        FormMain.sendMessage(CDCRUSH.ERROR, 3);
                    }

                    // Make progress bar and status message clear after
                    FormMain.FLAG_REQUEST_STATUS_CLEAR = true;
                });
            };


            // Reset the message color, incase it was red
            FormMain.sendMessage("", 1);

            // Fix progress reporting. HACKY WAY :-/
            CDCRUSH.HACK_CD_TRACKS = numberOfTracks;

            // Either compress to an archive, or just convert
            // Note : Progress updates are automatically being handled by the main FORM

            // This TUPLE will hold (CODECID, QUALITY INDEX)
            Tuple <string, int> audioQ = Tuple.Create(AudioMaster.codecs[combo_audio_c.SelectedIndex],
                                                      combo_audio_q.SelectedIndex);

            bool res = CDCRUSH.startJob_Convert_Crush(
                combo_method.SelectedIndex,
                loadedCuePath,
                input_out.Text,
                audioQ,
                combo_data_c.SelectedIndex,
                info_cdtitle.Text,
                preparedCover,
                jobCallback
                );

            // -- Check preliminary Job Status
            if (res)
            {
                form_lockSection("all", true);
            }
            else
            {
                FormMain.sendMessage(CDCRUSH.ERROR, 3);
            }
        }// -----------------------------------------
Beispiel #12
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 -
        }// -----------------------------------------