From 61755ea73dd137b7aa573175b33949e518da30d8 Mon Sep 17 00:00:00 2001 From: Maiko Date: Tue, 4 Jun 2024 21:51:02 +0900 Subject: [PATCH 1/4] Add recovery project function --- OpenUtau.Core/DocManager.cs | 6 +++-- OpenUtau.Core/Format/Formats.cs | 19 +++++++++++++++ OpenUtau.Core/Format/USTx.cs | 6 +++++ OpenUtau.Core/Util/Preferences.cs | 2 +- OpenUtau/Strings/Strings.axaml | 2 ++ OpenUtau/Strings/Strings.ja-JP.axaml | 2 ++ OpenUtau/ViewModels/MainWindowViewModel.cs | 28 ++++++++++++++++++++-- OpenUtau/Views/MainWindow.axaml.cs | 4 +++- 8 files changed, 63 insertions(+), 6 deletions(-) diff --git a/OpenUtau.Core/DocManager.cs b/OpenUtau.Core/DocManager.cs index 19a9f0986..d9d843d9d 100644 --- a/OpenUtau.Core/DocManager.cs +++ b/OpenUtau.Core/DocManager.cs @@ -115,11 +115,13 @@ public void SearchAllPlugins() { UCommandGroup? undoGroup = null; UCommandGroup? savedPoint = null; UCommandGroup? autosavedPoint = null; + public bool Recovered { get; set; } = false; public bool ChangesSaved { get { return (Project.Saved || (Project.tracks.Count <= 1 && Project.parts.Count == 0)) && - (undoQueue.Count > 0 && savedPoint == undoQueue.Last() || undoQueue.Count == 0 && savedPoint == null); + (undoQueue.Count > 0 && savedPoint == undoQueue.Last() || undoQueue.Count == 0 && savedPoint == null) && + !Recovered; } } @@ -142,7 +144,7 @@ private void CrashSave() { : Path.GetFileNameWithoutExtension(Project.FilePath); string backup = Path.Join(dir, filename + "-backup.ustx"); Log.Information($"Saving backup {backup}."); - Format.Ustx.Save(backup, Project); + Format.Ustx.AutoSave(backup, Project); Log.Information($"Saved backup {backup}."); } catch (Exception e) { Log.Error(e, "Save backup failed."); diff --git a/OpenUtau.Core/Format/Formats.cs b/OpenUtau.Core/Format/Formats.cs index 69ddbc990..4e4ddf7d1 100644 --- a/OpenUtau.Core/Format/Formats.cs +++ b/OpenUtau.Core/Format/Formats.cs @@ -102,6 +102,25 @@ public static UProject[] ReadProjects(string[] files){ .ToArray(); } + /// + /// Load project from backup file. + /// + /// Names of the files to be loaded + public static void RecoveryProject(string[] files) { + UProject project = ReadProject(files); + if (project != null) { + string originalPath = project.FilePath.Replace("-autosave.ustx", ".ustx").Replace("-backup.ustx", ".ustx"); + if (File.Exists(originalPath)) { + project.FilePath = originalPath; + } else { + project.FilePath = string.Empty; + project.Saved = false; + } + + DocManager.Inst.ExecuteCmd(new LoadProjectNotification(project)); + } + } + /// /// Import tracks from files to the current existing editing project. /// diff --git a/OpenUtau.Core/Format/USTx.cs b/OpenUtau.Core/Format/USTx.cs index 65b08d1c6..a4a7ceafc 100644 --- a/OpenUtau.Core/Format/USTx.cs +++ b/OpenUtau.Core/Format/USTx.cs @@ -5,6 +5,7 @@ using System.Text; using OpenUtau.Classic; using OpenUtau.Core.Ustx; +using OpenUtau.Core.Util; using Serilog; namespace OpenUtau.Core.Format { @@ -100,6 +101,9 @@ public static void Save(string filePath, UProject project) { File.WriteAllText(filePath, Yaml.DefaultSerializer.Serialize(project), Encoding.UTF8); project.Saved = true; project.AfterSave(); + Preferences.Default.RecoveryPath = string.Empty; + Preferences.Save(); + DocManager.Inst.Recovered = false; } public static void AutoSave(string filePath, UProject project) { @@ -107,6 +111,8 @@ public static void AutoSave(string filePath, UProject project) { project.BeforeSave(); File.WriteAllText(filePath, Yaml.DefaultSerializer.Serialize(project), Encoding.UTF8); project.AfterSave(); + Preferences.Default.RecoveryPath = filePath; + Preferences.Save(); } public static UProject Load(string filePath) { diff --git a/OpenUtau.Core/Util/Preferences.cs b/OpenUtau.Core/Util/Preferences.cs index 6a4c949aa..4d262e694 100644 --- a/OpenUtau.Core/Util/Preferences.cs +++ b/OpenUtau.Core/Util/Preferences.cs @@ -191,9 +191,9 @@ public class SerializablePreferences { public bool LockUnselectedNotesPitch = true; public bool LockUnselectedNotesVibrato = true; public bool LockUnselectedNotesExpressions = true; - public bool VoicebankPublishUseIgnore = true; public string VoicebankPublishIgnores = "#Adobe Audition\n*.pkf\n\n#UTAU Engines\n*.ctspec\n*.d4c\n*.dio\n*.frc\n*.frt\n*.frq\n*.harvest\n*.lessaudio\n*.llsm\n*.mrq\n*.pitchtier\n*.pkf\n*.platinum\n*.pmk\n*.star\n*.uspec\n*.vs4ufrq\n\n#UTAU related tools\n$read\n*.setParam-Scache\n*.lbp\n*.lbp.caches/*\n\n#OpenUtau\nerrors.txt"; + public string RecoveryPath = string.Empty; } } } diff --git a/OpenUtau/Strings/Strings.axaml b/OpenUtau/Strings/Strings.axaml index ddd5e6e0a..aeb135900 100644 --- a/OpenUtau/Strings/Strings.axaml +++ b/OpenUtau/Strings/Strings.axaml @@ -48,6 +48,8 @@ Yes No resampler No resampler! Put your favourite resampler exe or dll in the Resamplers folder and choose it in Preferences! + Previously, OpenUtau terminated abnormally. Do you want to recover? + Recovery project This tool will change the tempo of the project without changing the actual positions and durations (in seconds) of notes. New BPM: Time Signature diff --git a/OpenUtau/Strings/Strings.ja-JP.axaml b/OpenUtau/Strings/Strings.ja-JP.axaml index a1f265833..24f0f30d5 100644 --- a/OpenUtau/Strings/Strings.ja-JP.axaml +++ b/OpenUtau/Strings/Strings.ja-JP.axaml @@ -48,6 +48,8 @@ はい エンジンがありません エンジンが設定されていません!お好みのエンジンのEXEやDLLファイルをResamplerフォルダに入れて、環境設定でエンジンを選択してください! + 前回異常終了しました。復旧しますか? + プロジェクトの復旧 このツールでは、音符の実際の位置と長さ(秒単位)を変えずに、プロジェクトのテンポを変更します。 新しいBPM: 拍子 diff --git a/OpenUtau/ViewModels/MainWindowViewModel.cs b/OpenUtau/ViewModels/MainWindowViewModel.cs index d60a5ab47..7617eaf15 100644 --- a/OpenUtau/ViewModels/MainWindowViewModel.cs +++ b/OpenUtau/ViewModels/MainWindowViewModel.cs @@ -9,6 +9,7 @@ using OpenUtau.App.Views; using OpenUtau.Core; using OpenUtau.Core.Ustx; +using OpenUtau.Core.Util; using ReactiveUI; using ReactiveUI.Fody.Helpers; @@ -94,7 +95,28 @@ public void Redo() { return SingerManager.Inst.InitializationTask; } - public void InitProject() { + public async void InitProject(MainWindow window) { + var recPath = Preferences.Default.RecoveryPath; + if (!string.IsNullOrWhiteSpace(recPath) && File.Exists(recPath)) { + var result = await MessageBox.Show( + window, + ThemeManager.GetString("dialogs.recovery"), + ThemeManager.GetString("dialogs.recovery.caption"), + MessageBox.MessageBoxButtons.YesNo); + if (result == MessageBox.MessageBoxResult.Yes) { + DocManager.Inst.ExecuteCmd(new LoadingNotification(typeof(MainWindow), true, "project")); + try { + Core.Format.Formats.RecoveryProject(new string[] { recPath }); + DocManager.Inst.ExecuteCmd(new VoiceColorRemappingNotification(-1, true)); + DocManager.Inst.Recovered = true; + this.RaisePropertyChanged(nameof(Title)); + } finally { + DocManager.Inst.ExecuteCmd(new LoadingNotification(typeof(MainWindow), false, "project")); + } + return; + } + + } var args = Environment.GetCommandLineArgs(); if (args.Length == 2 && File.Exists(args[1])) { Core.Format.Formats.LoadProject(new string[] { args[1] }); @@ -118,6 +140,7 @@ public void NewProject() { } } DocManager.Inst.ExecuteCmd(new LoadProjectNotification(Core.Format.Ustx.Create())); + DocManager.Inst.Recovered = false; } public void OpenProject(string[] files) { @@ -132,6 +155,7 @@ public void OpenProject(string[] files) { } finally { DocManager.Inst.ExecuteCmd(new LoadingNotification(typeof(MainWindow), false, "project")); } + DocManager.Inst.Recovered = false; } public void SaveProject(string file = "") { @@ -141,7 +165,7 @@ public void SaveProject(string file = "") { DocManager.Inst.ExecuteCmd(new SaveProjectNotification(file)); this.RaisePropertyChanged(nameof(Title)); } - + public void ImportTracks(UProject[] loadedProjects, bool importTempo){ if (loadedProjects == null || loadedProjects.Length < 1) { return; diff --git a/OpenUtau/Views/MainWindow.axaml.cs b/OpenUtau/Views/MainWindow.axaml.cs index 9f6848ae1..eca365cd7 100644 --- a/OpenUtau/Views/MainWindow.axaml.cs +++ b/OpenUtau/Views/MainWindow.axaml.cs @@ -56,7 +56,7 @@ public MainWindow() { DataContext = viewModel = new MainWindowViewModel(); var scheduler = TaskScheduler.FromCurrentSynchronizationContext(); viewModel.GetInitSingerTask()!.ContinueWith(_ => { - viewModel.InitProject(); + viewModel.InitProject(this); viewModel.AddTempoChangeCmd = ReactiveCommand.Create(tick => AddTempoChange(tick)); viewModel.DelTempoChangeCmd = ReactiveCommand.Create(tick => DelTempoChange(tick)); viewModel.AddTimeSigChangeCmd = ReactiveCommand.Create(bar => AddTimeSigChange(bar)); @@ -1294,6 +1294,8 @@ public async void WindowClosing(object? sender, WindowClosingEventArgs e) { PathManager.Inst.ClearCache(); Log.Information("Cache cleared."); } + Preferences.Default.RecoveryPath = string.Empty; + Preferences.Save(); return; } e.Cancel = true; From 8dde7533025fd74598c5679b80e5dd4491852f9f Mon Sep 17 00:00:00 2001 From: Maiko Date: Tue, 4 Jun 2024 22:15:39 +0900 Subject: [PATCH 2/4] Add recovery path in dialog message --- OpenUtau/ViewModels/MainWindowViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenUtau/ViewModels/MainWindowViewModel.cs b/OpenUtau/ViewModels/MainWindowViewModel.cs index 7617eaf15..44844c364 100644 --- a/OpenUtau/ViewModels/MainWindowViewModel.cs +++ b/OpenUtau/ViewModels/MainWindowViewModel.cs @@ -100,7 +100,7 @@ public async void InitProject(MainWindow window) { if (!string.IsNullOrWhiteSpace(recPath) && File.Exists(recPath)) { var result = await MessageBox.Show( window, - ThemeManager.GetString("dialogs.recovery"), + $"{ThemeManager.GetString("dialogs.recovery")}\n{recPath}", ThemeManager.GetString("dialogs.recovery.caption"), MessageBox.MessageBoxButtons.YesNo); if (result == MessageBox.MessageBoxResult.Yes) { From bd9a518ddceb8b0d5e6cd5e516a9706ca2add9ba Mon Sep 17 00:00:00 2001 From: Maiko Date: Thu, 23 Jan 2025 13:56:21 +0900 Subject: [PATCH 3/4] add comment --- OpenUtau.Core/DocManager.cs | 2 +- OpenUtau.Core/Util/Preferences.cs | 1 - OpenUtau/Views/MainWindow.axaml.cs | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/OpenUtau.Core/DocManager.cs b/OpenUtau.Core/DocManager.cs index ad0360973..533ce7a6d 100644 --- a/OpenUtau.Core/DocManager.cs +++ b/OpenUtau.Core/DocManager.cs @@ -115,7 +115,7 @@ public void SearchAllPlugins() { UCommandGroup? undoGroup = null; UCommandGroup? savedPoint = null; UCommandGroup? autosavedPoint = null; - public bool Recovered { get; set; } = false; + public bool Recovered { get; set; } = false; // Flag to not overwrite backup file public bool ChangesSaved { get { diff --git a/OpenUtau.Core/Util/Preferences.cs b/OpenUtau.Core/Util/Preferences.cs index 3514726cf..58c47b3b0 100644 --- a/OpenUtau.Core/Util/Preferences.cs +++ b/OpenUtau.Core/Util/Preferences.cs @@ -193,7 +193,6 @@ public class SerializablePreferences { public bool LockUnselectedNotesVibrato = true; public bool LockUnselectedNotesExpressions = true; public bool VoicebankPublishUseIgnore = true; - public string VoicebankPublishIgnores = "#Adobe Audition\n*.pkf\n\n#UTAU Engines\n*.ctspec\n*.d4c\n*.dio\n*.frc\n*.frt\n#*.frq\n*.harvest\n*.lessaudio\n*.llsm\n*.mrq\n*.pitchtier\n*.pkf\n*.platinum\n*.pmk\n*.star\n*.uspec\n*.vs4ufrq\n\n#UTAU related tools\n$read\n*.setParam-Scache\n*.lbp\n*.lbp.caches/*\n\n#OpenUtau\nerrors.txt\n*.sc.npz"; public string RecoveryPath = string.Empty; } diff --git a/OpenUtau/Views/MainWindow.axaml.cs b/OpenUtau/Views/MainWindow.axaml.cs index 04226e5f4..d6ec849c6 100644 --- a/OpenUtau/Views/MainWindow.axaml.cs +++ b/OpenUtau/Views/MainWindow.axaml.cs @@ -52,7 +52,7 @@ public MainWindow() { InitializeComponent(); Log.Information("Initialized main window component."); DataContext = viewModel = new MainWindowViewModel(); - + viewModel.InitProject(this); viewModel.AddTempoChangeCmd = ReactiveCommand.Create(tick => AddTempoChange(tick)); viewModel.DelTempoChangeCmd = ReactiveCommand.Create(tick => DelTempoChange(tick)); @@ -1363,4 +1363,4 @@ public void OnNext(UCommand cmd, bool isUndo) { } } } -} \ No newline at end of file +} From dfd188e4418d222ccd02bff5a0e560100d185cfb Mon Sep 17 00:00:00 2001 From: Maiko Date: Fri, 24 Jan 2025 03:37:09 +0900 Subject: [PATCH 4/4] delay project loading at OU startup --- OpenUtau/ViewModels/MainWindowViewModel.cs | 2 -- OpenUtau/Views/MainWindow.axaml.cs | 7 +++++-- OpenUtau/Views/SplashWindow.axaml.cs | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/OpenUtau/ViewModels/MainWindowViewModel.cs b/OpenUtau/ViewModels/MainWindowViewModel.cs index f0b8207a9..64ecaec82 100644 --- a/OpenUtau/ViewModels/MainWindowViewModel.cs +++ b/OpenUtau/ViewModels/MainWindowViewModel.cs @@ -118,13 +118,11 @@ public async void InitProject(MainWindow window) { try { Core.Format.Formats.LoadProject(new string[] { args[1] }); DocManager.Inst.ExecuteCmd(new VoiceColorRemappingNotification(-1, true)); - return; } catch (Exception e) { var customEx = new MessageCustomizableException($"Failed to open file {args[1]}", $": {args[1]}", e); DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } - NewProject(); } public void NewProject() { diff --git a/OpenUtau/Views/MainWindow.axaml.cs b/OpenUtau/Views/MainWindow.axaml.cs index d6ec849c6..916f18993 100644 --- a/OpenUtau/Views/MainWindow.axaml.cs +++ b/OpenUtau/Views/MainWindow.axaml.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Reactive; -using System.Threading; using System.Threading.Tasks; using Avalonia; using Avalonia.Controls; @@ -53,7 +52,7 @@ public MainWindow() { Log.Information("Initialized main window component."); DataContext = viewModel = new MainWindowViewModel(); - viewModel.InitProject(this); + viewModel.NewProject(); viewModel.AddTempoChangeCmd = ReactiveCommand.Create(tick => AddTempoChange(tick)); viewModel.DelTempoChangeCmd = ReactiveCommand.Create(tick => DelTempoChange(tick)); viewModel.AddTimeSigChangeCmd = ReactiveCommand.Create(bar => AddTimeSigChange(bar)); @@ -88,6 +87,10 @@ public MainWindow() { Log.Information("Created main window."); } + public void InitProject() { + viewModel.InitProject(this); + } + void OnEditTimeSignature(object sender, PointerPressedEventArgs args) { var project = DocManager.Inst.Project; var timeSig = project.timeSignatures[0]; diff --git a/OpenUtau/Views/SplashWindow.axaml.cs b/OpenUtau/Views/SplashWindow.axaml.cs index edc90f2f4..902afdce9 100644 --- a/OpenUtau/Views/SplashWindow.axaml.cs +++ b/OpenUtau/Views/SplashWindow.axaml.cs @@ -54,6 +54,7 @@ private void Start() { var mainWindow = new MainWindow(); mainWindow.Show(); desktop.MainWindow = mainWindow; + mainWindow.InitProject(); Close(); } }, CancellationToken.None, TaskContinuationOptions.None, mainScheduler);