Initial commit

This commit is contained in:
2024-03-26 13:44:49 -05:00
commit 7fbe51f482
24 changed files with 103489 additions and 0 deletions

30
HidSliders.Gui/App.config Normal file
View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="VoicemeeterSliders.Gui.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<VoicemeeterSliders.Gui.Properties.Settings>
<setting name="VMVersion" serializeAs="String">
<value>0</value>
</setting>
<setting name="Channel1Strip" serializeAs="String">
<value>0</value>
</setting>
<setting name="Channel2Strip" serializeAs="String">
<value>0</value>
</setting>
<setting name="Channel3Strip" serializeAs="String">
<value>0</value>
</setting>
<setting name="Channel4Strip" serializeAs="String">
<value>0</value>
</setting>
<setting name="Channel5Strip" serializeAs="String">
<value>0</value>
</setting>
</VoicemeeterSliders.Gui.Properties.Settings>
</userSettings>
</configuration>

View File

@@ -0,0 +1,80 @@
using Voicemeeter;
namespace HidSliders.Gui;
public class ChannelControlCollection
{
public NumericUpDown ChannelSelector { get; }
public TrackBar TrackBar { get; }
public CheckBox BusA1Checkbox { get; }
public CheckBox BusA2Checkbox { get; }
public CheckBox BusA3Checkbox { get; }
public CheckBox BusA4Checkbox { get; }
public CheckBox BusA5Checkbox { get; }
public CheckBox BusB1Checkbox { get; }
public CheckBox BusB2Checkbox { get; }
public CheckBox BusB3Checkbox { get; }
public CheckBox SoloCheckBox { get; }
public CheckBox MuteCheckBox { get; }
public int CurrentStrip => (int)ChannelSelector.Value;
public ChannelControlCollection(NumericUpDown channelSelector, TrackBar trackBar, CheckBox busA1Checkbox, CheckBox busA2Checkbox, CheckBox busA3Checkbox, CheckBox busA4Checkbox, CheckBox busA5Checkbox, CheckBox busB1Checkbox, CheckBox busB2Checkbox, CheckBox busB3Checkbox, CheckBox soloCheckBox, CheckBox muteCheckBox)
{
ChannelSelector = channelSelector;
TrackBar = trackBar;
BusA1Checkbox = busA1Checkbox;
BusA1Checkbox.Tag = VMBus.A1;
BusA2Checkbox = busA2Checkbox;
BusA2Checkbox.Tag = VMBus.A2;
BusA3Checkbox = busA3Checkbox;
BusA3Checkbox.Tag = VMBus.A3;
BusA4Checkbox = busA4Checkbox;
BusA4Checkbox.Tag = VMBus.A4;
BusA5Checkbox = busA5Checkbox;
BusA5Checkbox.Tag = VMBus.A5;
BusB1Checkbox = busB1Checkbox;
BusB1Checkbox.Tag = VMBus.B1;
BusB2Checkbox = busB2Checkbox;
BusB2Checkbox.Tag = VMBus.B2;
BusB3Checkbox = busB3Checkbox;
BusB3Checkbox.Tag = VMBus.B3;
SoloCheckBox = soloCheckBox;
MuteCheckBox = muteCheckBox;
}
public void EnableBusses(RunVoicemeeterParam version)
{
BusA1Checkbox.Enabled = true;
BusB1Checkbox.Enabled = true;
if (version > RunVoicemeeterParam.Voicemeeter)
{
BusA2Checkbox.Enabled = true;
BusA3Checkbox.Enabled = true;
BusB2Checkbox.Enabled = true;
}
if (version > RunVoicemeeterParam.VoicemeeterBanana)
{
BusA4Checkbox.Enabled = true;
BusA5Checkbox.Enabled = true;
BusB3Checkbox.Enabled = true;
}
}
public bool OwnsControl(Control control)
{
return control == ChannelSelector ||
control == TrackBar ||
control == BusA1Checkbox ||
control == BusA2Checkbox ||
control == BusA3Checkbox ||
control == BusA4Checkbox ||
control == BusA5Checkbox ||
control == BusB1Checkbox ||
control == BusB2Checkbox ||
control == BusB3Checkbox ||
control == SoloCheckBox ||
control == MuteCheckBox;
}
}

