diff --git a/README.md b/README.md index 2c506bb..dd6cfa7 100644 --- a/README.md +++ b/README.md @@ -3,23 +3,17 @@ VoiceMeeter integration and live feedback for the Elgato Stream Deck device. **Author's website and contact information:** [https://barraider.com](https://barraider.com) -## What's new in v1.8 -- `AND/OR` support on the Mode1 Check in the `Advanced Toggle`! You can now do things like `Strip[0].Mute AND Strip[1].B2` or `Strip[0].Solo OR Strip[0].B2 OR Strip[1].B1` -- Customizable `Long Press` length on the Press/Long-Press action -- **Hotkey Support** :star_struck: - All advanced actions now support sending hotkeys to integrate with the :voicemeeter: Macros -- **Midi Support** :star_struck: :star_struck: - All advanced actions now support the :voicemeeter: `SendMidi` commands -- Support for `\n` (new line) in the Enabled/Disabled Texts - -## What's new in 1.7 -- VM Advanced actions now support renaming values that show 1 / 0 to a user-defined text (On/Off or Enabled/Disabled, etc.) -- Bugfix in which the second image was not stored correctly in the VM Advanced Toggle action -- Moved actions to a "VoiceMeeter" category in the Stream Deck app +## New in v1.9 +- :new: **MacroButton support!** Toggle VoiceMeeter Macro Buttons from the Stream Deck + - Supports both "Toggle" mode and "PTT" mode. +- `Mute/Unmute` action now supports sending hotkeys +- Core improvements and bug fixes ### Download: https://github.com/BarRaider/streamdeck-voicemeeter/releases/ ## Current functionality -### 5 Plugins built into one: +### 6 Plugins built into one: #### VoiceMeeter Mute/Unmute - Allows you to easily connect to one of VoiceMeeter's Strips or Buses - 3 different modes: Toggle/Push-To-Talk/Single Setting (on/off) @@ -62,6 +56,9 @@ https://github.com/BarRaider/streamdeck-voicemeeter/releases/ #### VoiceMeeter Advanced PTT The `Advanced PTT` action allows you to set a bunch of settings until you release the key. +#### MacroButton Toggle +Allows running VoiceMeeter macros from the Stream Deck. Supports both Toggle and Push modes. The `Logical ID` number is shown at the top-center of every VoiceMeeter macro. + ### Fields explained: - Mode1 Key Press - The configuration to set when we're toggling into Mode1 -> Use this to turn ON the setting e.g. `Strip[0].Mute=1` - Mode1 Check - True/False value to determine if we're in Mode1. Example: If you input: `Strip[0].Mute` the plugin will determine you're in Mode1 every time Strip0 is muted. @@ -73,6 +70,24 @@ The `Advanced PTT` action allows you to set a bunch of settings until you releas - Title Value - Value to display in the title. Example: If you input: `Strip[0].Mono` it will display `1` when Mono is enabled on Strip0 and `0` otherwise. +### Midi Usage +You can trigger Midi functions using the SendMidi command from the Advanced Actions. +Syntax: `SendMidi(DEVICE_NAME, COMMAND, CHANNEL, KEY_ID, VALUE);` + +**DEVICE_NAME:** Name of your device. Start of the name is good too (i.e. nano instead of nanoKORG). +Name can be found in VoiceMeeter Macro under `MIDI OUT1 device: + + +**COMMAND:** One of 3 options: + - note-on + - note-of + - ctrl-change + +**CHANNEL:** Integer value between 1 to 16 + +**KEY_ID:** The id of the Midi key to turn on/off. This can be found using the LEARN feature inside VoiceMeeter Macro: + + ### FAQ Q: Can I use this plugin to Restart VoiceMeeter? A: Yes! Choose one of the "VoiceMeeter Advanced" plugins and use the following command: `Command.Restart = 1;` @@ -86,6 +101,11 @@ A: Valid values can be found starting on page 9 of VoiceMeeter API PDF: https:// Q: Can I make the title multi-line? A: Yes, write `\n` in the `Title Prefix` parameter to add lines +Q: Is there AND/OR support for Mode1 Check? +A: Yes, there is now `AND/OR` support on the Mode1 Check in the `Advanced Toggle`! You can now do things like `Strip[0].Mute AND Strip[1].B2` or `Strip[0].Solo OR Strip[0].B2 OR Strip[1].B1` + +Q: Where can I find the Macro `Logical ID`? +A: The `Logical ID` number is shown at the top-center of every VoiceMeeter macro. ### Download * [Download plugin](https://github.com/BarRaider/streamdeck-voicemeeter/releases/) @@ -98,4 +118,18 @@ Please contact the developer. Contact information is available at https://barrai ## Dependencies * Uses StreamDeck-Tools by BarRaider: [![NuGet](https://img.shields.io/nuget/v/streamdeck-tools.svg?style=flat)](https://www.nuget.org/packages/streamdeck-tools) -* Uses [Easy-PI](https://github.com/BarRaider/streamdeck-easypi) by BarRaider - Provides seamless integration with the Stream Deck PI (Property Inspector) \ No newline at end of file +* Uses [Easy-PI](https://github.com/BarRaider/streamdeck-easypi) by BarRaider - Provides seamless integration with the Stream Deck PI (Property Inspector) + +## Change Log + +## What's new in v1.8 +- `AND/OR` support on the Mode1 Check in the `Advanced Toggle`! You can now do things like `Strip[0].Mute AND Strip[1].B2` or `Strip[0].Solo OR Strip[0].B2 OR Strip[1].B1` +- Customizable `Long Press` length on the Press/Long-Press action +- **Hotkey Support** :new: - All advanced actions now support sending hotkeys to integrate with the :voicemeeter: Macros +- **Midi Support** :new: - All advanced actions now support the :voicemeeter: `SendMidi` commands +- Support for `\n` (new line) in the Enabled/Disabled Texts + +## What's new in 1.7 +- VM Advanced actions now support renaming values that show 1 / 0 to a user-defined text (On/Off or Enabled/Disabled, etc.) +- Bugfix in which the second image was not stored correctly in the VM Advanced Toggle action +- Moved actions to a "VoiceMeeter" category in the Stream Deck app diff --git a/VoiceMeeter/Actions/VMAdvancedPTTAction.cs b/VoiceMeeter/Actions/VMAdvancedPTTAction.cs index d25da72..beb5869 100644 --- a/VoiceMeeter/Actions/VMAdvancedPTTAction.cs +++ b/VoiceMeeter/Actions/VMAdvancedPTTAction.cs @@ -69,6 +69,7 @@ public static PluginSettings CreateDefaultSettings() #region Private members private readonly PluginSettings settings; + private bool didSetNotConnected = false; #endregion @@ -90,8 +91,10 @@ public VMAdvancedPTTAction(SDConnection connection, InitialPayload payload) : ba public async override void KeyPressed(KeyPayload payload) { + Logger.Instance.LogMessage(TracingLevel.INFO, $"{this.GetType()} KeyPressed"); if (!VMManager.Instance.IsConnected) { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"Key pressed but VM is not connected!"); await Connection.ShowAlert(); return; } @@ -126,9 +129,15 @@ public async override void OnTick() { if (!VMManager.Instance.IsConnected) { + didSetNotConnected = true; await Connection.SetImageAsync(Properties.Plugin.Default.VMNotRunning); return; } + else if (didSetNotConnected) + { + didSetNotConnected = false; + await Connection.SetImageAsync((String)null); + } if (settings.TitleType == TitleTypeEnum.VMLive && !String.IsNullOrEmpty(settings.TitleParam)) { @@ -156,7 +165,6 @@ public override void ReceivedSettings(ReceivedSettingsPayload payload) { Tools.AutoPopulateSettings(settings, payload.Settings); InitializeSettings(); - Logger.Instance.LogMessage(TracingLevel.INFO, $"Settings loaded: {payload.Settings}"); } public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } diff --git a/VoiceMeeter/Actions/VMAdvancedPressAction.cs b/VoiceMeeter/Actions/VMAdvancedPressAction.cs index 5258e7c..2e46e71 100644 --- a/VoiceMeeter/Actions/VMAdvancedPressAction.cs +++ b/VoiceMeeter/Actions/VMAdvancedPressAction.cs @@ -79,11 +79,10 @@ public static PluginSettings CreateDefaultSettings() private const int LONG_KEYPRESS_LENGTH_MS = 600; private readonly PluginSettings settings; - private bool keyPressed = false; private bool longKeyPressed = false; - private DateTime keyPressStart; private int longKeypressTime = LONG_KEYPRESS_LENGTH_MS; private readonly System.Timers.Timer tmrRunLongPress = new System.Timers.Timer(); + private bool didSetNotConnected = false; #endregion @@ -113,6 +112,7 @@ private void TmrRunLongPress_Elapsed(object sender, System.Timers.ElapsedEventAr public void LongKeyPressed() { longKeyPressed = true; + Logger.Instance.LogMessage(TracingLevel.INFO, $"Long keypress"); if (!String.IsNullOrEmpty(settings.LongPressValue)) { VMManager.Instance.SetParameters(settings.LongPressValue); @@ -133,18 +133,18 @@ public override void ReceivedSettings(ReceivedSettingsPayload payload) { Tools.AutoPopulateSettings(settings, payload.Settings); InitializeSettings(); - Logger.Instance.LogMessage(TracingLevel.INFO, $"Settings loaded: {payload.Settings}"); } public async override void KeyPressed(KeyPayload payload) { + Logger.Instance.LogMessage(TracingLevel.INFO, $"{this.GetType()} KeyPressed"); + // Used for long press - keyPressed = true; longKeyPressed = false; - keyPressStart = DateTime.Now; if (!VMManager.Instance.IsConnected) { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"Key pressed but VM is not connected!"); await Connection.ShowAlert(); return; } @@ -155,11 +155,11 @@ public async override void KeyPressed(KeyPayload payload) public override void KeyReleased(KeyPayload payload) { - keyPressed = false; tmrRunLongPress.Stop(); if (!longKeyPressed && !String.IsNullOrEmpty(settings.SetValue)) { + Logger.Instance.LogMessage(TracingLevel.INFO, $"Short keypress"); VMManager.Instance.SetParameters(settings.SetValue); MidiCommandHandler.HandleMidiParameters(settings.KeypressMidi); if (!String.IsNullOrEmpty(settings.KeypressHotkey)) @@ -173,9 +173,15 @@ public async override void OnTick() { if (!VMManager.Instance.IsConnected) { + didSetNotConnected = true; await Connection.SetImageAsync(Properties.Plugin.Default.VMNotRunning); return; } + else if (didSetNotConnected) + { + didSetNotConnected = false; + await Connection.SetImageAsync((String)null); + } if (settings.TitleType == TitleTypeEnum.VMLive && !String.IsNullOrEmpty(settings.TitleParam)) { @@ -202,6 +208,8 @@ public async override void OnTick() public override void Dispose() { Logger.Instance.LogMessage(TracingLevel.INFO, "Destructor called"); + tmrRunLongPress.Stop(); + tmrRunLongPress.Elapsed -= TmrRunLongPress_Elapsed; } public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } diff --git a/VoiceMeeter/Actions/VMAdvancedToggle.cs b/VoiceMeeter/Actions/VMAdvancedToggle.cs index fcdb20e..0fbff08 100644 --- a/VoiceMeeter/Actions/VMAdvancedToggle.cs +++ b/VoiceMeeter/Actions/VMAdvancedToggle.cs @@ -102,6 +102,7 @@ public static PluginSettings CreateDefaultSettings() private const string LOGICAL_OR = " OR "; private readonly PluginSettings settings; + private bool didSetNotConnected = false; #endregion @@ -127,8 +128,10 @@ public VMAdvancedToggleAction(SDConnection connection, InitialPayload payload) : public async override void KeyPressed(KeyPayload payload) { + Logger.Instance.LogMessage(TracingLevel.INFO, $"{this.GetType()} KeyPressed"); if (!VMManager.Instance.IsConnected) { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"Key pressed but VM is not connected!"); await Connection.ShowAlert(); return; } @@ -168,9 +171,15 @@ public async override void OnTick() { if (!VMManager.Instance.IsConnected) { + didSetNotConnected = true; await Connection.SetImageAsync(Properties.Plugin.Default.VMNotRunning); return; } + else if (didSetNotConnected) + { + didSetNotConnected = false; + await Connection.SetImageAsync((String)null); + } // Set the image if (!String.IsNullOrEmpty(settings.UserImage1) && IsMode1(false)) @@ -213,8 +222,6 @@ public override void Dispose() public async override void ReceivedSettings(ReceivedSettingsPayload payload) { Tools.AutoPopulateSettings(settings, payload.Settings); - Logger.Instance.LogMessage(TracingLevel.INFO, $"Settings loaded: {payload.Settings}"); - InitializeSettings(); // Used to return the correct filename back to the Property Inspector await SaveSettings(); diff --git a/VoiceMeeter/Actions/VMMacroToggle.cs b/VoiceMeeter/Actions/VMMacroToggle.cs new file mode 100644 index 0000000..8479917 --- /dev/null +++ b/VoiceMeeter/Actions/VMMacroToggle.cs @@ -0,0 +1,296 @@ +using BarRaider.SdTools; +using HotkeyCommands; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Printing; +using System.Drawing.Text; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VoiceMeeter.Midi; +using WindowsInput.Native; + +namespace VoiceMeeter +{ + //--------------------------------------------------- + // BarRaider's Hall Of Fame + // Subscriber: JustVoxPop + // Subscriber: iMackx + // Subscriber: CyberlightGames + // Craigs_Cave - 5 Gifted Subs + // 100 Bits: iMackx + // JustVoxPop - 1 Gifted Subs + // iMackx - 1 Gifted Subs + // nubby_ninja - 5 Gifted Subs + // 500 Bits: MagicGuitarist + // Subscriber: SaintG85 + // Subscriber: MagicGuitarist + // 17 Bits: TwilightLinkable + //--------------------------------------------------- + [PluginActionId("com.barraider.vmmacrotoggle")] + class VMMacroToggle : PluginBase + { + private enum MacroToggleMode + { + Toggle = 0, + PTT = 1 + } + private class PluginSettings + { + public static PluginSettings CreateDefaultSettings() + { + PluginSettings instance = new PluginSettings + { + EnabledImage = String.Empty, + DisabledImage = String.Empty, + TitlePrefix = String.Empty, + EnabledText = String.Empty, + DisabledText = String.Empty, + ButtonId = DEFAULT_BUTTON_ID.ToString(), + ToggleMode = MacroToggleMode.Toggle + }; + + return instance; + } + + [JsonProperty(PropertyName = "buttonId")] + public string ButtonId { get; set; } + + [JsonProperty(PropertyName = "toggleMode")] + public MacroToggleMode ToggleMode { get; set; } + + [FilenameProperty] + [JsonProperty(PropertyName = "enabledImage")] + public string EnabledImage { get; set; } + + [FilenameProperty] + [JsonProperty(PropertyName = "disabledImage")] + public string DisabledImage { get; set; } + + [JsonProperty(PropertyName = "titlePrefix")] + public string TitlePrefix { get; set; } + + [JsonProperty(PropertyName = "enabledText")] + public string EnabledText { get; set; } + + [JsonProperty(PropertyName = "disabledText")] + public string DisabledText { get; set; } + } + + #region Private members + private const int DEFAULT_BUTTON_ID = 0; + private static readonly string[] DEFAULT_BUTTON_IMAGES = { @"images\buttonDisabled.png", @"images\buttonEnabled.png" }; + + private readonly PluginSettings settings; + private int buttonId = DEFAULT_BUTTON_ID; + private bool isButtonEnabled = false; + private bool startingToggleMode = false; + private Image enabledImage = null; + private Image disabledImage = null; + private bool didSetNotConnected = false; + + #endregion + + #region Public Methods + + public VMMacroToggle(SDConnection connection, InitialPayload payload) : base(connection, payload) + { + if (payload.Settings == null || payload.Settings.Count == 0) + { + this.settings = PluginSettings.CreateDefaultSettings(); + Connection.SetSettingsAsync(JObject.FromObject(settings)); + } + else + { + this.settings = payload.Settings.ToObject(); + } + InitializeSettings(); + } + + #endregion + + #region IPluginable + + public async override void KeyPressed(KeyPayload payload) + { + Logger.Instance.LogMessage(TracingLevel.INFO, $"{this.GetType()} KeyPressed"); + if (!VMManager.Instance.IsConnected) + { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"Key pressed but VM is not connected!"); + await Connection.ShowAlert(); + return; + } + + if (String.IsNullOrEmpty(settings.ButtonId)) + { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"Key pressed but ButtonID is null!"); + await Connection.ShowAlert(); + return; + } + + // Store the initial value so we can revert back to it + if (settings.ToggleMode == MacroToggleMode.PTT) + { + startingToggleMode = isButtonEnabled; + } + + VMManager.Instance.SetMacroStatus(buttonId, !isButtonEnabled); + + if (settings.ToggleMode == MacroToggleMode.Toggle) + { + await Connection.ShowOk(); + } + } + + public override void KeyReleased(KeyPayload payload) + { + if (settings.ToggleMode == MacroToggleMode.PTT) + { + Logger.Instance.LogMessage(TracingLevel.INFO, $"{this.GetType()} Key Released"); + if (!VMManager.Instance.IsConnected) + { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"Key released but VM is not connected!"); + return; + } + + if (String.IsNullOrEmpty(settings.ButtonId)) + { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"Key released but ButtonID is null!"); + return; + } + VMManager.Instance.SetMacroStatus(buttonId, startingToggleMode); + } + } + + public async override void OnTick() + { + if (!VMManager.Instance.IsConnected) + { + didSetNotConnected = true; + await Connection.SetImageAsync(Properties.Plugin.Default.VMNotRunning); + return; + } + else if (didSetNotConnected) + { + didSetNotConnected = false; + await Connection.SetImageAsync((String)null); + } + + isButtonEnabled = VMManager.Instance.GetMacroStatus(buttonId); + + // Set the image + if (isButtonEnabled) + { + await Connection.SetImageAsync(enabledImage); + } + else + { + await Connection.SetImageAsync(disabledImage); + } + + // Set the title + string prefix = String.Empty; + if (!String.IsNullOrEmpty(settings.TitlePrefix)) + { + prefix = settings.TitlePrefix.Replace(@"\n", "\n"); + } + + string value = isButtonEnabled ? "1" : "0"; + if (!String.IsNullOrEmpty(settings.EnabledText) && !String.IsNullOrEmpty(value) && value == Constants.ENABLED_VALUE) + { + value = settings.EnabledText.Replace(@"\n", "\n"); ; + } + else if (!String.IsNullOrEmpty(settings.DisabledText) && !String.IsNullOrEmpty(value) && value == Constants.DISABLED_VALUE) + { + value = settings.DisabledText.Replace(@"\n", "\n"); ; + } + + await Connection.SetTitleAsync($"{prefix}{value}"); + + } + + public override void Dispose() + { + Logger.Instance.LogMessage(TracingLevel.INFO, "Destructor called"); + } + + public async override void ReceivedSettings(ReceivedSettingsPayload payload) + { + Tools.AutoPopulateSettings(settings, payload.Settings); + InitializeSettings(); + // Used to return the correct filename back to the Property Inspector + await SaveSettings(); + } + + public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } + + #endregion + + #region Private Methods + + private Task SaveSettings() + { + return Connection.SetSettingsAsync(JObject.FromObject(settings)); + } + + private void InitializeSettings() + { + if (!Int32.TryParse(settings.ButtonId, out buttonId)) + { + settings.ButtonId = DEFAULT_BUTTON_ID.ToString(); + buttonId = DEFAULT_BUTTON_ID; + SaveSettings(); + } + + PrefetchImages(); + } + + private void PrefetchImages() + { + try + { + if (enabledImage != null) + { + enabledImage.Dispose(); + enabledImage = null; + } + + if (disabledImage != null) + { + disabledImage.Dispose(); + disabledImage = null; + } + + enabledImage = Image.FromFile(TryGetCustomFile(settings.EnabledImage, DEFAULT_BUTTON_IMAGES[1])); + disabledImage = Image.FromFile(TryGetCustomFile(settings.DisabledImage, DEFAULT_BUTTON_IMAGES[0])); + } + catch (Exception ex) + { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"PrefetchImages Exception {ex}"); + } + } + private string TryGetCustomFile(string fileName, string fallbackFilename) + { + string value = fallbackFilename; + if (!String.IsNullOrEmpty(fileName)) + { + if (!File.Exists(fileName)) + { + Logger.Instance.LogMessage(TracingLevel.WARN, $"TryGetCustomFile: File not found {fileName}"); + } + else + { + value = fileName; + } + } + + return value; + } + + #endregion + } +} diff --git a/VoiceMeeter/Actions/VMMicrophoneAction.cs b/VoiceMeeter/Actions/VMMicrophoneAction.cs index 4339345..9ffc01f 100644 --- a/VoiceMeeter/Actions/VMMicrophoneAction.cs +++ b/VoiceMeeter/Actions/VMMicrophoneAction.cs @@ -1,4 +1,5 @@ using BarRaider.SdTools; +using HotkeyCommands; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; @@ -36,7 +37,9 @@ public static PluginSettings CreateDefaultSettings() SingleValue = String.Empty, ImageType = ImageTypeEnum.Microphone, UserImage1 = String.Empty, - UserImage2 = String.Empty + UserImage2 = String.Empty, + MuteHotkey = String.Empty, + UnmuteHotkey = String.Empty }; return instance; @@ -64,11 +67,19 @@ public static PluginSettings CreateDefaultSettings() [FilenameProperty] [JsonProperty(PropertyName = "userImage2")] public string UserImage2 { get; set; } + + [JsonProperty(PropertyName = "muteHotkey")] + public string MuteHotkey { get; set; } + + [JsonProperty(PropertyName = "unmuteHotkey")] + public string UnmuteHotkey { get; set; } + } #region Private members private readonly PluginSettings settings; + private bool didSetNotConnected = false; #endregion @@ -93,12 +104,15 @@ public VMMicrophoneAction(SDConnection connection, InitialPayload payload) : bas public async override void KeyPressed(KeyPayload payload) { + Logger.Instance.LogMessage(TracingLevel.INFO, $"{this.GetType()} KeyPressed"); if (!VMManager.Instance.IsConnected) { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"Key pressed but VM is not connected!"); await Connection.ShowAlert(); return; } + bool triggeredMute = false; switch (settings.MicType) { case MicTypeEnum.SingleMode: @@ -106,6 +120,7 @@ public async override void KeyPressed(KeyPayload payload) if (Int32.TryParse(settings.SingleValue, out value)) { VMManager.Instance.SetParam(BuildDeviceName(), value); + triggeredMute = value != 0; } else { @@ -115,11 +130,23 @@ public async override void KeyPressed(KeyPayload payload) case MicTypeEnum.Toggle: bool isMuted = VMManager.Instance.GetParamBool(BuildDeviceName()); VMManager.Instance.SetParam(BuildDeviceName(), isMuted ? 0 : 1); + triggeredMute = !isMuted; break; case MicTypeEnum.PTT: VMManager.Instance.SetParam(BuildDeviceName(), 0); + triggeredMute = false; break; } + + if (triggeredMute && !String.IsNullOrEmpty(settings.MuteHotkey)) + { + HotkeyHandler.RunHotkey(settings.MuteHotkey); + } + else if (!triggeredMute && !String.IsNullOrEmpty(settings.UnmuteHotkey)) + { + HotkeyHandler.RunHotkey(settings.UnmuteHotkey); + } + } public override void KeyReleased(KeyPayload payload) @@ -127,6 +154,11 @@ public override void KeyReleased(KeyPayload payload) if (settings.MicType == MicTypeEnum.PTT) { VMManager.Instance.SetParam(BuildDeviceName(), 1); + + if (!String.IsNullOrEmpty(settings.MuteHotkey)) + { + HotkeyHandler.RunHotkey(settings.MuteHotkey); + } } } @@ -134,9 +166,15 @@ public async override void OnTick() { if (!VMManager.Instance.IsConnected) { + didSetNotConnected = true; await Connection.SetImageAsync(Properties.Plugin.Default.VMNotRunning); return; } + else if (didSetNotConnected) + { + didSetNotConnected = false; + await Connection.SetImageAsync((String)null); + } await Connection.SetImageAsync(GetBase64ImageStatus()); } @@ -150,7 +188,6 @@ public async override void ReceivedSettings(ReceivedSettingsPayload payload) { // New in StreamDeck-Tools v2.0: Tools.AutoPopulateSettings(settings, payload.Settings); - Logger.Instance.LogMessage(TracingLevel.INFO, $"Settings loaded: {payload.Settings}"); // Used to return the correct filename back to the Property Inspector await Connection.SetSettingsAsync(JObject.FromObject(settings)); diff --git a/VoiceMeeter/Actions/VMModifyAction.cs b/VoiceMeeter/Actions/VMModifyAction.cs index 03dff33..34763fd 100644 --- a/VoiceMeeter/Actions/VMModifyAction.cs +++ b/VoiceMeeter/Actions/VMModifyAction.cs @@ -80,6 +80,7 @@ public static PluginSettings CreateDefaultSettings() private bool keyPressed = false; private bool longKeyPressed = false; private DateTime keyPressStart; + private bool didSetNotConnected = false; #endregion @@ -113,8 +114,10 @@ public void LongKeyPressed() public async override void KeyPressed(KeyPayload payload) { + Logger.Instance.LogMessage(TracingLevel.INFO, $"{this.GetType()} KeyPressed"); if (!VMManager.Instance.IsConnected) { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"Key pressed but VM is not connected!"); await Connection.ShowAlert(); return; } @@ -142,10 +145,16 @@ public async override void OnTick() { if (!VMManager.Instance.IsConnected) { + didSetNotConnected = true; await Connection.SetImageAsync(Properties.Plugin.Default.VMNotRunning); return; } - + else if (didSetNotConnected) + { + didSetNotConnected = false; + await Connection.SetImageAsync((String)null); + } + // Stream Deck calls this function every second, // so this is the best place to determine if we need to call the long keypress if (!String.IsNullOrEmpty(settings.LongPressValue) && keyPressed && (DateTime.Now - keyPressStart).TotalSeconds > LONG_KEYPRESS_LENGTH) @@ -174,7 +183,6 @@ public override void ReceivedSettings(ReceivedSettingsPayload payload) { // New in StreamDeck-Tools v2.0: Tools.AutoPopulateSettings(settings, payload.Settings); - Logger.Instance.LogMessage(TracingLevel.INFO, $"Settings loaded: {payload.Settings}"); } public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } @@ -185,7 +193,7 @@ public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payloa private string BuildDeviceName() { - return $"{settings.Strip}[{settings.StripNum}].{settings.ParamType.ToString()}"; + return $"{settings.Strip}[{settings.StripNum}].{settings.ParamType}"; } #endregion diff --git a/VoiceMeeter/Images/buttonDisabled.png b/VoiceMeeter/Images/buttonDisabled.png new file mode 100644 index 0000000..2a0fdbe Binary files /dev/null and b/VoiceMeeter/Images/buttonDisabled.png differ diff --git a/VoiceMeeter/Images/buttonDisabled@2x.png b/VoiceMeeter/Images/buttonDisabled@2x.png new file mode 100644 index 0000000..d73b81b Binary files /dev/null and b/VoiceMeeter/Images/buttonDisabled@2x.png differ diff --git a/VoiceMeeter/Images/buttonEnabled.png b/VoiceMeeter/Images/buttonEnabled.png new file mode 100644 index 0000000..0b907f7 Binary files /dev/null and b/VoiceMeeter/Images/buttonEnabled.png differ diff --git a/VoiceMeeter/Images/buttonEnabled@2x.png b/VoiceMeeter/Images/buttonEnabled@2x.png new file mode 100644 index 0000000..9bd4326 Binary files /dev/null and b/VoiceMeeter/Images/buttonEnabled@2x.png differ diff --git a/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedKeypress.html b/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedKeypress.html index 18466bf..61ea719 100644 --- a/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedKeypress.html +++ b/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedKeypress.html @@ -6,15 +6,18 @@ BarRaider's VoiceMeeter Plugin - + + -
+
+ For feedback/suggestions contact me at https://BarRaider.com +
This plugins allows you to send a list of commands directly to VoiceMeeter (click this text for more info...)

