Skip to content

Commit

Permalink
UI now available via context menu on node or new Show/HideUI nodes on…
Browse files Browse the repository at this point in the history
… optional state output - needs latest vvvv build (not available yet)
  • Loading branch information
azeno committed Dec 10, 2024
1 parent c9c2ded commit cd90d10
Show file tree
Hide file tree
Showing 25 changed files with 265 additions and 249 deletions.
6 changes: 3 additions & 3 deletions VL.Audio.VST.vl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Document xmlns:p="property" xmlns:r="reflection" Id="UgcPFn5dcR2MW546v4XLqB" LanguageVersion="2024.6.7-0208-g078c5b3e84" Version="0.128">
<NugetDependency Id="UIwWjVtDngaQQN9ruSCYBE" Location="VL.CoreLib" Version="2024.6.7-0208-g078c5b3e84" />
<Document xmlns:p="property" xmlns:r="reflection" Id="UgcPFn5dcR2MW546v4XLqB" LanguageVersion="2024.6.7-0275-g694e82c3e3" Version="0.128">
<NugetDependency Id="UIwWjVtDngaQQN9ruSCYBE" Location="VL.CoreLib" Version="2024.6.7-0275-g694e82c3e3" />
<Patch Id="Qg9qJ1DPxuBMSYmlRd5fkQ">
<Canvas Id="HUKa0nTRGahMHSYnC7lmL0" DefaultCategory="Audio.VST" CanvasType="FullCategory" />
<!--
Expand All @@ -25,6 +25,6 @@
</Node>
</Patch>
<NugetDependency Id="PtRn3YsB37lPncqYUJefPp" Location="VL.Audio" IsForward="true" Version="1.8.4" />
<PlatformDependency Id="AFxd1LZA6evPGCWAh66A2Y" Location="./lib/net8.0-windows/VL.Audio.VST.dll" />
<PlatformDependency Id="AFxd1LZA6evPGCWAh66A2Y" Location="./lib/net8.0-windows/VL.Audio.VST.dll" IsForward="true" />
<NodeFactoryDependency Id="IFiy7md81vcL9q1xd8NlAm" Location="VL.Audio.VST.Nodes" IsForward="true" />
</Document>
2 changes: 1 addition & 1 deletion deployment/VL.Audio.VST.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<readme>docs\README.md</readme>
<dependencies>
<group targetFramework="net8.0-windows7.0">
<dependency id="VL.Audio" version="1.9.2" />
<dependency id="VL.Audio" version="1.9.3" />
</group>
</dependencies>
</metadata>
Expand Down
17 changes: 5 additions & 12 deletions sandbox/VSTHost/Form1.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
using Microsoft.VisualBasic.Devices;
using NAudio.Wave;
using Sanford.Multimedia.Midi;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.Marshalling;
using VL.Audio;
using VL.Audio.VST;
using VL.Core;
using VL.Audio.VST.Internal;
using VST3;
using VST3.Hosting;
using Utils = VL.Audio.VST.Utils;
Expand Down Expand Up @@ -62,7 +55,7 @@ protected override void OnHandleCreated(EventArgs e)
var processor = (IAudioProcessor)component;
var controller = plugProvider.Controller;

var outputSignal = new BufferCallerSignal()
var outputSignal = new VL.Audio.BufferCallerSignal()
{
};

Expand All @@ -78,8 +71,8 @@ protected override void OnHandleCreated(EventArgs e)
{
ProcessMode = ProcessModes.Realtime,
SymbolicSampleSize = Utils.GetSymbolicSampleSizes(outputSignal.WaveFormat),
MaxSamplesPerBlock = Math.Max(AudioService.Engine.Settings.BufferSize, 4096),
SampleRate = AudioService.Engine.Settings.SampleRate
MaxSamplesPerBlock = Math.Max(VL.Audio.AudioService.Engine.Settings.BufferSize, 4096),
SampleRate = VL.Audio.AudioService.Engine.Settings.SampleRate
});


Expand All @@ -88,7 +81,7 @@ protected override void OnHandleCreated(EventArgs e)
component.activateBus(MediaTypes.kEvent, BusDirections.kInput, 0, true);

