Decompiled source of REPOSoundBoard v0.2.0

REPOSoundBoard.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using NAudio.Wave;
using Newtonsoft.Json;
using Photon.Pun;
using Photon.Voice.Unity;
using REPOSoundBoard.Config;
using REPOSoundBoard.Core;
using REPOSoundBoard.Core.Exceptions;
using REPOSoundBoard.Core.Hotkeys;
using REPOSoundBoard.Core.Media;
using REPOSoundBoard.Core.Media.Converter;
using REPOSoundBoard.Patches;
using REPOSoundBoard.UI;
using REPOSoundBoard.UI.Components;
using REPOSoundBoard.UI.Utils;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("REPOSoundBoard")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ddae80319bf38fc5190635a3e7c05f831b16ba45")]
[assembly: AssemblyProduct("REPOSoundBoard")]
[assembly: AssemblyTitle("REPOSoundBoard")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace REPOSoundBoard
{
	[BepInPlugin("com.moli.repo-soundboard", "REPOSoundBoard", "0.2.0")]
	public class REPOSoundBoard : BaseUnityPlugin
	{
		public const string GUID = "com.moli.repo-soundboard";

		public const string NAME = "REPOSoundBoard";

		public const string VERSION = "0.2.0";

		private static readonly Harmony _harmony = new Harmony("com.moli.repo-soundboard");

		public static ManualLogSource Logger;

		public HotkeyManager HotkeyManager;

		public SoundBoard SoundBoard;

		public SoundBoardUI UI;

		public static REPOSoundBoard Instance { get; private set; }

		public AppConfig Config { get; private set; }

		private void Awake()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				Instance = this;
				Logger = ((BaseUnityPlugin)this).Logger;
				Config = AppConfig.LoadConfig();
				GameObject val = new GameObject("REPOSoundBoardMod");
				((Object)val).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)val);
				HotkeyManager = val.AddComponent<HotkeyManager>();
				SoundBoard = val.AddComponent<SoundBoard>();
				SoundBoard.LoadConfig(Config.SoundBoard);
				UI = val.AddComponent<SoundBoardUI>();
				Config.UiHotkey.OnPressed(delegate
				{
					UI.Visible = !UI.Visible;
				});
				HotkeyManager.RegisterHotkey(Config.UiHotkey);
				_harmony.PatchAll(typeof(ChatManagerPatch));
				_harmony.PatchAll(typeof(PlayerVoiceChatPatch));
				_harmony.PatchAll(typeof(MenuCursorPatch));
			}
		}

		public void SaveConfig()
		{
			SoundBoardConfig soundBoardConfig = new SoundBoardConfig();
			soundBoardConfig.Enabled = SoundBoard.Instance.Enabled;
			soundBoardConfig.StopHotkey = SoundBoard.Instance.StopHotkey;
			foreach (SoundButton soundButton in SoundBoard.Instance.SoundButtons)
			{
				soundBoardConfig.SoundButtons.Add(soundButton.CreateConfig());
			}
			Config.SoundBoard = soundBoardConfig;
			Config.SaveToFile();
		}
	}
}
namespace REPOSoundBoard.UI
{
	public class SoundBoardUI : MonoBehaviour
	{
		public static SoundBoardUI Instance;

		private bool _isVisible;

		private const float DefaultWindowGap = 20f;

		private IMGUIWindow _generalSettingsWindow;

		private GeneralSettingsUI _generalSettingsUI;

		private const float GeneralSettingsWindowWidth = 340f;

		private const float GeneralSettingsWindowHeight = 60f;

		private IMGUIWindow _soundButtonsWindow;

		private SoundButtonsUI _soundButtonsUI;

		private const float SoundButtonsWindowWidth = 600f;

		private const float SoundButtonsWindowHeight = 650f;

		public bool Visible
		{
			get
			{
				return _isVisible;
			}
			set
			{
				_isVisible = value;
				if (_isVisible)
				{
					UnlockCursor();
				}
				else
				{
					LockCursor();
				}
			}
		}

		public void Start()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			float num = 960f;
			float num2 = Mathf.Max(60f, 650f);
			_generalSettingsUI = new GeneralSettingsUI();
			_generalSettingsWindow = new IMGUIWindow("General Settings", new Rect(((float)Screen.width - num) / 2f, ((float)Screen.height - num2) / 2f, 340f, 60f), delegate
			{
				_generalSettingsUI.Draw();
			});
			_soundButtonsUI = new SoundButtonsUI();
			_soundButtonsWindow = new IMGUIWindow("Sound Buttons", new Rect(((float)Screen.width - num) / 2f + 340f + 20f, ((float)Screen.height - num2) / 2f, 600f, 650f), delegate
			{
				_soundButtonsUI.Draw();
			});
		}

		private void Update()
		{
			if (Visible)
			{
				InputManager.instance.DisableAiming();
				InputManager.instance.DisableMovement();
			}
		}

		private void OnGUI()
		{
			if (_isVisible)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
				_generalSettingsWindow.Draw();
				_soundButtonsWindow.Draw();
			}
		}

		private void UnlockCursor()
		{
			MenuCursorPatch.HideInGameCursor = true;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		private void LockCursor()
		{
			MenuCursorPatch.HideInGameCursor = false;
			Cursor.lockState = (CursorLockMode)1;
			Cursor.visible = false;
		}

		private void OnDestroy()
		{
			REPOSoundBoard.Instance.SaveConfig();
		}
	}
}
namespace REPOSoundBoard.UI.Utils
{
	public static class HotkeySelectorUtils
	{
		private static readonly List<KeyCode> _disallowedKeys;

		public static List<KeyCode> PossibleKeys { get; }

		static HotkeySelectorUtils()
		{
			_disallowedKeys = new List<KeyCode>
			{
				(KeyCode)323,
				(KeyCode)324,
				(KeyCode)311,
				(KeyCode)312,
				(KeyCode)310,
				(KeyCode)309
			};
			PossibleKeys = UnityInput.Current.SupportedKeyCodes.Where((KeyCode code) => !_disallowedKeys.Contains(code)).ToList();
		}