1050
HidSliders.Gui/Form1.Designer.cs generated Normal file

File diff suppressed because it is too large Load Diff

293
HidSliders.Gui/Form1.cs Normal file
View File

@@ -0,0 +1,293 @@
using System.Diagnostics;
using System.Reflection;
using HidLibrary;
using Voicemeeter;
using VoiceMeeter;
namespace HidSliders.Gui
{
public partial class Form1 : Form
{
private IDisposable? _vmClient;
private IHidDevice? _hidDevice;
private const float Resolution = 72.0f;
private readonly List<ChannelControlCollection> _channels;
public Form1()
{
InitializeComponent();
_channels = new List<ChannelControlCollection>
{
new (numericUpDown1, trackBar1, ch1A1Checkbox, ch1A2Checkbox, ch1A3Checkbox, ch1A4Checkbox, ch1A5Checkbox, ch1B1Checkbox, ch1B2Checkbox, ch1B3Checkbox, checkBox1, checkBox2),
new (numericUpDown2, trackBar2, checkBox12, checkBox11, checkBox10, checkBox9, checkBox8, checkBox7, checkBox6, checkBox5, checkBox4, checkBox3),
new (numericUpDown3, trackBar3, checkBox22, checkBox21, checkBox20, checkBox19, checkBox18, checkBox17, checkBox16, checkBox15, checkBox14, checkBox13),
new (numericUpDown4, trackBar4, checkBox32, checkBox31, checkBox30, checkBox29, checkBox28, checkBox27, checkBox26, checkBox25, checkBox24, checkBox23),
new (numericUpDown5, trackBar5, checkBox42, checkBox41, checkBox40, checkBox39, checkBox38, checkBox37, checkBox36, checkBox35, checkBox34, checkBox33),
};
switch (Properties.Settings.Default.VMVersion)
{
case 1:
vmRadio.Checked = true;
break;
case 2:
vmBananaRadio.Checked = true;
break;
case 3:
vmPotatoRadio.Checked = true;
break;
}
_channels[0].ChannelSelector.Value = Properties.Settings.Default.Channel1Strip;
_channels[1].ChannelSelector.Value = Properties.Settings.Default.Channel2Strip;
_channels[2].ChannelSelector.Value = Properties.Settings.Default.Channel3Strip;
_channels[3].ChannelSelector.Value = Properties.Settings.Default.Channel4Strip;
_channels[4].ChannelSelector.Value = Properties.Settings.Default.Channel5Strip;
var enumerator = new HidEnumerator();
var hidDevices = enumerator.Enumerate(0x0359, [0x6497]);
_hidDevice = hidDevices.FirstOrDefault();
label1.Text = $"Mixer {(_hidDevice?.IsConnected == true ? "" : "not ")}connected";
}
private async void connectButton_Click(object sender, EventArgs e)
{
RunVoicemeeterParam version = RunVoicemeeterParam.None;
if (vmRadio.Checked)
{
version = RunVoicemeeterParam.Voicemeeter;
}
else if (vmBananaRadio.Checked)
{
version = RunVoicemeeterParam.VoicemeeterBanana;
}
else if (vmPotatoRadio.Checked)
{
version = RunVoicemeeterParam.VoicemeeterPotato;
}
Properties.Settings.Default.VMVersion = (int)version;
_vmClient = await Remote.Initialize(version);
if (_vmClient != null)
{
EnableVMControls(version);
}
}
private void EnableVMControls(RunVoicemeeterParam version)
{
foreach (var channel in _channels)
{
channel.TrackBar.Enabled = true;
channel.SoloCheckBox.Enabled = true;
channel.MuteCheckBox.Enabled = true;
channel.EnableBusses(version);
SyncChannelControls(channel);
}
}
private void SyncChannelControls(ChannelControlCollection channel)
{
channel.BusA1Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.A1);
channel.BusB1Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.B1);
if (vmBananaRadio.Checked || vmPotatoRadio.Checked)
{
channel.BusA2Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.A2);
channel.BusA3Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.A3);
channel.BusB2Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.B2);
}
if (vmPotatoRadio.Checked)
{
channel.BusA4Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.A4);
channel.BusA5Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.A5);
channel.BusB3Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.B3);
}
channel.TrackBar.Value = (int)GetStripGain(channel.CurrentStrip);
channel.SoloCheckBox.Checked = GetChannelSolo(channel.CurrentStrip);
channel.MuteCheckBox.Checked = GetChannelMute(channel.CurrentStrip);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_vmClient?.Dispose();
Properties.Settings.Default.Save();
}
private async void button1_Click(object sender, EventArgs e)
{
if (_hidDevice == null) return;
var stopwatch = new Stopwatch();
while (true)
{
if (_hidDevice.IsConnected)
{
button1.Enabled = false;
stopwatch.Start();
//label1.Text = "waiting for report";
var progress = new Progress<string>();
progress.ProgressChanged += (o, s) => label1.Text = s;
var report = await Task.Run(() => _hidDevice.ReadReport());
var labelText = string.Empty;
if (report.ReadStatus == HidDeviceData.ReadStatus.Success)
{
var reportChunk = new byte[2];
for (int i = 0; i < 5; i++)
{
Array.Copy(report.Data, i * 2, reportChunk, 0, 2);
var sliderVal = BitConverter.ToInt16(reportChunk);
var gain = HidToGain(sliderVal);
labelText += $"Value {i}: {sliderVal} ({gain}dB)\n";
SetStripGain(_channels[i].CurrentStrip, gain);
_channels[i].TrackBar.Value = (int)gain;
}
}
stopwatch.Stop();
labelText += $"Report time: {stopwatch.ElapsedMilliseconds}ms";
stopwatch.Reset();
label1.Text = labelText;
//button1.Enabled = true;
}
else
{
button1.Enabled = true;
}
}
}
private float HidToGain(int hidValue)
{
// adjusted regression of yamaha board is approx y = 5.8456 + 17.0486 * ln(x)
// Truncate to first decimal (move decimal, int truncate, move decimal)
var realResult = 5.8456f + 17.0486f * (float)Math.Log(Math.Max(hidValue / Resolution, 0.02));
return ((int)(realResult * 10)) / 10.0f;
}
private void trackBar_Scroll(object sender, EventArgs e)
{
if (sender is TrackBar trackBar && _vmClient != null)
{
var channel = _channels.First(c => c.OwnsControl(trackBar));
SetStripGain(channel.CurrentStrip, trackBar.Value);
}
}
private void busCheckbox_CheckedChanged(object sender, EventArgs e)
{
if (sender is CheckBox { Tag: VMBus bus } checkBox && _vmClient != null)
{
var channel = _channels.First(c => c.OwnsControl(checkBox));
SetBusEnabled(channel.CurrentStrip, bus, checkBox.Checked);
}
}
private void SetStripGain(int strip, float value)
{
Remote.SetParameter($"Strip[{strip}].Gain", value);
}
private float GetStripGain(int index)
{
return Remote.GetParameter($"Strip[{index}].Gain");
}
private void vmRadio_CheckedChanged(object sender, EventArgs e)
{
if (vmRadio.Checked)
{
setMaxChannel(2);
}
}
private void vmBananaRadio_CheckedChanged(object sender, EventArgs e)
{
if (vmBananaRadio.Checked)
{
setMaxChannel(4);
}
}
private void setMaxChannel(int max)
{
numericUpDown1.Maximum = max;
numericUpDown2.Maximum = max;
numericUpDown3.Maximum = max;
numericUpDown4.Maximum = max;
numericUpDown5.Maximum = max;
}
private void vmPotatoRadio_CheckedChanged(object sender, EventArgs e)
{
if (vmPotatoRadio.Checked)
{
setMaxChannel(7);
}
}
private void SetBusEnabled(int strip, VMBus bus, bool enabled)
{
Remote.SetParameter($"Strip[{strip}].{bus}", enabled ? 1 : 0);
}
private bool GetBusEnabled(int strip, VMBus bus)
{
return (int)Remote.GetParameter($"Strip[{strip}].{bus}") == 1;
}
private void SetChannelSolo(int strip, bool enabled)
{
Remote.SetParameter($"Strip[{strip}].Solo", enabled ? 1 : 0);
}
private bool GetChannelSolo(int strip)
{
return (int)Remote.GetParameter($"Strip[{strip}].Solo") == 1;
}
private void SetChannelMute(int strip, bool enabled)
{
Remote.SetParameter($"Strip[{strip}].Mute", enabled ? 1 : 0);
}
private bool GetChannelMute(int strip)
{
return (int)Remote.GetParameter($"Strip[{strip}].Mute") == 1;
}
private void numericUpDown_ValueChanged(object sender, EventArgs e)
{
if (sender is NumericUpDown numericUpDown)
{
var channel = _channels.First(c => c.OwnsControl(numericUpDown));
if (_vmClient != null)
{
SyncChannelControls(channel);
}
var index = _channels.FindIndex(c => c == channel);
var settingsType = Properties.Settings.Default.GetType();
settingsType.GetProperty($"Channel{index + 1}Strip").SetValue(Properties.Settings.Default, (int)numericUpDown.Value);
}
}
private void soloCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (sender is CheckBox checkBox && _vmClient != null)
{
var channel = _channels.First(c => c.OwnsControl(checkBox));
SetChannelSolo(channel.CurrentStrip, checkBox.Checked);
}
}
private void muteCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (sender is CheckBox checkBox && _vmClient != null)
{
var channel = _channels.First(c => c.OwnsControl(checkBox));
SetChannelMute(channel.CurrentStrip, checkBox.Checked);
}
}
}
}

