public async Task AddFxbFxpFiles(List <string> files) { List <(string fileName, string reason)> failedFiles = new List <(string, string)>(); foreach (var filename in files) { var result = VstUtils.LoadFxp(filename, Plugin.PluginInfo.ToNonSurrogate()); if (result.result == VstUtils.LoadFxpResult.Error) { failedFiles.Add((filename, result.message)); } else { AddBankFile(filename); } } if (failedFiles.Count > 0) { var sb = new StringBuilder(); sb.AppendLine("The following FXB/FXP files could not be added:"); sb.AppendLine(); foreach (var fail in failedFiles) { sb.AppendLine($"{fail.fileName}: {fail.reason}"); sb.AppendLine(); } await _messageService.ShowErrorAsync(sb.ToString(), "Unable to add some FXB/FXP files", HelpLinks.SETTINGS_PLUGIN_FXBFXPNOTES); } }
public Guid RegisterPlugin(string dllPath, bool backgroundProcessing = true) { App.Ping(); var guid = Guid.NewGuid(); var logFile = VstUtils.GetWorkerPluginLog(Process.GetCurrentProcess().Id, guid); var plugin = new RemoteVstPlugin { DllPath = dllPath, BackgroundProcessing = backgroundProcessing, Logger = new MiniDiskLogger(logFile) }; _plugins.Add(guid, plugin); return(guid); }
private string GetUserContentDirectory() { string userContentDirectory; if (!Directory.Exists(UserContentDirectory)) { userContentDirectory = VstUtils.GetDefaultNativeInstrumentsUserContentDirectory(); } else { userContentDirectory = UserContentDirectory; } var bankDirectory = Path.Combine(userContentDirectory, GetNKSFPluginName(PluginName), GetNKSFBankName()); return(bankDirectory); }
public VstUtils.LoadFxpResult LoadFxp(string filePath) { var result = VstUtils.LoadFxp(filePath, PluginInstance.Plugin.PluginInfo.ToNonSurrogate()); if (result.result == VstUtils.LoadFxpResult.Error) { Logger.Error($"Error loading FXB/FXP {filePath}: {result.message}"); return(result.result); } // If your plug-in is configured to use chunks // the Host will ask for a block of memory describing the current // plug-in state for saving. // To restore the state at a later stage, the same data is passed // back to setChunk. var chunkData = result.fxp.ChunkDataByteArray; PluginInstance.SetProgram(0); PluginInstance.SetChunk(chunkData, result.result == VstUtils.LoadFxpResult.Program); return(result.result); }
protected int GetAdditionalBanksPresetCount() { var presetCount = 0; foreach (var bank in AdditionalBankFiles) { var result = VstUtils.LoadFxp(bank.Path, PluginInstance.Plugin.PluginInfo.ToNonSurrogate()); if (result.result == VstUtils.LoadFxpResult.Error) { continue; } if (result.result == VstUtils.LoadFxpResult.Program) { presetCount++; } else if (result.result == VstUtils.LoadFxpResult.Bank) { var ranges = bank.GetProgramRanges(); if (ranges.Count == 0) { presetCount += PluginInstance.Plugin.PluginInfo.ProgramCount; } else { foreach (var(_, length) in ranges) { presetCount += length; } } } } return(presetCount); }
protected override void OnStartup(StartupEventArgs e) { var path = VstUtils.GetVstWorkerLogDirectory(); var logFile = Path.Combine(path, "PresetMagician.RemoteVstHost" + Process.GetCurrentProcess().Id + ".log"); MiniDiskLogger = new MiniDiskLogger(logFile); AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException; Current.DispatcherUnhandledException += CurrentOnDispatcherUnhandledException; TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException; AppDomain.CurrentDomain.FirstChanceException += CurrentDomainOnFirstChanceException; string address = Constants.BaseAddress + Process.GetCurrentProcess().Id; _serviceHost = new ServiceHost(typeof(RemoteVstService)); var binding = WcfUtils.GetNetNamedPipeBinding(); var dummyWin = new Window(); Current.MainWindow = dummyWin; _serviceHost.AddServiceEndpoint(typeof(IRemoteVstService), binding, address); _serviceHost.Faulted += ServiceHostOnFaulted; _serviceHost.Opened += ServiceHostOnOpened; _serviceHost.Open(); _shutdownTimer = new Timer(); _shutdownTimer.Elapsed += OnIdleTimeout; _shutdownTimer.Interval = 60 * 2 * 1000; // 2 minutes idle timeout _shutdownTimer.Enabled = true; _shutdownTimer.AutoReset = false; base.OnStartup(e); }
public static void Main(string[] args) { FrontendInitializer.RegisterTypes(ServiceLocator.Default); FrontendInitializer.Initialize(ServiceLocator.Default); var vendorPresetParserService = ServiceLocator.Default.ResolveType <VendorPresetParserService>(); var logger = new RollingInMemoryLogListener(); LogManager.AddListener(logger); var pluginTestDirectory = @"C:\Program Files\VSTPlugins"; var testResults = new List <PluginTestResult>(); var presetParserDictionary = vendorPresetParserService.GetPresetHandlerListByPlugin(); var testData = ReadTestData(); var ignoredPlugins = ReadIgnoredPlugins(); List <string> IgnoredPresetParsers = new List <string>(); IgnoredPresetParsers.Add("VoidPresetParser"); var localLogger = new MiniConsoleLogger(); var hasIgnored = false; localLogger.SetConsoleLogLevelFilter(new HashSet <LogLevel> { LogLevel.Error, LogLevel.Warning }); if (args.Length > 0) { foreach (var key in presetParserDictionary.Keys.ToList()) { if (!presetParserDictionary[key].PresetParserType.ToLower().Contains(args[0].ToLower())) { presetParserDictionary.Remove(key); hasIgnored = true; } } } foreach (var presetParserKeyValue in presetParserDictionary) { var presetParser = presetParserKeyValue.Value; var pluginId = presetParserKeyValue.Key; if (IgnoredPresetParsers.Contains(presetParser.PresetParserType)) { continue; } if (IsIgnored(ignoredPlugins, presetParser.PresetParserType, pluginId)) { continue; } Console.Write(presetParser.PresetParserType + ": "); var start = DateTime.Now; var pluginLocation = new PluginLocation { DllPath = @"C:\Program Files\VstPlugins\Foobar.dll", IsPresent = true }; var plugin = new Plugin { VstPluginId = pluginId, PluginLocation = pluginLocation, PluginInfo = new VstPluginInfoSurrogate { ProgramCount = 1, Flags = VstPluginFlags.ProgramChunks, PluginID = pluginId } }; var stubProcess = new StubVstHostProcess(); stubProcess.PluginId = pluginId; var remoteInstance = new RemotePluginInstance(stubProcess, plugin); presetParser.DataPersistence = new NullPresetPersistence(); presetParser.PluginInstance = remoteInstance; presetParser.RootBank = plugin.RootBank.First(); presetParser.Logger.Clear(); presetParser.Logger.MirrorTo(localLogger); var testResult = new PluginTestResult { VendorPresetParser = presetParser.PresetParserType, PluginId = plugin.VstPluginId }; double timeForNumPresets = 0; double timeForDoScan = 0; double totalTime = 0; try { presetParser.Init(); testResult.ReportedPresets = presetParser.GetNumPresets(); timeForNumPresets = (DateTime.Now - start).TotalSeconds; start = DateTime.Now; presetParser.DoScan().GetAwaiter().GetResult(); timeForDoScan = (DateTime.Now - start).TotalSeconds; totalTime = timeForNumPresets + timeForDoScan; } catch (Exception e) { testResult.Error = "Errored"; Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } testResult.Presets = plugin.Presets.Count; var timePerPreset = (totalTime / testResult.Presets) * 1000; // ReSharper disable once LocalizableElement Console.WriteLine( $"{testResult.Presets} parsed in {totalTime:F3}s (avg {timePerPreset:F3}ms / Preset, DoScan {timeForDoScan:F3}s, NumPresets {timeForNumPresets:F3}s"); var testDataEntries = GetTestDataEntries(testData, presetParser.PresetParserType, pluginId); var hasTestDataEntries = testDataEntries.Count > 0; var testDataOk = true; foreach (var preset in plugin.Presets) { if (preset.Metadata.BankPath == "") { testResult.BankMissing++; } foreach (var testDataEntry in testDataEntries.ToList()) { if (preset.Metadata.PresetName == testDataEntry.ProgramName && preset.Metadata.BankPath == testDataEntry.BankPath) { var testFilename = PathUtils.SanitizeFilename( testDataEntry.PresetParser + "." + preset.OriginalMetadata.PresetName + ".testdata"); var myDocumentsTestDataFile = Path.Combine(GetPatchFilesDirectory(), testFilename); var localTestDataFile = Path.Combine("TestData", testFilename); var presetHash = testDataEntry.Hash.TrimEnd(); if (preset.PresetHash != presetHash) { var fileMessage = ""; var wrongPresetData = myDocumentsTestDataFile + ".wrong"; testDataOk = false; if (File.Exists(myDocumentsTestDataFile)) { fileMessage = $"Original preset data in {myDocumentsTestDataFile}" + Environment.NewLine + $"Current (wrong) preset data in {wrongPresetData}"; } else { fileMessage = $"Original preset data not found (expected in {myDocumentsTestDataFile})" + Environment.NewLine + $"Current (wrong) preset data in {wrongPresetData}"; } File.WriteAllBytes(wrongPresetData, LZ4Pickler.Unpickle( NullPresetPersistence.PresetData[preset.OriginalMetadata.SourceFile])); testResult.DetailedErrors.Add( $"Found preset {testDataEntry.ProgramName} with bank path " + $"{testDataEntry.BankPath} but the preset hashes were different. " + $"Expected hash {presetHash} but found hash {preset.PresetHash}" + Environment.NewLine + Environment.NewLine + $"{fileMessage}"); } else { // Check if the file exists in the output directory if (!File.Exists(myDocumentsTestDataFile)) { if (File.Exists(localTestDataFile)) { File.Copy(localTestDataFile, myDocumentsTestDataFile); } else { File.WriteAllBytes(myDocumentsTestDataFile, LZ4Pickler.Unpickle( NullPresetPersistence.PresetData[preset.OriginalMetadata.SourceFile])); } } else { if (!File.Exists(localTestDataFile)) { testResult.DetailedErrors.Add( $"Warning: The preset data file {testFilename} exists in the documents " + "folder but not in the source folder. Copy from documents to git folder. " + "If already done, remember to clean the presetparsertest project."); } } var hash = HashUtils.getIxxHash(File.ReadAllBytes(myDocumentsTestDataFile)); if (hash != presetHash) { testResult.DetailedErrors.Add( $"Warning: The preset data file {myDocumentsTestDataFile} exists but does not match the " + $"preset hash from the reference presets. Expected: {testDataEntry.Hash} found {hash}"); } } testDataEntries.Remove(testDataEntry); } } } if (testDataEntries.Count > 0) { foreach (var missingTestDataEntry in testDataEntries) { var presetHash = missingTestDataEntry.Hash.TrimEnd(); testResult.DetailedErrors.Add( $"Did not find preset {missingTestDataEntry.ProgramName} with bank path " + $"{missingTestDataEntry.BankPath} and hash {presetHash}"); } testResult.IsOK = false; } if (plugin.Presets.Count > 0) { var randomPreset = plugin.Presets.OrderBy(qu => Guid.NewGuid()).First(); testResult.RndHash = randomPreset.PresetHash; testResult.RndPresetName = randomPreset.Metadata.PresetName; testResult.RndBankPath = randomPreset.Metadata.BankPath; } var mockFxp = Path.Combine(Directory.GetCurrentDirectory(), "mock.fxp"); var fxp = new FXP(); fxp.ReadFile(Path.Combine(Directory.GetCurrentDirectory(), "test.fxp")); fxp.FxID = VstUtils.PluginIdNumberToIdString(pluginId); fxp.WriteFile(mockFxp); // Test additional banks var bankFile = new BankFile(); bankFile.Path = mockFxp; bankFile.BankName = "Default"; plugin.AdditionalBankFiles.Clear(); plugin.AdditionalBankFiles.Add(bankFile); bool additionalBankFileCountOk = false; if (presetParser.GetNumPresets() == testResult.ReportedPresets + 1) { additionalBankFileCountOk = true; } else { testResult.Error += " additionalBankFileCount failed"; } plugin.Presets.Clear(); NullPresetPersistence.PresetData.Clear(); presetParser.DoScan().GetAwaiter().GetResult(); var additionalBankFileScanOk = false; if (plugin.Presets.Count == testResult.Presets + 1) { additionalBankFileScanOk = true; } else { testResult.Error += " additionalBankFileScan failed"; } bool bankMissingOk = false; if (NumBankMissingsOk.ContainsKey(testResult.PluginId)) { if (testResult.BankMissing <= NumBankMissingsOk[testResult.PluginId]) { bankMissingOk = true; } } else { if (testResult.BankMissing < 2) { bankMissingOk = true; } } if (hasTestDataEntries && testDataOk && testResult.Presets > 5 && bankMissingOk && testResult.Presets == testResult.ReportedPresets && additionalBankFileCountOk && additionalBankFileScanOk) { testResult.IsOK = true; } testResults.Add(testResult); NullPresetPersistence.PresetData.Clear(); } var consoleTable = ConsoleTable.From(from testRes in testResults where testRes.IsOK == false orderby testRes.Presets select testRes); Console.WriteLine(consoleTable.ToMinimalString()); foreach (var testRes in (from testRes in testResults where testRes.DetailedErrors.Count > 0 orderby testRes.Presets select testRes)) { Console.WriteLine(Environment.NewLine); Console.WriteLine($"Detailed Errors for {testRes.VendorPresetParser}"); Console.WriteLine($"------------------------------------------------------------"); foreach (var detailedError in testRes.DetailedErrors) { Console.WriteLine($"Error #{testRes.DetailedErrors.IndexOf(detailedError)}: {detailedError}"); } } Console.WriteLine($"Stuff left: {consoleTable.Rows.Count} / {presetParserDictionary.Count}"); foreach (var data in GlobalMethodTimeLogger.GetTopMethods()) { Console.WriteLine($"{data.Name}: {data.Duration.TotalSeconds.ToString()}ms"); } if (hasIgnored) { Console.WriteLine("Warning: Filter active!!"); Console.WriteLine("Warning: Filter active!!"); Console.WriteLine("Warning: Filter active!!"); Console.WriteLine("Warning: Filter active!!"); Console.WriteLine("Warning: Filter active!!"); Console.WriteLine("Warning: Filter active!!"); Console.WriteLine("Warning: Filter active!!"); } }
private void OnOpenVstWorkerLogDirectoryExecute() { Process.Start(Path.GetDirectoryName(VstUtils.GetVstWorkerLogDirectory())); }
protected override async void OnStartup(StartupEventArgs e) { var languageService = ServiceLocator.Default.ResolveType <ILanguageService>(); languageService.PreferredCulture = new CultureInfo("en-US"); languageService.FallbackCulture = new CultureInfo("en-US"); #if DEBUG _debugListener = LogManager.AddDebugListener(true); #endif var fileLogListener = new FileLogListener { IgnoreCatelLogging = true, FilePath = FileLocations.LogFile, TimeDisplay = TimeDisplay.DateTime }; LogManager.IgnoreDuplicateExceptionLogging = false; LogManager.AddListener(fileLogListener); LogManager.GetCurrentClassLogger().Debug($"Started with command line {Environment.CommandLine}"); var serviceLocator = ServiceLocator.Default; var updateService = serviceLocator.ResolveType <IUpdateService>(); updateService.Initialize(Settings.Application.AutomaticUpdates.AvailableChannels, Settings.Application.AutomaticUpdates.DefaultChannel, Settings.Application.AutomaticUpdates.CheckForUpdatesDefaultValue); if (updateService.IsUpdateSystemAvailable) { LogManager.GetCurrentClassLogger().Debug("Update system available, processing squirrel events"); using (var mgr = new UpdateManager(updateService.CurrentChannel.DefaultUrl)) { // Note, in most of these scenarios, the app exits after this method // completes! SquirrelAwareApp.HandleEvents( onInitialInstall: v => { LogManager.GetCurrentClassLogger().Debug("Installing shortcuts"); mgr.CreateShortcutForThisExe(); Environment.Exit(0); }, onAppUpdate: v => { LogManager.GetCurrentClassLogger().Debug("Update: Installing shortcuts"); mgr.CreateShortcutForThisExe(); Environment.Exit(0); }, onAppUninstall: v => { mgr.RemoveShortcutForThisExe(); Environment.Exit(0); }); } } LogManager.GetCurrentClassLogger().Debug("Startup"); try { RotateLogFile(fileLogListener.FilePath); } catch (Exception exception) { LogManager.GetCurrentClassLogger().Error("Tried to rotate the log file, but it failed."); LogManager.GetCurrentClassLogger().Error(exception); MessageBox.Show( $"Unable to rotate the log file {fileLogListener.FilePath}. Please verify that you have access to that file. " + $"We will continue, but no logging will be available. Additional information: {Environment.NewLine}{Environment.NewLine}{exception}", "Log File Error", MessageBoxButton.OK, MessageBoxImage.Error); } // Clean up old RemoteVstHost logs VstUtils.CleanupVstWorkerLogDirectory(); await StartShell(); }
public List <PluginInfoItem> GetPluginInfoItems(IVstPluginContext pluginContext) { var pluginInfoItems = new List <PluginInfoItem>(); if (pluginContext == null) { return(pluginInfoItems); } // plugin product pluginInfoItems.Add(new PluginInfoItem("Base", "Plugin Name", pluginContext.PluginCommandStub.GetEffectName())); pluginInfoItems.Add(new PluginInfoItem("Base", "Product", pluginContext.PluginCommandStub.GetProductString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Vendor", pluginContext.PluginCommandStub.GetVendorString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Vendor Version", pluginContext.PluginCommandStub.GetVendorVersion().ToString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Vst Support", pluginContext.PluginCommandStub.GetVstVersion().ToString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Plugin Category", pluginContext.PluginCommandStub.GetCategory().ToString())); // plugin info pluginInfoItems.Add(new PluginInfoItem("Base", "Flags", pluginContext.PluginInfo.Flags.ToString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Plugin ID", pluginContext.PluginInfo.PluginID.ToString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Plugin ID String", VstUtils.PluginIdNumberToIdString(pluginContext.PluginInfo.PluginID))); pluginInfoItems.Add(new PluginInfoItem("Base", "Plugin Version", pluginContext.PluginInfo.PluginVersion.ToString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Audio Input Count", pluginContext.PluginInfo.AudioInputCount.ToString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Audio Output Count", pluginContext.PluginInfo.AudioOutputCount.ToString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Initial Delay", pluginContext.PluginInfo.InitialDelay.ToString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Program Count", pluginContext.PluginInfo.ProgramCount.ToString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Parameter Count", pluginContext.PluginInfo.ParameterCount.ToString())); pluginInfoItems.Add(new PluginInfoItem("Base", "Tail Size", pluginContext.PluginCommandStub.GetTailSize().ToString())); // can do pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.Bypass), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.Bypass)).ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.MidiProgramNames), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.MidiProgramNames)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.Offline), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.Offline)).ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.ReceiveVstEvents), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.ReceiveVstEvents)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.ReceiveVstMidiEvent), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.ReceiveVstMidiEvent)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.ReceiveVstTimeInfo), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.ReceiveVstTimeInfo)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.SendVstEvents), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.SendVstEvents)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.SendVstMidiEvent), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.SendVstMidiEvent)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.ConformsToWindowRules), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.ConformsToWindowRules)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.Metapass), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.Metapass)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.MixDryWet), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.MixDryWet)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.Multipass), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.Multipass)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.NoRealTime), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.NoRealTime)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.PlugAsChannelInsert), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.PlugAsChannelInsert)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.PlugAsSend), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.PlugAsSend)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.SendVstTimeInfo), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.SendVstTimeInfo)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.x1in1out), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.x1in1out)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.x1in2out), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.x1in2out)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.x2in1out), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.x2in1out)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.x2in2out), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.x2in2out)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.x2in4out), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.x2in4out)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.x4in2out), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.x4in2out)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.x4in4out), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.x4in4out)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.x4in8out), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.x4in8out)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.x8in4out), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.x8in4out)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("CanDo", nameof(VstPluginCanDo.x8in8out), pluginContext.PluginCommandStub.CanDo(VstCanDoHelper.ToString(VstPluginCanDo.x8in8out)) .ToString())); pluginInfoItems.Add(new PluginInfoItem("Program", "Current Program Index", pluginContext.PluginCommandStub.GetProgram().ToString())); pluginInfoItems.Add(new PluginInfoItem("Program", "Current Program Name", pluginContext.PluginCommandStub.GetProgramName())); return(pluginInfoItems); }