From 8475b7effb6eb625320f054ce2801ab3a74ad73b Mon Sep 17 00:00:00 2001 From: Anna Date: Mon, 24 Aug 2020 13:13:42 -0400 Subject: [PATCH] feat: allow volume control and more audio types Also allow choosing audio output device. --- Peeping Tom/Configuration.cs | 2 ++ Peeping Tom/Peeping Tom.csproj | 3 +++ Peeping Tom/PluginUI.cs | 44 ++++++++++++++++++++++++++++--- Peeping Tom/TargetWatcher.cs | 47 ++++++++++++++++++++++++---------- Peeping Tom/packages.config | 1 + 5 files changed, 79 insertions(+), 18 deletions(-) diff --git a/Peeping Tom/Configuration.cs b/Peeping Tom/Configuration.cs index 5fb06c4..6e16c2e 100644 --- a/Peeping Tom/Configuration.cs +++ b/Peeping Tom/Configuration.cs @@ -36,6 +36,8 @@ namespace PeepingTom { public bool FocusTargetOnHover { get; set; } = true; public bool PlaySoundOnTarget { get; set; } = false; public string SoundPath { get; set; } = null; + public float SoundVolume { get; set; } = 1f; + public int SoundDevice { get; set; } = -1; public float SoundCooldown { get; set; } = 10f; public bool PlaySoundWhenClosed { get; set; } = false; diff --git a/Peeping Tom/Peeping Tom.csproj b/Peeping Tom/Peeping Tom.csproj index 7a6db6c..89a2427 100644 --- a/Peeping Tom/Peeping Tom.csproj +++ b/Peeping Tom/Peeping Tom.csproj @@ -48,6 +48,9 @@ $(AppData)\XIVLauncher\addon\Hooks\ImGuiScene.dll + + ..\packages\NAudio.1.10.0\lib\net35\NAudio.dll + diff --git a/Peeping Tom/PluginUI.cs b/Peeping Tom/PluginUI.cs index 4fc3891..7aa536e 100644 --- a/Peeping Tom/PluginUI.cs +++ b/Peeping Tom/PluginUI.cs @@ -4,6 +4,7 @@ using Dalamud.Game.Chat.SeStringHandling.Payloads; using Dalamud.Game.ClientState; using Dalamud.Game.ClientState.Actors.Types; using ImGuiNET; +using NAudio.Wave; using System; using System.Collections.Generic; using System.Linq; @@ -89,8 +90,8 @@ namespace PeepingTom { private void ShowSettings() { // 700x250 if setting a size - ImGui.SetNextWindowSize(new Vector2(700, 250)); - if (ImGui.Begin($"{this.plugin.Name} settings", ref this._settingsOpen)) { + ImGui.SetNextWindowSize(new Vector2(700, 275)); + if (ImGui.Begin($"{this.plugin.Name} settings", ref this._settingsOpen, ImGuiWindowFlags.NoResize)) { if (ImGui.BeginTabBar("##settings-tabs")) { if (ImGui.BeginTabItem("Markers")) { bool markTargeted = this.plugin.Config.MarkTargeted; @@ -178,7 +179,7 @@ namespace PeepingTom { } string path = this.plugin.Config.SoundPath ?? ""; - if (ImGui.InputText("Path to WAV file", ref path, 1_000)) { + if (ImGui.InputText("Path to audio file", ref path, 1_000)) { path = path.Trim(); this.plugin.Config.SoundPath = path.Length == 0 ? null : path; this.plugin.Config.Save(); @@ -186,6 +187,41 @@ namespace PeepingTom { ImGui.Text("Leave this blank to use a built-in sound."); + float volume = this.plugin.Config.SoundVolume * 100f; + if (ImGui.DragFloat("Volume of sound", ref volume, .1f, 0f, 100f, "%.1f%%")) { + this.plugin.Config.SoundVolume = Math.Max(0f, Math.Min(1f, volume / 100f)); + this.plugin.Config.Save(); + } + + int soundDevice = this.plugin.Config.SoundDevice; + string name; + if (soundDevice == -1) { + name = "Default"; + } else if (soundDevice > -1 && soundDevice < WaveOut.DeviceCount) { + var caps = WaveOut.GetCapabilities(soundDevice); + name = caps.ProductName; + } else { + name = "Invalid device"; + } + if (ImGui.BeginCombo("Output device", name)) { + if (ImGui.Selectable("Default")) { + this.plugin.Config.SoundDevice = -1; + this.plugin.Config.Save(); + } + + ImGui.Separator(); + + for (int deviceNum = -1; deviceNum < WaveOut.DeviceCount; deviceNum++) { + var caps = WaveOut.GetCapabilities(deviceNum); + if (ImGui.Selectable(caps.ProductName)) { + this.plugin.Config.SoundDevice = deviceNum; + this.plugin.Config.Save(); + } + } + + ImGui.EndCombo(); + } + float soundCooldown = this.plugin.Config.SoundCooldown; if (ImGui.DragFloat("Cooldown for sound (seconds)", ref soundCooldown, .01f, 0f, 30f)) { soundCooldown = Math.Max(0f, soundCooldown); @@ -357,7 +393,7 @@ namespace PeepingTom { } actors = dict; } - + ImGuiWindowFlags flags = ImGuiWindowFlags.None; if (!this.plugin.Config.AllowMovement) { flags |= ImGuiWindowFlags.NoMove; diff --git a/Peeping Tom/TargetWatcher.cs b/Peeping Tom/TargetWatcher.cs index 1c1da49..995b998 100644 --- a/Peeping Tom/TargetWatcher.cs +++ b/Peeping Tom/TargetWatcher.cs @@ -4,6 +4,7 @@ using Dalamud.Game.Chat.SeStringHandling.Payloads; using Dalamud.Game.ClientState.Actors.Types; using Dalamud.Game.Internal; using Dalamud.Plugin; +using NAudio.Wave; using System; using System.Collections.Generic; using System.Diagnostics; @@ -12,6 +13,7 @@ using System.Linq; using System.Media; using System.Runtime.InteropServices; using System.Threading; +using System.Threading.Tasks; namespace PeepingTom { class TargetWatcher : IDisposable { @@ -188,28 +190,45 @@ namespace PeepingTom { } private void PlaySound() { - SoundPlayer player; - if (this.plugin.Config.SoundPath == null) { - player = new SoundPlayer(Properties.Resources.Target); - } else { - player = new SoundPlayer(this.plugin.Config.SoundPath); + int soundDevice = this.plugin.Config.SoundDevice; + if (soundDevice < -1 || soundDevice > WaveOut.DeviceCount) { + soundDevice = -1; } - using (player) { + + new Thread(new ThreadStart(() => { + WaveStream reader; try { - player.Play(); - } catch (FileNotFoundException e) { - this.SendError($"Could not play sound: {e.Message}"); - } catch (InvalidOperationException e) { - this.SendError($"Could not play sound: {e.Message}"); + if (this.plugin.Config.SoundPath == null) { + reader = new WaveFileReader(Properties.Resources.Target); + } else { + reader = new AudioFileReader(this.plugin.Config.SoundPath); + } +#pragma warning disable CA1031 // Do not catch general exception types + } catch (Exception e) { +#pragma warning restore CA1031 // Do not catch general exception types + this.SendError($"Could not play sound file: {e.Message}"); + return; } - } + + using (reader) { + using (var output = new WaveOutEvent() { DeviceNumber = soundDevice }) { + output.Init(reader); + output.Volume = this.plugin.Config.SoundVolume; + output.Play(); + + while (output.PlaybackState == PlaybackState.Playing) { + Thread.Sleep(500); + } + } + } + })).Start(); } private void SendError(string message) { - Payload[] payloads = { new TextPayload($"[Who's Looking] {message}") }; + Payload[] payloads = { new TextPayload($"[{this.plugin.Name}] {message}") }; this.plugin.Interface.Framework.Gui.Chat.PrintChat(new XivChatEntry { MessageBytes = new SeString(payloads).Encode(), - Type = XivChatType.ErrorMessage + Type = XivChatType.ErrorMessage, }); } diff --git a/Peeping Tom/packages.config b/Peeping Tom/packages.config index b8ca95a..12034ff 100644 --- a/Peeping Tom/packages.config +++ b/Peeping Tom/packages.config @@ -5,4 +5,5 @@ + \ No newline at end of file