@@ -103,10 +106,6 @@

"Disabled" text
-
- For feedback/suggestions contact me at https://BarRaider.com -
- diff --git a/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedPTT.html b/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedPTT.html index d68a358..ff6dfe5 100644 --- a/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedPTT.html +++ b/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedPTT.html @@ -6,14 +6,17 @@ BarRaider's VoiceMeeter Plugin - + + -
+
+ For feedback/suggestions contact me at https://BarRaider.com +
This plugins allows you to send a list of commands directly to VoiceMeeter (click this text for more info...)

diff --git a/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedToggle.html b/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedToggle.html index c2c194b..bae7aaa 100644 --- a/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedToggle.html +++ b/VoiceMeeter/PropertyInspector/VoiceMeeter/AdvancedToggle.html @@ -6,18 +6,18 @@ BarRaider's VoiceMeeter Plugin - + + -

Instructions
- Toggle between Mode1 and Mode2 by pressing the button (click this text for more info...) + Click Here for usage instructions

Mode1 is used to turn things ON. Mode 2 is used to turn things OFF.
Example: Lets use Mode1 to turn Mono on (and do aditional things): "Strip[0].mono=1;Bus[2].Gain=-20;"
diff --git a/VoiceMeeter/PropertyInspector/VoiceMeeter/MacroToggle.html b/VoiceMeeter/PropertyInspector/VoiceMeeter/MacroToggle.html new file mode 100644 index 0000000..a121b6e --- /dev/null +++ b/VoiceMeeter/PropertyInspector/VoiceMeeter/MacroToggle.html @@ -0,0 +1,61 @@ + + + + + + + + BarRaider's VoiceMeeter Plugin + + + + + + + +

