Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of AudioOutput v1.0.1
BepInEx/plugins/AudioOutput.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("AudioOutput")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("\r\n Change audio output devices live in-game.\r\n ")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("AudioOutput")] [assembly: AssemblyTitle("AudioOutput")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MoreAudioSettings { [BepInPlugin("cryingrgb.AudioOutput", "Audio Output", "1.0.1")] public class Plugin : BaseUnityPlugin { public static ConfigEntry<string> OutputDeviceConfig; private static readonly Dictionary<string, string> DeviceMap = new Dictionary<string, string>(); private string currentDevice = string.Empty; private const string DefaultDevice = "Default System Device"; private bool audioCmdletsInstalled; private void Awake() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown audioCmdletsInstalled = IsAudioDeviceCmdletsInstalled(); if (!audioCmdletsInstalled) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Audio switching will be disabled."); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Scanning Windows playback devices..."); List<string> windowsPlaybackDevices = GetWindowsPlaybackDevices(); windowsPlaybackDevices.Insert(0, "Default System Device"); DeviceMap["Default System Device"] = "__DEFAULT__"; if (windowsPlaybackDevices.Count == 1) { windowsPlaybackDevices.Add("No Devices Found"); } string text = windowsPlaybackDevices[0]; OutputDeviceConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Audio", "Output Device", text, new ConfigDescription(audioCmdletsInstalled ? "Select the audio output device." : "AudioDeviceCmdlets missing. Run: Install-Module AudioDeviceCmdlets -Scope CurrentUser", (AcceptableValueBase)(object)new AcceptableValueList<string>(windowsPlaybackDevices.ToArray()), Array.Empty<object>())); currentDevice = OutputDeviceConfig.Value; OutputDeviceConfig.SettingChanged += delegate { if (!audioCmdletsInstalled) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Cannot switch audio device: AudioDeviceCmdlets is not installed."); } else { ApplyDeviceRouting(OutputDeviceConfig.Value); } }; ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded with {windowsPlaybackDevices.Count - 1} playback devices."); } private void ApplyDeviceRouting(string friendlyName) { if (currentDevice == friendlyName) { return; } currentDevice = friendlyName; if (friendlyName == "Default System Device") { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Using Windows default audio device."); return; } if (!DeviceMap.TryGetValue(friendlyName, out string value)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Invalid device: " + friendlyName)); return; } try { string text = "Import-Module AudioDeviceCmdlets; Set-AudioDevice -ID '" + value + "'"; using Process process = new Process(); process.StartInfo.FileName = "powershell.exe"; process.StartInfo.Arguments = "-NoProfile -ExecutionPolicy Bypass -Command \"" + text + "\""; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.Start(); process.StandardOutput.ReadToEnd(); string text2 = process.StandardError.ReadToEnd(); process.WaitForExit(); if (process.ExitCode == 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Switched audio device to: " + friendlyName)); } else { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed switching to '" + friendlyName + "'\n" + text2)); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Device switch failed:\n{arg}"); } } private List<string> GetWindowsPlaybackDevices() { List<string> list = new List<string>(); DeviceMap.Clear(); try { using Process process = new Process(); process.StartInfo.FileName = "powershell.exe"; process.StartInfo.Arguments = "-NoProfile -ExecutionPolicy Bypass -Command \"Get-AudioDevice -List | Where-Object {$_.Type -eq 'Playback'} | Select-Object Name,ID\""; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.Start(); string text = process.StandardOutput.ReadToEnd(); string text2 = process.StandardError.ReadToEnd(); process.WaitForExit(); if (!string.IsNullOrWhiteSpace(text2)) { ((BaseUnityPlugin)this).Logger.LogError((object)("PowerShell Error:\n" + text2)); return list; } string[] array = text.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text3 = array[i].Trim(); if (text3.StartsWith("Name") || text3.StartsWith("---")) { continue; } int num = text3.IndexOf("{0.0.0."); if (num >= 0) { string text4 = text3.Substring(0, num).Trim(); string value = text3.Substring(num).Trim(); if (!string.IsNullOrWhiteSpace(text4) && !string.IsNullOrWhiteSpace(value) && !DeviceMap.ContainsKey(text4)) { DeviceMap[text4] = value; list.Add(text4); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Detected device: " + text4)); } } } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to enumerate devices:\n{arg}"); } return list; } private bool IsAudioDeviceCmdletsInstalled() { try { using Process process = Process.Start(new ProcessStartInfo { FileName = "powershell.exe", Arguments = "-NoProfile -ExecutionPolicy Bypass -Command \"Get-Module -ListAvailable AudioDeviceCmdlets\"", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }); string value = process.StandardOutput.ReadToEnd(); process.StandardError.ReadToEnd(); process.WaitForExit(); if (string.IsNullOrWhiteSpace(value)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"AudioDeviceCmdlets is NOT installed!"); ((BaseUnityPlugin)this).Logger.LogWarning((object)"Audio Output requires AudioDeviceCmdlets to switch devices."); ((BaseUnityPlugin)this).Logger.LogWarning((object)"Run this command in PowerShell:"); ((BaseUnityPlugin)this).Logger.LogWarning((object)"Install-Module AudioDeviceCmdlets -Scope CurrentUser"); return false; } ((BaseUnityPlugin)this).Logger.LogInfo((object)"AudioDeviceCmdlets detected."); return true; } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to check AudioDeviceCmdlets: {arg}"); return false; } } } }