123
HidSliders.Gui/Form1.resx Normal file
View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="backgroundWorker1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="hidlibrary" Version="3.3.40" />
<PackageReference Include="VoicemeeterRemote" Version="1.0.3" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
</Project>

17
HidSliders.Gui/Program.cs Normal file
View File

@@ -0,0 +1,17 @@
namespace HidSliders.Gui
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
}

View File

@@ -0,0 +1,98 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace HidSliders.Gui.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int VMVersion {
get {
return ((int)(this["VMVersion"]));
}
set {
this["VMVersion"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int Channel1Strip {
get {
return ((int)(this["Channel1Strip"]));
}
set {
this["Channel1Strip"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int Channel2Strip {
get {
return ((int)(this["Channel2Strip"]));
}
set {
this["Channel2Strip"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int Channel3Strip {
get {
return ((int)(this["Channel3Strip"]));
}
set {
this["Channel3Strip"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int Channel4Strip {
get {
return ((int)(this["Channel4Strip"]));
}
set {
this["Channel4Strip"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int Channel5Strip {
get {
return ((int)(this["Channel5Strip"]));
}
set {
this["Channel5Strip"] = value;
}
}
}
}

View File

@@ -0,0 +1,24 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="VoicemeeterSliders.Gui.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="VMVersion" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="Channel1Strip" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="Channel2Strip" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="Channel3Strip" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="Channel4Strip" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="Channel5Strip" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
</Settings>
</SettingsFile>

6
HidSliders.Gui/VMBus.cs Normal file
View File

@@ -0,0 +1,6 @@
namespace HidSliders.Gui;
public enum VMBus
{
A1, A2, A3, A4, A5, B1, B2, B3
}