component.setActive(true);
processor.SetProcessing_IgnoreNotImplementedException(true);
processor.setProcessing(true);


if (controller != null)
Expand Down
1 change: 1 addition & 0 deletions src/EffectHost.Audio.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Buffers;
using System.Runtime.InteropServices;
using VL.Audio.VST.Internal;
using VST3;

namespace VL.Audio.VST;
Expand Down
1 change: 1 addition & 0 deletions src/EffectHost.Midi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VL.Audio.VST.Internal;
using VL.Lib.IO.Midi;
using VST3;

Expand Down
135 changes: 9 additions & 126 deletions src/EffectHost.Reflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using System.Reactive.Linq;
using System.Runtime.CompilerServices;
using VL.Audio.VST.Internal;
using VL.Core;
using VL.Core.Reactive;
using VL.Lib.Collections;
Expand All @@ -16,6 +17,7 @@ partial class EffectHost : IVLObject, INotifyPropertyChanged
{
private DynamicTypeInfo? type;
private IDisposable? propertyChangedSubscription;
private event PropertyChangedEventHandler? propertyChanged;

IVLTypeInfo IVLObject.Type => type ??= new DynamicTypeInfo()
{
Expand All @@ -24,7 +26,12 @@ partial class EffectHost : IVLObject, INotifyPropertyChanged
LoadProperties = typeInfo => LoadProperties(typeInfo, this)
};

public event PropertyChangedEventHandler? PropertyChanged;

event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged
{
add => propertyChanged += value;
remove => propertyChanged -= value;
}

private IEnumerable<IVLPropertyInfo> LoadProperties(DynamicTypeInfo typeInfo, EffectHost effectHost)
{
Expand All @@ -38,7 +45,7 @@ private IEnumerable<IVLPropertyInfo> LoadProperties(DynamicTypeInfo typeInfo, Ef

propertyChangedSubscription = ParameterChanged
.Where(x => x.parameter.UnitId == Constants.kRootUnitId && ExposeAsProperty(in x.parameter))
.Subscribe(x => PropertyChanged?.Invoke(effectHost, new PropertyChangedEventArgs(x.parameter.Title)));
.Subscribe(x => propertyChanged?.Invoke(effectHost, new PropertyChangedEventArgs(x.parameter.Title)));

IEnumerable<IVLPropertyInfo> LoadPropertiesForUnit(IVLTypeInfo declaringType, int unitId)
{
Expand Down Expand Up @@ -108,127 +115,3 @@ static bool ExposeAsProperty(in ParameterInfo p)
!p.Flags.HasFlag(ParameterInfo.ParameterFlags.kIsBypass);
}
}

// TODO: vvvv crashes if not public
public sealed class DynamicObject : IVLObject, INotifyPropertyChanged
{
private PropertyChangedEventHandler? propertyChangedEventHandler;
private IDisposable? propertyChangedSubscription;
private int refCount;

public required IVLTypeInfo Type { get; init; }
public AppHost AppHost { get; init; } = AppHost.Current;
public NodeContext Context { get; init; } = NodeContext.CurrentRoot;
public uint Identity { get; init; }
public IObservable<PropertyChangedEventArgs>? PropertyChangedSource { get; init; }

// Needs to be a public event - using explicit implementation crashes Observable.FromEventPattern
public event PropertyChangedEventHandler? PropertyChanged
{
add
{
propertyChangedEventHandler += value;

if (Interlocked.Increment(ref refCount) == 1)
propertyChangedSubscription = PropertyChangedSource?.Subscribe(e => propertyChangedEventHandler?.Invoke(this, e));
}

remove
{
propertyChangedEventHandler -= value;

if (Interlocked.Decrement(ref refCount) == 0)
propertyChangedSubscription?.Dispose();
}
}

IVLObject IVLObject.With(IReadOnlyDictionary<string, object> values)
{
IVLObject that = this;
foreach (var (key, value) in values)
{
var property = Type.GetProperty(key);
if (property is null)
throw new Exception($"Property '{key}' not found on type '{Type}'");
that = property.WithValue(that, value);
}
return that;
}

object IVLObject.ReadProperty(string key)
{
var property = Type.GetProperty(key);
if (property is null)
throw new Exception($"Property '{key}' not found on type '{Type}'");
return property.GetValue(this);
}
}

public sealed class DynamicTypeInfo : IVLTypeInfo
{
private Spread<IVLPropertyInfo>? properties;

public required string Name { get; init; }
public required string Category { get; init; }
public required Func<DynamicTypeInfo, IEnumerable<IVLPropertyInfo>> LoadProperties { get; init; }

public Func<NodeContext, object>? CreateInstance { get; init; }

public Func<object>? GetDefaultValue { get; init; }

public string FullName => $"{Category}.{Name}";

public UniqueId Id => default;

public Type ClrType { get; init; } = typeof(object);

public bool IsPatched => false;

public bool IsClass => true;

public bool IsRecord => false;

public bool IsImmutable => false;

public bool IsInterface => false;

public Spread<IVLPropertyInfo> Properties => properties ??= LoadProperties(this).ToSpread();

Spread<IVLPropertyInfo> IVLTypeInfo.AllProperties => Properties;

object? IVLTypeInfo.CreateInstance(NodeContext context) => CreateInstance?.Invoke(context);

public Spread<Attribute> Attributes { get; init; } = Spread<Attribute>.Empty;

object? IVLTypeInfo.GetDefaultValue() => GetDefaultValue?.Invoke();

public IVLPropertyInfo? GetProperty(string name)
{
return Properties.FirstOrDefault(p => p.OriginalName == name);
}

public IVLTypeInfo MakeGenericType(IReadOnlyList<IVLTypeInfo> arguments)
{
throw new NotImplementedException();
}

public string ToString(bool includeCategory) => includeCategory ? FullName : Name;
}

public sealed class DynamicPropertyInfo : IVLPropertyInfo
{
public required IVLTypeInfo DeclaringType { get; init; }
public required string Name { get; init; }
public required IVLTypeInfo Type { get; init; }
public required Func<IVLObject, object> GetValue { get; init; }
public Func<IVLObject, object, IVLObject>? WithValue { get; init; }

public uint Id { get; init; }
public string NameForTextualCode => Name;
public string OriginalName => Name;
public bool IsManaged { get; init; }
public bool ShouldBeSerialized { get; init; }
public Spread<Attribute> Attributes { get; init; } = Spread<Attribute>.Empty;
object IVLPropertyInfo.GetValue(IVLObject instance) => GetValue(instance);
IVLObject IVLPropertyInfo.WithValue(IVLObject instance, object value) => WithValue?.Invoke(instance, value) ?? instance;
}
21 changes: 11 additions & 10 deletions src/EffectHost.UI.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
using Microsoft.Extensions.Logging;
using System.Drawing;
using System.Windows.Forms;
using VST3.Hosting;
using VST3;
using System.Runtime.InteropServices.Marshalling;
using System.Reactive.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using VL.Lang.PublicAPI;
using VL.Audio.VST.Internal;
using VST3.Hosting;

namespace VL.Audio.VST;

partial class EffectHost
{
private Form? window;

private void ShowEditor()
public void ShowUI()
{
if (controller is null)
return;
Expand Down Expand Up @@ -71,6 +72,13 @@ private void ShowEditor()
window.Activate();
}

public void HideUI()
{
window?.Close();
window?.Dispose();
window = null;
}

void SaveCurrentWindowBounds()
{
if (window is null || window.IsDisposed || boundsPin.Value is null)
Expand All @@ -90,13 +98,6 @@ private void SetWindowBounds(Stride.Core.Mathematics.RectangleF bounds)
window.ClientSize = new Size((int)bounds.Width, (int)bounds.Height);
}

private void HideEditor()
{
window?.Close();
window?.Dispose();
window = null;
}

[GeneratedComClass]
sealed partial class Window : Form, IPlugFrame
{
Expand Down
Loading

0 comments on commit cd90d10

Please sign in to comment.