+
+ For feedback/suggestions contact me at https://BarRaider.com +
+
+
Logical Id
+ +
+
+
Mode
+ +
+
+
Enabled Image
+
+ + + +
+
+
+
Disabled Image
+
+ + + +
+
+
+
Title Prefix
+ +
+
+
"Enabled" text
+ +
+
+
"Disabled" text
+ +
+
+ + diff --git a/VoiceMeeter/PropertyInspector/VoiceMeeter/Microphone.html b/VoiceMeeter/PropertyInspector/VoiceMeeter/Microphone.html index 79cfed9..aacdb02 100644 --- a/VoiceMeeter/PropertyInspector/VoiceMeeter/Microphone.html +++ b/VoiceMeeter/PropertyInspector/VoiceMeeter/Microphone.html @@ -6,8 +6,11 @@ BarRaider's VoiceMeeter Plugin - - + + + + +
@@ -57,21 +60,49 @@
-
User defined image1
+
Muted Image
+
+
Mute Sends Hotkey
+ + + +
+
-
User defined image2
+
Unmuted Image
+
+
Unmute Sends Hotkey
+ + + +
+
diff --git a/VoiceMeeter/PropertyInspector/VoiceMeeter/Modify.html b/VoiceMeeter/PropertyInspector/VoiceMeeter/Modify.html index 0601960..9d74645 100644 --- a/VoiceMeeter/PropertyInspector/VoiceMeeter/Modify.html +++ b/VoiceMeeter/PropertyInspector/VoiceMeeter/Modify.html @@ -6,8 +6,8 @@ BarRaider's VoiceMeeter Plugin - - + +
diff --git a/VoiceMeeter/PropertyInspector/sdpi.css b/VoiceMeeter/PropertyInspector/sdpi.css deleted file mode 100644 index 2648d0f..0000000 --- a/VoiceMeeter/PropertyInspector/sdpi.css +++ /dev/null @@ -1,1481 +0,0 @@ -.linkspan { - cursor: pointer; - color: #7397d2; - text-decoration: underline; -} - -html { - --sdpi-bgcolor: #2D2D2D; - --sdpi-background: #3D3D3D; - --sdpi-color: #d8d8d8; - --sdpi-bordercolor: #3a3a3a; - --sdpi-buttonbordercolor: #969696; - --sdpi-borderradius: 0px; - --sdpi-width: 224px; - --sdpi-fontweight: 600; - --sdpi-letterspacing: -0.25pt; - height: 100%; - width: 100%; - overflow: hidden; -} - -html, body { - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-size: 9pt; - background-color: var(--sdpi-bgcolor); - color: #9a9a9a; -} - -body { - height: 100%; - padding: 0; - overflow-x: hidden; - overflow-y: auto; - margin: 0; - -webkit-overflow-scrolling: touch; - -webkit-text-size-adjust: 100%; - -webkit-font-smoothing: antialiased; -} - -mark { - background-color: var(--sdpi-bgcolor); - color: var(--sdpi-color); -} - -hr, hr2 { - -webkit-margin-before: 1em; - -webkit-margin-after: 1em; - border-style: none; - background: var(--sdpi-background); - height: 1px; -} - -hr2, -.sdpi-heading { - display: flex; - flex-basis: 100%; - align-items: center; - color: inherit; - font-size: 9pt; - margin: 8px 0px; -} - -.sdpi-heading::before, -.sdpi-heading::after { - content: ""; - flex-grow: 1; - background: var(--sdpi-background); - height: 1px; - font-size: 0px; - line-height: 0px; - margin: 0px 16px; -} - -hr2 { - height: 2px; -} - -hr, hr2 { - margin-left:16px; - margin-right:16px; -} - -.sdpi-item-value, -option, -input, -select, -button { - font-size: 10pt; - font-weight: var(--sdpi-fontweight); - letter-spacing: var(--sdpi-letterspacing); -} - - - -.win .sdpi-item-value, -.win option, -.win input, -.win select, -.win button { - font-size: 11px; - font-style: normal; - letter-spacing: inherit; - font-weight: 100; -} - -.win button { - font-size: 12px; -} - -::-webkit-progress-value, -meter::-webkit-meter-optimum-value { - border-radius: 2px; - /* background: linear-gradient(#ccf, #99f 20%, #77f 45%, #77f 55%, #cdf); */ -} - -::-webkit-progress-bar, -meter::-webkit-meter-bar { - border-radius: 3px; - background: var(--sdpi-background); -} - -::-webkit-progress-bar:active, -meter::-webkit-meter-bar:active { - border-radius: 3px; - background: #222222; -} -::-webkit-progress-value:active, -meter::-webkit-meter-optimum-value:active { - background: #99f; -} - -progress, -progress.sdpi-item-value { - min-height: 5px !important; - height: 5px; - background-color: #303030; -} - -progress { - margin-top: 8px !important; - margin-bottom: 8px !important; -} - -.full progress, -progress.full { - margin-top: 3px !important; -} - -::-webkit-progress-inner-element { - background-color: transparent; -} - - -.sdpi-item[type="progress"] { - margin-top: 4px !important; - margin-bottom: 12px; - min-height: 15px; -} - -.sdpi-item-child.full:last-child { - margin-bottom: 4px; -} - -.tabs { - /** - * Setting display to flex makes this container lay - * out its children using flexbox, the exact same - * as in the above "Stepper input" example. - */ - display: flex; - - border-bottom: 1px solid #D7DBDD; -} - -.tab { - cursor: pointer; - padding: 5px 30px; - color: #16a2d7; - font-size: 9pt; - border-bottom: 2px solid transparent; -} - -.tab.is-tab-selected { - border-bottom-color: #4ebbe4; -} - -select { - -webkit-appearance: none; - -moz-appearance: none; - -o-appearance: none; - appearance: none; - background: url(caret.svg) no-repeat 97% center; -} - -label.sdpi-file-label, -input[type="button"], -input[type="submit"], -input[type="reset"], -input[type="file"], -input[type=file]::-webkit-file-upload-button, -button, -select { - color: var(--sdpi-color); - border: 1pt solid #303030; - font-size: 8pt; - background-color: var(--sdpi-background); - border-radius: var(--sdpi-borderradius); -} - -label.sdpi-file-label, -input[type="button"], -input[type="submit"], -input[type="reset"], -input[type="file"], -input[type=file]::-webkit-file-upload-button, -button { - border: 1pt solid var(--sdpi-buttonbordercolor); - border-radius: var(--sdpi-borderradius); - border-color: var(--sdpi-buttonbordercolor); - min-height: 23px !important; - height: 23px !important; - margin-right: 8px; -} - -input[type=number]::-webkit-inner-spin-button, -input[type=number]::-webkit-outer-spin-button { - -webkit-appearance: none; - margin: 0; -} - -input[type="file"] { - border-radius: var(--sdpi-borderradius); - max-width: 220px; -} - - -option { - height: 1.5em; - padding: 4px; -} - -/* SDPI */ - -.sdpi-wrapper { - overflow-x: hidden; -} - -.sdpi-item { - display: flex; - flex-direction: row; - min-height: 32px; - align-items: center; - margin-top: 2px; - max-width: 344px; -} - -.sdpi-item:first-child { - margin-top:1px; -} - -.sdpi-item:last-child { - margin-bottom: 0px; -} - -.sdpi-item > *:not(.sdpi-item-label):not(meter):not(details) { - min-height: 26px; - padding: 0px 4px 0px 4px; -} - -.sdpi-item > *:not(.sdpi-item-label.empty):not(meter) { - min-height: 26px; - padding: 0px 4px 0px 4px; -} - - -.sdpi-item-group { - padding: 0 !important; -} - -meter.sdpi-item-value { - margin-left: 6px; -} - -.sdpi-item[type="group"] { - display: block; - margin-top: 12px; - margin-bottom: 12px; - /* border: 1px solid white; */ - flex-direction: unset; - text-align: left; -} - -.sdpi-item[type="group"] > .sdpi-item-label, -.sdpi-item[type="group"].sdpi-item-label { - width: 96%; - text-align: left; - font-weight: 700; - margin-bottom: 4px; - padding-left: 4px; -} - -dl, -ul, -ol { - -webkit-margin-before: 0px; - -webkit-margin-after: 4px; - -webkit-padding-start: 1em; - max-height: 90px; - overflow-y: scroll; - cursor: pointer; - user-select: none; -} - -table.sdpi-item-value, -dl.sdpi-item-value, -ul.sdpi-item-value, -ol.sdpi-item-value { - -webkit-margin-before: 4px; - -webkit-margin-after: 8px; - -webkit-padding-start: 1em; - width: var(--sdpi-width); - text-align: center; -} - -table > caption { - margin: 2px; -} - -.list, -.sdpi-item[type="list"] { - align-items: baseline; -} - -.sdpi-item-label { - text-align: right; - flex: none; - width: 94px; - padding-right: 4px; - font-weight: 600; - -webkit-user-select: none; -} - -.win .sdpi-item-label, -.sdpi-item-label > small{ - font-weight: normal; -} - -.sdpi-item-label:after { - content: ": "; -} - -.sdpi-item-label.empty:after { - content: ""; -} - -.sdpi-test, -.sdpi-item-value { - flex: 1 0 0; - /* flex-grow: 1; - flex-shrink: 0; */ - margin-right: 14px; - margin-left: 4px; - justify-content: space-evenly; -} - -canvas.sdpi-item-value { - max-width: 144px; - max-height: 144px; - width: 144px; - height: 144px; - margin: 0 auto; - cursor: pointer; -} - -input.sdpi-item-value { - margin-left: 5px; -} - -.sdpi-item-value button, -button.sdpi-item-value { - margin-left: 7px; - margin-right: 19px; -} - -.sdpi-item-value.range { - margin-left: 0px; -} - -table, -dl.sdpi-item-value, -ul.sdpi-item-value, -ol.sdpi-item-value, -.sdpi-item-value > dl, -.sdpi-item-value > ul, -.sdpi-item-value > ol -{ - list-style-type: none; - list-style-position: outside; - margin-left: -4px; - margin-right: -4px; - padding: 4px; - border: 1px solid var(--sdpi-bordercolor); -} - -dl.sdpi-item-value, -ul.sdpi-item-value, -ol.sdpi-item-value, -.sdpi-item-value > ol { - list-style-type: none; - list-style-position: inside; - margin-left: 5px; - margin-right: 12px; - padding: 4px !important; -} - -ol.sdpi-item-value, -.sdpi-item-value > ol[listtype="none"] { - list-style-type: none; -} -ol.sdpi-item-value[type="decimal"], -.sdpi-item-value > ol[type="decimal"] { - list-style-type: decimal; -} - -ol.sdpi-item-value[type="decimal-leading-zero"], -.sdpi-item-value > ol[type="decimal-leading-zero"] { - list-style-type: decimal-leading-zero; -} - -ol.sdpi-item-value[type="lower-alpha"], -.sdpi-item-value > ol[type="lower-alpha"] { - list-style-type: lower-alpha; -} - -ol.sdpi-item-value[type="upper-alpha"], -.sdpi-item-value > ol[type="upper-alpha"] { - list-style-type: upper-alpha; -} - -ol.sdpi-item-value[type="upper-roman"], -.sdpi-item-value > ol[type="upper-roman"] { - list-style-type: upper-roman; -} - -ol.sdpi-item-value[type="lower-roman"], -.sdpi-item-value > ol[type="lower-roman"] { - list-style-type: upper-roman; -} - -tr:nth-child(even), -.sdpi-item-value > ul > li:nth-child(even), -.sdpi-item-value > ol > li:nth-child(even), -li:nth-child(even) { - background-color: rgba(0,0,0,.2) -} - -td:hover, -.sdpi-item-value > ul > li:hover:nth-child(even), -.sdpi-item-value > ol > li:hover:nth-child(even), -li:hover:nth-child(even), -li:hover { - background-color: rgba(255,255,255,.1); -} - -td.selected, -td.selected:hover, -li.selected:hover, -li.selected { - color: white; - background-color: #77f; -} - -tr { - border: 1px solid var(--sdpi-bordercolor); -} - -td { - border-right: 1px solid var(--sdpi-bordercolor); - -webkit-user-select: none; -} - -tr:last-child, -td:last-child { - border: none; -} - -.sdpi-item-value.select, -.sdpi-item-value > select { - margin-right: 13px; - margin-left: 4px; -} - -.sdpi-item-child, -.sdpi-item-group > .sdpi-item > input[type="color"] { - margin-top: 0.4em; - margin-right: 4px; -} - -.full, -.full *, -.sdpi-item-value.full, -.sdpi-item-child > full > *, -.sdpi-item-child.full, -.sdpi-item-child.full > *, -.full > .sdpi-item-child, -.full > .sdpi-item-child > *{ - display: flex; - flex: 1 1 0; - margin-bottom: 4px; - margin-left: 0px; - width: 100%; - - justify-content: space-evenly; -} - -.sdpi-item-group > .sdpi-item > input[type="color"] { - margin-top: 0px; -} - -::-webkit-calendar-picker-indicator:focus, -input[type=file]::-webkit-file-upload-button:focus, -button:focus, -textarea:focus, -input:focus, -select:focus, -option:focus, -details:focus, -summary:focus, -.custom-select select { - outline: none; -} - -summary { - cursor: default; - -webkit-user-select: none; -} - -.pointer, -summary .pointer { - cursor: pointer; -} - -details.message { - padding: 4px 18px 4px 12px; -} - -details.message summary { - font-size: 10pt; - font-weight: 600; - min-height: 18px; -} - -details.message:first-child { - margin-top: 4px; - margin-left: 0; - padding-left: 106px; -} - -details.message h1 { - text-align: left; -} - -.message > summary::-webkit-details-marker { - display: none; -} - -.info20, -.question, -.caution, -.info { - background-repeat: no-repeat; - background-position: 70px center; -} - -.info20 { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath fill='%23999' d='M10,20 C4.4771525,20 0,15.5228475 0,10 C0,4.4771525 4.4771525,0 10,0 C15.5228475,0 20,4.4771525 20,10 C20,15.5228475 15.5228475,20 10,20 Z M10,8 C8.8954305,8 8,8.84275812 8,9.88235294 L8,16.1176471 C8,17.1572419 8.8954305,18 10,18 C11.1045695,18 12,17.1572419 12,16.1176471 L12,9.88235294 C12,8.84275812 11.1045695,8 10,8 Z M10,3 C8.8954305,3 8,3.88165465 8,4.96923077 L8,5.03076923 C8,6.11834535 8.8954305,7 10,7 C11.1045695,7 12,6.11834535 12,5.03076923 L12,4.96923077 C12,3.88165465 11.1045695,3 10,3 Z'/%3E%3C/svg%3E%0A"); -} - -.info { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath fill='%23999' d='M10,18 C5.581722,18 2,14.418278 2,10 C2,5.581722 5.581722,2 10,2 C14.418278,2 18,5.581722 18,10 C18,14.418278 14.418278,18 10,18 Z M10,8 C9.44771525,8 9,8.42137906 9,8.94117647 L9,14.0588235 C9,14.5786209 9.44771525,15 10,15 C10.5522847,15 11,14.5786209 11,14.0588235 L11,8.94117647 C11,8.42137906 10.5522847,8 10,8 Z M10,5 C9.44771525,5 9,5.44082732 9,5.98461538 L9,6.01538462 C9,6.55917268 9.44771525,7 10,7 C10.5522847,7 11,6.55917268 11,6.01538462 L11,5.98461538 C11,5.44082732 10.5522847,5 10,5 Z'/%3E%3C/svg%3E%0A"); -} - -.info2 { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 15 15'%3E%3Cpath fill='%23999' d='M7.5,15 C3.35786438,15 0,11.6421356 0,7.5 C0,3.35786438 3.35786438,0 7.5,0 C11.6421356,0 15,3.35786438 15,7.5 C15,11.6421356 11.6421356,15 7.5,15 Z M7.5,2 C6.67157287,2 6,2.66124098 6,3.47692307 L6,3.52307693 C6,4.33875902 6.67157287,5 7.5,5 C8.32842705,5 9,4.33875902 9,3.52307693 L9,3.47692307 C9,2.66124098 8.32842705,2 7.5,2 Z M5,6 L5,7.02155172 L6,7 L6,12 L5,12.0076778 L5,13 L10,13 L10,12 L9,12.0076778 L9,6 L5,6 Z'/%3E%3C/svg%3E%0A"); -} - -.sdpi-more-info { - background-image: linear-gradient(to right, #00000000 0%,#00000040 80%), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpolygon fill='%23999' points='4 7 8 7 8 5 12 8 8 11 8 9 4 9'/%3E%3C/svg%3E%0A"); -} -.caution { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath fill='%23999' fill-rule='evenodd' d='M9.03952676,0.746646542 C9.57068894,-0.245797319 10.4285735,-0.25196227 10.9630352,0.746646542 L19.7705903,17.2030214 C20.3017525,18.1954653 19.8777595,19 18.8371387,19 L1.16542323,19 C0.118729947,19 -0.302490098,18.2016302 0.231971607,17.2030214 L9.03952676,0.746646542 Z M10,2.25584053 L1.9601405,17.3478261 L18.04099,17.3478261 L10,2.25584053 Z M10,5.9375 C10.531043,5.9375 10.9615385,6.37373537 10.9615385,6.91185897 L10.9615385,11.6923077 C10.9615385,12.2304313 10.531043,12.6666667 10,12.6666667 C9.46895697,12.6666667 9.03846154,12.2304313 9.03846154,11.6923077 L9.03846154,6.91185897 C9.03846154,6.37373537 9.46895697,5.9375 10,5.9375 Z M10,13.4583333 C10.6372516,13.4583333 11.1538462,13.9818158 11.1538462,14.6275641 L11.1538462,14.6641026 C11.1538462,15.3098509 10.6372516,15.8333333 10,15.8333333 C9.36274837,15.8333333 8.84615385,15.3098509 8.84615385,14.6641026 L8.84615385,14.6275641 C8.84615385,13.9818158 9.36274837,13.4583333 10,13.4583333 Z'/%3E%3C/svg%3E%0A"); -} - -.question { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath fill='%23999' d='M10,18 C5.581722,18 2,14.418278 2,10 C2,5.581722 5.581722,2 10,2 C14.418278,2 18,5.581722 18,10 C18,14.418278 14.418278,18 10,18 Z M6.77783203,7.65332031 C6.77783203,7.84798274 6.85929281,8.02888914 7.0222168,8.19604492 C7.18514079,8.36320071 7.38508996,8.44677734 7.62207031,8.44677734 C8.02409055,8.44677734 8.29703704,8.20768468 8.44091797,7.72949219 C8.59326248,7.27245865 8.77945854,6.92651485 8.99951172,6.69165039 C9.2195649,6.45678594 9.56233491,6.33935547 10.027832,6.33935547 C10.4256205,6.33935547 10.7006836,6.37695313 11.0021973,6.68847656 C11.652832,7.53271484 10.942627,8.472229 10.3750916,9.1321106 C9.80755615,9.79199219 8.29492188,11.9897461 10.027832,12.1347656 C10.4498423,12.1700818 10.7027991,11.9147157 10.7832031,11.4746094 C11.0021973,9.59857178 13.1254883,8.82415771 13.1254883,7.53271484 C13.1254883,7.07568131 12.9974785,6.65250846 12.7414551,6.26318359 C12.4854317,5.87385873 12.1225609,5.56600048 11.652832,5.33959961 C11.1831031,5.11319874 10.6414419,5 10.027832,5 C9.36767248,5 8.79004154,5.13541531 8.29492187,5.40625 C7.79980221,5.67708469 7.42317837,6.01879677 7.16503906,6.43139648 C6.90689975,6.8439962 6.77783203,7.25130007 6.77783203,7.65332031 Z M10.0099668,15 C10.2713191,15 10.5016601,14.9108147 10.7009967,14.7324415 C10.9003332,14.5540682 11,14.3088087 11,13.9966555 C11,13.7157177 10.9047629,13.4793767 10.7142857,13.2876254 C10.5238086,13.0958742 10.2890379,13 10.0099668,13 C9.72646591,13 9.48726565,13.0958742 9.2923588,13.2876254 C9.09745196,13.4793767 9,13.7157177 9,13.9966555 C9,14.313268 9.10077419,14.5596424 9.30232558,14.735786 C9.50387698,14.9119295 9.73975502,15 10.0099668,15 Z'/%3E%3C/svg%3E%0A"); -} - - -.sdpi-more-info { - position: fixed; - left: 0px; - right: 0px; - bottom: 0px; - min-height:16px; - padding-right: 16px; - text-align: right; - -webkit-touch-callout: none; - cursor: pointer; - user-select: none; - background-position: right center; - background-repeat: no-repeat; - border-radius: var(--sdpi-borderradius); - text-decoration: none; - color: var(--sdpi-color); -} - -.sdpi-more-info-button { - display: flex; - align-self: right; - margin-left: auto; - position: fixed; - right: 17px; - bottom: 0px; -} - -details a { - background-position: right !important; - min-height: 24px; - display: inline-block; - line-height: 24px; - padding-right: 28px; -} -input:not([type="range"]), -textarea { - -webkit-appearance: none; - background: var(--sdpi-background); - color: var(--sdpi-color); - font-weight: normal; - font-size: 9pt; - border: none; - margin-top: 2px; - margin-bottom: 2px; -} - -textarea + label { - display: flex; - justify-content: flex-end -} -input[type="radio"], -input[type="checkbox"] { - display: none; -} -input[type="radio"] + label, -input[type="checkbox"] + label { - font-size: 9pt; - color: var(--sdpi-color); - font-weight: normal; - margin-right: 8px; - -webkit-user-select: none; -} - -input[type="radio"] + label:after, -input[type="checkbox"] + label:after { - content: " " !important; -} - -.sdpi-item[type="radio"] > .sdpi-item-value, -.sdpi-item[type="checkbox"] > .sdpi-item-value { - padding-top: 2px; -} - -.sdpi-item[type="checkbox"] > .sdpi-item-value > * { - margin-top: 4px; -} - -.sdpi-item[type="checkbox"] .sdpi-item-child, -.sdpi-item[type="radio"] .sdpi-item-child { - display: inline-block; -} - -.sdpi-item[type="range"] .sdpi-item-value, -.sdpi-item[type="meter"] .sdpi-item-child, -.sdpi-item[type="progress"] .sdpi-item-child { - display: flex; -} - -.sdpi-item[type="range"] .sdpi-item-value { - min-height: 26px; -} - -.sdpi-item[type="range"] .sdpi-item-value span, -.sdpi-item[type="meter"] .sdpi-item-child span, -.sdpi-item[type="progress"] .sdpi-item-child span { - margin-top: -2px; - min-width: 8px; - text-align: right; - user-select: none; - cursor: pointer; -} - -.sdpi-item[type="range"] .sdpi-item-value span { - margin-top: 7px; - text-align: right; -} - -span + input[type="range"] { - display: flex; - max-width: 168px; - -} - -.sdpi-item[type="range"] .sdpi-item-value span:first-child, -.sdpi-item[type="meter"] .sdpi-item-child span:first-child, -.sdpi-item[type="progress"] .sdpi-item-child span:first-child { - margin-right: 4px; -} - -.sdpi-item[type="range"] .sdpi-item-value span:last-child, -.sdpi-item[type="meter"] .sdpi-item-child span:last-child, -.sdpi-item[type="progress"] .sdpi-item-child span:last-child { - margin-left: 4px; -} - -.reverse { - transform: rotate(180deg); -} - -.sdpi-item[type="meter"] .sdpi-item-child meter + span:last-child { - margin-left: -10px; -} - -.sdpi-item[type="progress"] .sdpi-item-child meter + span:last-child { - margin-left: -14px; -} - -.sdpi-item[type="radio"] > .sdpi-item-value > * { - margin-top: 2px; -} - -details { - padding: 8px 18px 8px 12px; - min-width: 86px; -} - -details > h4 { - border-bottom: 1px solid var(--sdpi-bordercolor); -} - -legend { - display: none; -} -.sdpi-item-value > textarea { - padding: 0px; - width: 227px; - margin-left: 1px; -} - -input[type="radio"] + label span, -input[type="checkbox"] + label span { - display: inline-block; - width: 16px; - height: 16px; - margin: 2px 4px 2px 0; - border-radius: 3px; - vertical-align: middle; - background: var(--sdpi-background); - cursor: pointer; - border: 1px solid rgb(0,0,0,.2); -} - -input[type="radio"] + label span { - border-radius: 100%; -} - -input[type="radio"]:checked + label span, -input[type="checkbox"]:checked + label span { - background-color: #77f; - background-image: url(check.svg); - background-repeat: no-repeat; - background-position: center center; - border: 1px solid rgb(0,0,0,.4); -} - -input[type="radio"]:active:checked + label span, -input[type="radio"]:active + label span, -input[type="checkbox"]:active:checked + label span, -input[type="checkbox"]:active + label span { - background-color: #303030; -} - -input[type="radio"]:checked + label span { - background-image: url(rcheck.svg); -} - - -/* -input[type="radio"] + label span { - background: url(buttons.png) -38px top no-repeat; -} - -input[type="radio"]:checked + label span { - background: url(buttons.png) -57px top no-repeat; -} -*/ - -input[type="range"] { - width: var(--sdpi-width); - height: 30px; - overflow: hidden; - cursor: pointer; - background: transparent !important; -} - -.sdpi-item > input[type="range"] { - margin-left: 8px; - max-width: var(--sdpi-width); - width: var(--sdpi-width); - padding: 0px; -} - -/* -input[type="range"], -input[type="range"]::-webkit-slider-runnable-track, -input[type="range"]::-webkit-slider-thumb { - -webkit-appearance: none; -} -*/ - -input[type="range"]::-webkit-slider-runnable-track { - height: 5px; - background: #979797; - border-radius: 3px; - padding:0px !important; - border: 1px solid var(--sdpi-background); -} - -input[type="range"]::-webkit-slider-thumb { - position: relative; - -webkit-appearance: none; - background-color: var(--sdpi-color); - width: 12px; - height: 12px; - border-radius: 20px; - margin-top: -5px; - border: none; - -} -input[type="range" i]{ - margin: 0; -} - -input[type="range"]::-webkit-slider-thumb::before { - position: absolute; - content: ""; - height: 5px; /* equal to height of runnable track or 1 less */ - width: 500px; /* make this bigger than the widest range input element */ - left: -502px; /* this should be -2px - width */ - top: 8px; /* don't change this */ - background: #77f; -} - -input[type="color"] { - min-width: 32px; - min-height: 32px; - width: 32px; - height: 32px; - padding: 0; - background-color: var(--sdpi-bgcolor); - flex: none; -} - -::-webkit-color-swatch { - min-width: 24px; -} - -textarea { - height: 3em; - word-break: break-word; - line-height: 1.5em; -} - -.textarea { - padding: 0px !important; -} - -textarea { - width: 221px; /*98%;*/ - height: 96%; - min-height: 6em; - resize: none; - border-radius: var(--sdpi-borderradius); -} - -/* CAROUSEL */ - -.sdpi-item[type="carousel"]{ - -} - -.sdpi-item.card-carousel-wrapper, -.sdpi-item > .card-carousel-wrapper { - padding: 0; -} - - -.card-carousel-wrapper { - display: flex; - align-items: center; - justify-content: center; - margin: 12px auto; - color: #666a73; -} - -.card-carousel { - display: flex; - justify-content: center; - width: 278px; -} -.card-carousel--overflow-container { - overflow: hidden; -} -.card-carousel--nav__left, -.card-carousel--nav__right { - /* display: inline-block; */ - width: 12px; - height: 12px; - border-top: 2px solid #42b883; - border-right: 2px solid #42b883; - cursor: pointer; - margin: 0 4px; - transition: transform 150ms linear; -} -.card-carousel--nav__left[disabled], -.card-carousel--nav__right[disabled] { - opacity: 0.2; - border-color: black; -} -.card-carousel--nav__left { - transform: rotate(-135deg); -} -.card-carousel--nav__left:active { - transform: rotate(-135deg) scale(0.85); -} -.card-carousel--nav__right { - transform: rotate(45deg); -} -.card-carousel--nav__right:active { - transform: rotate(45deg) scale(0.85); -} -.card-carousel-cards { - display: flex; - transition: transform 150ms ease-out; - transform: translatex(0px); -} -.card-carousel-cards .card-carousel--card { - margin: 0 5px; - cursor: pointer; - /* box-shadow: 0 4px 15px 0 rgba(40, 44, 53, 0.06), 0 2px 2px 0 rgba(40, 44, 53, 0.08); */ - background-color: #fff; - border-radius: 4px; - z-index: 3; -} -.xxcard-carousel-cards .card-carousel--card:first-child { - margin-left: 0; -} -.xxcard-carousel-cards .card-carousel--card:last-child { - margin-right: 0; -} -.card-carousel-cards .card-carousel--card img { - vertical-align: bottom; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - transition: opacity 150ms linear; - width: 60px; -} -.card-carousel-cards .card-carousel--card img:hover { - opacity: 0.5; -} -.card-carousel-cards .card-carousel--card--footer { - border-top: 0; - max-width: 80px; - overflow: hidden; - display: flex; - height: 100%; - flex-direction: column; -} -.card-carousel-cards .card-carousel--card--footer p { - padding: 3px 0; - margin: 0; - margin-bottom: 2px; - font-size: 15px; - font-weight: 500; - color: #2c3e50; -} -.card-carousel-cards .card-carousel--card--footer p:nth-of-type(2) { - font-size: 12px; - font-weight: 300; - padding: 6px; - color: #666a73; -} - - -h1 { - font-size: 1.3em; - font-weight: 500; - text-align: center; - margin-bottom: 12px; -} - -::-webkit-datetime-edit { - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - background: url(elg_calendar_inv.svg) no-repeat left center; - padding-right: 1em; - padding-left: 25px; - background-position: 4px 0px; - } -::-webkit-datetime-edit-fields-wrapper { - - } -::-webkit-datetime-edit-text { padding: 0 0.3em; } -::-webkit-datetime-edit-month-field { } -::-webkit-datetime-edit-day-field {} -::-webkit-datetime-edit-year-field {} -::-webkit-inner-spin-button { - - /* display: none; */ - } -::-webkit-calendar-picker-indicator { - background: transparent; - font-size: 17px; -} - -::-webkit-calendar-picker-indicator:focus { - background-color: rgba(0,0,0,0.2); -} - -input[type="date"] { - -webkit-align-items: center; - display: -webkit-inline-flex; - font-family: monospace; - overflow: hidden; - padding: 0; - -webkit-padding-start: 1px; -} - -input::-webkit-datetime-edit { - -webkit-flex: 1; - -webkit-user-modify: read-only !important; - display: inline-block; - min-width: 0; - overflow: hidden; -} - -/* -input::-webkit-datetime-edit-fields-wrapper { - -webkit-user-modify: read-only !important; - display: inline-block; - padding: 1px 0; - white-space: pre; - -} -*/ - -/* -input[type="date"] { - background-color: red; - outline: none; -} - -input[type="date"]::-webkit-clear-button { - font-size: 18px; - height: 30px; - position: relative; -} - -input[type="date"]::-webkit-inner-spin-button { - height: 28px; -} - -input[type="date"]::-webkit-calendar-picker-indicator { - font-size: 15px; -} */ - -input[type="file"] { - opacity: 0; - display: none; -} - -.sdpi-item > input[type="file"] { - opacity: 1; - display: flex; -} - -input[type="file"] + span { - display: flex; - flex: 0 1 auto; - background-color: #0000ff50; -} - -label.sdpi-file-label { - cursor: pointer; - user-select: none; - display: inline-block; - min-height: 21px !important; - height: 21px !important; - line-height: 20px; - padding: 0px 4px; - margin: auto; - margin-right: 0px; - float:right; -} - -.sdpi-file-label > label:active, -.sdpi-file-label.file:active, -label.sdpi-file-label:active, -label.sdpi-file-info:active, -input[type="file"]::-webkit-file-upload-button:active, -button:active { - background-color: var(--sdpi-color); - color:#303030; -} - - -input:required:invalid, input:focus:invalid { - background: var(--sdpi-background) url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5IiBoZWlnaHQ9IjkiIHZpZXdCb3g9IjAgMCA5IDkiPgogICAgPHBhdGggZmlsbD0iI0Q4RDhEOCIgZD0iTTQuNSwwIEM2Ljk4NTI4MTM3LC00LjU2NTM4NzgyZS0xNiA5LDIuMDE0NzE4NjMgOSw0LjUgQzksNi45ODUyODEzNyA2Ljk4NTI4MTM3LDkgNC41LDkgQzIuMDE0NzE4NjMsOSAzLjA0MzU5MTg4ZS0xNiw2Ljk4NTI4MTM3IDAsNC41IEMtMy4wNDM1OTE4OGUtMTYsMi4wMTQ3MTg2MyAyLjAxNDcxODYzLDQuNTY1Mzg3ODJlLTE2IDQuNSwwIFogTTQsMSBMNCw2IEw1LDYgTDUsMSBMNCwxIFogTTQuNSw4IEM0Ljc3NjE0MjM3LDggNSw3Ljc3NjE0MjM3IDUsNy41IEM1LDcuMjIzODU3NjMgNC43NzYxNDIzNyw3IDQuNSw3IEM0LjIyMzg1NzYzLDcgNCw3LjIyMzg1NzYzIDQsNy41IEM0LDcuNzc2MTQyMzcgNC4yMjM4NTc2Myw4IDQuNSw4IFoiLz4KICA8L3N2Zz4) no-repeat 98% center; -} - -input:required:valid { - background: var(--sdpi-background) url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5IiBoZWlnaHQ9IjkiIHZpZXdCb3g9IjAgMCA5IDkiPjxwb2x5Z29uIGZpbGw9IiNEOEQ4RDgiIHBvaW50cz0iNS4yIDEgNi4yIDEgNi4yIDcgMy4yIDcgMy4yIDYgNS4yIDYiIHRyYW5zZm9ybT0icm90YXRlKDQwIDQuNjc3IDQpIi8+PC9zdmc+) no-repeat 98% center; -} - -.tooltip, -:tooltip, -:title { - color: yellow; -} - -[title]:hover { - display: flex; - align-items: center; - justify-content: center; -} - -[title]:hover::after { - content: ''; - position: absolute; - bottom: -1000px; - left: 8px; - display: none; - color: #fff; - border: 8px solid transparent; - border-bottom: 8px solid #000; -} -[title]:hover::before { -content: attr(title); - display: flex; - justify-content: center; - align-self: center; - padding: 6px 12px; - border-radius: 5px; - background: rgba(0,0,0,0.8); - color: var(--sdpi-color); - font-size: 9pt; - font-family: sans-serif; - opacity: 1; - position: absolute; - height: auto; - /* width: 50%; - left: 35%; */ - text-align: center; - bottom: 2px; - z-index: 100; - box-shadow: 0px 3px 6px rgba(0, 0, 0, .5); - /* box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); */ -} - -.sdpi-item-group.file { - width: 232px; - display: flex; - align-items: center; -} - -.sdpi-file-info { - overflow-wrap: break-word; - word-wrap: break-word; - hyphens: auto; - - min-width: 132px; - max-width: 144px; - max-height: 32px; - margin-top: 0px; - margin-left: 5px; - display: inline-block; - overflow: hidden; - padding: 6px 4px; - background-color: var(--sdpi-background); -} - - -::-webkit-scrollbar { - width: 8px; -} - -::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); -} - -::-webkit-scrollbar-thumb { - background-color: #999999; - outline: 1px solid slategrey; - border-radius: 8px; -} - -a { - color: #7397d2; -} - -.testcontainer { - display: flex; - background-color: #0000ff20; - max-width: 400px; - height: 200px; - align-content: space-evenly; -} - -input[type=range] { - -webkit-appearance: none; - /* background-color: green; */ - height:6px; - margin-top: 12px; - z-index: 0; - overflow: visible; -} - -/* -input[type="range"]::-webkit-slider-thumb { - -webkit-appearance: none; - background-color: var(--sdpi-color); - width: 12px; - height: 12px; - border-radius: 20px; - margin-top: -6px; - border: none; -} */ - -:-webkit-slider-thumb { - -webkit-appearance: none; - background-color: var(--sdpi-color); - width: 16px; - height: 16px; - border-radius: 20px; - margin-top: -6px; - border: 1px solid #999999; -} - -.sdpi-item[type="range"] .sdpi-item-group { - display: flex; - flex-direction: column; -} - -.xxsdpi-item[type="range"] .sdpi-item-group input { - max-width: 204px; -} - -.sdpi-item[type="range"] .sdpi-item-group span { - margin-left: 0px !important; -} - -.sdpi-item[type="range"] .sdpi-item-group > .sdpi-item-child { - display: flex; - flex-direction: row; -} - -:disabled { - color: #993333; -} - -select, -select option { - color: var(--sdpi-color); -} - -select.disabled, -select option:disabled { - color: #fd9494; - font-style: italic; -} - -.runningAppsContainer { - display: none; -} - -/* debug -div { - background-color: rgba(64,128,255,0.2); -} -*/ - -.min80 > .sdpi-item-child { - min-width: 80px; -} - -.min100 > .sdpi-item-child { - min-width: 100px; -} - -.min120 > .sdpi-item-child { - min-width: 120px; -} - -.min140 > .sdpi-item-child { - min-width: 140px; -} - -.min160 > .sdpi-item-child { - min-width: 160px; -} - -.min200 > .sdpi-item-child { - min-width: 200px; -} - -.max40 { - flex-basis: 40%; - flex-grow: 0; -} - -.max30 { - flex-basis: 30%; - flex-grow: 0; -} - -.max20 { - flex-basis: 20%; - flex-grow: 0; -} - -.up20 { - margin-top: -20px; -} - -.alignCenter { - align-items: center; -} - -.alignTop { - align-items: flex-start; -} - -.alignBaseline { - align-items: baseline; -} - -.noMargins, -.noMargins *, -.noInnerMargins * { - margin: 0; - padding: 0; -} - -.hidden { - display: none; -} - -.icon-brighter, -.icon-darker, -.icon-warmer, -.icon-cooler { - margin-top: 5px !important; - min-width: 20px; - width: 20px; - background-repeat: no-repeat; -} - -.icon-brighter { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Ccircle cx='10' cy='10' r='4'/%3E%3Cpath d='M14.8532861,7.77530426 C14.7173255,7.4682615 14.5540843,7.17599221 14.3666368,6.90157083 L16.6782032,5.5669873 L17.1782032,6.4330127 L14.8532861,7.77530426 Z M10.5,4.5414007 C10.2777625,4.51407201 10.051423,4.5 9.82179677,4.5 C9.71377555,4.5 9.60648167,4.50311409 9.5,4.50925739 L9.5,2 L10.5,2 L10.5,4.5414007 Z M5.38028092,6.75545367 C5.18389364,7.02383457 5.01124349,7.31068015 4.86542112,7.61289977 L2.82179677,6.4330127 L3.32179677,5.5669873 L5.38028092,6.75545367 Z M4.86542112,12.3871002 C5.01124349,12.6893198 5.18389364,12.9761654 5.38028092,13.2445463 L3.32179677,14.4330127 L2.82179677,13.5669873 L4.86542112,12.3871002 Z M9.5,15.4907426 C9.60648167,15.4968859 9.71377555,15.5 9.82179677,15.5 C10.051423,15.5 10.2777625,15.485928 10.5,15.4585993 L10.5,18 L9.5,18 L9.5,15.4907426 Z M14.3666368,13.0984292 C14.5540843,12.8240078 14.7173255,12.5317385 14.8532861,12.2246957 L17.1782032,13.5669873 L16.6782032,14.4330127 L14.3666368,13.0984292 Z'/%3E%3C/g%3E%3C/svg%3E"); -} -.icon-darker { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M10 14C7.790861 14 6 12.209139 6 10 6 7.790861 7.790861 6 10 6 12.209139 6 14 7.790861 14 10 14 12.209139 12.209139 14 10 14zM10 13C11.6568542 13 13 11.6568542 13 10 13 8.34314575 11.6568542 7 10 7 8.34314575 7 7 8.34314575 7 10 7 11.6568542 8.34314575 13 10 13zM14.8532861 7.77530426C14.7173255 7.4682615 14.5540843 7.17599221 14.3666368 6.90157083L16.6782032 5.5669873 17.1782032 6.4330127 14.8532861 7.77530426zM10.5 4.5414007C10.2777625 4.51407201 10.051423 4.5 9.82179677 4.5 9.71377555 4.5 9.60648167 4.50311409 9.5 4.50925739L9.5 2 10.5 2 10.5 4.5414007zM5.38028092 6.75545367C5.18389364 7.02383457 5.01124349 7.31068015 4.86542112 7.61289977L2.82179677 6.4330127 3.32179677 5.5669873 5.38028092 6.75545367zM4.86542112 12.3871002C5.01124349 12.6893198 5.18389364 12.9761654 5.38028092 13.2445463L3.32179677 14.4330127 2.82179677 13.5669873 4.86542112 12.3871002zM9.5 15.4907426C9.60648167 15.4968859 9.71377555 15.5 9.82179677 15.5 10.051423 15.5 10.2777625 15.485928 10.5 15.4585993L10.5 18 9.5 18 9.5 15.4907426zM14.3666368 13.0984292C14.5540843 12.8240078 14.7173255 12.5317385 14.8532861 12.2246957L17.1782032 13.5669873 16.6782032 14.4330127 14.3666368 13.0984292z'/%3E%3C/g%3E%3C/svg%3E"); -} -.icon-warmer { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M12.3247275 11.4890349C12.0406216 11.0007637 11.6761954 10.5649925 11.2495475 10.1998198 11.0890394 9.83238991 11 9.42659309 11 9 11 7.34314575 12.3431458 6 14 6 15.6568542 6 17 7.34314575 17 9 17 10.6568542 15.6568542 12 14 12 13.3795687 12 12.8031265 11.8116603 12.3247275 11.4890349zM17.6232392 11.6692284C17.8205899 11.4017892 17.9890383 11.1117186 18.123974 10.8036272L20.3121778 12.0669873 19.8121778 12.9330127 17.6232392 11.6692284zM18.123974 7.19637279C17.9890383 6.88828142 17.8205899 6.5982108 17.6232392 6.33077158L19.8121778 5.0669873 20.3121778 5.9330127 18.123974 7.19637279zM14.5 4.52746439C14.3358331 4.50931666 14.1690045 4.5 14 4.5 13.8309955 4.5 13.6641669 4.50931666 13.5 4.52746439L13.5 2 14.5 2 14.5 4.52746439zM13.5 13.4725356C13.6641669 13.4906833 13.8309955 13.5 14 13.5 14.1690045 13.5 14.3358331 13.4906833 14.5 13.4725356L14.5 16 13.5 16 13.5 13.4725356zM14 11C15.1045695 11 16 10.1045695 16 9 16 7.8954305 15.1045695 7 14 7 12.8954305 7 12 7.8954305 12 9 12 10.1045695 12.8954305 11 14 11zM9.5 11C10.6651924 11.4118364 11.5 12.5 11.5 14 11.5 16 10 17.5 8 17.5 6 17.5 4.5 16 4.5 14 4.5 12.6937812 5 11.5 6.5 11L6.5 7 9.5 7 9.5 11z'/%3E%3Cpath d='M12,14 C12,16.209139 10.209139,18 8,18 C5.790861,18 4,16.209139 4,14 C4,12.5194353 4.80439726,11.2267476 6,10.5351288 L6,4 C6,2.8954305 6.8954305,2 8,2 C9.1045695,2 10,2.8954305 10,4 L10,10.5351288 C11.1956027,11.2267476 12,12.5194353 12,14 Z M11,14 C11,12.6937812 10.1651924,11.5825421 9,11.1707057 L9,4 C9,3.44771525 8.55228475,3 8,3 C7.44771525,3 7,3.44771525 7,4 L7,11.1707057 C5.83480763,11.5825421 5,12.6937812 5,14 C5,15.6568542 6.34314575,17 8,17 C9.65685425,17 11,15.6568542 11,14 Z'/%3E%3C/g%3E%3C/svg%3E"); -} - -.icon-cooler { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M10.4004569 11.6239517C10.0554735 10.9863849 9.57597206 10.4322632 9 9.99963381L9 9.7450467 9.53471338 9.7450467 10.8155381 8.46422201C10.7766941 8.39376637 10.7419749 8.32071759 10.7117062 8.2454012L9 8.2454012 9 6.96057868 10.6417702 6.96057868C10.6677696 6.86753378 10.7003289 6.77722682 10.7389179 6.69018783L9.44918707 5.40045694 9 5.40045694 9 4.34532219 9.32816127 4.34532219 9.34532219 2.91912025 10.4004569 2.91912025 10.4004569 4.53471338 11.6098599 5.74411634C11.7208059 5.68343597 11.8381332 5.63296451 11.9605787 5.59396526L11.9605787 3.8884898 10.8181818 2.74609294 11.5642748 2 12.5727518 3.00847706 13.5812289 2 14.3273218 2.74609294 13.2454012 3.82801356 13.2454012 5.61756719C13.3449693 5.65339299 13.4408747 5.69689391 13.5324038 5.74735625L14.7450467 4.53471338 14.7450467 2.91912025 15.8001815 2.91912025 15.8001815 4.34532219 17.2263834 4.34532219 17.2263834 5.40045694 15.6963166 5.40045694 14.4002441 6.69652946C14.437611 6.78161093 14.4692249 6.86979146 14.4945934 6.96057868L16.2570138 6.96057868 17.3994107 5.81818182 18.1455036 6.56427476 17.1370266 7.57275182 18.1455036 8.58122888 17.3994107 9.32732182 16.3174901 8.2454012 14.4246574 8.2454012C14.3952328 8.31861737 14.3616024 8.38969062 14.3240655 8.45832192L15.6107903 9.7450467 17.2263834 9.7450467 17.2263834 10.8001815 15.8001815 10.8001815 15.8001815 12.2263834 14.7450467 12.2263834 14.7450467 10.6963166 13.377994 9.32926387C13.3345872 9.34850842 13.2903677 9.36625331 13.2454012 9.38243281L13.2454012 11.3174901 14.3273218 12.3994107 13.5812289 13.1455036 12.5848864 12.1491612 11.5642748 13.1455036 10.8181818 12.3994107 11.9605787 11.2570138 11.9605787 9.40603474C11.8936938 9.38473169 11.828336 9.36000556 11.7647113 9.33206224L10.4004569 10.6963166 10.4004569 11.6239517zM12.75 8.5C13.3022847 8.5 13.75 8.05228475 13.75 7.5 13.75 6.94771525 13.3022847 6.5 12.75 6.5 12.1977153 6.5 11.75 6.94771525 11.75 7.5 11.75 8.05228475 12.1977153 8.5 12.75 8.5zM9.5 14C8.5 16.3333333 7.33333333 17.5 6 17.5 4.66666667 17.5 3.5 16.3333333 2.5 14L9.5 14z'/%3E%3Cpath d='M10,14 C10,16.209139 8.209139,18 6,18 C3.790861,18 2,16.209139 2,14 C2,12.5194353 2.80439726,11.2267476 4,10.5351288 L4,4 C4,2.8954305 4.8954305,2 6,2 C7.1045695,2 8,2.8954305 8,4 L8,10.5351288 C9.19560274,11.2267476 10,12.5194353 10,14 Z M9,14 C9,12.6937812 8.16519237,11.5825421 7,11.1707057 L7,4 C7,3.44771525 6.55228475,3 6,3 C5.44771525,3 5,3.44771525 5,4 L5,11.1707057 C3.83480763,11.5825421 3,12.6937812 3,14 C3,15.6568542 4.34314575,17 6,17 C7.65685425,17 9,15.6568542 9,14 Z'/%3E%3C/g%3E%3C/svg%3E"); -} - -.doubleLineTextArea { - height: 30px; - overflow: hidden; -} - -.singleLineTextArea { - height: 26px !important; - overflow: hidden; -} - -/** -input[type=range].vVertical { - -webkit-appearance: none; - background-color: green; - margin-left: -60px; - width: 100px; - height:6px; - margin-top: 0px; - transform:rotate(90deg); - z-index: 0; - overflow: visible; -} - -input[type=range].vHorizon { - -webkit-appearance: none; - background-color: pink; - height: 10px; - width:200px; - -} - -.test2 { - background-color: #00ff0020; - display: flex; -} - - -.vertical.sdpi-item[type="range"] .sdpi-item-value { - display: block; -} - - -.vertical.sdpi-item:first-child, -.vertical { - margin-top: 12px; - margin-bottom: 16px; -} -.vertical > .sdpi-item-value { - margin-right: 16px; -} - -.vertical .sdpi-item-group { - width: 100%; - display: flex; - justify-content: space-evenly; -} - -.vertical input[type=range] { - height: 100px; - width: 21px; - -webkit-appearance: slider-vertical; - display: flex; - flex-flow: column; -} - -.vertical input[type="range"]::-webkit-slider-runnable-track { - height: auto; - width: 5px; -} - -.vertical input[type="range"]::-webkit-slider-thumb { - margin-top: 0px; - margin-left: -6px; -} - -.vertical .sdpi-item-value { - flex-flow: column; - align-items: flex-start; -} - -.vertical.sdpi-item[type="range"] .sdpi-item-value { - align-items: center; - margin-right: 16px; - text-align: center; -} - -.vertical.sdpi-item[type="range"] .sdpi-item-value span, -.vertical input[type="range"] .sdpi-item-value span { - text-align: center; - margin: 4px 0px; -} -*/ - diff --git a/VoiceMeeter/PropertyInspector/sdtools.common.js b/VoiceMeeter/PropertyInspector/sdtools.common.js deleted file mode 100644 index d262dc9..0000000 --- a/VoiceMeeter/PropertyInspector/sdtools.common.js +++ /dev/null @@ -1,299 +0,0 @@ -// **************************************************************** -// * EasyPI v1.3 -// * Author: BarRaider -// * -// * JS library to simplify the communication between the -// * Stream Deck's Property Inspector and the plugin. -// * -// * Project page: https://github.com/BarRaider/streamdeck-easypi -// * Support: http://discord.barraider.com -// **************************************************************** - -var websocket = null, - uuid = null, - registerEventName = null, - actionInfo = {}, - inInfo = {}, - runningApps = [], - isQT = navigator.appVersion.includes('QtWebEngine'); - -function connectElgatoStreamDeckSocket(inPort, inUUID, inRegisterEvent, inInfo, inActionInfo) { - uuid = inUUID; - registerEventName = inRegisterEvent; - console.log(inUUID, inActionInfo); - actionInfo = JSON.parse(inActionInfo); // cache the info - inInfo = JSON.parse(inInfo); - websocket = new WebSocket('ws://127.0.0.1:' + inPort); - - addDynamicStyles(inInfo.colors); - - websocket.onopen = websocketOnOpen; - websocket.onmessage = websocketOnMessage; - - // Allow others to get notified that the websocket is created - var event = new Event('websocketCreate'); - document.dispatchEvent(event); - - loadConfiguration(actionInfo.payload.settings); -} - -function websocketOnOpen() { - var json = { - event: registerEventName, - uuid: uuid - }; - websocket.send(JSON.stringify(json)); - - // Notify the plugin that we are connected - sendValueToPlugin('propertyInspectorConnected', 'property_inspector'); -} - -function websocketOnMessage(evt) { - // Received message from Stream Deck - var jsonObj = JSON.parse(evt.data); - - if (jsonObj.event === 'sendToPropertyInspector') { - var payload = jsonObj.payload; - loadConfiguration(payload); - } - else if (jsonObj.event === 'didReceiveSettings') { - var payload = jsonObj.payload; - loadConfiguration(payload.settings); - } - else { - console.log("Unhandled websocketOnMessage: " + jsonObj.event); - } -} - -function loadConfiguration(payload) { - console.log('loadConfiguration'); - console.log(payload); - for (var key in payload) { - try { - var elem = document.getElementById(key); - if (elem.classList.contains("sdCheckbox")) { // Checkbox - elem.checked = payload[key]; - } - else if (elem.classList.contains("sdFile")) { // File - var elemFile = document.getElementById(elem.id + "Filename"); - elemFile.innerText = payload[key]; - if (!elemFile.innerText) { - elemFile.innerText = "No file..."; - } - } - else if (elem.classList.contains("sdList")) { // Dynamic dropdown - var textProperty = elem.getAttribute("sdListTextProperty"); - var valueProperty = elem.getAttribute("sdListValueProperty"); - var valueField = elem.getAttribute("sdValueField"); - - var items = payload[key]; - elem.options.length = 0; - - for (var idx = 0; idx < items.length; idx++) { - var opt = document.createElement('option'); - opt.value = items[idx][valueProperty]; - opt.text = items[idx][textProperty]; - elem.appendChild(opt); - } - elem.value = payload[valueField]; - } - else if (elem.classList.contains("sdHTML")) { // HTML element - elem.innerHTML = payload[key]; - } - else { // Normal value - elem.value = payload[key]; - } - console.log("Load: " + key + "=" + payload[key]); - } - catch (err) { - console.log("loadConfiguration failed for key: " + key + " - " + err); - } - } -} - -function setSettings() { - var payload = {}; - var elements = document.getElementsByClassName("sdProperty"); - - Array.prototype.forEach.call(elements, function (elem) { - var key = elem.id; - if (elem.classList.contains("sdCheckbox")) { // Checkbox - payload[key] = elem.checked; - } - else if (elem.classList.contains("sdFile")) { // File - var elemFile = document.getElementById(elem.id + "Filename"); - payload[key] = elem.value; - if (!elem.value) { - // Fetch innerText if file is empty (happens when we lose and regain focus to this key) - payload[key] = elemFile.innerText; - } - else { - // Set value on initial file selection - elemFile.innerText = elem.value; - } - } - else if (elem.classList.contains("sdList")) { // Dynamic dropdown - var valueField = elem.getAttribute("sdValueField"); - payload[valueField] = elem.value; - } - else if (elem.classList.contains("sdHTML")) { // HTML element - var valueField = elem.getAttribute("sdValueField"); - payload[valueField] = elem.innerHTML; - } - else { // Normal value - payload[key] = elem.value; - } - console.log("Save: " + key + "<=" + payload[key]); - }); - setSettingsToPlugin(payload); -} - -function setSettingsToPlugin(payload) { - if (websocket && (websocket.readyState === 1)) { - const json = { - 'event': 'setSettings', - 'context': uuid, - 'payload': payload - }; - websocket.send(JSON.stringify(json)); - var event = new Event('settingsUpdated'); - document.dispatchEvent(event); - } -} - -// Sends an entire payload to the sendToPlugin method -function sendPayloadToPlugin(payload) { - if (websocket && (websocket.readyState === 1)) { - const json = { - 'action': actionInfo['action'], - 'event': 'sendToPlugin', - 'context': uuid, - 'payload': payload - }; - websocket.send(JSON.stringify(json)); - } -} - -// Sends one value to the sendToPlugin method -function sendValueToPlugin(value, param) { - if (websocket && (websocket.readyState === 1)) { - const json = { - 'action': actionInfo['action'], - 'event': 'sendToPlugin', - 'context': uuid, - 'payload': { - [param]: value - } - }; - websocket.send(JSON.stringify(json)); - } -} - -function openWebsite() { - if (websocket && (websocket.readyState === 1)) { - const json = { - 'event': 'openUrl', - 'payload': { - 'url': 'https://BarRaider.com' - } - }; - websocket.send(JSON.stringify(json)); - } -} - -if (!isQT) { - document.addEventListener('DOMContentLoaded', function () { - initPropertyInspector(); - }); -} - -window.addEventListener('beforeunload', function (e) { - e.preventDefault(); - - // Notify the plugin we are about to leave - sendValueToPlugin('propertyInspectorWillDisappear', 'property_inspector'); - - // Don't set a returnValue to the event, otherwise Chromium with throw an error. -}); - -function initPropertyInspector() { - // Place to add functions -} - - -function addDynamicStyles(clrs) { - const node = document.getElementById('#sdpi-dynamic-styles') || document.createElement('style'); - if (!clrs.mouseDownColor) clrs.mouseDownColor = fadeColor(clrs.highlightColor, -100); - const clr = clrs.highlightColor.slice(0, 7); - const clr1 = fadeColor(clr, 100); - const clr2 = fadeColor(clr, 60); - const metersActiveColor = fadeColor(clr, -60); - - node.setAttribute('id', 'sdpi-dynamic-styles'); - node.innerHTML = ` - - input[type="radio"]:checked + label span, - input[type="checkbox"]:checked + label span { - background-color: ${clrs.highlightColor}; - } - - input[type="radio"]:active:checked + label span, - input[type="radio"]:active + label span, - input[type="checkbox"]:active:checked + label span, - input[type="checkbox"]:active + label span { - background-color: ${clrs.mouseDownColor}; - } - - input[type="radio"]:active + label span, - input[type="checkbox"]:active + label span { - background-color: ${clrs.buttonPressedBorderColor}; - } - - td.selected, - td.selected:hover, - li.selected:hover, - li.selected { - color: white; - background-color: ${clrs.highlightColor}; - } - - .sdpi-file-label > label:active, - .sdpi-file-label.file:active, - label.sdpi-file-label:active, - label.sdpi-file-info:active, - input[type="file"]::-webkit-file-upload-button:active, - button:active { - background-color: ${clrs.buttonPressedBackgroundColor}; - color: ${clrs.buttonPressedTextColor}; - border-color: ${clrs.buttonPressedBorderColor}; - } - - ::-webkit-progress-value, - meter::-webkit-meter-optimum-value { - background: linear-gradient(${clr2}, ${clr1} 20%, ${clr} 45%, ${clr} 55%, ${clr2}) - } - - ::-webkit-progress-value:active, - meter::-webkit-meter-optimum-value:active { - background: linear-gradient(${clr}, ${clr2} 20%, ${metersActiveColor} 45%, ${metersActiveColor} 55%, ${clr}) - } - `; - document.body.appendChild(node); -}; - -/** UTILITIES */ - -/* - Quick utility to lighten or darken a color (doesn't take color-drifting, etc. into account) - Usage: - fadeColor('#061261', 100); // will lighten the color - fadeColor('#200867'), -100); // will darken the color -*/ -function fadeColor(col, amt) { - const min = Math.min, max = Math.max; - const num = parseInt(col.replace(/#/g, ''), 16); - const r = min(255, max((num >> 16) + amt, 0)); - const g = min(255, max((num & 0x0000FF) + amt, 0)); - const b = min(255, max(((num >> 8) & 0x00FF) + amt, 0)); - return '#' + (g | (b << 8) | (r << 16)).toString(16).padStart(6, 0); -} \ No newline at end of file diff --git a/VoiceMeeter/VMManager.cs b/VoiceMeeter/VMManager.cs index bd295d6..e7397c9 100644 --- a/VoiceMeeter/VMManager.cs +++ b/VoiceMeeter/VMManager.cs @@ -36,7 +36,7 @@ public sealed class VMManager IsConnected = true; tmrCheckDirty = new Timer(); tmrCheckDirty.Elapsed += TmrCheckDirty_Elapsed; - tmrCheckDirty.Interval = 10; + tmrCheckDirty.Interval = 100; tmrCheckDirty.Start(); } @@ -89,5 +89,15 @@ public void SetParameters(string parameters) { client.SetParameters(parameters); } + + public bool GetMacroStatus(int buttonId) + { + return client.GetMacroStatus(buttonId) > 0; + } + + public void SetMacroStatus(int buttonId, bool isEnabled) + { + client.SetMacroStatus(buttonId, isEnabled ? 1f : 0f); + } } } diff --git a/VoiceMeeter/VoiceMeeter.csproj b/VoiceMeeter/VoiceMeeter.csproj index 3161d9a..6bfe944 100644 --- a/VoiceMeeter/VoiceMeeter.csproj +++ b/VoiceMeeter/VoiceMeeter.csproj @@ -36,34 +36,37 @@ 4 8.0 + + brlogo.ico + - - ..\..\..\DotNet\StreamDeck\packages\CommandLineParser.2.7.82\lib\net461\CommandLine.dll + + ..\..\..\DotNet\StreamDeck\packages\CommandLineParser.2.8.0\lib\net461\CommandLine.dll ..\..\..\DotNet\StreamDeck\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll - ..\..\..\DotNet\StreamDeck\packages\NLog.4.7.0\lib\net45\NLog.dll + ..\..\..\DotNet\StreamDeck\packages\NLog.4.7.5\lib\net45\NLog.dll - ..\..\..\DotNet\StreamDeck\packages\RtMidi.Core.1.0.50\lib\netstandard2.0\RtMidi.Core.dll + ..\..\..\DotNet\StreamDeck\packages\RtMidi.Core.1.0.51\lib\netstandard2.0\RtMidi.Core.dll - ..\..\..\DotNet\StreamDeck\packages\Serilog.2.9.0\lib\net46\Serilog.dll + ..\..\..\DotNet\StreamDeck\packages\Serilog.2.10.0\lib\net46\Serilog.dll - - ..\..\..\DotNet\StreamDeck\packages\streamdeck-client-csharp.4.1.1\lib\netstandard2.0\streamdeck-client-csharp.dll + + ..\..\..\DotNet\StreamDeck\packages\streamdeck-client-csharp.4.2.0\lib\netstandard2.0\streamdeck-client-csharp.dll - - ..\..\..\DotNet\StreamDeck\packages\StreamDeck-Tools.2.8.0\lib\net472\StreamDeckTools.dll + + ..\..\..\DotNet\StreamDeck\packages\StreamDeck-Tools.3.1.0\lib\net472\StreamDeckTools.dll - ..\..\..\DotNet\StreamDeck\packages\System.Drawing.Common.4.7.0\lib\net461\System.Drawing.Common.dll + ..\..\..\DotNet\StreamDeck\packages\System.Drawing.Common.5.0.0\lib\net461\System.Drawing.Common.dll @@ -81,6 +84,7 @@ + @@ -114,6 +118,19 @@ + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -156,22 +173,19 @@ PreserveNewest - - PreserveNewest - PreserveNewest PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest @@ -179,11 +193,11 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/VoiceMeeter/VoiceMeeterWrapper/VmClient.cs b/VoiceMeeter/VoiceMeeterWrapper/VmClient.cs index dfc4086..87d8ca4 100644 --- a/VoiceMeeter/VoiceMeeterWrapper/VmClient.cs +++ b/VoiceMeeter/VoiceMeeterWrapper/VmClient.cs @@ -48,9 +48,21 @@ public void SetParameters(string parameters) VoiceMeeterRemote.SetParameters(parameters); } + public void SetMacroStatus(int buttonId, float value) + { + VoiceMeeterRemote.SetMacroStatus(buttonId, value, 0); + } + + public float GetMacroStatus(int buttonId) + { + float value = 0; + VoiceMeeterRemote.GetMacroStatus(buttonId, ref value, 0); + return value; + } + public int Poll() { - return VoiceMeeterRemote.IsParametersDirty(); + return VoiceMeeterRemote.IsParametersDirty() + VoiceMeeterRemote.IsMacrosDirty(); } private bool disposed = false; diff --git a/VoiceMeeter/VoiceMeeterWrapper/VoiceMeeterRemote.cs b/VoiceMeeter/VoiceMeeterWrapper/VoiceMeeterRemote.cs index de29e1a..c66b737 100644 --- a/VoiceMeeter/VoiceMeeterWrapper/VoiceMeeterRemote.cs +++ b/VoiceMeeter/VoiceMeeterWrapper/VoiceMeeterRemote.cs @@ -25,12 +25,21 @@ public static class VoiceMeeterRemote [DllImport("VoicemeeterRemote.dll", EntryPoint = "VBVMR_IsParametersDirty")] public static extern int IsParametersDirty(); + [DllImport("VoicemeeterRemote.dll", EntryPoint = "VBVMR_MacroButton_IsDirty")] + public static extern int IsMacrosDirty(); + [DllImport("VoicemeeterRemote.dll", EntryPoint = "VBVMR_GetVoicemeeterVersion")] public static extern int GetVoicemeeterVersion(ref long value); [DllImport("VoicemeeterRemote.dll", EntryPoint = "VBVMR_SetParameters")] public static extern int SetParameters(string szParameters); + [DllImport("VoicemeeterRemote.dll", EntryPoint = "VBVMR_MacroButton_GetStatus")] + public static extern int GetMacroStatus(int buttonId, ref float value, int bitmode); + + [DllImport("VoicemeeterRemote.dll", EntryPoint = "VBVMR_MacroButton_SetStatus")] + public static extern int SetMacroStatus(int buttonId, float value, int bitmode); + [DllImport("kernel32.dll")] private static extern IntPtr LoadLibrary(string dllToLoad); private static IntPtr? _dllHandle; diff --git a/VoiceMeeter/brlogo.ico b/VoiceMeeter/brlogo.ico new file mode 100644 index 0000000..4dd029a Binary files /dev/null and b/VoiceMeeter/brlogo.ico differ diff --git a/VoiceMeeter/manifest.json b/VoiceMeeter/manifest.json index 4e2389e..8a41feb 100644 --- a/VoiceMeeter/manifest.json +++ b/VoiceMeeter/manifest.json @@ -2,37 +2,39 @@ "Actions": [ { "Icon": "Images/icon", - "Name": "VoiceMeeter Mute/Unmute", + "Name": "Modify Setting", "States": [ { - "Image": "Images/vm", + "Image": "Images/vmTop", "TitleAlignment": "bottom", "FontSize": "11" } ], "SupportedInMultiActions": true, - "Tooltip": "VoiceMeeter Mute/Unmute - See a live indication of the current status on Stream Deck (never forget your microphone on again!).", - "UUID": "com.barraider.vmmicrophone", - "PropertyInspectorPath": "PropertyInspector/VoiceMeeter/Microphone.html" + "DisableCaching": true, + "Tooltip": "Modify Setting - Allows you to easily modify various VoiceMeeter settings.", + "UUID": "com.barraider.vmmodify", + "PropertyInspectorPath": "PropertyInspector/VoiceMeeter/Modify.html" }, { "Icon": "Images/icon", - "Name": "VoiceMeeter Modify Setting", + "Name": "Mute/Unmute", "States": [ { - "Image": "Images/vmTop", + "Image": "Images/vm", "TitleAlignment": "bottom", "FontSize": "11" } ], "SupportedInMultiActions": true, - "Tooltip": "VoiceMeeter Modify Setting - Allows you to easily modify various VoiceMeeter settings.", - "UUID": "com.barraider.vmmodify", - "PropertyInspectorPath": "PropertyInspector/VoiceMeeter/Modify.html" + "DisableCaching": true, + "Tooltip": "Mute/Unmute - See a live indication of the current status on Stream Deck (never forget your microphone on again!).", + "UUID": "com.barraider.vmmicrophone", + "PropertyInspectorPath": "PropertyInspector/VoiceMeeter/Microphone.html" }, { "Icon": "Images/icon", - "Name": "VoiceMeeter Advanced Press/Long-Press", + "Name": "Advanced Press/Long-Press", "States": [ { "Image": "Images/vmTop", @@ -41,13 +43,14 @@ } ], "SupportedInMultiActions": true, - "Tooltip": "VoiceMeeter Advanced Press/Long-Press - Directly access any setting through text. Supports both Press and Long-Press (allows you to change between two preset list of settings).", + "DisableCaching": true, + "Tooltip": "Advanced Press/Long-Press - Directly access any setting through text. Supports both Press and Long-Press (allows you to change between two preset list of settings).", "UUID": "com.barraider.vmadvanced", "PropertyInspectorPath": "PropertyInspector/VoiceMeeter/AdvancedKeypress.html" }, { "Icon": "Images/icon", - "Name": "VoiceMeeter Advanced Toggle", + "Name": "Advanced Toggle", "States": [ { "Image": "Images/vmTop", @@ -56,13 +59,14 @@ } ], "SupportedInMultiActions": true, - "Tooltip": "VoiceMeeter Advanced Toggle - Focused on toggling between two modes (versus click and long click in the VoiceMeeter Advanced Click/Long-Click).", + "DisableCaching": true, + "Tooltip": "Advanced Toggle - Focused on toggling between two modes (versus click and long click in the VoiceMeeter Advanced Click/Long-Click).", "UUID": "com.barraider.vmadvancedtoggle", "PropertyInspectorPath": "PropertyInspector/VoiceMeeter/AdvancedToggle.html" }, { "Icon": "Images/icon", - "Name": "VoiceMeeter Advanced PTT", + "Name": "Advanced PTT", "States": [ { "Image": "Images/vmTop", @@ -71,9 +75,26 @@ } ], "SupportedInMultiActions": true, - "Tooltip": "VoiceMeeter Advanced PTT - Enable settings until you release the button", + "DisableCaching": true, + "Tooltip": "Advanced PTT - Enable settings until you release the button", "UUID": "com.barraider.vmadvancedptt", "PropertyInspectorPath": "PropertyInspector/VoiceMeeter/AdvancedPTT.html" + }, + { + "Icon": "Images/icon", + "Name": "MacroButton Toggle", + "States": [ + { + "Image": "Images/buttonDisabled", + "TitleAlignment": "middle", + "FontSize": "11" + } + ], + "SupportedInMultiActions": true, + "DisableCaching": true, + "Tooltip": "MacroButton Toggle - Enable/Disable a VoiceMeeter MacroButton", + "UUID": "com.barraider.vmmacrotoggle", + "PropertyInspectorPath": "PropertyInspector/VoiceMeeter/MacroToggle.html" } ], "Author": "BarRaider", @@ -81,7 +102,7 @@ "Name": "VoiceMeeter Integration", "Icon": "Images/pluginIcon", "URL": "https://BarRaider.com/", - "Version": "1.8", + "Version": "1.9", "CodePath": "com.barraider.voicemeeter.exe", "Category": "VoiceMeeter [BarRaider]", "CategoryIcon": "Images/categoryIcon", @@ -93,6 +114,6 @@ ], "SDKVersion": 2, "Software": { - "MinimumVersion": "4.5.1" + "MinimumVersion": "4.9" } } diff --git a/VoiceMeeter/packages.config b/VoiceMeeter/packages.config index a41b513..748b447 100644 --- a/VoiceMeeter/packages.config +++ b/VoiceMeeter/packages.config @@ -1,11 +1,11 @@  - + - - - - - - + + + + + + \ No newline at end of file