diff --git a/MSUScripter/Configs/Settings.cs b/MSUScripter/Configs/Settings.cs index 3730f60..780b29e 100644 --- a/MSUScripter/Configs/Settings.cs +++ b/MSUScripter/Configs/Settings.cs @@ -17,4 +17,5 @@ public class Settings public bool AutomaticallyRunPyMusicLooper { get; set; } = true; public bool RunMsuPcmWithKeepTemps { get; set; } public bool HasDoneFirstTimeSetup { get; set; } + public string? PyMusicLooperPath { get; set; } } \ No newline at end of file diff --git a/MSUScripter/MSUScripter.csproj b/MSUScripter/MSUScripter.csproj index 664868b..378d13d 100644 --- a/MSUScripter/MSUScripter.csproj +++ b/MSUScripter/MSUScripter.csproj @@ -8,7 +8,7 @@ true MSUScripterIcon.ico MSUScripterIcon.ico - 4.2.0 + 4.2.1-beta.1 8.0.0 false 12 diff --git a/MSUScripter/Services/ControlServices/SettingsWindowService.cs b/MSUScripter/Services/ControlServices/SettingsWindowService.cs index 2c4f3e4..f469039 100644 --- a/MSUScripter/Services/ControlServices/SettingsWindowService.cs +++ b/MSUScripter/Services/ControlServices/SettingsWindowService.cs @@ -1,3 +1,4 @@ +using System; using Avalonia; using Avalonia.Styling; using AvaloniaControls.ControlServices; @@ -5,13 +6,14 @@ namespace MSUScripter.Services.ControlServices; -public class SettingsWindowService(SettingsService settingsService, ConverterService converterService, MsuPcmService msuPcmService) : ControlService +public class SettingsWindowService(SettingsService settingsService, ConverterService converterService, MsuPcmService msuPcmService, PyMusicLooperService pyMusicLooperService) : ControlService { private SettingsWindowViewModel _model = new(); public SettingsWindowViewModel InitializeModel() { converterService.ConvertViewModel(settingsService.Settings, _model); + _model.CanSetPyMusicLooperPath = OperatingSystem.IsWindows(); return _model; } @@ -26,4 +28,9 @@ public bool ValidateMsuPcm() { return msuPcmService.ValidateMsuPcmPath(_model.MsuPcmPath!, out _); } + + public bool ValidatePyMusicLooper() + { + return pyMusicLooperService.TestService(out _, _model.PyMusicLooperPath); + } } \ No newline at end of file diff --git a/MSUScripter/Services/PyMusicLooperService.cs b/MSUScripter/Services/PyMusicLooperService.cs index 4b2c1bc..d8864cc 100644 --- a/MSUScripter/Services/PyMusicLooperService.cs +++ b/MSUScripter/Services/PyMusicLooperService.cs @@ -11,6 +11,7 @@ using MSUScripter.Models; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; +using Settings = MSUScripter.Configs.Settings; namespace MSUScripter.Services; @@ -26,13 +27,20 @@ public class PyMusicLooperService private bool _canReturnMultipleResults; private readonly string _cachePath; private int _currentVersion; + private string _pyMusicLooperCommand = "pymusiclooper"; + private readonly Settings _settings; - public PyMusicLooperService(ILogger logger, PythonCommandRunnerService python, YamlService yamlService) + public PyMusicLooperService(ILogger logger, PythonCommandRunnerService python, YamlService yamlService, Settings settings) { _logger = logger; _python = python; _yamlService = yamlService; + _settings = settings; _cachePath = Path.Combine(Directories.CacheFolder, "pymusiclooper"); + if (!string.IsNullOrEmpty(settings.PyMusicLooperPath) && File.Exists(settings.PyMusicLooperPath)) + { + _pyMusicLooperCommand = settings.PyMusicLooperPath; + } if (!Directory.Exists(_cachePath)) { Directory.CreateDirectory(_cachePath); @@ -125,15 +133,29 @@ public void ClearCache() return loopPoints; } - public bool TestService(out string message) + public bool TestService(out string message, string? testPath = null) { - if (_hasValidated) + if (_hasValidated && testPath == null) { message = ""; return true; } + + if (testPath != null) + { + _settings.PyMusicLooperPath = testPath; + _pyMusicLooperCommand = string.Empty == testPath ? "pymusiclooper" : testPath; + } + else if (!string.IsNullOrEmpty(_settings.PyMusicLooperPath) && File.Exists(_settings.PyMusicLooperPath)) + { + _pyMusicLooperCommand = _settings.PyMusicLooperPath; + } + else + { + _pyMusicLooperCommand = "pymusiclooper"; + } - if (!_python.SetBaseCommand("pymusiclooper", "--version", out var result, out _) || !result.StartsWith("pymusiclooper ", StringComparison.OrdinalIgnoreCase)) + if (!_python.SetBaseCommand(_pyMusicLooperCommand, "--version", out var result, out _) || !result.StartsWith("pymusiclooper ", StringComparison.OrdinalIgnoreCase)) { message = "Could not run PyMusicLooper. Make sure it's installed and executable in command line."; return false; diff --git a/MSUScripter/Services/PythonCommandRunnerService.cs b/MSUScripter/Services/PythonCommandRunnerService.cs index 766a230..02f0baf 100644 --- a/MSUScripter/Services/PythonCommandRunnerService.cs +++ b/MSUScripter/Services/PythonCommandRunnerService.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.IO; using System.Runtime.InteropServices; using System.Text; using System.Threading; @@ -108,12 +109,24 @@ private bool RunInternal(string command, string arguments, out string result, ou if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + var workingDirectory = ""; + if (System.IO.File.Exists(command)) + { + workingDirectory = Directory.GetParent(command)?.FullName; + if (!string.IsNullOrEmpty(workingDirectory)) + { + var file = Path.GetFileName(command); + innerCommand = $"{file} {arguments}"; + } + } + procStartInfo= new ProcessStartInfo("cmd", "/c " + innerCommand) { RedirectStandardOutput = redirectOutput, RedirectStandardError = redirectOutput, UseShellExecute = false, - CreateNoWindow = true + CreateNoWindow = true, + WorkingDirectory = workingDirectory }; } else diff --git a/MSUScripter/ViewModels/SettingsWindowViewModel.cs b/MSUScripter/ViewModels/SettingsWindowViewModel.cs index cba0bfa..3d0e21e 100644 --- a/MSUScripter/ViewModels/SettingsWindowViewModel.cs +++ b/MSUScripter/ViewModels/SettingsWindowViewModel.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using MSUScripter.Configs; +using MSUScripter.Models; using ReactiveUI.Fody.Helpers; namespace MSUScripter.ViewModels; @@ -18,7 +19,9 @@ public class SettingsWindowViewModel : ViewModelBase [Reactive] public bool RunMsuPcmWithKeepTemps { get; set; } [Reactive] public bool AutomaticallyRunPyMusicLooper { get; set; } [Reactive] public bool HideSubTracksSubChannelsWarning { get; set; } + [Reactive] public string? PyMusicLooperPath { get; set; } public bool HasDoneFirstTimeSetup { get; set; } + [SkipConvert] public bool CanSetPyMusicLooperPath { get; set; } public override ViewModelBase DesignerExample() { diff --git a/MSUScripter/Views/SettingsWindow.axaml b/MSUScripter/Views/SettingsWindow.axaml index 75ba5cb..1332e1c 100644 --- a/MSUScripter/Views/SettingsWindow.axaml +++ b/MSUScripter/Views/SettingsWindow.axaml @@ -52,6 +52,25 @@ + + + + + + + + diff --git a/MSUScripter/Views/SettingsWindow.axaml.cs b/MSUScripter/Views/SettingsWindow.axaml.cs index 7f21fe7..3b8b7a1 100644 --- a/MSUScripter/Views/SettingsWindow.axaml.cs +++ b/MSUScripter/Views/SettingsWindow.axaml.cs @@ -51,4 +51,19 @@ await MessageWindow.ShowErrorDialog( await MessageWindow.ShowInfoDialog("msupcm++ verification successful!", "Success", this); } } + + private async void ValidatePyMusicLooper_OnClick(object? sender, RoutedEventArgs e) + { + var isSuccessful = _service?.ValidatePyMusicLooper(); + if (isSuccessful != true) + { + await MessageWindow.ShowErrorDialog( + "There was an error verifying PyMusicLooper. Please verify that the application runs independently.", + "PyMusicLooper Error", this); + } + else + { + await MessageWindow.ShowInfoDialog("PyMusicLooper verification successful!", "Success", this); + } + } } \ No newline at end of file