public void New()
    {
        if (!EditCheck())
        {
            return;
        }

        while (isSaving)
        {
            ;
        }

        if (errorManager.HasErrorToDisplay())
        {
            return;
        }

        lastLoadedFile = string.Empty;
        currentSongAudio.FreeAudioStreams();
        currentSong = new Song();

        sessionFlags &= ~ChartEditorSessionFlags.CurrentChartSavedInProprietyFormat;

        LoadSong(currentSong);

        movement.SetPosition(0);
        //StartCoroutine(resetLag());

        selectedObjectsManager.currentSelectedObject = null;
        isDirty = true;
    }
    public IEnumerator _Load(string currentFileName, bool recordLastLoaded = true)
    {
        LoadingTasksManager tasksManager = services.loadingTasksManager;

        bool error  = false;
        Song backup = currentSong;

#if TIMING_DEBUG
        float totalLoadTime = Time.realtimeSinceStartup;
#endif
        bool mid = false;

        Song newSong = null;
        MidReader.CallbackState midiCallbackState = MidReader.CallbackState.None;

        List <LoadingTask> tasks = new List <LoadingTask>()
        {
            new LoadingTask("Loading file", () =>
            {
                // Wait for saving to complete just in case
                while (isSaving)
                {
                }

                if (errorManager.HasErrorToDisplay())
                {
                    error = true;
                    return;
                }

                mid = System.IO.Path.GetExtension(currentFileName) == ".mid";

                try
                {
                    if (mid)
                    {
                        newSong = MidReader.ReadMidi(currentFileName, ref midiCallbackState);
                    }
                    else
                    {
                        newSong = ChartReader.ReadChart(currentFileName);
                    }
                }
                catch (Exception e)
                {
                    currentSong = backup;

                    if (mid)
                    {
                        errorManager.QueueErrorMessage(Logger.LogException(e, "Failed to open mid file"));
                    }
                    else
                    {
                        errorManager.QueueErrorMessage(Logger.LogException(e, "Failed to open chart file"));
                    }

                    error = true;
                }

                try
                {
                    string directory = System.IO.Path.GetDirectoryName(currentFileName);
                    string iniPath   = System.IO.Path.Combine(directory, "song.ini");
                    if (newSong != null && System.IO.File.Exists(iniPath))
                    {
                        try
                        {
                            newSong.iniProperties.Open(iniPath);
                            newSong.iniProperties = SongIniFunctions.FixupSongIniWhitespace(newSong.iniProperties);
                        }
                        catch (Exception e)
                        {
                            errorManager.QueueErrorMessage(Logger.LogException(e, "Failed to parse song.ini"));
                        }
                        finally
                        {
                            newSong.iniProperties.Close();
                        }
                    }
                }
                catch (Exception e)
                {
                    // TODO
                }
            }),

            new LoadingTask("Loading audio", () =>
            {
                if (error)
                {
                    return;
                }

                // Free the previous audio clips
                currentSongAudio.FreeAudioStreams();
                currentSongAudio.LoadAllAudioClips(newSong);
            }),
        };

        tasksManager.KickTasks(tasks);

        while (tasksManager.isRunningTask)
        {
            while (midiCallbackState == MidReader.CallbackState.WaitingForExternalInformation)
            {
                // Halt main thread until message box is complete
            }
            yield return(null);
        }

        // Tasks have finished
        if (error)
        {
            yield break;    // Immediate exit
        }
        isDirty = false;

        if (mid)
        {
            currentFileName = string.Empty;
            isDirty         = true;
            Debug.Log("Loaded mid file");
        }

        if (recordLastLoaded && currentFileName != string.Empty && !mid)
        {
            lastLoadedFile = System.IO.Path.GetFullPath(currentFileName);
        }
        else
        {
            lastLoadedFile = string.Empty;
        }

        currentSong = newSong;

        sessionFlags &= ~ChartEditorSessionFlags.CurrentChartSavedInProprietyFormat;

        LoadSong(currentSong);

#if TIMING_DEBUG
        Debug.Log("Total load time: " + (Time.realtimeSinceStartup - totalLoadTime));
#endif
    }
    /// <summary>
    /// Saves the song data in a .chart format to the specified path.
    /// </summary>
    /// <param name="filepath">The path and filename to save to.</param>
    /// <param name="forced">Will the notes from each chart have their flag properties saved into the file?</param>
    void SaveSong(Song song, string filepath, ExportOptions exportOptions)
    {
        string saveErrorMessage;

        try
        {
            ChartWriter.ErrorReport errorReport;
            new ChartWriter(filepath).Write(song, exportOptions, out errorReport);

            Debug.Log("Save complete!");

            saveErrorMessage = errorReport.errorList.ToString();

            bool shouldQueueErrors = true; /*errorReport.hasNonErrorFileTypeRelatedErrors;
                                            * if (!sessionFlags.HasFlag(ChartEditorSessionFlags.CurrentChartSavedInProprietyFormat))
                                            * {
                                            * // We haven't warned users about this particular error yet, let's queue it up.
                                            * shouldQueueErrors = true;
                                            * }*/

            if (errorReport.resultantFileType == ChartIOHelper.FileSubType.MoonscraperPropriety)
            {
                filepath       = System.IO.Path.ChangeExtension(filepath, MsceIOHelper.FileExtention);
                lastLoadedFile = filepath;
            }

            if (saveErrorMessage != string.Empty && shouldQueueErrors)
            {
                errorManager.QueueErrorMessage("Save completed with the following errors: " + Globals.LINE_ENDING + saveErrorMessage);
            }

            if (errorReport.resultantFileType == ChartIOHelper.FileSubType.MoonscraperPropriety)
            {
                sessionFlags |= ChartEditorSessionFlags.CurrentChartSavedInProprietyFormat;
            }

            string iniPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(filepath), SongIniFunctions.INI_FILENAME);
            if (!song.iniProperties.IsEmpty)
            {
                Debug.Log("Saving song.ini");

                INIParser parser = new INIParser();
                try
                {
                    parser.Open(iniPath);
                    parser.WriteValue(song.iniProperties);
                }
                catch (System.Exception e)
                {
                    Debug.LogError("Error encountered when trying to write song.ini. " + e.Message);
                }
                finally
                {
                    parser.Close();
                }

                Debug.Log("song.ini save complete!");
            }
            else if (System.IO.File.Exists(iniPath))
            {
                System.IO.File.Delete(iniPath);
            }
        }
        catch (System.Exception e)
        {
            errorManager.QueueErrorMessage(Logger.LogException(e, "Save failed!"));
        }
    }