		public static List<KeyCode> GetPressedKeys()
		{
			return ((IEnumerable<KeyCode>)PossibleKeys).Where((Func<KeyCode, bool>)Input.GetKey).ToList();
		}
	}
	public class IMGUITabs
	{
		private string[] tabs;

		private int selectedTab;

		private Action<int>[] tabContents;

		private GUIStyle tabStyle;

		private GUIStyle activeTabStyle;

		public int SelectedTab => selectedTab;

		public IMGUITabs(string[] tabs, Action<int>[] tabContents)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			this.tabs = tabs;
			this.tabContents = tabContents;
			tabStyle = new GUIStyle(GUI.skin.button);
			activeTabStyle = new GUIStyle(GUI.skin.button);
			activeTabStyle.normal.background = activeTabStyle.active.background;
		}

		public void SetStyles(GUIStyle tabStyle, GUIStyle activeTabStyle)
		{
			this.tabStyle = tabStyle;
			this.activeTabStyle = activeTabStyle;
		}

		public void Draw()
		{
			IMGUIUtils.HorizontalGroup(delegate
			{
				for (int i = 0; i < tabs.Length; i++)
				{
					bool flag = i == selectedTab;
					if (GUILayout.Button(tabs[i], flag ? activeTabStyle : tabStyle, Array.Empty<GUILayoutOption>()))
					{
						selectedTab = i;
					}
				}
			});
			IMGUIUtils.BoxGroup(delegate
			{
				if (selectedTab >= 0 && selectedTab < tabContents.Length)
				{
					tabContents[selectedTab]?.Invoke(selectedTab);
				}
			});
		}
	}
	public class IMGUIUtils
	{
		public static readonly GUIStyle DisabledTextStyle;

		public static readonly GUIStyle HeadingStyle;

		static IMGUIUtils()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			DisabledTextStyle = GUI.skin.label;
			DisabledTextStyle.normal.textColor = new Color(120f, 120f, 120f);
			HeadingStyle = new GUIStyle(GUI.skin.label);
			HeadingStyle.normal.textColor = Color.white;
			HeadingStyle.fontSize = 15;
		}

		public static void HorizontalGroup(Action guiAction)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			guiAction?.Invoke();
			GUILayout.EndHorizontal();
		}

		public static void VerticalGroup(Action guiAction)
		{
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			guiAction?.Invoke();
			GUILayout.EndVertical();
		}

		public static Vector2 ScrollGroup(Vector2 scrollPosition, Action guiAction, GUIStyle style = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Vector2 result = GUILayout.BeginScrollView(scrollPosition, style ?? GUI.skin.scrollView);
			guiAction?.Invoke();
			GUILayout.EndScrollView();
			return result;
		}

		public static void BoxGroup(Action guiAction, GUIStyle style = null)
		{
			GUILayout.BeginVertical(style ?? GUI.skin.box, Array.Empty<GUILayoutOption>());
			guiAction?.Invoke();
			GUILayout.EndVertical();
		}

		public static void AreaGroup(Rect rect, Action guiAction)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginArea(rect);
			guiAction?.Invoke();
			GUILayout.EndArea();
		}

		public static void WithColor(Color color, Action guiAction)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Color color2 = GUI.color;
			GUI.color = color;
			guiAction?.Invoke();
			GUI.color = color2;
		}

		public static void WithContentColor(Color color, Action guiAction)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Color contentColor = GUI.contentColor;
			GUI.contentColor = color;
			guiAction?.Invoke();
			GUI.contentColor = contentColor;
		}

		public static void WithBackgroundColor(Color color, Action guiAction)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Color backgroundColor = GUI.backgroundColor;
			GUI.backgroundColor = color;
			guiAction?.Invoke();
			GUI.backgroundColor = backgroundColor;
		}

		public static void WithEnabled(bool enabled, Action guiAction)
		{
			bool enabled2 = GUI.enabled;
			GUI.enabled = enabled;
			guiAction?.Invoke();
			GUI.enabled = enabled2;
		}

		public static float LabeledSlider(string label, float value, float leftValue, float rightValue)
		{
			HorizontalGroup(delegate
			{
				GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.ExpandWidth(false),
					GUILayout.Height(20f)
				});
				value = GUILayout.HorizontalSlider(value, leftValue, rightValue, Array.Empty<GUILayoutOption>());
				GUILayout.Label(value.ToString("F2"), (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(50f),
					GUILayout.Height(20f)
				});
			});
			return value;
		}

		public static string LabeledTextField(string label, string text)
		{
			HorizontalGroup(delegate
			{
				GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				text = GUILayout.TextField(text, Array.Empty<GUILayoutOption>());
			});
			return text;
		}

		public static bool LabeledToggle(string label, bool value)
		{
			HorizontalGroup(delegate
			{
				GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				value = GUILayout.Toggle(value, "", Array.Empty<GUILayoutOption>());
			});
			return value;
		}

		public static bool LabeledHotkeyInput(string label, Hotkey hotkey, bool selecting)
		{
			HorizontalGroup(delegate
			{
				GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				if (!selecting)
				{
					if (hotkey.Keys.Count == 0)
					{
						GUILayout.Label("No hotkey selected", DisabledTextStyle, Array.Empty<GUILayoutOption>());
					}
					else
					{
						GUILayout.Label(string.Join(" + ", hotkey.Keys), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
					}
					if (GUILayout.Button("Change", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
					{
						selecting = true;
						GUIUtility.keyboardControl = 0;
					}
				}
				else
				{
					if (HotkeySelectorUtils.GetPressedKeys().Count == 0)
					{
						GUILayout.Label("Start pressing keys...", DisabledTextStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
					}
					else
					{
						GUILayout.Label(string.Join(" + ", HotkeySelectorUtils.GetPressedKeys()), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
						if (GUILayout.Button("Apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
						{
							hotkey.Keys = HotkeySelectorUtils.GetPressedKeys();
							selecting = false;
						}
					}
					if (GUILayout.Button("Reset", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
					{
						selecting = false;
					}
				}
			});
			return selecting;
		}

		public static string LabeledPathInput(string label, string originalPath, string inputPath, ref bool changing, Action<string> pathChanged)
		{
			bool localChanging = changing;
			HorizontalGroup(delegate
			{
				GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				if (!localChanging)
				{
					GUILayout.Label(originalPath, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
					if (GUILayout.Button("Change", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
					{
						localChanging = true;
					}
				}
				else
				{
					inputPath = GUILayout.TextField(inputPath.Replace("\"", ""), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
					if (GUILayout.Button("Apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
					{
						pathChanged?.Invoke(inputPath);
						localChanging = false;
					}
					if (GUILayout.Button("Reset", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
					{
						inputPath = originalPath;
						localChanging = false;
					}
				}
			});
			changing = localChanging;
			return inputPath;
		}

		public static bool ConfirmButton(string buttonText, string confirmationText, ref bool confirmationShown)
		{
			bool result = false;
			bool localConfirmationShown = confirmationShown;
			if (!localConfirmationShown)
			{
				if (GUILayout.Button(buttonText, Array.Empty<GUILayoutOption>()))
				{
					localConfirmationShown = true;
				}
			}
			else
			{
				HorizontalGroup(delegate
				{
					GUILayout.Label(confirmationText, Array.Empty<GUILayoutOption>());
					if (GUILayout.Button("Yes", Array.Empty<GUILayoutOption>()))
					{
						result = true;
						localConfirmationShown = false;
					}
					if (GUILayout.Button("No", Array.Empty<GUILayoutOption>()))
					{
						localConfirmationShown = false;
					}
				});
			}
			confirmationShown = localConfirmationShown;
			return result;
		}
	}
	public class IMGUIWindow
	{
		private Rect _windowRect;

		private string _title;

		private Action<int> _drawContent;

		private bool _isDraggable = true;

		private int _id;

		private static int _nextId;

		public Rect WindowRect => _windowRect;

		public IMGUIWindow(string title, Rect initialRect, Action<int> drawContent)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			_title = title;
			_windowRect = initialRect;
			_drawContent = drawContent;
			_id = _nextId++;
		}

		public void SetDraggable(bool isDraggable)
		{
			_isDraggable = isDraggable;
		}

		public void Draw()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (_isDraggable)
			{
				_windowRect = GUILayout.Window(_id, _windowRect, new WindowFunction(WindowFunction), _title, Array.Empty<GUILayoutOption>());
				return;
			}
			IMGUIUtils.AreaGroup(_windowRect, delegate
			{
				GUILayout.Label(_title, GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				_drawContent?.Invoke(_id);
			});
		}

		private void WindowFunction(int windowId)
		{
			_drawContent?.Invoke(windowId);
			if (_isDraggable)
			{
				GUI.DragWindow();
			}
		}
	}
}
namespace REPOSoundBoard.UI.Components
{
	public class GeneralSettingsUI
	{
		private bool _selectionStopHotkey;

		public void Draw()
		{
			SoundBoard.Instance.Enabled = IMGUIUtils.LabeledToggle("Global enabled:", SoundBoard.Instance.Enabled);
			_selectionStopHotkey = IMGUIUtils.LabeledHotkeyInput("Stop hotkey:", SoundBoard.Instance.StopHotkey, _selectionStopHotkey);
			IMGUIUtils.HorizontalGroup(delegate
			{
				if (GUILayout.Button("Save changes", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
				{
					REPOSoundBoard.Instance.SaveConfig();
				}
				if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }))
				{
					SoundBoardUI.Instance.Visible = false;
				}
			});
		}
	}
	public class SoundButtonsUI
	{
		private string _search = string.Empty;

		private Vector2 _scrollPosition = Vector2.zero;

		private List<SoundButtonUI> _soundButtonUis;

		private SoundButtonUI _buttonToDelete;

		public SoundButtonsUI()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			_soundButtonUis = SoundBoard.Instance.SoundButtons.Select(delegate(SoundButton button)
			{
				SoundButtonUI soundButtonUI = new SoundButtonUI(button);
				soundButtonUI.OnDeleteClicked += HandleDeleteButtonPress;
				return soundButtonUI;
			}).ToList();
		}

		private void HandleDeleteButtonPress(SoundButtonUI buttonUI)
		{
			_buttonToDelete = buttonUI;
		}

		private void HandleCurrentDeletion()
		{
			if (_buttonToDelete != null)
			{
				_soundButtonUis.Remove(_buttonToDelete);
				SoundBoard.Instance.RemoveSoundButton(_buttonToDelete.SoundButton);
			}
		}

		public void Draw()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			HandleCurrentDeletion();
			_search = IMGUIUtils.LabeledTextField("Search:", _search).ToLower();
			_scrollPosition = IMGUIUtils.ScrollGroup(_scrollPosition, delegate
			{
				foreach (SoundButtonUI item in _soundButtonUis.Where((SoundButtonUI buttonUI) => buttonUI.SoundButton.Name.ToLower().Contains(_search)))
				{
					item.Draw();
				}
			});
			if (GUILayout.Button("Add new sound button", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
			{
				SoundButton soundButton = new SoundButton();
				SoundButtonUI soundButtonUI = new SoundButtonUI(soundButton, editing: true);
				soundButtonUI.OnDeleteClicked += HandleDeleteButtonPress;
				SoundBoard.Instance.AddSoundButton(soundButton);
				_soundButtonUis.Insert(0, soundButtonUI);
			}
		}
	}
	public class SoundButtonUI
	{
		private static GUIStyle _pathStyle;

		private static GUIStyle _disabledButtonLabelStyle;

		private bool _isEditing;

		private bool _isEditingHotkey;

		private bool _changingPath;

		private string _pathInput;

		private static GUIStyle PathStyle
		{
			get
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				if (_pathStyle == null)
				{
					_pathStyle = new GUIStyle(GUI.skin.label);
					_pathStyle.normal.textColor = new Color(0.6f, 0.6f, 0.6f);
					_pathStyle.fontStyle = (FontStyle)2;
					_pathStyle.fontSize = 12;
				}
				return _pathStyle;
			}
		}

		private static GUIStyle DisabledButtonLabelStyle
		{
			get
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				if (_disabledButtonLabelStyle == null)
				{
					_disabledButtonLabelStyle = new GUIStyle(GUI.skin.label);
					_disabledButtonLabelStyle.normal.textColor = new Color(0.6f, 0.6f, 0.6f);
				}
				return _disabledButtonLabelStyle;
			}
		}

		public SoundButton SoundButton { get; }

		[CanBeNull]
		public event Action<SoundButtonUI> OnDeleteClicked;

		public SoundButtonUI(SoundButton soundButton, bool editing = false)
		{
			SoundButton = soundButton;
			_isEditing = editing;
			_pathInput = SoundButton.Clip?.OriginalPath ?? string.Empty;
		}

		public void Draw()
		{
			IMGUIUtils.BoxGroup(delegate
			{
				DrawState();
				if (!_isEditing)
				{
					DrawDetailUI();
				}
				else
				{
					DrawEditUI();
				}
			});
		}

		private static Color GetStateColor(MediaClip.MediaClipState state)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(state switch
			{
				MediaClip.MediaClipState.Idle => Color.white, 
				MediaClip.MediaClipState.Converting => Color.yellow, 
				MediaClip.MediaClipState.Converted => Color.white, 
				MediaClip.MediaClipState.FailedToConvert => Color.red, 
				MediaClip.MediaClipState.Loading => Color.cyan, 
				MediaClip.MediaClipState.Loaded => Color.green, 
				MediaClip.MediaClipState.FailedToLoad => Color.red, 
				_ => Color.white, 
			});
		}

		private void DrawState()
		{
			if (SoundButton.Clip != null && SoundButton.Clip.State != MediaClip.MediaClipState.Loaded)
			{
				IMGUIUtils.HorizontalGroup(delegate
				{
					//IL_0023: Unknown result type (might be due to invalid IL or missing references)
					//IL_0029: Expected O, but got Unknown
					//IL_003f: Unknown result type (might be due to invalid IL or missing references)
					GUILayout.Label("State:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
					GUIStyle val = new GUIStyle(GUI.skin.label);
					val.normal.textColor = GetStateColor(SoundButton.Clip.State);
					GUILayout.Label(SoundButton.Clip.StateMessage, val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				});
			}
		}

		private void DrawDetailUI()
		{
			IMGUIUtils.HorizontalGroup(delegate
			{
				if (SoundButton.Enabled)
				{
					GUILayout.Label(SoundButton.Name, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				}
				else
				{
					GUILayout.Label(SoundButton.Name + " [disabled]", DisabledButtonLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				}
				if (GUILayout.Button((SoundButton.Hotkey.Keys.Count == 0) ? "[no hotkey]" : string.Join(" + ", SoundButton.Hotkey.Keys), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }))
				{
					SoundBoard.Instance.Play(SoundButton, ignoreEnabledChecks: true);
				}
				if (GUILayout.Button("Edit", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
				{
					_isEditing = true;
				}
				if (GUILayout.Button("Delete", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					this.OnDeleteClicked?.Invoke(this);
				}
			});
			if (SoundButton.Clip == null)
			{
				GUILayout.Label("No file selected...", PathStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			}
			else
			{
				GUILayout.Label(SoundButton.Clip.OriginalPath, PathStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			}
		}

		private void DrawEditUI()
		{
			IMGUIUtils.VerticalGroup(delegate
			{
				SoundButton.Name = IMGUIUtils.LabeledTextField("Name:", SoundButton.Name);
				_isEditingHotkey = IMGUIUtils.LabeledHotkeyInput("Hotkey:", SoundButton.Hotkey, _isEditingHotkey);
				SoundButton.Enabled = IMGUIUtils.LabeledToggle("Enabled:", SoundButton.Enabled);
				SoundButton.Volume = IMGUIUtils.LabeledSlider("Volume:", SoundButton.Volume, 0f, 1f);
				_pathInput = IMGUIUtils.LabeledPathInput("Path:", SoundButton.Clip?.OriginalPath ?? string.Empty, _pathInput, ref _changingPath, OnPathChanged);
				if (GUILayout.Button("Done", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
				{
					_isEditing = false;
				}
			});
		}

		private void OnPathChanged(string path)
		{
			if (SoundButton.Clip != null)
			{
				SoundButton.Clip.DeleteCacheFile();
			}
			SoundButton.Clip = new MediaClip(path);
			((MonoBehaviour)SoundBoard.Instance).StartCoroutine(SoundButton.LoadClip());
		}
	}
}
namespace REPOSoundBoard.Patches
{
	public static class ChatManagerPatch
	{
		[HarmonyPatch(typeof(ChatManager), "StateInactive")]
		[HarmonyPrefix]
		public static bool BeforeStateInactive(ref string ___chatMessage, ref bool ___chatActive)
		{
			if (SoundBoardUI.Instance.Visible)
			{
				((SemiUI)ChatUI.instance).Hide();
				___chatMessage = "";
				___chatActive = false;
				return false;
			}
			return true;
		}
	}
	public class MenuCursorPatch
	{
		public static bool HideInGameCursor;

		[HarmonyPatch(typeof(CursorManager), "Update")]
		[HarmonyPrefix]
		public static bool BeforeCursorManagerUpdate()
		{
			return !HideInGameCursor;
		}

		[HarmonyPatch(typeof(CursorManager), "Unlock")]
		[HarmonyPrefix]
		public static bool BeforeCursorManagerUnlock()
		{
			return !HideInGameCursor;
		}
	}
	public class PlayerVoiceChatPatch
	{
		[HarmonyPatch(typeof(PlayerVoiceChat), "Start")]
		[HarmonyPostfix]
		public static void PostStart(PlayerVoiceChat __instance, ref Recorder ___recorder, ref PhotonView ___photonView)
		{
			if (___photonView.IsMine)
			{
				REPOSoundBoard.Instance.SoundBoard.ChangeRecorder(___recorder);
			}
		}
	}
}
namespace REPOSoundBoard.Core
{
	public class SoundBoard : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <StopAfterEnd>d__20 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public SoundButton soundButton;

			public SoundBoard <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <StopAfterEnd>d__20(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Expected O, but got Unknown
				int num = <>1__state;
				SoundBoard soundBoard = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (soundButton.Clip == null)
					{
						return false;
					}
					<>2__current = (object)new WaitForSeconds(soundButton.Clip.AudioClip.length);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					soundBoard.StopCurrent();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static SoundBoard Instance;

		public Hotkey StopHotkey;

		private Recorder _recorder;

		private AudioSource _audioSource;

		private bool _isPlaying;

		private bool _enabled;

		private SoundButton _currentSoundButton;

		private Coroutine _stopAfterEndCoroutine;

		public List<SoundButton> SoundButtons { get; } = new List<SoundButton>();


		public bool Enabled
		{
			get
			{
				return _enabled;
			}
			set
			{
				_enabled = value;
			}
		}

		private void Start()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			_audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		}

		public void LoadConfig(SoundBoardConfig config)
		{
			_enabled = config.Enabled;
			StopHotkey = config.StopHotkey;
			StopHotkey.OnPressed(StopCurrent);
			REPOSoundBoard.Instance.HotkeyManager.RegisterHotkey(config.StopHotkey);
			foreach (SoundButtonConfig soundButton2 in config.SoundButtons)
			{
				if (soundButton2.Hotkey != null && soundButton2.Path != null)
				{
					SoundButton soundButton = SoundButton.FromConfig(soundButton2);
					((MonoBehaviour)this).StartCoroutine(soundButton.LoadClip());
					AddSoundButton(soundButton);
				}
			}
		}

		public void AddSoundButton(SoundButton soundButton)
		{
			soundButton.Hotkey.OnPressed(delegate
			{
				Play(soundButton);
			});
			REPOSoundBoard.Instance.HotkeyManager.RegisterHotkey(soundButton.Hotkey);
			SoundButtons.Add(soundButton);
			string text = ((soundButton.Hotkey != null) ? string.Join(" + ", soundButton.Hotkey.Keys) : "none");
			REPOSoundBoard.Logger.LogInfo((object)("Sound Button registered: " + soundButton.Name + ", with hotkey: " + text + " and path: " + soundButton.Clip?.OriginalPath));
		}

		public void RemoveSoundButton(SoundButton soundButton)
		{
			SoundButtons.Remove(soundButton);
			REPOSoundBoard.Instance.HotkeyManager.UnregisterHotkey(soundButton.Hotkey);
		}

		public void ChangeRecorder(Recorder recorder)
		{
			StopCurrent();
			_recorder = recorder;
		}

		public void Play(SoundButton soundButton, bool ignoreEnabledChecks = false)
		{
			StopCurrent();
			if ((ignoreEnabledChecks || (((Behaviour)this).enabled && soundButton.Enabled)) && soundButton.Clip != null && soundButton.Clip.IsReady)
			{
				_isPlaying = true;
				_currentSoundButton = soundButton;
				_audioSource.clip = soundButton.Clip.AudioClip;
				_audioSource.volume = soundButton.Volume;
				_audioSource.Play();
				if ((Object)(object)_recorder != (Object)null)
				{
					_recorder.TransmitEnabled = false;
					_recorder.SourceType = (InputSourceType)1;
					_recorder.AudioClip = soundButton.Clip.AudioClip;
					_recorder.TransmitEnabled = true;
				}
				_stopAfterEndCoroutine = ((MonoBehaviour)this).StartCoroutine(StopAfterEnd(soundButton));
			}
		}

		[IteratorStateMachine(typeof(<StopAfterEnd>d__20))]
		private IEnumerator StopAfterEnd(SoundButton soundButton)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <StopAfterEnd>d__20(0)
			{
				<>4__this = this,
				soundButton = soundButton
			};
		}

		private void StopCurrent()
		{
			if (_isPlaying)
			{
				if (_stopAfterEndCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(_stopAfterEndCoroutine);
					_stopAfterEndCoroutine = null;
				}
				_audioSource.Stop();
				if ((Object)(object)_recorder != (Object)null)
				{
					_recorder.SourceType = (InputSourceType)0;
					_recorder.AudioClip = null;
					_recorder.TransmitEnabled = true;
				}
				_isPlaying = false;
				_currentSoundButton = null;
			}
		}
	}
	public class SoundButton
	{
		public string Name;

		public bool Enabled;

		public float Volume;

		public Hotkey Hotkey;

		[CanBeNull]
		public MediaClip Clip;

		public SoundButton()
		{
			Name = string.Empty;
			Enabled = true;
			Volume = 1f;
			Hotkey = new Hotkey();
		}

		public static SoundButton FromConfig(SoundButtonConfig config)
		{
			return new SoundButton
			{
				Name = config.Name,
				Enabled = config.Enabled,
				Volume = config.Volume,
				Hotkey = config.Hotkey,
				Clip = new MediaClip(config.Path)
			};
		}

		public SoundButtonConfig CreateConfig()
		{
			return new SoundButtonConfig
			{
				Name = Name,
				Volume = Volume,
				Hotkey = Hotkey,
				Path = Clip?.OriginalPath,
				Enabled = Enabled
			};
		}

		public IEnumerator LoadClip()
		{
			return Clip?.Load();
		}
	}
}
namespace REPOSoundBoard.Core.Media
{
	public static class CacheFileHelper
	{
		private static readonly string CacheDirectory = Path.Combine(Paths.PluginPath, "Moli-REPOSoundBoard-0.2.0/_cache");

		public static void DeleteFromCache(string fileName)
		{
			File.Delete(Path.Combine(CacheDirectory, fileName));
		}

		public static string GetFullCachePath(string cacheFileName)
		{
			return Path.Combine(CacheDirectory, cacheFileName);
		}

		public static bool ExistsInCache(string cacheFileName)
		{
			return File.Exists(GetFullCachePath(cacheFileName));
		}

		public static string GetCacheFilePath(string originalFilePath, string cacheExtension = ".cache")
		{
			return Path.Combine(CacheDirectory, GetCacheFileName(originalFilePath, cacheExtension));
		}

		public static void EnsureCacheDirectoryExists()
		{
			if (!Directory.Exists(CacheDirectory))
			{
				Directory.CreateDirectory(CacheDirectory);
			}
		}

		public static string GetCacheFileName(string originalFilePath, string cacheExtension = ".cache")
		{
			using SHA256 sHA = SHA256.Create();
			byte[] bytes = Encoding.UTF8.GetBytes(originalFilePath);
			return BitConverter.ToString(sHA.ComputeHash(bytes)).Replace("-", "").ToLowerInvariant() + cacheExtension;
		}
	}
	public class MediaClip
	{
		public enum MediaClipState
		{
			Idle,
			Converting,
			Converted,
			FailedToConvert,
			Loading,
			Loaded,
			FailedToLoad
		}

		[CompilerGenerated]
		private sealed class <Convert>d__30 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public MediaClip <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <Convert>d__30(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				MediaClip CS$<>8__locals0 = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					CS$<>8__locals0.SetState(MediaClipState.Converting, "Converting media file...");
					CS$<>8__locals0._conversionComplete = false;
					CS$<>8__locals0._conversionException = null;
					ThreadPool.QueueUserWorkItem(delegate
					{
						try
						{
							IMediaConverter converterForFile = MediaConverterFactory.GetConverterForFile(CS$<>8__locals0.OriginalPath);
							if (converterForFile != null)
							{
								CacheFileHelper.EnsureCacheDirectoryExists();
								converterForFile.Convert(CS$<>8__locals0.OriginalPath, CS$<>8__locals0._cachePath, ConversionOptions.Default);
								CS$<>8__locals0._isConverted = true;
							}
						}
						catch (Exception conversionException)
						{
							CS$<>8__locals0._conversionException = conversionException;
						}
						finally
						{
							CS$<>8__locals0._conversionComplete = true;
						}
					});
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!CS$<>8__locals0._conversionComplete)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				if (CS$<>8__locals0._conversionException != null)
				{
					string message = ((CS$<>8__locals0._conversionException is AudioConversionException) ? CS$<>8__locals0._conversionException.Message : "Failed to convert to .wav. Check logs for more information.");
					CS$<>8__locals0.SetState(MediaClipState.FailedToConvert, message);
					string text = "Failed to convert to .wav. Error " + CS$<>8__locals0._conversionException.Message + ". File: " + CS$<>8__locals0.OriginalPath;
					REPOSoundBoard.Logger.LogError((object)text);
					return false;
				}
				if (MediaConverterFactory.GetConverterForFile(CS$<>8__locals0.OriginalPath) == null)
				{
					CS$<>8__locals0.SetState(MediaClipState.FailedToConvert, "Failed to convert to .wav. Invalid file format.");
					REPOSoundBoard.Logger.LogWarning((object)("Unsupported file format: " + CS$<>8__locals0.OriginalPath));
					return false;
				}
				CS$<>8__locals0.SetState(MediaClipState.Converted, "Successfully converted to .wav. Waiting to load...");
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <Load>d__28 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public MediaClip <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <Load>d__28(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				MediaClip mediaClip = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (mediaClip.HasError || mediaClip.State == MediaClipState.Loaded)
					{
						return false;
					}
					if (!File.Exists(mediaClip.OriginalPath))
					{
						mediaClip.SetState(MediaClipState.FailedToLoad, "Failed to load. Could not find file.");
						return false;
					}
					if (!mediaClip._isConverted)
					{
						<>2__current = mediaClip.Convert();
						<>1__state = 1;
						return true;
					}
					goto IL_0085;
				case 1:
					<>1__state = -1;
					if (!mediaClip._isConverted)
					{
						return false;
					}
					goto IL_0085;
				case 2:
					{
						<>1__state = -1;
						return false;
					}
					IL_0085:
					<>2__current = mediaClip.LoadAudioClip();
					<>1__state = 2;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <LoadAudioClip>d__31 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public MediaClip <>4__this;

			private UnityWebRequest <www>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadAudioClip>d__31(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<www>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Invalid comparison between Unknown and I4
				try
				{
					int num = <>1__state;
					MediaClip mediaClip = <>4__this;
					switch (num)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						mediaClip.SetState(MediaClipState.Loading, "Loading clip...");
						<www>5__2 = UnityWebRequestMultimedia.GetAudioClip(mediaClip._cachePath, (AudioType)20);
						<>1__state = -3;
						<>2__current = <www>5__2.SendWebRequest();
						<>1__state = 1;
						return true;
					case 1:
						<>1__state = -3;
						if ((int)<www>5__2.result == 1)
						{
							mediaClip.AudioClip = DownloadHandlerAudioClip.GetContent(<www>5__2);
							mediaClip.SetState(MediaClipState.Loaded, "Sound button loaded successfully.");
						}
						else
						{
							string text = "Failed to load media: " + <www>5__2.error + ". Path: " + mediaClip.OriginalPath + ". Cache Path: " + mediaClip._cachePath;
							REPOSoundBoard.Logger.LogError((object)text);
							mediaClip.SetState(MediaClipState.FailedToLoad, "Failed to load. Check logs for more information.");
						}
						<>m__Finally1();
						<www>5__2 = null;
						return false;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<www>5__2 != null)
				{
					((IDisposable)<www>5__2).Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private readonly string _cachePath;

		private readonly string _cacheFileName;

		private bool _isConverted;

		private bool _conversionComplete;

		private Exception _conversionException;

		public MediaClipState State { get; private set; }

		public string StateMessage { get; private set; }

		public string OriginalPath { get; private set; }

		public AudioClip AudioClip { get; private set; }

		public bool IsReady => State == MediaClipState.Loaded;

		public bool HasError
		{
			get
			{
				if (State != MediaClipState.FailedToConvert)
				{
					return State == MediaClipState.FailedToLoad;
				}
				return true;
			}
		}

		public MediaClip(string path)
		{
			OriginalPath = path;
			_cacheFileName = CacheFileHelper.GetCacheFileName(path, ".wav");
			_cachePath = CacheFileHelper.GetFullCachePath(_cacheFileName);
			_isConverted = CacheFileHelper.ExistsInCache(_cacheFileName);
			SetState(MediaClipState.Idle, "Waiting for instructions...");
		}

		public void DeleteCacheFile()
		{
			CacheFileHelper.DeleteFromCache(_cacheFileName);
			SetState(MediaClipState.Idle, "Cache file deleted. Waiting for conversion to start...");
		}

		[IteratorStateMachine(typeof(<Load>d__28))]
		public IEnumerator Load()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Load>d__28(0)
			{
				<>4__this = this
			};
		}

		private void SetState(MediaClipState state, string message)
		{
			State = state;
			StateMessage = message;
		}

		[IteratorStateMachine(typeof(<Convert>d__30))]
		private IEnumerator Convert()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Convert>d__30(0)
			{
				<>4__this = this
			};
		}

		[IteratorStateMachine(typeof(<LoadAudioClip>d__31))]
		private IEnumerator LoadAudioClip()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadAudioClip>d__31(0)
			{
				<>4__this = this
			};
		}
	}
}
namespace REPOSoundBoard.Core.Media.Converter
{
	public class AiffConverter : IMediaConverter
	{
		public static bool IsCompatible(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				return false;
			}
			string text = Path.GetExtension(path)?.ToLowerInvariant();
			if (!string.IsNullOrEmpty(text))
			{
				return text == ".aiff";
			}
			return false;
		}

		public void Convert(string sourcePath, string targetPath, ConversionOptions options)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if (!File.Exists(sourcePath))
			{
				throw new FileNotFoundException("Source file " + sourcePath + " not found");
			}
			AiffFileReader val = new AiffFileReader(sourcePath);
			try
			{
				MediaFoundationResampler val2 = new MediaFoundationResampler((IWaveProvider)(object)val, new WaveFormat(options.SampleRate, options.BitsPerSample, options.ChannelCount));
				val2.ResamplerQuality = 60;
				WaveFileWriter.CreateWaveFile(targetPath, (IWaveProvider)(object)val2);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
	}
	public struct ConversionOptions
	{
		public int SampleRate;

		public int ChannelCount;

		public int BitsPerSample;

		public string AudioCodec;

		public static ConversionOptions Default = new ConversionOptions
		{
			SampleRate = 48000,
			ChannelCount = 1,
			BitsPerSample = 16,
			AudioCodec = "pcm_s16le"
		};
	}
	public interface IMediaConverter
	{
		static bool IsCompatible(string path)
		{
			return false;
		}

		void Convert(string sourcePath, string targetPath, ConversionOptions options);
	}
	public static class MediaConverterFactory
	{
		public static IMediaConverter GetConverterForFile(string path)
		{
			if (WavConverter.IsCompatible(path))
			{
				return new WavConverter();
			}
			if (Mp3Converter.IsCompatible(path))
			{
				return new Mp3Converter();
			}
			if (AiffConverter.IsCompatible(path))
			{
				return new AiffConverter();
			}
			if (VideoConverter.IsCompatible(path))
			{
				return new VideoConverter();
			}
			return null;
		}
	}
	public class Mp3Converter : IMediaConverter
	{
		public static bool IsCompatible(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				return false;
			}
			string text = Path.GetExtension(path)?.ToLowerInvariant();
			if (!string.IsNullOrEmpty(text))
			{
				return text == ".mp3";
			}
			return false;
		}

		public void Convert(string sourcePath, string targetPath, ConversionOptions options)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if (!File.Exists(sourcePath))
			{
				throw new FileNotFoundException("Source file " + sourcePath + " not found");
			}
			AudioFileReader val = new AudioFileReader(sourcePath);
			try
			{
				MediaFoundationResampler val2 = new MediaFoundationResampler((IWaveProvider)(object)val, new WaveFormat(options.SampleRate, options.BitsPerSample, options.ChannelCount));
				val2.ResamplerQuality = 60;
				WaveFileWriter.CreateWaveFile(targetPath, (IWaveProvider)(object)val2);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
	}
	public class VideoConverter : IMediaConverter
	{
		private static readonly string[] _supportedExtensions = new string[5] { ".mp4", ".webm", ".avi", ".mov", ".ogg" };

		private static bool? _isFfmpegInstalled;

		private static TimeSpan _ffmpegTimeout = TimeSpan.FromSeconds(30.0);

		public static bool IsCompatible(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				return false;
			}
			string value = Path.GetExtension(path)?.ToLowerInvariant();
			if (!string.IsNullOrEmpty(value))
			{
				return _supportedExtensions.Contains(value);
			}
			return false;
		}

		private string BuildFfmpegArguments(string sourcePath, string targetPath, ConversionOptions options)
		{
			return $"-i \"{sourcePath}\" -vn -acodec {options.AudioCodec} -ar {options.SampleRate} -ac {options.ChannelCount} \"{targetPath}\"";
		}

		public void Convert(string sourcePath, string targetPath, ConversionOptions options)
		{
			if (!IsFfmpegInstalled())
			{
				throw new AudioConversionException("Failed to convert video file. ffmpeg is not installed.");
			}
			if (!File.Exists(sourcePath))
			{
				throw new FileNotFoundException("Source file " + sourcePath + " not found");
			}
			RunFfmpegProcess(sourcePath, targetPath, options);
		}

		private void RunFfmpegProcess(string sourcePath, string targetPath, ConversionOptions options)
		{
			string arguments = BuildFfmpegArguments(sourcePath, targetPath, options);
			ProcessStartInfo startInfo = new ProcessStartInfo
			{
				FileName = "ffmpeg",
				Arguments = arguments,
				UseShellExecute = false,
				CreateNoWindow = true,
				RedirectStandardOutput = true,
				RedirectStandardError = true
			};
			using Process process = new Process
			{
				StartInfo = startInfo
			};
			StringBuilder errorOutput = new StringBuilder();
			process.ErrorDataReceived += delegate(object sender, DataReceivedEventArgs e)
			{
				if (!string.IsNullOrEmpty(e.Data))
				{
					errorOutput.AppendLine(e.Data);
				}
			};
			if (!process.Start())
			{
				throw new AudioConversionException("Failed to start FFmpeg process");
			}
			process.BeginErrorReadLine();
			process.WaitForExit((int)_ffmpegTimeout.TotalMilliseconds);
			if (!process.HasExited)
			{
				try
				{
					process.Kill();
				}
				catch
				{
				}
				throw new AudioConversionException("FFmpeg process timed out");
			}
			if (process.ExitCode != 0)
			{
				string arg = errorOutput.ToString();
				REPOSoundBoard.Logger.LogError((object)$"FFmpeg exited with error code {process.ExitCode}. Error: {arg}");
				throw new AudioConversionException($"FFmpeg failed with exit code {process.ExitCode}: {arg}");
			}
			if (!File.Exists(targetPath))
			{
				throw new AudioConversionException("FFmpeg completed but the output file was not created");
			}
		}

		private static bool IsFfmpegInstalled()
		{
			if (!_isFfmpegInstalled.HasValue)
			{
				try
				{
					using Process process = Process.Start(new ProcessStartInfo
					{
						FileName = "ffmpeg",
						Arguments = "-version",
						RedirectStandardOutput = true,
						RedirectStandardError = true,
						UseShellExecute = false,
						CreateNoWindow = true
					});
					if (process == null)
					{
						_isFfmpegInstalled = false;
					}
					else
					{
						process.WaitForExit(2000);
						_isFfmpegInstalled = process.ExitCode == 0 || process.ExitCode == 1;
					}
				}
				catch
				{
					_isFfmpegInstalled = false;
				}
			}
			return _isFfmpegInstalled.Value;
		}
	}
	public class WavConverter : IMediaConverter
	{
		public static bool IsCompatible(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				return false;
			}
			string text = Path.GetExtension(path)?.ToLowerInvariant();
			if (!string.IsNullOrEmpty(text))
			{
				return text == ".wav";
			}
			return false;
		}

		public void Convert(string sourcePath, string targetPath, ConversionOptions options)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if (!File.Exists(sourcePath))
			{
				throw new FileNotFoundException("Source file " + sourcePath + " not found");
			}
			AudioFileReader val = new AudioFileReader(sourcePath);
			try
			{
				MediaFoundationResampler val2 = new MediaFoundationResampler((IWaveProvider)(object)val, new WaveFormat(options.SampleRate, options.BitsPerSample, options.ChannelCount));
				val2.ResamplerQuality = 60;
				WaveFileWriter.CreateWaveFile(targetPath, (IWaveProvider)(object)val2);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
	}
}
namespace REPOSoundBoard.Core.Hotkeys
{
	public class Hotkey
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public List<KeyCode> Keys { get; set; }

		[CanBeNull]
		[JsonIgnore]
		private Action Callback { get; set; }

		[JsonIgnore]
		public bool IsPressed { get; set; }

		[JsonConstructor]
		public Hotkey()
		{
			Keys = new List<KeyCode>();
		}

		public Hotkey(KeyCode key, [CanBeNull] Action callback)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Keys = new List<KeyCode> { key };
			Callback = callback;
		}

		public Hotkey(List<KeyCode> keys, [CanBeNull] Action callback)
		{
			Keys = new List<KeyCode>(keys);
			Callback = callback;
		}

		public Hotkey OnPressed(Action callback)
		{
			Callback = callback;
			return this;
		}

		public void Trigger()
		{
			if (Callback != null)
			{
				Callback();
			}
		}

		public string ConcatKeys()
		{
			return string.Join(" + ", Keys);
		}
	}
	public class HotkeyManager : MonoBehaviour
	{
		private List<Hotkey> _hotkeys = new List<Hotkey>();

		public void RegisterHotkey(Hotkey hotkey)
		{
			_hotkeys.Add(hotkey);
		}

		public void UnregisterHotkey(Hotkey hotkey)
		{
			_hotkeys.Remove(hotkey);
		}

		public void Update()
		{
			foreach (Hotkey hotkey in _hotkeys)
			{
				if (hotkey.Keys.Count != 0)
				{
					if (hotkey.IsPressed)
					{
						HandlePressedHotkey(hotkey);
					}
					else
					{
						HandleReleasedHotkey(hotkey);
					}
				}
			}
		}

		private static void HandlePressedHotkey(Hotkey hotkey)
		{
			if (hotkey.Keys.Any((KeyCode key) => !Input.GetKey(key)))
			{
				hotkey.IsPressed = false;
			}
		}

		private static void HandleReleasedHotkey(Hotkey hotkey)
		{
			if (hotkey.Keys.All((KeyCode key) => Input.GetKey(key)))
			{
				hotkey.IsPressed = true;
				hotkey.Trigger();
			}
		}
	}
}
namespace REPOSoundBoard.Core.Exceptions
{
	public class AudioConversionException : Exception
	{
		public AudioConversionException(string message)
			: base(message)
		{
		}
	}
}
namespace REPOSoundBoard.Config
{
	public class AppConfig
	{
		private static string _configFilePath;

		public Hotkey UiHotkey;

		public SoundBoardConfig SoundBoard;

		public AppConfig()
		{
			_configFilePath = Path.Combine(Paths.ConfigPath, "Moli.REPOSoundBoard.json");
			UiHotkey = new Hotkey((KeyCode)285, null);
			SoundBoard = new SoundBoardConfig();
		}

		public static AppConfig LoadConfig()
		{
			AppConfig result = new AppConfig();
			try
			{
				result = ConfigSerializer.DeserializeConfig(File.ReadAllText(_configFilePath));
				return result;
			}
			catch (Exception ex)
			{
				REPOSoundBoard.Logger.LogWarning((object)("Failed to read config file" + ex.Message));
				return result;
			}
		}

		public void SaveToFile()
		{
			string contents = ConfigSerializer.SerializeConfig(this);
			File.WriteAllText(_configFilePath, contents);
		}
	}
	public class ConfigSerializer
	{
		public static string SerializeConfig(AppConfig config)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			JsonSerializerSettings val = new JsonSerializerSettings
			{
				Formatting = (Formatting)1,
				NullValueHandling = (NullValueHandling)1
			};
			return JsonConvert.SerializeObject((object)config, val);
		}

		public static AppConfig DeserializeConfig(string json)
		{
			return JsonConvert.DeserializeObject<AppConfig>(json);
		}
	}
	public class SoundBoardConfig
	{
		public bool Enabled = true;

		public Hotkey StopHotkey = new Hotkey((KeyCode)104, null);

		public List<SoundButtonConfig> SoundButtons = new List<SoundButtonConfig>();
	}
	public class SoundButtonConfig
	{
		public string Name;

		public bool Enabled = true;

		public string Path;

		public float Volume = 0.75f;

		public Hotkey Hotkey;
	}
}