Decompiled source of OBSControl v1.1.2
Mods/OBSControl.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BoneLib; using BoneLib.BoneMenu; using BoneLib.Notifications; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using OBSWebsocketDotNet; using OBSWebsocketDotNet.Types; using OBSWebsocketDotNet.Types.Events; using UnityEngine; using UnityEngine.Diagnostics; using WeatherElectric.OBSControl; using WeatherElectric.OBSControl.Handlers; using WeatherElectric.OBSControl.Melon; using WeatherElectric.OBSControl.Menu; using WeatherElectric.OBSControl.OBS; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Control OBS from within BONELAB.")] [assembly: AssemblyDescription("Control OBS from within BONELAB.")] [assembly: AssemblyCompany("Weather Electric")] [assembly: AssemblyProduct("OBSControl")] [assembly: AssemblyCopyright("Developed by SoulWithMae")] [assembly: AssemblyTrademark("Weather Electric")] [assembly: AssemblyFileVersion("1.1.2")] [assembly: MelonInfo(typeof(Main), "OBSControl", "1.1.2", "SoulWithMae", "https://thunderstore.io/c/bonelab/p/SoulWithMae/OBSControl/")] [assembly: MelonColor(255, 0, 0, 255)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyVersion("1.1.2.0")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WeatherElectric.OBSControl { internal static class ControlHandler { private static bool _isFirstTap; private static float _doubleTapTimer; public static void Update() { switch (Preferences.ReplayControlHand.Value) { case ControlHand.Left: HandleLeft(); break; case ControlHand.Right: HandleRight(); break; case ControlHand.Both: HandleBoth(); break; default: throw new ArgumentOutOfRangeException(); } if (_isFirstTap) { _doubleTapTimer += Time.deltaTime; if (_doubleTapTimer > Preferences.DoubleTapTime.Value) { _isFirstTap = false; } } static void HandleBoth() { if (Player.RightController._menuTap || Player.LeftController._menuTap) { if (!_isFirstTap) { _isFirstTap = true; _doubleTapTimer = 0f; } else if (_doubleTapTimer < Preferences.DoubleTapTime.Value) { ObsBridge.SaveReplayBuffer(); NotificationHandler.SendNotif(NotificationHandler.ReplaySaved); _isFirstTap = false; } } } static void HandleLeft() { if (Player.LeftController._menuTap) { if (!_isFirstTap) { _isFirstTap = true; _doubleTapTimer = 0f; } else if (_doubleTapTimer < Preferences.DoubleTapTime.Value) { ObsBridge.SaveReplayBuffer(); NotificationHandler.SendNotif(NotificationHandler.ReplaySaved); _isFirstTap = false; } } } static void HandleRight() { if (Player.RightController._menuTap) { if (!_isFirstTap) { _isFirstTap = true; _doubleTapTimer = 0f; } else if (_doubleTapTimer < Preferences.DoubleTapTime.Value) { ObsBridge.SaveReplayBuffer(); NotificationHandler.SendNotif(NotificationHandler.ReplaySaved); _isFirstTap = false; } } } } } public class Main : MelonMod { internal const string Name = "OBSControl"; internal const string Description = "Control OBS from within BONELAB."; internal const string Author = "SoulWithMae"; internal const string Company = "Weather Electric"; internal const string Version = "1.1.2"; internal const string DownloadLink = "https://thunderstore.io/c/bonelab/p/SoulWithMae/OBSControl/"; private static bool _rigExists; public override void OnInitializeMelon() { ModConsole.Setup(((MelonBase)this).LoggerInstance); Preferences.Setup(); Hooking.OnUIRigCreated += OnUIRigCreated; Hooking.OnLevelUnloaded += OnLevelUnloaded; BoneMenu.SetupBaseMenu(); } public override void OnApplicationQuit() { ObsBridge.Disconnect(); } public override void OnUpdate() { if (_rigExists && ObsBridge.IsConnected()) { ControlHandler.Update(); } } private static void OnUIRigCreated() { _rigExists = true; if (!ObsBridge.IsConnected()) { ObsBridge.Connect(); ObsBridge.InitHooks(); } } private static void OnLevelUnloaded() { _rigExists = false; } } } namespace WeatherElectric.OBSControl.OBS { public static class ObsBridge { private static readonly OBSWebsocket Obs = new OBSWebsocket(); public static Action<object, RecordStateChangedEventArgs> OnRecordStateChanged; public static Action<object, ReplayBufferSavedEventArgs> OnReplayBufferSaved; public static Action<object, ReplayBufferStateChangedEventArgs> OnReplayBufferStateChanged; public static Action<object, StreamStateChangedEventArgs> OnStreamStateChanged; public static Action<object, ProgramSceneChangedEventArgs> OnSceneChanged; public static Action<object, SceneCreatedEventArgs> OnSceneCreated; public static Action<object, VirtualcamStateChangedEventArgs> OnVirtualCamStateChanged; public static Action<object, SceneRemovedEventArgs> OnSceneRemoved; private static void RecordStateChanged(object sender, RecordStateChangedEventArgs e) { OnRecordStateChanged?.Invoke(sender, e); } private static void ReplaySaved(object sender, ReplayBufferSavedEventArgs e) { OnReplayBufferSaved?.Invoke(sender, e); } private static void ReplayStateChanged(object sender, ReplayBufferStateChangedEventArgs e) { OnReplayBufferStateChanged?.Invoke(sender, e); } private static void StreamStateChanged(object sender, StreamStateChangedEventArgs e) { OnStreamStateChanged?.Invoke(sender, e); } private static void SceneChanged(object sender, ProgramSceneChangedEventArgs e) { OnSceneChanged?.Invoke(sender, e); } private static void VirtualCamStateChanged(object sender, VirtualcamStateChangedEventArgs e) { OnVirtualCamStateChanged?.Invoke(sender, e); } private static void SceneCreated(object sender, SceneCreatedEventArgs e) { OnSceneCreated?.Invoke(sender, e); } private static void SceneRemoved(object sender, SceneRemovedEventArgs e) { } internal static void Connect() { //IL_003a: Expected O, but got Unknown ModConsole.Msg("Attempting to connect to OBS...", 1); try { Obs.ConnectAsync(Preferences.WebsocketURL.Value, Preferences.WebsocketPassword.Value); } catch (AuthFailureException) { ModConsole.Error("Failed to authenticate with OBS. Check your password."); } catch (ErrorResponseException val2) { ErrorResponseException val3 = val2; ModConsole.Error("Failed to connect to OBS. Error: " + ((Exception)(object)val3).Message); } catch (Exception ex) { ModConsole.Error("Failed to connect to OBS. Error: " + ex.Message); } ModConsole.Msg("If you still aren't connected, it's likely the wrong password.", 1); } internal static void Disconnect() { ModConsole.Msg("Disconnecting from OBS...", 1); Obs.Disconnect(); } internal static void InitHooks() { Obs.RecordStateChanged += RecordStateChanged; Obs.ReplayBufferSaved += ReplaySaved; Obs.ReplayBufferStateChanged += ReplayStateChanged; Obs.StreamStateChanged += StreamStateChanged; Obs.CurrentProgramSceneChanged += SceneChanged; Obs.VirtualcamStateChanged += VirtualCamStateChanged; Obs.SceneCreated += SceneCreated; Obs.SceneRemoved += SceneRemoved; Obs.Connected += ObsConnected; } private static void ObsConnected(object sender, EventArgs e) { ModConsole.Msg("OBS connected!", 1); BoneMenu.SetupObsControls(); } public static List<SceneBasicInfo> GetScenes() { return Obs.GetSceneList().Scenes; } public static void SetScene(string sceneName) { Obs.SetCurrentProgramScene(sceneName); } public static bool IsConnected() { return Obs.IsConnected; } public static bool IsRecording() { return Obs.GetRecordStatus().IsRecording; } public static bool IsRecordingPaused() { return Obs.GetRecordStatus().IsRecordingPaused; } public static bool IsStreaming() { return Obs.GetStreamStatus().IsActive; } public static bool IsReplayBufferActive() { return Obs.GetReplayBufferStatus(); } public static bool IsVirtualCamActive() { return Obs.GetVirtualCamStatus().IsActive; } public static void StartRecording() { //IL_0020: Expected O, but got Unknown if (IsRecording()) { return; } ModConsole.Msg("Starting recording...", 1); try { Obs.StartRecord(); } catch (ErrorResponseException val) { ErrorResponseException val2 = val; ModConsole.Error("Failed to start recording. Error: " + ((Exception)(object)val2).Message); } catch (Exception ex) { ModConsole.Error("Failed to start recording. Error: " + ex.Message); } } public static void PauseRecording() { //IL_0020: Expected O, but got Unknown if (IsRecordingPaused()) { return; } ModConsole.Msg("Pausing recording...", 1); try { Obs.PauseRecord(); } catch (ErrorResponseException val) { ErrorResponseException val2 = val; ModConsole.Error("Failed to pause recording. Error: " + ((Exception)(object)val2).Message); } catch (Exception ex) { ModConsole.Error("Failed to pause recording. Error: " + ex.Message); } } public static void ResumeRecording() { //IL_0020: Expected O, but got Unknown if (!IsRecordingPaused()) { return; } ModConsole.Msg("Resuming recording...", 1); try { Obs.ResumeRecord(); } catch (ErrorResponseException val) { ErrorResponseException val2 = val; ModConsole.Error("Failed to resume recording. Error: " + ((Exception)(object)val2).Message); } catch (Exception ex) { ModConsole.Error("Failed to resume recording. Error: " + ex.Message); } } public static void StopRecording() { //IL_0021: Expected O, but got Unknown if (!IsRecording()) { return; } ModConsole.Msg("Stopping recording...", 1); try { Obs.StopRecord(); } catch (ErrorResponseException val) { ErrorResponseException val2 = val; ModConsole.Error("Failed to stop recording. Error: " + ((Exception)(object)val2).Message); } catch (Exception ex) { ModConsole.Error("Failed to stop recording. Error: " + ex.Message); } } public static void StartStreaming() { //IL_0020: Expected O, but got Unknown if (IsStreaming()) { return; } ModConsole.Msg("Starting stream...", 1); try { Obs.StartStream(); } catch (ErrorResponseException val) { ErrorResponseException val2 = val; ModConsole.Error("Failed to start streaming. Error: " + ((Exception)(object)val2).Message); } catch (Exception ex) { ModConsole.Error("Failed to start streaming. Error: " + ex.Message); } } public static void StopStreaming() { //IL_0020: Expected O, but got Unknown if (!IsStreaming()) { return; } ModConsole.Msg("Stopping stream...", 1); try { Obs.StopStream(); } catch (ErrorResponseException val) { ErrorResponseException val2 = val; ModConsole.Error("Failed to stop streaming. Error: " + ((Exception)(object)val2).Message); } catch (Exception ex) { ModConsole.Error("Failed to stop streaming. Error: " + ex.Message); } } public static void StartReplayBuffer() { //IL_0020: Expected O, but got Unknown if (IsReplayBufferActive()) { return; } ModConsole.Msg("Starting replay buffer...", 1); try { Obs.StartReplayBuffer(); } catch (ErrorResponseException val) { ErrorResponseException val2 = val; ModConsole.Error("Failed to start replay buffer. Error: " + ((Exception)(object)val2).Message); } catch (Exception ex) { ModConsole.Error("Failed to start replay buffer. Error: " + ex.Message); } } public static void StopReplayBuffer() { //IL_0020: Expected O, but got Unknown if (!IsReplayBufferActive()) { return; } ModConsole.Msg("Stopping replay buffer...", 1); try { Obs.StopReplayBuffer(); } catch (ErrorResponseException val) { ErrorResponseException val2 = val; ModConsole.Error("Failed to stop replay buffer. Error: " + ((Exception)(object)val2).Message); } catch (Exception ex) { ModConsole.Error("Failed to stop replay buffer. Error: " + ex.Message); } } public static void SaveReplayBuffer() { //IL_0020: Expected O, but got Unknown if (!IsReplayBufferActive()) { return; } ModConsole.Msg("Saving replay buffer...", 1); try { Obs.SaveReplayBuffer(); } catch (ErrorResponseException val) { ErrorResponseException val2 = val; ModConsole.Error("Failed to save replay buffer. Error: " + ((Exception)(object)val2).Message); } catch (Exception ex) { ModConsole.Error("Failed to save replay buffer. Error: " + ex.Message); } } } } namespace WeatherElectric.OBSControl.Melon { internal static class ModConsole { private static Instance _logger; public static void Setup(Instance loggerInstance) { _logger = loggerInstance; } public static void Msg(object obj, int loggingMode = 0) { string text = ((loggingMode == 1) ? $"[DEBUG] {obj}" : obj.ToString()); ConsoleColor consoleColor = ((loggingMode == 1) ? ConsoleColor.Yellow : ConsoleColor.Gray); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Msg(consoleColor, text); } } public static void Msg(string txt, int loggingMode = 0) { string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt); ConsoleColor consoleColor = ((loggingMode == 1) ? ConsoleColor.Yellow : ConsoleColor.Gray); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Msg(consoleColor, text); } } public static void Msg(ConsoleColor txtcolor, object obj, int loggingMode = 0) { string text = ((loggingMode == 1) ? $"[DEBUG] {obj}" : obj.ToString()); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Msg(txtcolor, text); } } public static void Msg(ConsoleColor txtcolor, string txt, int loggingMode = 0) { string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Msg(txtcolor, text); } } public static void Msg(string txt, int loggingMode = 0, params object[] args) { string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt); ConsoleColor consoleColor = ((loggingMode == 1) ? ConsoleColor.Yellow : ConsoleColor.Gray); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Msg(consoleColor, text, args); } } public static void Msg(ConsoleColor txtcolor, string txt, int loggingMode = 0, params object[] args) { string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Msg(txtcolor, text, args); } } public static void Error(object obj, int loggingMode = 0) { string text = ((loggingMode == 1) ? $"[DEBUG] {obj}" : obj.ToString()); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Error(text); } } public static void Error(string txt, int loggingMode = 0) { string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Error(text); } } public static void Error(string txt, int loggingMode = 0, params object[] args) { string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Error(text, args); } } public static void Warning(object obj, int loggingMode = 0) { string text = ((loggingMode == 1) ? $"[DEBUG] {obj}" : obj.ToString()); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Warning(text); } } public static void Warning(string txt, int loggingMode = 0) { string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Warning(text); } } public static void Warning(string txt, int loggingMode = 0, params object[] args) { string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt); if (Preferences.LoggingMode.Value >= loggingMode) { _logger.Warning(text, args); } } } internal static class Preferences { public static readonly MelonPreferences_Category GlobalCategory = MelonPreferences.CreateCategory("Global"); public static readonly MelonPreferences_Category OwnCategory = MelonPreferences.CreateCategory("OBSControl"); public static MelonPreferences_Entry<int> LoggingMode { get; set; } public static MelonPreferences_Entry<bool> ShowNotifications { get; set; } public static MelonPreferences_Entry<string> WebsocketURL { get; set; } public static MelonPreferences_Entry<string> WebsocketPassword { get; set; } public static MelonPreferences_Entry<ControlHand> ReplayControlHand { get; set; } public static MelonPreferences_Entry<float> DoubleTapTime { get; set; } public static void Setup() { LoggingMode = GlobalCategory.GetEntry<int>("LoggingMode") ?? GlobalCategory.CreateEntry<int>("LoggingMode", 0, "Logging Mode", "The level of logging to use. 0 = Important Only, 1 = All", false, false, (ValueValidator)null, (string)null); GlobalCategory.SetFilePath(MelonEnvironment.UserDataDirectory + "/WeatherElectric.cfg"); GlobalCategory.SaveToFile(false); ShowNotifications = OwnCategory.CreateEntry<bool>("ShowNotifications", true, "Show Notifications", "Whether to show notifications when OBS events occur.", false, false, (ValueValidator)null, (string)null); WebsocketURL = OwnCategory.CreateEntry<string>("WebsocketURL", "ws://127.0.0.1:4455", "Websocket URL", "The URL to use for the websocket connection. Usually don't have to change this.", false, false, (ValueValidator)null, (string)null); WebsocketPassword = OwnCategory.CreateEntry<string>("WebsocketPassword", "REPLACEME", "Websocket Password", "The password to use for the websocket connection. Change this to the password you set in OBS.", false, false, (ValueValidator)null, (string)null); ReplayControlHand = OwnCategory.CreateEntry<ControlHand>("ReplayControlHand", ControlHand.Right, "Replay Control Hand", "The hand to use for saving replays. Left = Left hand, Right = Right hand, Both = Both hands.", false, false, (ValueValidator)null, (string)null); DoubleTapTime = OwnCategory.CreateEntry<float>("DoubleTapTime", 0.3f, "Double Tap Time", "The time to wait between taps to trigger saving a replay.", false, false, (ValueValidator)null, (string)null); OwnCategory.SetFilePath(MelonEnvironment.UserDataDirectory + "/WeatherElectric.cfg"); OwnCategory.SaveToFile(false); ModConsole.Msg("Finished preferences setup for OBSControl", 1); } } internal enum ControlHand { Left, Right, Both } } namespace WeatherElectric.OBSControl.Handlers { internal static class NotificationHandler { public static Notification SceneChanged { get; } = new Notification { Title = NotificationText.op_Implicit("Scene Changed"), Message = NotificationText.op_Implicit("Scene has been changed."), Type = (NotificationType)0, PopupLength = 1f, ShowTitleOnPopup = true }; public static Notification RecordingStarted { get; } = new Notification { Title = NotificationText.op_Implicit("Recording Started"), Message = NotificationText.op_Implicit("Recording has started."), Type = (NotificationType)0, PopupLength = 1f, ShowTitleOnPopup = true }; public static Notification RecordingStopped { get; } = new Notification { Title = NotificationText.op_Implicit("Recording Stopped"), Message = NotificationText.op_Implicit("Recording has stopped."), Type = (NotificationType)0, PopupLength = 1f, ShowTitleOnPopup = true }; public static Notification RecordingPaused { get; } = new Notification { Title = NotificationText.op_Implicit("Recording Paused"), Message = NotificationText.op_Implicit("Recording has been paused."), Type = (NotificationType)0, PopupLength = 1f, ShowTitleOnPopup = true }; public static Notification RecordingResumed { get; } = new Notification { Title = NotificationText.op_Implicit("Recording Resumed"), Message = NotificationText.op_Implicit("Recording has been resumed."), Type = (NotificationType)0, PopupLength = 1f, ShowTitleOnPopup = true }; public static Notification StreamStarted { get; } = new Notification { Title = NotificationText.op_Implicit("Stream Started"), Message = NotificationText.op_Implicit("Stream has started."), Type = (NotificationType)0, PopupLength = 1f, ShowTitleOnPopup = true }; public static Notification StreamStopped { get; } = new Notification { Title = NotificationText.op_Implicit("Stream Stopped"), Message = NotificationText.op_Implicit("Stream has stopped."), Type = (NotificationType)0, PopupLength = 1f, ShowTitleOnPopup = true }; public static Notification ReplayBufferStarted { get; } = new Notification { Title = NotificationText.op_Implicit("Replay Buffer Started"), Message = NotificationText.op_Implicit("Replay buffer has started."), Type = (NotificationType)0, PopupLength = 1f, ShowTitleOnPopup = true }; public static Notification ReplayBufferStopped { get; } = new Notification { Title = NotificationText.op_Implicit("Replay Buffer Stopped"), Message = NotificationText.op_Implicit("Replay buffer has stopped."), Type = (NotificationType)0, PopupLength = 1f, ShowTitleOnPopup = true }; public static Notification ReplaySaved { get; } = new Notification { Title = NotificationText.op_Implicit("Replay Saved"), Message = NotificationText.op_Implicit("Replay has been saved."), Type = (NotificationType)0, PopupLength = 1f, ShowTitleOnPopup = true }; public static void SendNotif(Notification notification) { if (Preferences.ShowNotifications.Value) { Notifier.Send(notification); } } } } namespace WeatherElectric.OBSControl.Menu { internal static class BoneMenu { private static Page _subCat; private static FunctionElement _recordButton; private static FunctionElement _pauseButton; private static FunctionElement _streamButton; private static FunctionElement _replayButton; private static FunctionElement _connectButton; private static Page _scenesPanel; private static readonly List<FunctionElement> SceneButtons = new List<FunctionElement>(); public static void SetupBaseMenu() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) _subCat = Page.Root.CreatePage("<color=#6FBDFF>Weather Electric</color>", Color.cyan, 0, true).CreatePage("<color=#284cb8>OBSControl</color>", Color.white, 0, true); _connectButton = _subCat.CreateFunction("If you see this, it failed to connect.", Color.red, (Action)delegate { Utils.ForceCrash((ForcedCrashCategory)0); }); } public static void SetupObsControls() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) _subCat.Remove((Element)(object)_connectButton); Page obj = _subCat.CreatePage("Record", Color.green, 0, true); _recordButton = obj.CreateFunction("Record Button", Color.green, (Action)delegate { if (ObsBridge.IsRecording()) { ObsBridge.StopRecording(); NotificationHandler.SendNotif(NotificationHandler.RecordingStopped); } else { ObsBridge.StartRecording(); NotificationHandler.SendNotif(NotificationHandler.RecordingStarted); } }); SetRecordButton(ObsBridge.IsRecording()); _pauseButton = obj.CreateFunction("Pause Button", Color.yellow, (Action)delegate { if (ObsBridge.IsRecordingPaused()) { ObsBridge.ResumeRecording(); NotificationHandler.SendNotif(NotificationHandler.RecordingResumed); } else { ObsBridge.PauseRecording(); NotificationHandler.SendNotif(NotificationHandler.RecordingPaused); } }); SetPauseButton(ObsBridge.IsRecordingPaused()); _streamButton = _subCat.CreatePage("Stream", Color.blue, 0, true).CreateFunction("Stream Button", Color.blue, (Action)delegate { if (ObsBridge.IsStreaming()) { ObsBridge.StopStreaming(); NotificationHandler.SendNotif(NotificationHandler.StreamStopped); } else { ObsBridge.StartStreaming(); NotificationHandler.SendNotif(NotificationHandler.StreamStarted); } }); SetStreamButton(ObsBridge.IsStreaming()); Page obj2 = _subCat.CreatePage("Replay", Color.yellow, 0, true); _replayButton = obj2.CreateFunction("Replay Button", Color.blue, (Action)delegate { if (ObsBridge.IsReplayBufferActive()) { ObsBridge.StopReplayBuffer(); NotificationHandler.SendNotif(NotificationHandler.ReplayBufferStopped); } else { ObsBridge.StartReplayBuffer(); NotificationHandler.SendNotif(NotificationHandler.ReplayBufferStarted); } }); SetReplayButton(ObsBridge.IsReplayBufferActive()); obj2.CreateFunction("Save Replay", Color.blue, (Action)delegate { ObsBridge.SaveReplayBuffer(); NotificationHandler.SendNotif(NotificationHandler.ReplaySaved); }); _scenesPanel = _subCat.CreatePage("Scenes", Color.red, 0, true); List<SceneBasicInfo> scenes = ObsBridge.GetScenes(); ModConsole.Msg("Finding scenes", 1); foreach (SceneBasicInfo scene in scenes) { ModConsole.Msg("Found scene: " + scene.Name, 1); FunctionElement item = _scenesPanel.CreateFunction(scene.Name, Color.white, (Action)delegate { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) ObsBridge.SetScene(scene.Name); NotificationHandler.SceneChanged.Message = NotificationText.op_Implicit("Scene changed to " + scene.Name); NotificationHandler.SendNotif(NotificationHandler.SceneChanged); }); SceneButtons.Add(item); } Page obj3 = _subCat.CreatePage("Settings", Color.gray, 0, true); obj3.CreateBoolPreference("Show Notifications", Color.white, Preferences.ShowNotifications, Preferences.OwnCategory); obj3.CreateEnum("Replay Control Hand", Color.white, (Enum)Preferences.ReplayControlHand.Value, (Action<Enum>)delegate(Enum v) { Preferences.ReplayControlHand.Value = (ControlHand)(object)v; Preferences.OwnCategory.SaveToFile(false); }); obj3.CreateFloatPreference("Double Tap Time", Color.white, 0.1f, 0.1f, 1f, Preferences.DoubleTapTime, Preferences.OwnCategory); ConnectHooks(); } private static void ConnectHooks() { ObsBridge.OnRecordStateChanged = (Action<object, RecordStateChangedEventArgs>)Delegate.Combine(ObsBridge.OnRecordStateChanged, new Action<object, RecordStateChangedEventArgs>(RecordStatusChanged)); ObsBridge.OnStreamStateChanged = (Action<object, StreamStateChangedEventArgs>)Delegate.Combine(ObsBridge.OnStreamStateChanged, new Action<object, StreamStateChangedEventArgs>(StreamStatusChanged)); ObsBridge.OnReplayBufferStateChanged = (Action<object, ReplayBufferStateChangedEventArgs>)Delegate.Combine(ObsBridge.OnReplayBufferStateChanged, new Action<object, ReplayBufferStateChangedEventArgs>(ReplayStatusChanged)); ObsBridge.OnSceneCreated = (Action<object, SceneCreatedEventArgs>)Delegate.Combine(ObsBridge.OnSceneCreated, new Action<object, SceneCreatedEventArgs>(SceneCreated)); ObsBridge.OnSceneRemoved = (Action<object, SceneRemovedEventArgs>)Delegate.Combine(ObsBridge.OnSceneRemoved, new Action<object, SceneRemovedEventArgs>(SceneDeleted)); } private static void RecordStatusChanged(object sender, RecordStateChangedEventArgs e) { SetRecordButton(((OutputStateChanged)e.OutputState).IsActive); } private static void StreamStatusChanged(object sender, StreamStateChangedEventArgs e) { SetStreamButton(e.OutputState.IsActive); } private static void ReplayStatusChanged(object sender, ReplayBufferStateChangedEventArgs e) { SetReplayButton(e.OutputState.IsActive); } private static void SceneCreated(object sender, SceneCreatedEventArgs e) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) ModConsole.Msg("Scene created: " + e.SceneName, 1); FunctionElement item = _scenesPanel.CreateFunction(e.SceneName, Color.white, (Action)delegate { ObsBridge.SetScene(e.SceneName); }); SceneButtons.Add(item); } private static void SceneDeleted(object sender, SceneRemovedEventArgs e) { ModConsole.Msg("Scene deleted: " + e.SceneName, 1); using IEnumerator<FunctionElement> enumerator = SceneButtons.Where((FunctionElement button) => ((Element)button).ElementName == e.SceneName).GetEnumerator(); if (enumerator.MoveNext()) { FunctionElement current = enumerator.Current; _scenesPanel.Remove((Element)(object)current); SceneButtons.Remove(current); } } private static void SetRecordButton(bool isRecording) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (isRecording) { ((Element)_recordButton).ElementColor = Color.red; ((Element)_recordButton).ElementName = "Stop Recording"; } else { ((Element)_recordButton).ElementColor = Color.green; ((Element)_recordButton).ElementName = "Start Recording"; } } private static void SetPauseButton(bool isPaused) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (isPaused) { ((Element)_pauseButton).ElementColor = Color.white; ((Element)_pauseButton).ElementName = "Resume Recording"; } else { ((Element)_pauseButton).ElementColor = Color.yellow; ((Element)_pauseButton).ElementName = "Pause Recording"; } } private static void SetStreamButton(bool isStreaming) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (isStreaming) { ((Element)_streamButton).ElementColor = Color.red; ((Element)_streamButton).ElementName = "Stop Streaming"; } else { ((Element)_streamButton).ElementColor = Color.green; ((Element)_streamButton).ElementName = "Start Streaming"; } } private static void SetReplayButton(bool isReplayActive) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (isReplayActive) { ((Element)_replayButton).ElementColor = Color.red; ((Element)_replayButton).ElementName = "Stop Replay Buffer"; } else { ((Element)_replayButton).ElementColor = Color.green; ((Element)_replayButton).ElementName = "Start Replay Buffer"; } } } internal static class BoneMenuExtensions { public static BoolElement CreateBoolPreference(this Page category, string name, Color color, MelonPreferences_Entry<bool> pref, MelonPreferences_Category prefCategory, bool autoSave = true) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) return category.CreateBool(name, color, pref.Value, (Action<bool>)delegate(bool v) { pref.Value = v; if (autoSave) { prefCategory.SaveToFile(false); } }); } public static FloatElement CreateFloatPreference(this Page category, string name, Color color, float increment, float min, float max, MelonPreferences_Entry<float> pref, MelonPreferences_Category prefCategory, bool autoSave = true) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) return category.CreateFloat(name, color, pref.Value, increment, min, max, (Action<float>)delegate(float v) { pref.Value = v; if (autoSave) { prefCategory.SaveToFile(false); } }); } public static IntElement CreateIntPreference(this Page category, string name, Color color, int increment, int min, int max, MelonPreferences_Entry<int> pref, MelonPreferences_Category prefCategory, bool autoSave = true) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) return category.CreateInt(name, color, pref.Value, increment, min, max, (Action<int>)delegate(int v) { pref.Value = v; if (autoSave) { prefCategory.SaveToFile(false); } }); } public static EnumElement CreateEnumPreference(this Page category, string name, Color color, Enum pref, MelonPreferences_Category prefCategory, bool autoSave = true) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) return category.CreateEnum(name, color, pref, (Action<Enum>)delegate(Enum v) { pref = v; if (autoSave) { prefCategory.SaveToFile(false); } }); } } }
UserLibs/obs-websocket-dotnet.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using OBSWebsocketDotNet.Communication; using OBSWebsocketDotNet.Types; using OBSWebsocketDotNet.Types.Events; using Websocket.Client; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("BarRaider")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © BarRaider 2022")] [assembly: AssemblyDescription("Official obs-websocket .NET library. Written in C#. Supports .NET Standard")] [assembly: AssemblyFileVersion("5.0.0.3")] [assembly: AssemblyInformationalVersion("5.0.0.3")] [assembly: AssemblyProduct("obs-websocket-dotnet")] [assembly: AssemblyTitle("obs-websocket-dotnet")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/BarRaider/obs-websocket-dotnet")] [assembly: AssemblyVersion("5.0.0.3")] namespace OBSWebsocketDotNet { public class OBSWebsocket : IOBSWebsocket { private delegate void RequestCallback(OBSWebsocket sender, JObject body); private const string WEBSOCKET_URL_PREFIX = "ws://"; private const int SUPPORTED_RPC_VERSION = 1; private TimeSpan wsTimeout = TimeSpan.FromSeconds(10.0); private string connectionPassword; private WebsocketClient wsConnection; private readonly ConcurrentDictionary<string, TaskCompletionSource<JObject>> responseHandlers; private static readonly Random random = new Random(); private const string REQUEST_FIELD_VOLUME_DB = "inputVolumeDb"; private const string REQUEST_FIELD_VOLUME_MUL = "inputVolumeMul"; private const string RESPONSE_FIELD_IMAGE_DATA = "imageData"; public TimeSpan WSTimeout { get { WebsocketClient obj = wsConnection; return ((obj != null) ? obj.ReconnectTimeout : null) ?? wsTimeout; } set { wsTimeout = value; if (wsConnection != null) { wsConnection.ReconnectTimeout = wsTimeout; } } } public bool IsConnected { get { if (wsConnection != null) { return wsConnection.IsRunning; } return false; } } public event EventHandler<ProgramSceneChangedEventArgs> CurrentProgramSceneChanged; public event EventHandler<SceneListChangedEventArgs> SceneListChanged; public event EventHandler<SceneItemListReindexedEventArgs> SceneItemListReindexed; public event EventHandler<SceneItemCreatedEventArgs> SceneItemCreated; public event EventHandler<SceneItemRemovedEventArgs> SceneItemRemoved; public event EventHandler<SceneItemEnableStateChangedEventArgs> SceneItemEnableStateChanged; public event EventHandler<SceneItemLockStateChangedEventArgs> SceneItemLockStateChanged; public event EventHandler<CurrentSceneCollectionChangedEventArgs> CurrentSceneCollectionChanged; public event EventHandler<SceneCollectionListChangedEventArgs> SceneCollectionListChanged; public event EventHandler<CurrentSceneTransitionChangedEventArgs> CurrentSceneTransitionChanged; public event EventHandler<CurrentSceneTransitionDurationChangedEventArgs> CurrentSceneTransitionDurationChanged; public event EventHandler<SceneTransitionStartedEventArgs> SceneTransitionStarted; public event EventHandler<SceneTransitionEndedEventArgs> SceneTransitionEnded; public event EventHandler<SceneTransitionVideoEndedEventArgs> SceneTransitionVideoEnded; public event EventHandler<CurrentProfileChangedEventArgs> CurrentProfileChanged; public event EventHandler<ProfileListChangedEventArgs> ProfileListChanged; public event EventHandler<StreamStateChangedEventArgs> StreamStateChanged; public event EventHandler<RecordStateChangedEventArgs> RecordStateChanged; public event EventHandler<ReplayBufferStateChangedEventArgs> ReplayBufferStateChanged; public event EventHandler<CurrentPreviewSceneChangedEventArgs> CurrentPreviewSceneChanged; public event EventHandler<StudioModeStateChangedEventArgs> StudioModeStateChanged; public event EventHandler ExitStarted; public event EventHandler Connected; public event EventHandler<ObsDisconnectionInfo> Disconnected; public event EventHandler<SceneItemSelectedEventArgs> SceneItemSelected; public event EventHandler<SceneItemTransformEventArgs> SceneItemTransformChanged; public event EventHandler<InputAudioSyncOffsetChangedEventArgs> InputAudioSyncOffsetChanged; public event EventHandler<SourceFilterCreatedEventArgs> SourceFilterCreated; public event EventHandler<SourceFilterRemovedEventArgs> SourceFilterRemoved; public event EventHandler<SourceFilterListReindexedEventArgs> SourceFilterListReindexed; public event EventHandler<SourceFilterEnableStateChangedEventArgs> SourceFilterEnableStateChanged; public event EventHandler<InputMuteStateChangedEventArgs> InputMuteStateChanged; public event EventHandler<InputVolumeChangedEventArgs> InputVolumeChanged; public event EventHandler<VendorEventArgs> VendorEvent; public event EventHandler<MediaInputPlaybackEndedEventArgs> MediaInputPlaybackEnded; public event EventHandler<MediaInputPlaybackStartedEventArgs> MediaInputPlaybackStarted; public event EventHandler<MediaInputActionTriggeredEventArgs> MediaInputActionTriggered; public event EventHandler<VirtualcamStateChangedEventArgs> VirtualcamStateChanged; public event EventHandler<CurrentSceneCollectionChangingEventArgs> CurrentSceneCollectionChanging; public event EventHandler<CurrentProfileChangingEventArgs> CurrentProfileChanging; public event EventHandler<SourceFilterNameChangedEventArgs> SourceFilterNameChanged; public event EventHandler<InputCreatedEventArgs> InputCreated; public event EventHandler<InputRemovedEventArgs> InputRemoved; public event EventHandler<InputNameChangedEventArgs> InputNameChanged; public event EventHandler<InputActiveStateChangedEventArgs> InputActiveStateChanged; public event EventHandler<InputShowStateChangedEventArgs> InputShowStateChanged; public event EventHandler<InputAudioBalanceChangedEventArgs> InputAudioBalanceChanged; public event EventHandler<InputAudioTracksChangedEventArgs> InputAudioTracksChanged; public event EventHandler<InputAudioMonitorTypeChangedEventArgs> InputAudioMonitorTypeChanged; public event EventHandler<InputVolumeMetersEventArgs> InputVolumeMeters; public event EventHandler<ReplayBufferSavedEventArgs> ReplayBufferSaved; public event EventHandler<SceneCreatedEventArgs> SceneCreated; public event EventHandler<SceneRemovedEventArgs> SceneRemoved; public event EventHandler<SceneNameChangedEventArgs> SceneNameChanged; protected void ProcessEventType(string eventType, JObject body) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_10d1: Unknown result type (might be due to invalid IL or missing references) //IL_10db: Expected O, but got Unknown //IL_0ce3: Unknown result type (might be due to invalid IL or missing references) //IL_0cf3: Unknown result type (might be due to invalid IL or missing references) //IL_0cfd: Expected O, but got Unknown //IL_0cfd: Expected O, but got Unknown //IL_0f86: Unknown result type (might be due to invalid IL or missing references) //IL_0f96: Unknown result type (might be due to invalid IL or missing references) //IL_0fa0: Expected O, but got Unknown //IL_0fa0: Expected O, but got Unknown //IL_0bec: Unknown result type (might be due to invalid IL or missing references) //IL_0bf6: Expected O, but got Unknown body = (JObject)body["eventData"]; switch (eventType) { case "CurrentProgramSceneChanged": this.CurrentProgramSceneChanged?.Invoke(this, new ProgramSceneChangedEventArgs((string)body["sceneName"])); break; case "SceneListChanged": this.SceneListChanged?.Invoke(this, new SceneListChangedEventArgs(JsonConvert.DeserializeObject<List<JObject>>((string)body["scenes"]))); break; case "SceneItemListReindexed": this.SceneItemListReindexed?.Invoke(this, new SceneItemListReindexedEventArgs((string)body["sceneName"], JsonConvert.DeserializeObject<List<JObject>>((string)body["sceneItems"]))); break; case "SceneItemCreated": this.SceneItemCreated?.Invoke(this, new SceneItemCreatedEventArgs((string)body["sceneName"], (string)body["sourceName"], (int)body["sceneItemId"], (int)body["sceneItemIndex"])); break; case "SceneItemRemoved": this.SceneItemRemoved?.Invoke(this, new SceneItemRemovedEventArgs((string)body["sceneName"], (string)body["sourceName"], (int)body["sceneItemId"])); break; case "SceneItemEnableStateChanged": this.SceneItemEnableStateChanged?.Invoke(this, new SceneItemEnableStateChangedEventArgs((string)body["sceneName"], (int)body["sceneItemId"], (bool)body["sceneItemEnabled"])); break; case "SceneItemLockStateChanged": this.SceneItemLockStateChanged?.Invoke(this, new SceneItemLockStateChangedEventArgs((string)body["sceneName"], (int)body["sceneItemId"], (bool)body["sceneItemLocked"])); break; case "CurrentSceneCollectionChanged": this.CurrentSceneCollectionChanged?.Invoke(this, new CurrentSceneCollectionChangedEventArgs((string)body["sceneCollectionName"])); break; case "SceneCollectionListChanged": this.SceneCollectionListChanged?.Invoke(this, new SceneCollectionListChangedEventArgs(JsonConvert.DeserializeObject<List<string>>((string)body["sceneCollections"]))); break; case "CurrentSceneTransitionChanged": this.CurrentSceneTransitionChanged?.Invoke(this, new CurrentSceneTransitionChangedEventArgs((string)body["transitionName"])); break; case "CurrentSceneTransitionDurationChanged": this.CurrentSceneTransitionDurationChanged?.Invoke(this, new CurrentSceneTransitionDurationChangedEventArgs((int)body["transitionDuration"])); break; case "SceneTransitionStarted": this.SceneTransitionStarted?.Invoke(this, new SceneTransitionStartedEventArgs((string)body["transitionName"])); break; case "SceneTransitionEnded": this.SceneTransitionEnded?.Invoke(this, new SceneTransitionEndedEventArgs((string)body["transitionName"])); break; case "SceneTransitionVideoEnded": this.SceneTransitionVideoEnded?.Invoke(this, new SceneTransitionVideoEndedEventArgs((string)body["transitionName"])); break; case "CurrentProfileChanged": this.CurrentProfileChanged?.Invoke(this, new CurrentProfileChangedEventArgs((string)body["profileName"])); break; case "ProfileListChanged": this.ProfileListChanged?.Invoke(this, new ProfileListChangedEventArgs(JsonConvert.DeserializeObject<List<string>>((string)body["profiles"]))); break; case "StreamStateChanged": this.StreamStateChanged?.Invoke(this, new StreamStateChangedEventArgs(new OutputStateChanged(body))); break; case "RecordStateChanged": this.RecordStateChanged?.Invoke(this, new RecordStateChangedEventArgs(new RecordStateChanged(body))); break; case "CurrentPreviewSceneChanged": this.CurrentPreviewSceneChanged?.Invoke(this, new CurrentPreviewSceneChangedEventArgs((string)body["sceneName"])); break; case "StudioModeStateChanged": this.StudioModeStateChanged?.Invoke(this, new StudioModeStateChangedEventArgs((bool)body["studioModeEnabled"])); break; case "ReplayBufferStateChanged": this.ReplayBufferStateChanged?.Invoke(this, new ReplayBufferStateChangedEventArgs(new OutputStateChanged(body))); break; case "ExitStarted": this.ExitStarted?.Invoke(this, EventArgs.Empty); break; case "SceneItemSelected": this.SceneItemSelected?.Invoke(this, new SceneItemSelectedEventArgs((string)body["sceneName"], (string)body["sceneItemId"])); break; case "SceneItemTransformChanged": this.SceneItemTransformChanged?.Invoke(this, new SceneItemTransformEventArgs((string)body["sceneName"], (string)body["sceneItemId"], new SceneItemTransformInfo((JObject)body["sceneItemTransform"]))); break; case "InputAudioSyncOffsetChanged": this.InputAudioSyncOffsetChanged?.Invoke(this, new InputAudioSyncOffsetChangedEventArgs((string)body["inputName"], (int)body["inputAudioSyncOffset"])); break; case "InputMuteStateChanged": this.InputMuteStateChanged?.Invoke(this, new InputMuteStateChangedEventArgs((string)body["inputName"], (bool)body["inputMuted"])); break; case "InputVolumeChanged": this.InputVolumeChanged?.Invoke(this, new InputVolumeChangedEventArgs(new InputVolume(body))); break; case "SourceFilterCreated": this.SourceFilterCreated?.Invoke(this, new SourceFilterCreatedEventArgs((string)body["sourceName"], (string)body["filterName"], (string)body["filterKind"], (int)body["filterIndex"], (JObject)body["filterSettings"], (JObject)body["defaultFilterSettings"])); break; case "SourceFilterRemoved": this.SourceFilterRemoved?.Invoke(this, new SourceFilterRemovedEventArgs((string)body["sourceName"], (string)body["filterName"])); break; case "SourceFilterListReindexed": if (this.SourceFilterListReindexed != null) { List<FilterReorderItem> list = new List<FilterReorderItem>(); JsonConvert.PopulateObject(((object)body["filters"]).ToString(), (object)list); this.SourceFilterListReindexed?.Invoke(this, new SourceFilterListReindexedEventArgs((string)body["sourceName"], list)); } break; case "SourceFilterEnableStateChanged": this.SourceFilterEnableStateChanged?.Invoke(this, new SourceFilterEnableStateChangedEventArgs((string)body["sourceName"], (string)body["filterName"], (bool)body["filterEnabled"])); break; case "VendorEvent": this.VendorEvent?.Invoke(this, new VendorEventArgs((string)body["vendorName"], (string)body["eventType"], body)); break; case "MediaInputPlaybackEnded": this.MediaInputPlaybackEnded?.Invoke(this, new MediaInputPlaybackEndedEventArgs((string)body["inputName"])); break; case "MediaInputPlaybackStarted": this.MediaInputPlaybackStarted?.Invoke(this, new MediaInputPlaybackStartedEventArgs((string)body["sourceName"])); break; case "MediaInputActionTriggered": this.MediaInputActionTriggered?.Invoke(this, new MediaInputActionTriggeredEventArgs((string)body["inputName"], (string)body["mediaAction"])); break; case "VirtualcamStateChanged": this.VirtualcamStateChanged?.Invoke(this, new VirtualcamStateChangedEventArgs(new OutputStateChanged(body))); break; case "CurrentSceneCollectionChanging": this.CurrentSceneCollectionChanging?.Invoke(this, new CurrentSceneCollectionChangingEventArgs((string)body["sceneCollectionName"])); break; case "CurrentProfileChanging": this.CurrentProfileChanging?.Invoke(this, new CurrentProfileChangingEventArgs((string)body["profileName"])); break; case "SourceFilterNameChanged": this.SourceFilterNameChanged?.Invoke(this, new SourceFilterNameChangedEventArgs((string)body["sourceName"], (string)body["oldFilterName"], (string)body["filterName"])); break; case "InputCreated": this.InputCreated?.Invoke(this, new InputCreatedEventArgs((string)body["inputName"], (string)body["inputKind"], (string)body["unversionedInputKind"], (JObject)body["inputSettings"], (JObject)body["defaultInputSettings"])); break; case "InputRemoved": this.InputRemoved?.Invoke(this, new InputRemovedEventArgs((string)body["inputName"])); break; case "InputNameChanged": this.InputNameChanged?.Invoke(this, new InputNameChangedEventArgs((string)body["oldInputName"], (string)body["inputName"])); break; case "InputActiveStateChanged": this.InputActiveStateChanged?.Invoke(this, new InputActiveStateChangedEventArgs((string)body["inputName"], (bool)body["videoActive"])); break; case "InputShowStateChanged": this.InputShowStateChanged?.Invoke(this, new InputShowStateChangedEventArgs((string)body["inputName"], (bool)body["videoShowing"])); break; case "InputAudioBalanceChanged": this.InputAudioBalanceChanged?.Invoke(this, new InputAudioBalanceChangedEventArgs((string)body["inputName"], (double)body["inputAudioBalance"])); break; case "InputAudioTracksChanged": this.InputAudioTracksChanged?.Invoke(this, new InputAudioTracksChangedEventArgs((string)body["inputName"], (JObject)body["inputAudioTracks"])); break; case "InputAudioMonitorTypeChanged": this.InputAudioMonitorTypeChanged?.Invoke(this, new InputAudioMonitorTypeChangedEventArgs((string)body["inputName"], (string)body["monitorType"])); break; case "InputVolumeMeters": this.InputVolumeMeters?.Invoke(this, new InputVolumeMetersEventArgs(JsonConvert.DeserializeObject<List<JObject>>((string)body["inputs"]))); break; case "ReplayBufferSaved": this.ReplayBufferSaved?.Invoke(this, new ReplayBufferSavedEventArgs((string)body["savedReplayPath"])); break; case "SceneCreated": this.SceneCreated?.Invoke(this, new SceneCreatedEventArgs((string)body["sceneName"], (bool)body["isGroup"])); break; case "SceneRemoved": this.SceneRemoved?.Invoke(this, new SceneRemovedEventArgs((string)body["sceneName"], (bool)body["isGroup"])); break; case "SceneNameChanged": this.SceneNameChanged?.Invoke(this, new SceneNameChangedEventArgs((string)body["oldSceneName"], (string)body["sceneName"])); break; default: Console.WriteLine($"Unsupported Event: {eventType}\n{body}"); break; } } public OBSWebsocket() { responseHandlers = new ConcurrentDictionary<string, TaskCompletionSource<JObject>>(); } [Obsolete("Please use ConnectAsync, this function will be removed in the next version")] public void Connect(string url, string password) { ConnectAsync(url, password); } public void ConnectAsync(string url, string password) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown if (!url.ToLower().StartsWith("ws://")) { throw new ArgumentException("Invalid url, must start with 'ws://'"); } if (wsConnection != null && wsConnection.IsRunning) { Disconnect(); } wsConnection = new WebsocketClient(new Uri(url), (Func<ClientWebSocket>)null); wsConnection.IsReconnectionEnabled = false; wsConnection.ReconnectTimeout = null; wsConnection.ErrorReconnectTimeout = null; ObservableExtensions.Subscribe<ResponseMessage>(wsConnection.MessageReceived, (Action<ResponseMessage>)delegate(ResponseMessage m) { Task.Run(delegate { WebsocketMessageHandler(this, m); }); }); ObservableExtensions.Subscribe<DisconnectionInfo>(wsConnection.DisconnectionHappened, (Action<DisconnectionInfo>)delegate(DisconnectionInfo d) { Task.Run(delegate { OnWebsocketDisconnect(this, d); }); }); connectionPassword = password; wsConnection.StartOrFail(); } public void Disconnect() { connectionPassword = null; if (wsConnection != null) { try { wsConnection.Stop(WebSocketCloseStatus.NormalClosure, "User requested disconnect"); ((IDisposable)wsConnection).Dispose(); } catch { } wsConnection = null; } KeyValuePair<string, TaskCompletionSource<JObject>>[] array = responseHandlers.ToArray(); responseHandlers.Clear(); KeyValuePair<string, TaskCompletionSource<JObject>>[] array2 = array; foreach (KeyValuePair<string, TaskCompletionSource<JObject>> keyValuePair in array2) { keyValuePair.Value.TrySetCanceled(); } } private void OnWebsocketDisconnect(object sender, DisconnectionInfo d) { if (d == null || !d.CloseStatus.HasValue) { this.Disconnected?.Invoke(sender, new ObsDisconnectionInfo(ObsCloseCodes.UnknownReason, null, d)); } else { this.Disconnected?.Invoke(sender, new ObsDisconnectionInfo((ObsCloseCodes)d.CloseStatus.Value, d.CloseStatusDescription, d)); } } private void WebsocketMessageHandler(object sender, ResponseMessage e) { if (e.MessageType != 0) { return; } ServerMessage serverMessage = JsonConvert.DeserializeObject<ServerMessage>(e.Text); JObject body = serverMessage.Data; switch (serverMessage.OperationCode) { case MessageTypes.Hello: HandleHello(body); break; case MessageTypes.Identified: Task.Run(delegate { this.Connected?.Invoke(this, EventArgs.Empty); }); break; case MessageTypes.RequestResponse: case MessageTypes.RequestBatchResponse: if (body.ContainsKey("requestId")) { string key = (string)body["requestId"]; if (responseHandlers.TryRemove(key, out var value)) { value.SetResult(body); } } break; case MessageTypes.Event: { string eventType = ((object)body["eventType"]).ToString(); Task.Run(delegate { ProcessEventType(eventType, body); }); break; } } } public JObject SendRequest(string requestType, JObject additionalFields = null) { return SendRequest(MessageTypes.Request, requestType, additionalFields); } internal JObject SendRequest(MessageTypes operationCode, string requestType, JObject additionalFields = null, bool waitForReply = true) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown if (wsConnection == null) { throw new NullReferenceException("Websocket is not initialized"); } TaskCompletionSource<JObject> taskCompletionSource = new TaskCompletionSource<JObject>(); JObject val = null; string messageId; do { val = MessageFactory.BuildMessage(operationCode, requestType, additionalFields, out messageId); } while (waitForReply && !responseHandlers.TryAdd(messageId, taskCompletionSource)); wsConnection.Send(((object)val).ToString()); if (!waitForReply) { return null; } taskCompletionSource.Task.Wait(wsTimeout.Milliseconds); if (taskCompletionSource.Task.IsCanceled) { throw new ErrorResponseException("Request canceled", 0); } JObject result = taskCompletionSource.Task.Result; if (!(bool)result["requestStatus"][(object)"result"]) { JObject val2 = (JObject)result["requestStatus"]; throw new ErrorResponseException(string.Format("ErrorCode: {0}{1}", val2["code"], val2.ContainsKey("comment") ? string.Format(", Comment: {0}", val2["comment"]) : ""), (int)val2["code"]); } if (result.ContainsKey("responseData")) { return result["responseData"].ToObject<JObject>(); } return new JObject(); } public OBSAuthInfo GetAuthInfo() { return new OBSAuthInfo(SendRequest("GetAuthRequired")); } protected void SendIdentify(string password, OBSAuthInfo authInfo = null) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("rpcVersion", JToken.op_Implicit(1)); JObject val2 = val; if (authInfo != null) { string text = HashEncode(password + authInfo.PasswordSalt); string text2 = HashEncode(text + authInfo.Challenge); val2.Add("authentication", JToken.op_Implicit(text2)); } SendRequest(MessageTypes.Identify, null, val2, waitForReply: false); } protected string HashEncode(string input) { using SHA256Managed sHA256Managed = new SHA256Managed(); byte[] bytes = Encoding.ASCII.GetBytes(input); return Convert.ToBase64String(sHA256Managed.ComputeHash(bytes)); } protected string NewMessageID(int length = 16) { string text = ""; for (int i = 0; i < length; i++) { int index = random.Next(0, "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".Length - 1); text += "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[index]; } return text; } private void HandleHello(JObject payload) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown if (wsConnection.IsStarted) { OBSAuthInfo authInfo = null; if (payload.ContainsKey("authentication")) { authInfo = new OBSAuthInfo((JObject)payload["authentication"]); } SendIdentify(connectionPassword, authInfo); connectionPassword = null; } } public ObsVideoSettings GetVideoSettings() { return JsonConvert.DeserializeObject<ObsVideoSettings>(((object)SendRequest("GetVideoSettings")).ToString()); } public string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("imageFormat", JToken.op_Implicit(imageFormat)); val.Add("imageFilePath", JToken.op_Implicit(imageFilePath)); JObject val2 = val; if (imageWidth > -1) { val2.Add("imageWidth", JToken.op_Implicit(imageWidth)); } if (imageHeight > -1) { val2.Add("imageHeight", JToken.op_Implicit(imageHeight)); } if (imageCompressionQuality > -1) { val2.Add("imageCompressionQuality", JToken.op_Implicit(imageCompressionQuality)); } return (string)SendRequest("SaveSourceScreenshot", val2)["imageData"]; } public string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath) { return SaveSourceScreenshot(sourceName, imageFormat, imageFilePath, -1, -1, -1); } public void TriggerHotkeyByName(string hotkeyName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("hotkeyName", JToken.op_Implicit(hotkeyName)); JObject additionalFields = val; SendRequest("TriggerHotkeyByName", additionalFields); } public void TriggerHotkeyByKeySequence(OBSHotkey keyId, KeyModifier keyModifier = KeyModifier.None) { //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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_008b: Expected O, but got Unknown JObject val = new JObject(); val.Add("keyId", JToken.op_Implicit(keyId.ToString())); JObject val2 = new JObject(); val2.Add("shift", JToken.op_Implicit((keyModifier & KeyModifier.Shift) == KeyModifier.Shift)); val2.Add("alt", JToken.op_Implicit((keyModifier & KeyModifier.Alt) == KeyModifier.Alt)); val2.Add("control", JToken.op_Implicit((keyModifier & KeyModifier.Control) == KeyModifier.Control)); val2.Add("command", JToken.op_Implicit((keyModifier & KeyModifier.Command) == KeyModifier.Command)); val.Add("keyModifiers", (JToken)val2); JObject additionalFields = val; SendRequest("TriggerHotkeyByKeySequence", additionalFields); } public string GetCurrentProgramScene() { return (string)SendRequest("GetCurrentProgramScene")["currentProgramSceneName"]; } public void SetCurrentProgramScene(string sceneName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); JObject additionalFields = val; SendRequest("SetCurrentProgramScene", additionalFields); } public ObsStats GetStats() { return JsonConvert.DeserializeObject<ObsStats>(((object)SendRequest("GetStats")).ToString()); } public List<SceneBasicInfo> ListScenes() { return GetSceneList().Scenes; } public GetSceneListInfo GetSceneList() { return JsonConvert.DeserializeObject<GetSceneListInfo>(((object)SendRequest("GetSceneList")).ToString()); } public TransitionOverrideInfo GetSceneSceneTransitionOverride(string sceneName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); JObject additionalFields = val; return ((JToken)SendRequest("GetSceneSceneTransitionOverride", additionalFields)).ToObject<TransitionOverrideInfo>(); } public void SetSceneSceneTransitionOverride(string sceneName, string transitionName, int transitionDuration = -1) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("transitionName", JToken.op_Implicit(transitionName)); JObject val2 = val; if (transitionDuration >= 0) { val2.Add("transitionDuration", JToken.op_Implicit(transitionDuration)); } SendRequest("SetSceneSceneTransitionOverride", val2); } public void SetTBarPosition(double position, bool release = true) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_004b: Expected O, but got Unknown if (position < 0.0 || position > 1.0) { throw new ArgumentOutOfRangeException("position"); } JObject val = new JObject(); val.Add("position", JToken.op_Implicit(position)); val.Add("release", JToken.op_Implicit(release)); JObject additionalFields = val; SendRequest("SetTBarPosition", additionalFields); } public void SetSourceFilterSettings(string sourceName, string filterName, JObject filterSettings, bool overlay = false) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("filterName", JToken.op_Implicit(filterName)); val.Add("filterSettings", (JToken)(object)filterSettings); val.Add("overlay", JToken.op_Implicit(overlay)); JObject additionalFields = val; SendRequest("SetSourceFilterSettings", additionalFields); } public void SetSourceFilterSettings(string sourceName, string filterName, FilterSettings filterSettings, bool overlay = false) { SetSourceFilterSettings(sourceName, filterName, JObject.FromObject((object)filterSettings), overlay); } public void SetSourceFilterEnabled(string sourceName, string filterName, bool filterEnabled) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("filterName", JToken.op_Implicit(filterName)); val.Add("filterEnabled", JToken.op_Implicit(filterEnabled)); JObject additionalFields = val; SendRequest("SetSourceFilterEnabled", additionalFields); } public List<FilterSettings> GetSourceFilterList(string sourceName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); JObject additionalFields = val; JObject val2 = SendRequest("GetSourceFilterList", additionalFields); if (!((JToken)val2).HasValues) { return new List<FilterSettings>(); } return JsonConvert.DeserializeObject<List<FilterSettings>>(((object)val2["filters"]).ToString()); } public FilterSettings GetSourceFilter(string sourceName, string filterName) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("filterName", JToken.op_Implicit(filterName)); JObject additionalFields = val; return JsonConvert.DeserializeObject<FilterSettings>(((object)SendRequest("GetSourceFilter", additionalFields)).ToString()); } public bool RemoveSourceFilter(string sourceName, string filterName) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("filterName", JToken.op_Implicit(filterName)); JObject additionalFields = val; try { SendRequest("RemoveSourceFilter", additionalFields); return true; } catch (Exception ex) { Console.WriteLine(ex.Message); } return false; } public void CreateSourceFilter(string sourceName, string filterName, string filterKind, JObject filterSettings) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("filterName", JToken.op_Implicit(filterName)); val.Add("filterKind", JToken.op_Implicit(filterKind)); val.Add("filterSettings", (JToken)(object)filterSettings); JObject additionalFields = val; SendRequest("CreateSourceFilter", additionalFields); } public void CreateSourceFilter(string sourceName, string filterName, string filterKind, FilterSettings filterSettings) { CreateSourceFilter(sourceName, filterName, filterKind, JObject.FromObject((object)filterSettings)); } public bool ToggleStream() { return (bool)SendRequest("ToggleStream")["outputActive"]; } public void ToggleRecord() { SendRequest("ToggleRecord"); } public OutputStatus GetStreamStatus() { return new OutputStatus(SendRequest("GetStreamStatus")); } public TransitionSettings GetCurrentSceneTransition() { return new TransitionSettings(SendRequest("GetCurrentSceneTransition")); } public void SetCurrentSceneTransition(string transitionName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("transitionName", JToken.op_Implicit(transitionName)); JObject additionalFields = val; SendRequest("SetCurrentSceneTransition", additionalFields); } public void SetCurrentSceneTransitionDuration(int transitionDuration) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("transitionDuration", JToken.op_Implicit(transitionDuration)); JObject additionalFields = val; SendRequest("SetCurrentSceneTransitionDuration", additionalFields); } public void SetCurrentSceneTransitionSettings(JObject transitionSettings, bool overlay) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("transitionSettings", JToken.FromObject((object)transitionSettings)); val.Add("overlay", JToken.op_Implicit(overlay)); JObject additionalFields = val; SendRequest("SetCurrentSceneTransitionSettings", additionalFields); } public void SetInputVolume(string inputName, float inputVolume, bool inputVolumeDb = false) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject val2 = val; if (inputVolumeDb) { val2.Add("inputVolumeDb", JToken.op_Implicit(inputVolume)); } else { val2.Add("inputVolumeMul", JToken.op_Implicit(inputVolume)); } SendRequest("SetInputVolume", val2); } public VolumeInfo GetInputVolume(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; return new VolumeInfo(SendRequest("GetInputVolume", additionalFields)); } public bool GetInputMute(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; return (bool)SendRequest("GetInputMute", additionalFields)["inputMuted"]; } public void SetInputMute(string inputName, bool inputMuted) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("inputMuted", JToken.op_Implicit(inputMuted)); JObject additionalFields = val; SendRequest("SetInputMute", additionalFields); } public void ToggleInputMute(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; SendRequest("ToggleInputMute", additionalFields); } public void SetSceneItemTransform(string sceneName, int sceneItemId, JObject sceneItemTransform) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); val.Add("sceneItemTransform", (JToken)(object)sceneItemTransform); JObject additionalFields = val; SendRequest("SetSceneItemTransform", additionalFields); } public void SetSceneItemTransform(string sceneName, int sceneItemId, SceneItemTransformInfo sceneItemTransform) { SetSceneItemTransform(sceneName, sceneItemId, JObject.FromObject((object)sceneItemTransform)); } public void SetCurrentSceneCollection(string sceneCollectionName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneCollectionName", JToken.op_Implicit(sceneCollectionName)); JObject additionalFields = val; SendRequest("SetCurrentSceneCollection", additionalFields); } public string GetCurrentSceneCollection() { return (string)SendRequest("GetSceneCollectionList")["currentSceneCollectionName"]; } public List<string> GetSceneCollectionList() { return JsonConvert.DeserializeObject<List<string>>(((object)SendRequest("GetSceneCollectionList")["sceneCollections"]).ToString()); } public void SetCurrentProfile(string profileName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("profileName", JToken.op_Implicit(profileName)); JObject additionalFields = val; SendRequest("SetCurrentProfile", additionalFields); } public GetProfileListInfo GetProfileList() { return JsonConvert.DeserializeObject<GetProfileListInfo>(((object)SendRequest("GetProfileList")).ToString()); } public void StartStream() { SendRequest("StartStream"); } public void StopStream() { SendRequest("StopStream"); } public void StartRecord() { SendRequest("StartRecord"); } public string StopRecord() { return (string)SendRequest("StopRecord")["outputPath"]; } public void PauseRecord() { SendRequest("PauseRecord"); } public void ResumeRecord() { SendRequest("ResumeRecord"); } public string GetRecordDirectory() { return (string)SendRequest("GetRecordDirectory")["recordDirectory"]; } public RecordingStatus GetRecordStatus() { return JsonConvert.DeserializeObject<RecordingStatus>(((object)SendRequest("GetRecordStatus")).ToString()); } public bool GetReplayBufferStatus() { return (bool)SendRequest("GetReplayBufferStatus")["outputActive"]; } public GetTransitionListInfo GetSceneTransitionList() { return JsonConvert.DeserializeObject<GetTransitionListInfo>(((object)SendRequest("GetSceneTransitionList")).ToString()); } public bool GetStudioModeEnabled() { return (bool)SendRequest("GetStudioModeEnabled")["studioModeEnabled"]; } public void SetStudioModeEnabled(bool studioModeEnabled) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("studioModeEnabled", JToken.op_Implicit(studioModeEnabled)); JObject additionalFields = val; SendRequest("SetStudioModeEnabled", additionalFields); } public string GetCurrentPreviewScene() { return (string)SendRequest("GetCurrentPreviewScene")["currentPreviewSceneName"]; } public void SetCurrentPreviewScene(string sceneName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); JObject additionalFields = val; SendRequest("SetCurrentPreviewScene", additionalFields); } public void SetCurrentPreviewScene(ObsScene previewScene) { SetCurrentPreviewScene(previewScene.Name); } public void TriggerStudioModeTransition() { SendRequest("TriggerStudioModeTransition"); } public void ToggleReplayBuffer() { SendRequest("ToggleReplayBuffer"); } public void StartReplayBuffer() { SendRequest("StartReplayBuffer"); } public void StopReplayBuffer() { SendRequest("StopReplayBuffer"); } public void SaveReplayBuffer() { SendRequest("SaveReplayBuffer"); } public void SetInputAudioSyncOffset(string inputName, int inputAudioSyncOffset) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("inputAudioSyncOffset", JToken.op_Implicit(inputAudioSyncOffset)); JObject additionalFields = val; SendRequest("SetInputAudioSyncOffset", additionalFields); } public int GetInputAudioSyncOffset(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; return (int)SendRequest("GetInputAudioSyncOffset", additionalFields)["inputAudioSyncOffset"]; } public void RemoveSceneItem(string sceneName, int sceneItemId) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); JObject additionalFields = val; SendRequest("RemoveSceneItem", additionalFields); } public void SendStreamCaption(string captionText) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("captionText", JToken.op_Implicit(captionText)); JObject additionalFields = val; SendRequest("SendStreamCaption", additionalFields); } public void DuplicateSceneItem(string sceneName, int sceneItemId, string destinationSceneName = null) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); JObject val2 = val; if (!string.IsNullOrEmpty(destinationSceneName)) { val2.Add("destinationSceneName", JToken.op_Implicit(destinationSceneName)); } SendRequest("DuplicateSceneItem", val2); } public Dictionary<string, string> GetSpecialInputs() { JObject obj = SendRequest("GetSpecialInputs"); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (KeyValuePair<string, JToken> item in obj) { string key = item.Key; string value = (string)item.Value; if (key != "requestType") { dictionary.Add(key, value); } } return dictionary; } public void SetStreamServiceSettings(StreamingService service) { //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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown JObject val = new JObject(); val.Add("streamServiceType", JToken.op_Implicit(service.Type)); val.Add("streamServiceSettings", JToken.FromObject((object)service.Settings)); JObject additionalFields = val; SendRequest("SetStreamServiceSettings", additionalFields); } public StreamingService GetStreamServiceSettings() { return JsonConvert.DeserializeObject<StreamingService>(((object)SendRequest("GetStreamServiceSettings")).ToString()); } public string GetInputAudioMonitorType(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; return (string)SendRequest("GetInputAudioMonitorType", additionalFields)["monitorType"]; } public void SetInputAudioMonitorType(string inputName, string monitorType) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("monitorType", JToken.op_Implicit(monitorType)); JObject additionalFields = val; SendRequest("SetInputAudioMonitorType", additionalFields); } public void BroadcastCustomEvent(JObject eventData) { //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_0012: Expected O, but got Unknown JObject val = new JObject(); val.Add("eventData", (JToken)(object)eventData); JObject additionalFields = val; SendRequest("BroadcastCustomEvent", additionalFields); } public void SetMediaInputCursor(string inputName, int mediaCursor) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("mediaCursor", JToken.op_Implicit(mediaCursor)); JObject additionalFields = val; SendRequest("SetMediaInputCursor", additionalFields); } public void OffsetMediaInputCursor(string inputName, int mediaCursorOffset) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("mediaCursorOffset", JToken.op_Implicit(mediaCursorOffset)); JObject additionalFields = val; SendRequest("OffsetMediaInputCursor", additionalFields); } public int CreateInput(string sceneName, string inputName, string inputKind, JObject inputSettings, bool? sceneItemEnabled) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("inputKind", JToken.op_Implicit(inputKind)); JObject val2 = val; if (inputSettings != null) { val2.Add("inputSettings", (JToken)(object)inputSettings); } if (sceneItemEnabled.HasValue) { val2.Add("sceneItemEnabled", JToken.op_Implicit(sceneItemEnabled.Value)); } return (int)SendRequest("CreateInput", val2)["sceneItemId"]; } public JObject GetInputDefaultSettings(string inputKind) { //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_0017: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputKind", JToken.op_Implicit(inputKind)); JObject additionalFields = val; return (JObject)SendRequest("GetInputDefaultSettings", additionalFields)["defaultInputSettings"]; } public List<SceneItemDetails> GetSceneItemList(string sceneName) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown JObject additionalFields = null; if (!string.IsNullOrEmpty(sceneName)) { JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); additionalFields = val; } return ((IEnumerable<JToken>)SendRequest("GetSceneItemList", additionalFields)["sceneItems"]).Select((JToken m) => new SceneItemDetails((JObject)m)).ToList(); } public int CreateSceneItem(string sceneName, string sourceName, bool sceneItemEnabled = true) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("sceneItemEnabled", JToken.op_Implicit(sceneItemEnabled)); JObject additionalFields = val; return (int)SendRequest("CreateSceneItem", additionalFields)["sceneItemId"]; } public void CreateScene(string sceneName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); JObject additionalFields = val; SendRequest("CreateScene", additionalFields); } public SourceTracks GetInputAudioTracks(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; return new SourceTracks(SendRequest("GetInputAudioTracks", additionalFields)); } public void SetInputAudioTracks(string inputName, JObject inputAudioTracks) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("inputAudioTracks", (JToken)(object)inputAudioTracks); JObject additionalFields = val; SendRequest("SetInputAudioTracks", additionalFields); } public void SetInputAudioTracks(string inputName, SourceTracks inputAudioTracks) { SetInputAudioTracks(inputName, JObject.FromObject((object)inputAudioTracks)); } public SourceActiveInfo GetSourceActive(string sourceName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); JObject additionalFields = val; return new SourceActiveInfo(SendRequest("GetSourceActive", additionalFields)); } public VirtualCamStatus GetVirtualCamStatus() { return new VirtualCamStatus(SendRequest("GetVirtualCamStatus")); } public void StartVirtualCam() { SendRequest("StartVirtualCam"); } public void StopVirtualCam() { SendRequest("StopVirtualCam"); } public VirtualCamStatus ToggleVirtualCam() { return new VirtualCamStatus(SendRequest("ToggleVirtualCam")); } public JObject GetPersistentData(string realm, string slotName) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("realm", JToken.op_Implicit(realm)); val.Add("slotName", JToken.op_Implicit(slotName)); JObject additionalFields = val; return SendRequest("GetPersistentData", additionalFields); } public void SetPersistentData(string realm, string slotName, JObject slotValue) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown JObject val = new JObject(); val.Add("realm", JToken.op_Implicit(realm)); val.Add("slotName", JToken.op_Implicit(slotName)); val.Add("slotValue", (JToken)(object)slotValue); JObject additionalFields = val; SendRequest("SetPersistentData", additionalFields); } public void CreateSceneCollection(string sceneCollectionName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneCollectionName", JToken.op_Implicit(sceneCollectionName)); JObject additionalFields = val; SendRequest("CreateSceneCollection", additionalFields); } public void CreateProfile(string profileName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("profileName", JToken.op_Implicit(profileName)); JObject additionalFields = val; SendRequest("CreateProfile", additionalFields); } public void RemoveProfile(string profileName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("profileName", JToken.op_Implicit(profileName)); JObject additionalFields = val; SendRequest("RemoveProfile", additionalFields); } public JObject GetProfileParameter(string parameterCategory, string parameterName) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("parameterCategory", JToken.op_Implicit(parameterCategory)); val.Add("parameterName", JToken.op_Implicit(parameterName)); JObject additionalFields = val; return SendRequest("GetProfileParameter", additionalFields); } public void SetProfileParameter(string parameterCategory, string parameterName, string parameterValue) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("parameterCategory", JToken.op_Implicit(parameterCategory)); val.Add("parameterName", JToken.op_Implicit(parameterName)); val.Add("parameterValue", JToken.op_Implicit(parameterValue)); JObject additionalFields = val; SendRequest("SetProfileParameter", additionalFields); } public void SetVideoSettings(ObsVideoSettings obsVideoSettings) { SendRequest("SetVideoSettings", JObject.FromObject((object)obsVideoSettings)); } public JObject GetSourceFilterDefaultSettings(string filterKind) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("filterKind", JToken.op_Implicit(filterKind)); JObject additionalFields = val; return SendRequest("GetSourceFilterDefaultSettings", additionalFields); } public void SetSourceFilterName(string sourceName, string filterName, string newFilterName) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("filterName", JToken.op_Implicit(filterName)); val.Add("newFilterName", JToken.op_Implicit(newFilterName)); JObject additionalFields = val; SendRequest("SetSourceFilterName", additionalFields); } public void SetSourceFilterIndex(string sourceName, string filterName, int filterIndex) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("filterName", JToken.op_Implicit(filterName)); val.Add("filterIndex", JToken.op_Implicit(filterIndex)); JObject additionalFields = val; SendRequest("SetSourceFilterIndex", additionalFields); } public ObsVersion GetVersion() { return new ObsVersion(SendRequest("GetVersion")); } public JObject CallVendorRequest(string vendorName, string requestType, JObject requestData = null) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown JObject val = new JObject(); val.Add("vendorName", JToken.op_Implicit(vendorName)); val.Add("requestType", JToken.op_Implicit(requestType)); val.Add("requestData", (JToken)(object)requestData); JObject additionalFields = val; return SendRequest("CallVendorRequest", additionalFields); } public List<string> GetHotkeyList() { return JsonConvert.DeserializeObject<List<string>>(((object)SendRequest("GetHotkeyList")["hotkeys"]).ToString()); } public void Sleep(int sleepMillis, int sleepFrames) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sleepMillis", JToken.op_Implicit(sleepMillis)); val.Add("sleepFrames", JToken.op_Implicit(sleepFrames)); JObject additionalFields = val; SendRequest("Sleep", additionalFields); } public List<InputBasicInfo> GetInputList(string inputKind = null) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputKind", JToken.op_Implicit(inputKind)); JObject additionalFields = val; JObject obj = ((inputKind == null) ? SendRequest("GetInputList") : SendRequest("GetInputList", additionalFields)); List<InputBasicInfo> list = new List<InputBasicInfo>(); foreach (JToken item in (IEnumerable<JToken>)obj["inputs"]) { list.Add(new InputBasicInfo((JObject)(object)((item is JObject) ? item : null))); } return list; } public List<string> GetInputKindList(bool unversioned = false) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("unversioned", JToken.op_Implicit(unversioned)); JObject additionalFields = val; return JsonConvert.DeserializeObject<List<string>>(((object)((!unversioned) ? SendRequest("GetInputKindList") : SendRequest("GetInputKindList", additionalFields))["inputKinds"]).ToString()); } public void RemoveInput(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; SendRequest("RemoveInput", additionalFields); } public void SetInputName(string inputName, string newInputName) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("newInputName", JToken.op_Implicit(newInputName)); JObject additionalFields = val; SendRequest("SetInputName", additionalFields); } public InputSettings GetInputSettings(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject val2 = val; JObject obj = SendRequest("GetInputSettings", val2); ((JContainer)obj).Merge((object)val2); return new InputSettings(obj); } public void SetInputSettings(InputSettings inputSettings, bool overlay = true) { SetInputSettings(inputSettings.InputName, inputSettings.Settings, overlay); } public void SetInputSettings(string inputName, JObject inputSettings, bool overlay = true) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("inputSettings", (JToken)(object)inputSettings); val.Add("overlay", JToken.op_Implicit(overlay)); JObject additionalFields = val; SendRequest("SetInputSettings", additionalFields); } public double GetInputAudioBalance(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; return (double)SendRequest("GetInputAudioBalance", additionalFields)["inputAudioBalance"]; } public void SetInputAudioBalance(string inputName, double inputAudioBalance) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("inputAudioBalance", JToken.op_Implicit(inputAudioBalance)); JObject additionalFields = val; SendRequest("SetInputAudioBalance", additionalFields); } public List<JObject> GetInputPropertiesListPropertyItems(string inputName, string propertyName) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("propertyName", JToken.op_Implicit(propertyName)); JObject additionalFields = val; return Extensions.Value<List<JObject>>((IEnumerable<JToken>)SendRequest("GetInputPropertiesListPropertyItems", additionalFields)["propertyItems"]); } public void PressInputPropertiesButton(string inputName, string propertyName) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("propertyName", JToken.op_Implicit(propertyName)); JObject additionalFields = val; SendRequest("PressInputPropertiesButton", additionalFields); } public MediaInputStatus GetMediaInputStatus(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; return new MediaInputStatus(SendRequest("GetMediaInputStatus", additionalFields)); } public void TriggerMediaInputAction(string inputName, string mediaAction) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); val.Add("mediaAction", JToken.op_Implicit(mediaAction)); JObject additionalFields = val; SendRequest("TriggerMediaInputAction", additionalFields); } public string GetLastReplayBufferReplay() { return (string)SendRequest("GetLastReplayBufferReplay")["savedReplayPath"]; } public void ToggleRecordPause() { SendRequest("ToggleRecordPause"); } public List<JObject> GetGroupSceneItemList(string sceneName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); JObject additionalFields = val; return JsonConvert.DeserializeObject<List<JObject>>((string)SendRequest("GetGroupSceneItemList", additionalFields)["sceneItems"]); } public int GetSceneItemId(string sceneName, string sourceName, int searchOffset) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("searchOffset", JToken.op_Implicit(searchOffset)); JObject additionalFields = val; return (int)SendRequest("GetSceneItemId", additionalFields)["sceneItemId"]; } public SceneItemTransformInfo GetSceneItemTransform(string sceneName, int sceneItemId) { return JsonConvert.DeserializeObject<SceneItemTransformInfo>(((object)GetSceneItemTransformRaw(sceneName, sceneItemId)["sceneItemTransform"]).ToString()); } public JObject GetSceneItemTransformRaw(string sceneName, int sceneItemId) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); JObject additionalFields = val; return SendRequest("GetSceneItemTransform", additionalFields); } public bool GetSceneItemEnabled(string sceneName, int sceneItemId) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); JObject additionalFields = val; return (bool)SendRequest("GetSceneItemEnabled", additionalFields)["sceneItemEnabled"]; } public void SetSceneItemEnabled(string sceneName, int sceneItemId, bool sceneItemEnabled) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); val.Add("sceneItemEnabled", JToken.op_Implicit(sceneItemEnabled)); JObject additionalFields = val; SendRequest("SetSceneItemEnabled", additionalFields); } public bool GetSceneItemLocked(string sceneName, int sceneItemId) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); JObject additionalFields = val; return (bool)SendRequest("GetSceneItemLocked", additionalFields)["sceneItemLocked"]; } public void SetSceneItemLocked(string sceneName, int sceneItemId, bool sceneItemLocked) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); val.Add("sceneItemLocked", JToken.op_Implicit(sceneItemLocked)); JObject additionalFields = val; SendRequest("SetSceneItemLocked", additionalFields); } public int GetSceneItemIndex(string sceneName, int sceneItemId) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); JObject additionalFields = val; return (int)SendRequest("GetSceneItemIndex", additionalFields)["sceneItemIndex"]; } public void SetSceneItemIndex(string sceneName, int sceneItemId, int sceneItemIndex) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); val.Add("sceneItemIndex", JToken.op_Implicit(sceneItemIndex)); JObject additionalFields = val; SendRequest("SetSceneItemIndex", additionalFields); } public string GetSceneItemBlendMode(string sceneName, int sceneItemId) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); JObject additionalFields = val; return (string)SendRequest("GetSceneItemBlendMode", additionalFields)["sceneItemBlendMode"]; } public void SetSceneItemBlendMode(string sceneName, int sceneItemId, string sceneItemBlendMode) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("sceneItemId", JToken.op_Implicit(sceneItemId)); val.Add("sceneItemBlendMode", JToken.op_Implicit(sceneItemBlendMode)); JObject additionalFields = val; SendRequest("SetSceneItemBlendMode", additionalFields); } public List<string> GetGroupList() { return JsonConvert.DeserializeObject<List<string>>(((object)SendRequest("GetGroupList")["groups"]).ToString()); } public void RemoveScene(string sceneName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); JObject additionalFields = val; SendRequest("RemoveScene", additionalFields); } public void SetSceneName(string sceneName, string newSceneName) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sceneName", JToken.op_Implicit(sceneName)); val.Add("newSceneName", JToken.op_Implicit(newSceneName)); JObject additionalFields = val; SendRequest("SetSceneName", additionalFields); } public string GetSourceScreenshot(string sourceName, string imageFormat, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("imageFormat", JToken.op_Implicit(imageFormat)); JObject val2 = val; if (imageWidth > -1) { val2.Add("imageWidth", JToken.op_Implicit(imageWidth)); } if (imageHeight > -1) { val2.Add("imageHeight", JToken.op_Implicit(imageHeight)); } if (imageCompressionQuality > -1) { val2.Add("imageCompressionQuality", JToken.op_Implicit(imageCompressionQuality)); } return (string)SendRequest("GetSourceScreenshot", val2)["imageData"]; } public List<string> GetTransitionKindList() { return JsonConvert.DeserializeObject<List<string>>(((object)SendRequest("GetTransitionKindList")["transitionKinds"]).ToString()); } public double GetCurrentSceneTransitionCursor() { return (double)SendRequest("GetCurrentSceneTransitionCursor")["transitionCursor"]; } public void OpenInputPropertiesDialog(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; SendRequest("OpenInputPropertiesDialog", additionalFields); } public void OpenInputFiltersDialog(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; SendRequest("OpenInputFiltersDialog", additionalFields); } public void OpenInputInteractDialog(string inputName) { //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_0017: Expected O, but got Unknown JObject val = new JObject(); val.Add("inputName", JToken.op_Implicit(inputName)); JObject additionalFields = val; SendRequest("OpenInputInteractDialog", additionalFields); } public List<Monitor> GetMonitorList() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown JObject obj = SendRequest("GetMonitorList"); List<Monitor> list = new List<Monitor>(); foreach (JToken item in (IEnumerable<JToken>)obj["monitors"]) { list.Add(new Monitor((JObject)item)); } return list; } public void OpenSourceProjector(string sourceName, string projectorGeometry, int monitorIndex = -1) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("sourceName", JToken.op_Implicit(sourceName)); val.Add("projectorGeometry", JToken.op_Implicit(projectorGeometry)); val.Add("monitorIndex", JToken.op_Implicit(monitorIndex)); JObject additionalFields = val; SendRequest("OpenSourceProjector", additionalFields); } public void OpenVideoMixProjector(string videoMixType, string projectorGeometry, int monitorIndex = -1) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown JObject val = new JObject(); val.Add("videoMixType", JToken.op_Implicit(videoMixType)); val.Add("projectorGeometry", JToken.op_Implicit(projectorGeometry)); val.Add("monitorIndex", JToken.op_Implicit(monitorIndex)); JObject additionalFields = val; SendRequest("OpenVideoMixProjector", additionalFields); } } public class AuthFailureException : Exception { } public class ErrorResponseException : Exception { public int ErrorCode { get; set; } public ErrorResponseException(string message, int errorCode) : base(message) { ErrorCode = errorCode; } } public interface IOBSWebsocket { TimeSpan WSTimeout { get; set; } bool IsConnected { get; } event EventHandler<ProgramSceneChangedEventArgs> CurrentProgramSceneChanged; event EventHandler<SceneListChangedEventArgs> SceneListChanged; event EventHandler<SceneItemListReindexedEventArgs> SceneItemListReindexed; event EventHandler<SceneItemCreatedEventArgs> SceneItemCreated; event EventHandler<SceneItemRemovedEventArgs> SceneItemRemoved; event EventHandler<SceneItemEnableStateChangedEventArgs> SceneItemEnableStateChanged; event EventHandler<SceneItemLockStateChangedEventArgs> SceneItemLockStateChanged; event EventHandler<CurrentSceneCollectionChangedEventArgs> CurrentSceneCollectionChanged; event EventHandler<SceneCollectionListChangedEventArgs> SceneCollectionListChanged; event EventHandler<CurrentSceneTransitionChangedEventArgs> CurrentSceneTransitionChanged; event EventHandler<CurrentSceneTransitionDurationChangedEventArgs> CurrentSceneTransitionDurationChanged; event EventHandler<SceneTransitionStartedEventArgs> SceneTransitionStarted; event EventHandler<SceneTransitionEndedEventArgs> SceneTransitionEnded; event EventHandler<SceneTransitionVideoEndedEventArgs> SceneTransitionVideoEnded; event EventHandler<CurrentProfileChangedEventArgs> CurrentProfileChanged; event EventHandler<ProfileListChangedEventArgs> ProfileListChanged; event EventHandler<StreamStateChangedEventArgs> StreamStateChanged; event EventHandler<RecordStateChangedEventArgs> RecordStateChanged; event EventHandler<ReplayBufferStateChangedEventArgs> ReplayBufferStateChanged; event EventHandler<CurrentPreviewSceneChangedEventArgs> CurrentPreviewSceneChanged; event EventHandler<StudioModeStateChangedEventArgs> StudioModeStateChanged; event EventHandler ExitStarted; event EventHandler Connected; event EventHandler<ObsDisconnectionInfo> Disconnected; event EventHandler<SceneItemSelectedEventArgs> SceneItemSelected; event EventHandler<SceneItemTransformEventArgs> SceneItemTransformChanged; event EventHandler<InputAudioSyncOffsetChangedEventArgs> InputAudioSyncOffsetChanged; event EventHandler<SourceFilterCreatedEventArgs> SourceFilterCreated; event EventHandler<SourceFilterRemovedEventArgs> SourceFilterRemoved; event EventHandler<SourceFilterListReindexedEventArgs> SourceFilterListReindexed; event EventHandler<SourceFilterEnableStateChangedEventArgs> SourceFilterEnableStateChanged; event EventHandler<InputMuteStateChangedEventArgs> InputMuteStateChanged; event EventHandler<InputVolumeChangedEventArgs> InputVolumeChanged; event EventHandler<VendorEventArgs> VendorEvent; event EventHandler<MediaInputPlaybackEndedEventArgs> MediaInputPlaybackEnded; event EventHandler<MediaInputPlaybackStartedEventArgs> MediaInputPlaybackStarted; event EventHandler<MediaInputActionTriggeredEventArgs> MediaInputActionTriggered; event EventHandler<VirtualcamStateChangedEventArgs> VirtualcamStateChanged; event EventHandler<CurrentSceneCollectionChangingEventArgs> CurrentSceneCollectionChanging; event EventHandler<CurrentProfileChangingEventArgs> CurrentProfileChanging; event EventHandler<SourceFilterNameChangedEventArgs> SourceFilterNameChanged; event EventHandler<InputCreatedEventArgs> InputCreated; event EventHandler<InputRemovedEventArgs> InputRemoved; event EventHandler<InputNameChangedEventArgs> InputNameChanged; event EventHandler<InputActiveStateChangedEventArgs> InputActiveStateChanged; event EventHandler<InputShowStateChangedEventArgs> InputShowStateChanged; event EventHandler<InputAudioBalanceChangedEventArgs> InputAudioBalanceChanged; event EventHandler<InputAudioTracksChangedEventArgs> InputAudioTracksChanged; event EventHandler<InputAudioMonitorTypeChangedEventArgs> InputAudioMonitorTypeChanged; event EventHandler<InputVolumeMetersEventArgs> InputVolumeMeters; event EventHandler<ReplayBufferSavedEventArgs> ReplayBufferSaved; event EventHandler<SceneCreatedEventArgs> SceneCreated; event EventHandler<SceneRemovedEventArgs> SceneRemoved; event EventHandler<SceneNameChangedEventArgs> SceneNameChanged; ObsVideoSettings GetVideoSettings(); string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1); string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath); void TriggerHotkeyByName(string hotkeyName); void TriggerHotkeyByKeySequence(OBSHotkey keyId, KeyModifier keyModifier = KeyModifier.None); string GetCurrentProgramScene(); void SetCurrentProgramScene(string sceneName); ObsStats GetStats(); List<SceneBasicInfo> ListScenes(); GetSceneListInfo GetSceneList(); TransitionOverrideInfo GetSceneSceneTransitionOverride(string sceneName); void SetSceneSceneTransitionOverride(string sceneName, string transitionName, int transitionDuration = -1); void SetTBarPosition(double position, bool release = true); void SetSourceFilterSettings(string sourceName, string filterName, JObject filterSettings, bool overlay = false); void SetSourceFilterSettings(string sourceName, string filterName, FilterSettings filterSettings, bool overlay = false); void SetSourceFilterEnabled(string sourceName, string filterName, bool filterEnabled); List<FilterSettings> GetSourceFilterList(string sourceName); FilterSettings GetSourceFilter(string sourceName, string filterName); bool RemoveSourceFilter(string sourceName, string filterName); void CreateSourceFilter(string sourceName, string filterName, string filterKind, JObject filterSettings); void CreateSourceFilter(string sourceName, string filterName, string filterKind, FilterSettings filterSettings); bool ToggleStream(); void ToggleRecord(); OutputStatus GetStreamStatus(); TransitionSettings GetCurrentSceneTransition(); void SetCurrentSceneTransition(string transitionName); void SetCurrentSceneTransitionDuration(int transitionDuration); void SetCurrentSceneTransitionSettings(JObject transitionSettings, bool overlay); void SetInputVolume(string inputName, float inputVolume, bool inputVolumeDb = false); VolumeInfo GetInputVolume(string inputName); bool GetInputMute(string inputName); void SetInputMute(string inputName, bool inputMuted); void ToggleInputMute(string inputName); void SetSceneItemTransform(string sceneName, int sceneItemId, JObject sceneItemTransform); void SetSceneItemTransform(string sceneName, int sceneItemId, SceneItemTransformInfo sceneItemTransform); void SetCurrentSceneCollection(string sceneCollectionName); string GetCurrentSceneCollection(); List<string> GetSceneCollectionList(); void SetCurrentProfile(string profileName); GetProfileListInfo GetProfileList(); void StartStream(); void StopStream(); void StartRecord(); string StopRecord(); void PauseRecord(); void ResumeRecord(); string GetRecordDirectory(); RecordingStatus GetRecordStatus(); bool GetReplayBufferStatus(); GetTransitionListInfo GetSceneTransitionList(); bool GetStudioModeEnabled(); void SetStudioModeEnabled(bool studioModeEnabled); string GetCurrentPreviewScene(); void SetCurrentPreviewScene(string sceneName); void SetCurrentPreviewScene(ObsScene previewScene); void TriggerStudioModeTransition(); void ToggleReplayBuffer(); void StartReplayBuffer(); void StopReplayBuffer(); void SaveReplayBuffer(); void SetInputAudioSyncOffset(string inputName, int inputAudioSyncOffset); int GetInputAudioSyncOffset(string inputName); void RemoveSceneItem(string sceneName, int sceneItemId); void SendStreamCaption(string captionText); void DuplicateSceneItem(string sceneName, int sceneItemId, string destinationSceneName = null); Dictionary<string, string> GetSpecialInputs(); void SetStreamServiceSettings(StreamingService service); StreamingService GetStreamServiceSettings(); string GetInputAudioMonitorType(string inputName); void SetInputAudioMonitorType(string inputName, string monitorType); void BroadcastCustomEvent(JObject eventData); void SetMediaInputCursor(string inputName, int mediaCursor); void OffsetMediaInputCursor(string inputName, int mediaCursorOffset); int CreateInput(string sceneName, string inputName, string inputKind, JObject inputSettings, bool? sceneItemEnabled); JObject GetInputDefaultSettings(string inputKind); List<SceneItemDetails> GetSceneItemList(string sceneName); int CreateSceneItem(string sceneName, string sourceName, bool sceneItemEnabled = true); void CreateScene(string sceneName); SourceTracks GetInputAudioTracks(string inputName); void SetInputAudioTracks(string inputName, JObject inputAudioTracks); void SetInputAudioTracks(string inputName, SourceTracks inputAudioTracks); SourceActiveInfo GetSourceActive(string sourceName); VirtualCamStatus GetVirtualCamStatus(); void StartVirtualCam(); void StopVirtualCam(); VirtualCamStatus ToggleVirtualCam(); JObject GetPersistentData(string realm, string slotName); void SetPersistentData(string realm, string slotName, JObject slotValue); void CreateSceneCollection(string sceneCollectionName); void CreateProfile(string profileName); void RemoveProfile(string profileName); JObject GetProfileParameter(string parameterCategory, string parameterName); void SetProfileParameter(string parameterCategory, string parameterName, string parameterValue); void SetVideoSettings(ObsVideoSettings obsVideoSettings); JObject GetSourceFilterDefaultSettings(string filterKind); void SetSourceFilterName(string sourceName, string filterName, string newFilterName); void SetSourceFilterIndex(string sourceName, string filterName, int filterIndex); ObsVersion GetVersion(); JObject CallVendorRequest(string vendorName, string requestType, JObject requestData = null); List<string> GetHotkeyList(); void Sleep(int sleepMillis, int sleepFrames); List<InputBasicInfo> GetInputList(string inputKind = null); List<string> GetInputKindList(bool unversioned = false); void RemoveInput(string inputName); void SetInputName(string inputName, string newInputName); InputSettings GetInputSettings(string inputName); void SetInputSettings(InputSettings inputSettings, bool overlay = true); void SetInputSettings(string inputName, JObject inputSettings, bool overlay = true); double GetInputAudioBalance(string inputName); void SetInputAudioBalance(string inputName, double inputAudioBalance); List<JObject> GetInputPropertiesListPropertyItems(string inputName, string propertyName); void PressInputPropertiesButton(string inputName, string propertyName); MediaInputStatus GetMediaInputStatus(string inputName); void TriggerMediaInputAction(string inputName, string mediaAction); string GetLastReplayBufferReplay(); void ToggleRecordPause(); List<JObject> GetGroupSceneItemList(string sceneName); int GetSceneItemId(string sceneName, string sourceName, int searchOffset); SceneItemTransformInfo GetSceneItemTransform(string sceneName, int sceneItemId); JObject GetSceneItemTransformRaw(string sceneName, int sceneItemId); bool GetSceneItemEnabled(string sceneName, int sceneItemId); void SetSceneItemEnabled(string sceneName, int sceneItemId, bool sceneItemEnabled); bool GetSceneItemLocked(string sceneName, int sceneItemId); void SetSceneItemLocked(string sceneName, int sceneItemId, bool sceneItemLocked); int GetSceneItemIndex(string sceneName, int sceneItemId); void SetSceneItemIndex(string sceneName, int sceneItemId, int sceneItemIndex); string GetSceneItemBlendMode(string sceneName, int sceneItemId); void SetSceneItemBlendMode(string sceneName, int sceneItemId, string sceneItemBlendMode); List<string> GetGroupList(); void RemoveScene(string sceneName); void SetSceneName(string sceneName, string newSceneName); string GetSourceScreenshot(string sourceName, string imageFormat, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1); List<string> GetTransitionKindList(); double GetCurrentSceneTransitionCursor(); void OpenInputPropertiesDialog(string inputName); void OpenInputFiltersDialog(string inputName); void OpenInputInteractDialog(string inputName); List<Monitor> GetMonitorList(); [Obsolete("Please use ConnectAsync, this function will be removed in the next version")] void Connect(string url, string password); void ConnectAsync(string url, string password); void Disconnect(); JObject SendRequest(string requestType, JObject additionalFields = null); OBSAuthInfo GetAuthInfo(); } } namespace OBSWebsocketDotNet.Types { public class FilterReorderItem { [JsonProper
UserLibs/System.Reactive.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
#define TRACE using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Disposables; using System.Reactive.Joins; using System.Reactive.Linq; using System.Reactive.Linq.ObservableImpl; using System.Reactive.PlatformServices; using System.Reactive.Subjects; using System.Reactive.Threading.Tasks; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.WindowsRuntime; using System.Runtime.Versioning; using System.Security; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("4.3.2.55399")] [assembly: AssemblyInformationalVersion("4.3.2+67d891dfbf")] [assembly: InternalsVisibleTo("Tests.System.Reactive, PublicKey=00240000048000009400000006020000002400005253413100040000010001008f5cff058631087031f8350f30a36fa078027e5df2316b564352dc9eb7af7ce856016d3c5e9d058036fe73bb5c83987bd3fc0793fbe25d633cc4f37c2bd5f1d717cd2a81661bec08f0971dc6078e17bde372b89005e7738a0ebd501b896ca3e8315270ff64df7809dd912c372df61785a5085b3553b7872e39b1b1cc0ff5a6bc")] [assembly: InternalsVisibleTo("Tests.System.Reactive.Uwp.DeviceRunner, PublicKey=00240000048000009400000006020000002400005253413100040000010001008f5cff058631087031f8350f30a36fa078027e5df2316b564352dc9eb7af7ce856016d3c5e9d058036fe73bb5c83987bd3fc0793fbe25d633cc4f37c2bd5f1d717cd2a81661bec08f0971dc6078e17bde372b89005e7738a0ebd501b896ca3e8315270ff64df7809dd912c372df61785a5085b3553b7872e39b1b1cc0ff5a6bc")] [assembly: ComVisible(false)] [assembly: CLSCompliant(true)] [assembly: NeutralResourcesLanguage("en-US")] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: AssemblyMetadata("CommitHash", "67d891dfbf7263781dceedaa62548c1baaa33163")] [assembly: AssemblyCompany(".NET Foundation and Contributors")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors.")] [assembly: AssemblyDescription("Reactive Extensions (Rx) for .NET")] [assembly: AssemblyProduct("System.Reactive (netstandard2.0)")] [assembly: AssemblyTitle("System.Reactive")] [assembly: AssemblyVersion("4.3.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } [GeneratedCode("Nerdbank.GitVersioning.Tasks", "3.0.28.11123")] internal static class ThisAssembly { internal const string AssemblyVersion = "4.3.0.0"; internal const string AssemblyFileVersion = "4.3.2.55399"; internal const string AssemblyInformationalVersion = "4.3.2+67d891dfbf"; internal const string AssemblyName = "System.Reactive"; internal const string AssemblyTitle = "System.Reactive"; internal const string AssemblyConfiguration = "Release"; internal const string GitCommitId = "67d891dfbf7263781dceedaa62548c1baaa33163"; internal const string PublicKey = "00240000048000009400000006020000002400005253413100040000010001008f5cff058631087031f8350f30a36fa078027e5df2316b564352dc9eb7af7ce856016d3c5e9d058036fe73bb5c83987bd3fc0793fbe25d633cc4f37c2bd5f1d717cd2a81661bec08f0971dc6078e17bde372b89005e7738a0ebd501b896ca3e8315270ff64df7809dd912c372df61785a5085b3553b7872e39b1b1cc0ff5a6bc"; internal const string PublicKeyToken = "94bc3704cddfc263"; internal static readonly DateTime GitCommitDate = new DateTime(637127137800000000L, DateTimeKind.Utc); internal const string RootNamespace = "System.Reactive"; } namespace System { public static class ObservableExtensions { public static IDisposable Subscribe<T>(this IObservable<T> source) { if (source == null) { throw new ArgumentNullException("source"); } return source.Subscribe(new AnonymousObserver<T>(Stubs<T>.Ignore, Stubs.Throw, Stubs.Nop)); } public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext) { if (source == null) { throw new ArgumentNullException("source"); } if (onNext == null) { throw new ArgumentNullException("onNext"); } return source.Subscribe(new AnonymousObserver<T>(onNext, Stubs.Throw, Stubs.Nop)); } public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError) { if (source == null) { throw new ArgumentNullException("source"); } if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } return source.Subscribe(new AnonymousObserver<T>(onNext, onError, Stubs.Nop)); } public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action onCompleted) { if (source == null) { throw new ArgumentNullException("source"); } if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } return source.Subscribe(new AnonymousObserver<T>(onNext, Stubs.Throw, onCompleted)); } public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError, Action onCompleted) { if (source == null) { throw new ArgumentNullException("source"); } if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } return source.Subscribe(new AnonymousObserver<T>(onNext, onError, onCompleted)); } public static void Subscribe<T>(this IObservable<T> source, IObserver<T> observer, CancellationToken token) { if (source == null) { throw new ArgumentNullException("source"); } if (observer == null) { throw new ArgumentNullException("observer"); } source.Subscribe_(observer, token); } public static void Subscribe<T>(this IObservable<T> source, CancellationToken token) { if (source == null) { throw new ArgumentNullException("source"); } source.Subscribe_(new AnonymousObserver<T>(Stubs<T>.Ignore, Stubs.Throw, Stubs.Nop), token); } public static void Subscribe<T>(this IObservable<T> source, Action<T> onNext, CancellationToken token) { if (source == null) { throw new ArgumentNullException("source"); } if (onNext == null) { throw new ArgumentNullException("onNext"); } source.Subscribe_(new AnonymousObserver<T>(onNext, Stubs.Throw, Stubs.Nop), token); } public static void Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError, CancellationToken token) { if (source == null) { throw new ArgumentNullException("source"); } if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } source.Subscribe_(new AnonymousObserver<T>(onNext, onError, Stubs.Nop), token); } public static void Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action onCompleted, CancellationToken token) { if (source == null) { throw new ArgumentNullException("source"); } if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } source.Subscribe_(new AnonymousObserver<T>(onNext, Stubs.Throw, onCompleted), token); } public static void Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError, Action onCompleted, CancellationToken token) { if (source == null) { throw new ArgumentNullException("source"); } if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } source.Subscribe_(new AnonymousObserver<T>(onNext, onError, onCompleted), token); } private static void Subscribe_<T>(this IObservable<T> source, IObserver<T> observer, CancellationToken token) { if (token.CanBeCanceled) { if (!token.IsCancellationRequested) { ISafeObserver<T> safeObserver = SafeObserver<T>.Wrap(observer); IDisposable state2 = source.Subscribe(safeObserver); safeObserver.SetResource(token.Register(delegate(object state) { ((IDisposable)state).Dispose(); }, state2)); } } else { source.Subscribe(observer); } } [EditorBrowsable(EditorBrowsableState.Advanced)] public static IDisposable SubscribeSafe<T>(this IObservable<T> source, IObserver<T> observer) { if (source == null) { throw new ArgumentNullException("source"); } if (observer == null) { throw new ArgumentNullException("observer"); } if (source is ObservableBase<T>) { return source.Subscribe(observer); } if (source is IProducer<T> producer) { return producer.SubscribeRaw(observer, enableSafeguard: false); } IDisposable result = Disposable.Empty; try { result = source.Subscribe(observer); } catch (Exception error) { observer.OnError(error); } return result; } } } namespace System.Runtime.CompilerServices { public struct TaskObservableMethodBuilder<T> { internal sealed class TaskObservable : ITaskObservable<T>, IObservable<T>, ITaskObservableAwaiter<T>, INotifyCompletion { private readonly AsyncSubject<T> _subject; private readonly T _result; private readonly Exception _exception; public bool IsCompleted => _subject?.IsCompleted ?? true; public TaskObservable() { _subject = new AsyncSubject<T>(); } public TaskObservable(T result) { _result = result; } public TaskObservable(Exception exception) { _exception = exception; } public void SetResult(T result) { if (IsCompleted) { throw new InvalidOperationException(); } _subject.OnNext(result); _subject.OnCompleted(); } public void SetException(Exception exception) { if (IsCompleted) { throw new InvalidOperationException(); } _subject.OnError(exception); } public IDisposable Subscribe(IObserver<T> observer) { if (_subject != null) { return _subject.Subscribe(observer); } if (_exception != null) { observer.OnError(_exception); return Disposable.Empty; } observer.OnNext(_result); return Disposable.Empty; } public ITaskObservableAwaiter<T> GetAwaiter() { return this; } public T GetResult() { if (_subject != null) { return _subject.GetResult(); } _exception.ThrowIfNotNull(); return _result; } public void OnCompleted(Action continuation) { if (_subject != null) { _subject.OnCompleted(continuation); } else { continuation(); } } } private IAsyncStateMachine _stateMachine; private TaskObservable _inner; public ITaskObservable<T> Task => _inner ?? (_inner = new TaskObservable()); public static TaskObservableMethodBuilder<T> Create() { return default(TaskObservableMethodBuilder<T>); } public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { if (stateMachine == null) { throw new ArgumentNullException("stateMachine"); } stateMachine.MoveNext(); } public void SetStateMachine(IAsyncStateMachine stateMachine) { if (_stateMachine != null) { throw new InvalidOperationException(); } _stateMachine = stateMachine ?? throw new ArgumentNullException("stateMachine"); } public void SetResult(T result) { if (_inner == null) { _inner = new TaskObservable(result); } else { _inner.SetResult(result); } } public void SetException(Exception exception) { if (exception == null) { throw new ArgumentNullException("exception"); } if (_inner == null) { _inner = new TaskObservable(exception); } else { _inner.SetException(exception); } } public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { try { if (_stateMachine == null) { _ = Task; _stateMachine = stateMachine; _stateMachine.SetStateMachine(_stateMachine); } awaiter.OnCompleted(_stateMachine.MoveNext); } catch (Exception exception) { Rethrow(exception); } } [SecuritySafeCritical] public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { try { if (_stateMachine == null) { _ = Task; _stateMachine = stateMachine; _stateMachine.SetStateMachine(_stateMachine); } awaiter.UnsafeOnCompleted(_stateMachine.MoveNext); } catch (Exception exception) { Rethrow(exception); } } private static void Rethrow(Exception exception) { Scheduler.Default.Schedule(exception, delegate(Exception ex, Action<Exception> recurse) { ex.Throw(); }); } } } namespace System.Threading.Tasks { internal static class TaskExtensions { public static Task ContinueWithState<TState>(this Task task, Action<Task, TState> continuationAction, TState state) { return task.ContinueWith(delegate(Task t, object tupleObject) { var (action, arg) = ((Action<Task, TState>, TState))tupleObject; action(t, arg); }, (continuationAction, state)); } public static Task ContinueWithState<TState>(this Task task, Action<Task, TState> continuationAction, TState state, CancellationToken cancellationToken) { return task.ContinueWith(delegate(Task t, object tupleObject) { var (action, arg) = ((Action<Task, TState>, TState))tupleObject; action(t, arg); }, (continuationAction, state), cancellationToken); } public static Task ContinueWithState<TState>(this Task task, Action<Task, TState> continuationAction, TState state, TaskContinuationOptions continuationOptions) { return task.ContinueWith(delegate(Task t, object tupleObject) { var (action, arg) = ((Action<Task, TState>, TState))tupleObject; action(t, arg); }, (continuationAction, state), continuationOptions); } public static Task ContinueWithState<TState>(this Task task, Action<Task, TState> continuationAction, TState state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions) { return task.ContinueWith(delegate(Task t, object tupleObject) { var (action, arg) = ((Action<Task, TState>, TState))tupleObject; action(t, arg); }, (continuationAction, state), cancellationToken, continuationOptions, TaskScheduler.Default); } public static Task ContinueWithState<TResult, TState>(this Task<TResult> task, Action<Task<TResult>, TState> continuationAction, TState state) { return task.ContinueWith(delegate(Task<TResult> t, object tupleObject) { var (action, arg) = ((Action<Task<TResult>, TState>, TState))tupleObject; action(t, arg); }, (continuationAction, state)); } public static Task ContinueWithState<TResult, TState>(this Task<TResult> task, Action<Task<TResult>, TState> continuationAction, TState state, CancellationToken cancellationToken) { return task.ContinueWith(delegate(Task<TResult> t, object tupleObject) { var (action, arg) = ((Action<Task<TResult>, TState>, TState))tupleObject; action(t, arg); }, (continuationAction, state), cancellationToken); } public static Task ContinueWithState<TResult, TState>(this Task<TResult> task, Action<Task<TResult>, TState> continuationAction, TState state, TaskContinuationOptions continuationOptions) { return task.ContinueWith(delegate(Task<TResult> t, object tupleObject) { var (action, arg) = ((Action<Task<TResult>, TState>, TState))tupleObject; action(t, arg); }, (continuationAction, state), continuationOptions); } public static Task ContinueWithState<TResult, TState>(this Task<TResult> task, Action<Task<TResult>, TState> continuationAction, TState state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions) { return task.ContinueWith(delegate(Task<TResult> t, object tupleObject) { var (action, arg) = ((Action<Task<TResult>, TState>, TState))tupleObject; action(t, arg); }, (continuationAction, state), cancellationToken, continuationOptions, TaskScheduler.Default); } } } namespace System.Reactive { public sealed class AnonymousObservable<T> : ObservableBase<T> { private readonly Func<IObserver<T>, IDisposable> _subscribe; public AnonymousObservable(Func<IObserver<T>, IDisposable> subscribe) { _subscribe = subscribe ?? throw new ArgumentNullException("subscribe"); } protected override IDisposable SubscribeCore(IObserver<T> observer) { return _subscribe(observer) ?? Disposable.Empty; } } public sealed class AnonymousObserver<T> : ObserverBase<T> { private readonly Action<T> _onNext; private readonly Action<Exception> _onError; private readonly Action _onCompleted; public AnonymousObserver(Action<T> onNext, Action<Exception> onError, Action onCompleted) { _onNext = onNext ?? throw new ArgumentNullException("onNext"); _onError = onError ?? throw new ArgumentNullException("onError"); _onCompleted = onCompleted ?? throw new ArgumentNullException("onCompleted"); } public AnonymousObserver(Action<T> onNext) : this(onNext, Stubs.Throw, Stubs.Nop) { } public AnonymousObserver(Action<T> onNext, Action<Exception> onError) : this(onNext, onError, Stubs.Nop) { } public AnonymousObserver(Action<T> onNext, Action onCompleted) : this(onNext, Stubs.Throw, onCompleted) { } protected override void OnNextCore(T value) { _onNext(value); } protected override void OnErrorCore(Exception error) { _onError(error); } protected override void OnCompletedCore() { _onCompleted(); } internal ISafeObserver<T> MakeSafe() { return new AnonymousSafeObserver<T>(_onNext, _onError, _onCompleted); } } internal sealed class AnonymousSafeObserver<T> : SafeObserver<T> { private readonly Action<T> _onNext; private readonly Action<Exception> _onError; private readonly Action _onCompleted; private int _isStopped; public AnonymousSafeObserver(Action<T> onNext, Action<Exception> onError, Action onCompleted) { _onNext = onNext; _onError = onError; _onCompleted = onCompleted; } public override void OnNext(T value) { if (_isStopped != 0) { return; } bool flag = false; try { _onNext(value); flag = true; } finally { if (!flag) { Dispose(); } } } public override void OnError(Exception error) { if (Interlocked.Exchange(ref _isStopped, 1) == 0) { using (this) { _onError(error); } } } public override void OnCompleted() { if (Interlocked.Exchange(ref _isStopped, 1) == 0) { using (this) { _onCompleted(); } } } } public class EventPattern<TEventArgs> : EventPattern<object, TEventArgs> { public EventPattern(object sender, TEventArgs e) : base(sender, e) { } } public class EventPattern<TSender, TEventArgs> : IEquatable<EventPattern<TSender, TEventArgs>>, IEventPattern<TSender, TEventArgs> { public TSender Sender { get; } public TEventArgs EventArgs { get; } public EventPattern(TSender sender, TEventArgs e) { Sender = sender; EventArgs = e; } public bool Equals(EventPattern<TSender, TEventArgs> other) { if ((object)other == null) { return false; } if ((object)this == other) { return true; } if (EqualityComparer<TSender>.Default.Equals(Sender, other.Sender)) { return EqualityComparer<TEventArgs>.Default.Equals(EventArgs, other.EventArgs); } return false; } public override bool Equals(object obj) { return Equals(obj as EventPattern<TSender, TEventArgs>); } public override int GetHashCode() { int hashCode = EqualityComparer<TSender>.Default.GetHashCode(Sender); int hashCode2 = EqualityComparer<TEventArgs>.Default.GetHashCode(EventArgs); return (hashCode << 5) + (hashCode ^ hashCode2); } public static bool operator ==(EventPattern<TSender, TEventArgs> first, EventPattern<TSender, TEventArgs> second) { return object.Equals(first, second); } public static bool operator !=(EventPattern<TSender, TEventArgs> first, EventPattern<TSender, TEventArgs> second) { return !object.Equals(first, second); } } internal sealed class EventPatternSource<TEventArgs> : EventPatternSourceBase<object, TEventArgs>, IEventPatternSource<TEventArgs> { event EventHandler<TEventArgs> IEventPatternSource<TEventArgs>.OnNext { add { Add(value, delegate(object o, TEventArgs e) { value(o, e); }); } remove { Remove(value); } } public EventPatternSource(IObservable<EventPattern<object, TEventArgs>> source, Action<Action<object, TEventArgs>, EventPattern<object, TEventArgs>> invokeHandler) : base(source, invokeHandler) { } } public abstract class EventPatternSourceBase<TSender, TEventArgs> { private sealed class Observer : ObserverBase<EventPattern<TSender, TEventArgs>>, ISafeObserver<EventPattern<TSender, TEventArgs>>, IObserver<EventPattern<TSender, TEventArgs>>, IDisposable { private bool _isDone; private bool _isAdded; private readonly Delegate _handler; private readonly object _gate = new object(); private readonly Action<TSender, TEventArgs> _invoke; private readonly EventPatternSourceBase<TSender, TEventArgs> _sourceBase; public Observer(EventPatternSourceBase<TSender, TEventArgs> sourceBase, Delegate handler, Action<TSender, TEventArgs> invoke) { _handler = handler; _invoke = invoke; _sourceBase = sourceBase; } protected override void OnNextCore(EventPattern<TSender, TEventArgs> value) { _sourceBase._invokeHandler(_invoke, value); } protected override void OnErrorCore(Exception error) { Remove(); error.Throw(); } protected override void OnCompletedCore() { Remove(); } private void Remove() { lock (_gate) { if (_isAdded) { _sourceBase.Remove(_handler); } else { _isDone = true; } } } public void SetResource(IDisposable resource) { lock (_gate) { if (!_isDone) { _sourceBase.Add(_handler, resource); _isAdded = true; } } } } private readonly IObservable<EventPattern<TSender, TEventArgs>> _source; private readonly Dictionary<Delegate, Stack<IDisposable>> _subscriptions; private readonly Action<Action<TSender, TEventArgs>, EventPattern<TSender, TEventArgs>> _invokeHandler; protected EventPatternSourceBase(IObservable<EventPattern<TSender, TEventArgs>> source, Action<Action<TSender, TEventArgs>, EventPattern<TSender, TEventArgs>> invokeHandler) { _source = source ?? throw new ArgumentNullException("source"); _invokeHandler = invokeHandler ?? throw new ArgumentNullException("invokeHandler"); _subscriptions = new Dictionary<Delegate, Stack<IDisposable>>(); } protected void Add(Delegate handler, Action<TSender, TEventArgs> invoke) { if ((object)handler == null) { throw new ArgumentNullException("handler"); } if (invoke == null) { throw new ArgumentNullException("invoke"); } Observer observer = new Observer(this, handler, invoke); observer.SetResource(_source.Subscribe(observer)); } private void Add(Delegate handler, IDisposable disposable) { lock (_subscriptions) { if (!_subscriptions.TryGetValue(handler, out var value)) { value = (_subscriptions[handler] = new Stack<IDisposable>()); } value.Push(disposable); } } protected void Remove(Delegate handler) { if ((object)handler == null) { throw new ArgumentNullException("handler"); } IDisposable disposable = null; lock (_subscriptions) { if (_subscriptions.TryGetValue(handler, out var value)) { disposable = value.Pop(); if (value.Count == 0) { _subscriptions.Remove(handler); } } } disposable?.Dispose(); } } internal sealed class EventSource<T> : IEventSource<T> { private readonly IObservable<T> _source; private readonly Dictionary<Delegate, Stack<IDisposable>> _subscriptions; private readonly Action<Action<T>, T> _invokeHandler; public event Action<T> OnNext { add { object gate = new object(); bool isAdded = false; bool isDone = false; Action remove = delegate { lock (gate) { if (isAdded) { Remove(value); } else { isDone = true; } } }; IDisposable disposable = _source.Subscribe(delegate(T x) { _invokeHandler(value, x); }, delegate(Exception ex) { remove(); ex.Throw(); }, remove); lock (gate) { if (!isDone) { Add(value, disposable); isAdded = true; } } } remove { Remove(value); } } public EventSource(IObservable<T> source, Action<Action<T>, T> invokeHandler) { _source = source; _invokeHandler = invokeHandler; _subscriptions = new Dictionary<Delegate, Stack<IDisposable>>(); } private void Add(Delegate handler, IDisposable disposable) { lock (_subscriptions) { if (!_subscriptions.TryGetValue(handler, out var value)) { value = (_subscriptions[handler] = new Stack<IDisposable>()); } value.Push(disposable); } } private void Remove(Delegate handler) { IDisposable disposable = null; lock (_subscriptions) { Stack<IDisposable> value = new Stack<IDisposable>(); if (_subscriptions.TryGetValue(handler, out value)) { disposable = value.Pop(); if (value.Count == 0) { _subscriptions.Remove(handler); } } } disposable?.Dispose(); } } [Experimental] [AttributeUsage(AttributeTargets.All)] public sealed class ExperimentalAttribute : Attribute { } public interface IEventPattern<out TSender, out TEventArgs> { TSender Sender { get; } TEventArgs EventArgs { get; } } public interface IEventPatternSource<TEventArgs> { event EventHandler<TEventArgs> OnNext; } public interface IEventSource<out T> { event Action<T> OnNext; } internal sealed class AnonymousEnumerable<T> : IEnumerable<T>, IEnumerable { private readonly Func<IEnumerator<T>> _getEnumerator; public AnonymousEnumerable(Func<IEnumerator<T>> getEnumerator) { _getEnumerator = getEnumerator; } public IEnumerator<T> GetEnumerator() { return _getEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _getEnumerator(); } } internal sealed class AsyncLockObserver<T> : ObserverBase<T> { private readonly AsyncLock _gate; private readonly IObserver<T> _observer; public AsyncLockObserver(IObserver<T> observer, AsyncLock gate) { _gate = gate; _observer = observer; } protected override void OnNextCore(T value) { _gate.Wait((_observer, value), delegate((IObserver<T> _observer, T value) tuple) { tuple._observer.OnNext(tuple.value); }); } protected override void OnErrorCore(Exception exception) { _gate.Wait((_observer, exception), delegate((IObserver<T> _observer, Exception exception) tuple) { tuple._observer.OnError(tuple.exception); }); } protected override void OnCompletedCore() { _gate.Wait(_observer, delegate(IObserver<T> closureObserver) { closureObserver.OnCompleted(); }); } } internal sealed class AutoDetachObserver<T> : ObserverBase<T>, ISafeObserver<T>, IObserver<T>, IDisposable { private readonly IObserver<T> _observer; private IDisposable _disposable; public AutoDetachObserver(IObserver<T> observer) { _observer = observer; } public void SetResource(IDisposable resource) { Disposable.SetSingle(ref _disposable, resource); } protected override void OnNextCore(T value) { bool flag = false; try { _observer.OnNext(value); flag = true; } finally { if (!flag) { Dispose(); } } } protected override void OnErrorCore(Exception exception) { try { _observer.OnError(exception); } finally { Dispose(); } } protected override void OnCompletedCore() { try { _observer.OnCompleted(); } finally { Dispose(); } } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { Disposable.TryDispose(ref _disposable); } } } internal sealed class BinaryObserver<TLeft, TRight> : IObserver<Either<Notification<TLeft>, Notification<TRight>>> { public IObserver<TLeft> LeftObserver { get; } public IObserver<TRight> RightObserver { get; } public BinaryObserver(IObserver<TLeft> leftObserver, IObserver<TRight> rightObserver) { LeftObserver = leftObserver; RightObserver = rightObserver; } public BinaryObserver(Action<Notification<TLeft>> left, Action<Notification<TRight>> right) : this(left.ToObserver(), right.ToObserver()) { } void IObserver<Either<Notification<TLeft>, Notification<TRight>>>.OnNext(Either<Notification<TLeft>, Notification<TRight>> value) { value.Switch(delegate(Notification<TLeft> left) { left.Accept(LeftObserver); }, delegate(Notification<TRight> right) { right.Accept(RightObserver); }); } void IObserver<Either<Notification<TLeft>, Notification<TRight>>>.OnError(Exception exception) { } void IObserver<Either<Notification<TLeft>, Notification<TRight>>>.OnCompleted() { } } internal sealed class CheckedObserver<T> : IObserver<T> { private readonly IObserver<T> _observer; private int _state; private const int Idle = 0; private const int Busy = 1; private const int Done = 2; public CheckedObserver(IObserver<T> observer) { _observer = observer; } public void OnNext(T value) { CheckAccess(); try { _observer.OnNext(value); } finally { Interlocked.Exchange(ref _state, 0); } } public void OnError(Exception error) { CheckAccess(); try { _observer.OnError(error); } finally { Interlocked.Exchange(ref _state, 2); } } public void OnCompleted() { CheckAccess(); try { _observer.OnCompleted(); } finally { Interlocked.Exchange(ref _state, 2); } } private void CheckAccess() { switch (Interlocked.CompareExchange(ref _state, 1, 0)) { case 1: throw new InvalidOperationException(Strings_Core.REENTRANCY_DETECTED); case 2: throw new InvalidOperationException(Strings_Core.OBSERVER_TERMINATED); } } } internal abstract class ConcatSink<TSource> : TailRecursiveSink<TSource> { protected ConcatSink(IObserver<TSource> observer) : base(observer) { } protected override IEnumerable<IObservable<TSource>> Extract(IObservable<TSource> source) { return (source as IConcatenatable<TSource>)?.GetSources(); } public override void OnCompleted() { Recurse(); } } internal static class Constants_Core { private const string ObsoleteRefactoring = "This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies."; public const string ObsoleteSchedulerNewthread = "This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies. Please use NewThreadScheduler.Default to obtain an instance of this scheduler type."; public const string ObsoleteSchedulerTaskpool = "This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies. Please use TaskPoolScheduler.Default to obtain an instance of this scheduler type."; public const string ObsoleteSchedulerThreadpool = "This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies. Consider using Scheduler.Default to obtain the platform's most appropriate pool-based scheduler. In order to access a specific pool-based scheduler, please add a reference to the System.Reactive.PlatformServices assembly for your target platform and use the appropriate scheduler in the System.Reactive.Concurrency namespace."; public const string ObsoleteSchedulerequired = "This instance property is no longer supported. Use CurrentThreadScheduler.IsScheduleRequired instead."; } internal static class Constants_Linq { public const string UseAsync = "This blocking operation is no longer supported. Instead, use the async version in combination with C# and Visual Basic async/await support. In case you need a blocking operation, use Wait or convert the resulting observable sequence to a Task object and block."; public const string UseTaskFromAsyncPattern = "This conversion is no longer supported. Replace use of the Begin/End asynchronous method pair with a new Task-based async method, and convert the result using ToObservable. If no Task-based async method is available, use Task.Factory.FromAsync to obtain a Task object."; } internal abstract class Either<TLeft, TRight> { public sealed class Left : Either<TLeft, TRight>, IEquatable<Left> { public TLeft Value { get; } public Left(TLeft value) { Value = value; } public override TResult Switch<TResult>(Func<TLeft, TResult> caseLeft, Func<TRight, TResult> caseRight) { return caseLeft(Value); } public override void Switch(Action<TLeft> caseLeft, Action<TRight> caseRight) { caseLeft(Value); } public bool Equals(Left other) { if (other == this) { return true; } if (other == null) { return false; } return EqualityComparer<TLeft>.Default.Equals(Value, other.Value); } public override bool Equals(object obj) { return Equals(obj as Left); } public override int GetHashCode() { return EqualityComparer<TLeft>.Default.GetHashCode(Value); } public override string ToString() { return string.Format(CultureInfo.CurrentCulture, "Left({0})", Value); } } public sealed class Right : Either<TLeft, TRight>, IEquatable<Right> { public TRight Value { get; } public Right(TRight value) { Value = value; } public override TResult Switch<TResult>(Func<TLeft, TResult> caseLeft, Func<TRight, TResult> caseRight) { return caseRight(Value); } public override void Switch(Action<TLeft> caseLeft, Action<TRight> caseRight) { caseRight(Value); } public bool Equals(Right other) { if (other == this) { return true; } if (other == null) { return false; } return EqualityComparer<TRight>.Default.Equals(Value, other.Value); } public override bool Equals(object obj) { return Equals(obj as Right); } public override int GetHashCode() { return EqualityComparer<TRight>.Default.GetHashCode(Value); } public override string ToString() { return string.Format(CultureInfo.CurrentCulture, "Right({0})", Value); } } private Either() { } public static Either<TLeft, TRight> CreateLeft(TLeft value) { return new Left(value); } public static Either<TLeft, TRight> CreateRight(TRight value) { return new Right(value); } public abstract TResult Switch<TResult>(Func<TLeft, TResult> caseLeft, Func<TRight, TResult> caseRight); public abstract void Switch(Action<TLeft> caseLeft, Action<TRight> caseRight); } internal static class ExceptionHelper { private sealed class TerminatedException : Exception { internal TerminatedException() : base("No further exceptions") { } } public static Exception Terminated { get; } = new TerminatedException(); public static bool TrySetException(ref Exception field, Exception ex) { return Interlocked.CompareExchange(ref field, ex, null) == null; } public static Exception Terminate(ref Exception field) { Exception ex = Volatile.Read(ref field); if (ex != Terminated) { ex = Interlocked.Exchange(ref field, Terminated); } return ex; } public static bool TryAddException(ref Exception field, Exception ex) { Exception ex2; Exception value; do { ex2 = Volatile.Read(ref field); if (ex2 == Terminated) { return false; } value = ((ex2 == null) ? ex : ((!(ex2 is AggregateException ex3)) ? new AggregateException(ex2, ex) : new AggregateException(new List<Exception>(ex3.InnerExceptions) { ex }))); } while (Interlocked.CompareExchange(ref field, value, ex2) != ex2); return true; } } internal static class ExceptionHelpers { private static readonly Lazy<IExceptionServices> Services = new Lazy<IExceptionServices>(Initialize); public static void Throw(this Exception exception) { Services.Value.Rethrow(exception); } public static void ThrowIfNotNull(this Exception exception) { if (exception != null) { Services.Value.Rethrow(exception); } } private static IExceptionServices Initialize() { return PlatformEnlightenmentProvider.Current.GetService<IExceptionServices>(Array.Empty<object>()) ?? new DefaultExceptionServices(); } } internal static class HalfSerializer { public static void ForwardOnNext<T>(ISink<T> sink, T item, ref int wip, ref Exception error) { if (Interlocked.CompareExchange(ref wip, 1, 0) == 0) { sink.ForwardOnNext(item); if (Interlocked.Decrement(ref wip) != 0) { Exception ex = error; if (ex != ExceptionHelper.Terminated) { error = ExceptionHelper.Terminated; sink.ForwardOnError(ex); } else { sink.ForwardOnCompleted(); } } } else if (error == null) { Trace.TraceWarning("OnNext called while another OnNext call was in progress on the same Observer."); } } public static void ForwardOnError<T>(ISink<T> sink, Exception ex, ref int wip, ref Exception error) { if (ExceptionHelper.TrySetException(ref error, ex) && Interlocked.Increment(ref wip) == 1) { error = ExceptionHelper.Terminated; sink.ForwardOnError(ex); } } public static void ForwardOnCompleted<T>(ISink<T> sink, ref int wip, ref Exception error) { if (ExceptionHelper.TrySetException(ref error, ExceptionHelper.Terminated) && Interlocked.Increment(ref wip) == 1) { sink.ForwardOnCompleted(); } } } internal static class Helpers { public static int? GetLength<T>(IEnumerable<T> source) { if (source is T[] array) { return array.Length; } if (source is IList<T> list) { return list.Count; } return null; } public static IObservable<T> Unpack<T>(IObservable<T> source) { bool flag; do { flag = false; if (source is IEvaluatableObservable<T> evaluatableObservable) { source = evaluatableObservable.Eval(); flag = true; } } while (flag); return source; } public static bool All(this bool[] values) { for (int i = 0; i < values.Length; i++) { if (!values[i]) { return false; } } return true; } public static bool AllExcept(this bool[] values, int index) { for (int i = 0; i < values.Length; i++) { if (i != index && !values[i]) { return false; } } return true; } } internal interface IConcatenatable<out TSource> { IEnumerable<IObservable<TSource>> GetSources(); } internal abstract class IdentitySink<T> : Sink<T, T> { protected IdentitySink(IObserver<T> observer) : base(observer) { } public override void OnNext(T value) { ForwardOnNext(value); } } internal interface IEvaluatableObservable<out T> { IObservable<T> Eval(); } internal sealed class ImmutableList<T> { public static readonly ImmutableList<T> Empty = new ImmutableList<T>(); private readonly T[] _data; public T[] Data => _data; private ImmutableList() { _data = Array.Empty<T>(); } public ImmutableList(T[] data) { _data = data; } public ImmutableList<T> Add(T value) { T[] array = new T[_data.Length + 1]; Array.Copy(_data, array, _data.Length); array[_data.Length] = value; return new ImmutableList<T>(array); } public ImmutableList<T> Remove(T value) { int num = IndexOf(value); if (num < 0) { return this; } int num2 = _data.Length; if (num2 == 1) { return Empty; } T[] array = new T[num2 - 1]; Array.Copy(_data, 0, array, 0, num); Array.Copy(_data, num + 1, array, num, num2 - num - 1); return new ImmutableList<T>(array); } private int IndexOf(T value) { for (int i = 0; i < _data.Length; i++) { if (object.Equals(_data[i], value)) { return i; } } return -1; } } internal interface ISafeObserver<in T> : IObserver<T>, IDisposable { void SetResource(IDisposable resource); } internal sealed class Lookup<K, E> : ILookup<K, E>, IEnumerable<IGrouping<K, E>>, IEnumerable { private sealed class Grouping : IGrouping<K, E>, IEnumerable<E>, IEnumerable { private readonly KeyValuePair<K, List<E>> _keyValuePair; public K Key { get { KeyValuePair<K, List<E>> keyValuePair = _keyValuePair; return keyValuePair.Key; } } public Grouping(KeyValuePair<K, List<E>> keyValuePair) { _keyValuePair = keyValuePair; } public IEnumerator<E> GetEnumerator() { KeyValuePair<K, List<E>> keyValuePair = _keyValuePair; return keyValuePair.Value.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private readonly Dictionary<K, List<E>> _dictionary; public int Count => _dictionary.Count; public IEnumerable<E> this[K key] { get { if (!_dictionary.TryGetValue(key, out var value)) { return Enumerable.Empty<E>(); } return Hide(value); } } public Lookup(IEqualityComparer<K> comparer) { _dictionary = new Dictionary<K, List<E>>(comparer); } public void Add(K key, E element) { if (!_dictionary.TryGetValue(key, out var value)) { value = (_dictionary[key] = new List<E>()); } value.Add(element); } public bool Contains(K key) { return _dictionary.ContainsKey(key); } private static IEnumerable<E> Hide(List<E> elements) { return elements.Skip(0); } public IEnumerator<IGrouping<K, E>> GetEnumerator() { foreach (KeyValuePair<K, List<E>> item in _dictionary) { yield return new Grouping(item); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal sealed class NopObserver<T> : IObserver<T> { public static readonly IObserver<T> Instance = new NopObserver<T>(); public void OnCompleted() { } public void OnError(Exception error) { } public void OnNext(T value) { } } internal sealed class PriorityQueue<T> where T : IComparable<T> { private struct IndexedItem : IComparable<IndexedItem> { public T Value; public long Id; public int CompareTo(IndexedItem other) { int num = Value.CompareTo(other.Value); if (num == 0) { num = Id.CompareTo(other.Id); } return num; } } private long _count = long.MinValue; private IndexedItem[] _items; private int _size; public int Count => _size; public PriorityQueue() : this(16) { } public PriorityQueue(int capacity) { _items = new IndexedItem[capacity]; _size = 0; } private bool IsHigherPriority(int left, int right) { return _items[left].CompareTo(_items[right]) < 0; } private int Percolate(int index) { if (index >= _size || index < 0) { return index; } int num = (index - 1) / 2; while (num >= 0 && num != index && IsHigherPriority(index, num)) { IndexedItem indexedItem = _items[index]; _items[index] = _items[num]; _items[num] = indexedItem; index = num; num = (index - 1) / 2; } return index; } private void Heapify(int index) { if (index >= _size || index < 0) { return; } while (true) { int num = 2 * index + 1; int num2 = 2 * index + 2; int num3 = index; if (num < _size && IsHigherPriority(num, num3)) { num3 = num; } if (num2 < _size && IsHigherPriority(num2, num3)) { num3 = num2; } if (num3 != index) { IndexedItem indexedItem = _items[index]; _items[index] = _items[num3]; _items[num3] = indexedItem; index = num3; continue; } break; } } public T Peek() { if (_size == 0) { throw new InvalidOperationException(Strings_Core.HEAP_EMPTY); } return _items[0].Value; } private void RemoveAt(int index) { _items[index] = _items[--_size]; _items[_size] = default(IndexedItem); if (Percolate(index) == index) { Heapify(index); } if (_size < _items.Length / 4) { IndexedItem[] items = _items; _items = new IndexedItem[_items.Length / 2]; Array.Copy(items, 0, _items, 0, _size); } } public T Dequeue() { T result = Peek(); RemoveAt(0); return result; } public void Enqueue(T item) { if (_size >= _items.Length) { IndexedItem[] items = _items; _items = new IndexedItem[_items.Length * 2]; Array.Copy(items, _items, items.Length); } int num = _size++; _items[num] = new IndexedItem { Value = item, Id = ++_count }; Percolate(num); } public bool Remove(T item) { for (int i = 0; i < _size; i++) { if (EqualityComparer<T>.Default.Equals(_items[i].Value, item)) { RemoveAt(i); return true; } } return false; } } internal interface IProducer<out TSource> : IObservable<TSource> { IDisposable SubscribeRaw(IObserver<TSource> observer, bool enableSafeguard); } internal abstract class BasicProducer<TSource> : IProducer<TSource>, IObservable<TSource> { public IDisposable Subscribe(IObserver<TSource> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return SubscribeRaw(observer, enableSafeguard: true); } public IDisposable SubscribeRaw(IObserver<TSource> observer, bool enableSafeguard) { ISafeObserver<TSource> safeObserver = null; if (enableSafeguard) { observer = (safeObserver = SafeObserver<TSource>.Wrap(observer)); } IDisposable disposable; if (CurrentThreadScheduler.IsScheduleRequired) { SingleAssignmentDisposable singleAssignmentDisposable = new SingleAssignmentDisposable(); CurrentThreadScheduler.Instance.ScheduleAction((this, singleAssignmentDisposable, observer), ((BasicProducer<TSource> @this, SingleAssignmentDisposable runAssignable, IObserver<TSource> observer) tuple) => tuple.runAssignable.Disposable = tuple.@this.Run(tuple.observer)); disposable = singleAssignmentDisposable; } else { disposable = Run(observer); } safeObserver?.SetResource(disposable); return disposable; } protected abstract IDisposable Run(IObserver<TSource> observer); } internal abstract class Producer<TTarget, TSink> : IProducer<TTarget>, IObservable<TTarget> where TSink : IDisposable { public IDisposable Subscribe(IObserver<TTarget> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return SubscribeRaw(observer, enableSafeguard: true); } public IDisposable SubscribeRaw(IObserver<TTarget> observer, bool enableSafeguard) { ISafeObserver<TTarget> safeObserver = null; if (enableSafeguard) { observer = (safeObserver = SafeObserver<TTarget>.Wrap(observer)); } TSink val = CreateSink(observer); safeObserver?.SetResource(val); if (CurrentThreadScheduler.IsScheduleRequired) { CurrentThreadScheduler.Instance.ScheduleAction((this, val), delegate((Producer<TTarget, TSink> @this, TSink sink) tuple) { tuple.@this.Run(tuple.sink); }); } else { Run(val); } return val; } protected abstract void Run(TSink sink); protected abstract TSink CreateSink(IObserver<TTarget> observer); } internal static class ReflectionUtils { public static TDelegate CreateDelegate<TDelegate>(object o, MethodInfo method) { return (TDelegate)(object)Delegate.CreateDelegate(typeof(TDelegate), o, method); } public static Delegate CreateDelegate(Type delegateType, object o, MethodInfo method) { return Delegate.CreateDelegate(delegateType, o, method); } public static void GetEventMethods<TSender, TEventArgs>(Type targetType, object target, string eventName, out MethodInfo addMethod, out MethodInfo removeMethod, out Type delegateType, out bool isWinRT) { EventInfo eventInfo = null; if (target == null) { eventInfo = targetType.GetEventEx(eventName, isStatic: true); if (eventInfo == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.COULD_NOT_FIND_STATIC_EVENT, eventName, targetType.FullName)); } } else { eventInfo = targetType.GetEventEx(eventName, isStatic: false); if (eventInfo == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.COULD_NOT_FIND_INSTANCE_EVENT, eventName, targetType.FullName)); } } addMethod = eventInfo.GetAddMethod(); removeMethod = eventInfo.GetRemoveMethod(); if (addMethod == null) { throw new InvalidOperationException(Strings_Linq.EVENT_MISSING_ADD_METHOD); } if (removeMethod == null) { throw new InvalidOperationException(Strings_Linq.EVENT_MISSING_REMOVE_METHOD); } ParameterInfo[] parameters = addMethod.GetParameters(); if (parameters.Length != 1) { throw new InvalidOperationException(Strings_Linq.EVENT_ADD_METHOD_SHOULD_TAKE_ONE_PARAMETER); } ParameterInfo[] parameters2 = removeMethod.GetParameters(); if (parameters2.Length != 1) { throw new InvalidOperationException(Strings_Linq.EVENT_REMOVE_METHOD_SHOULD_TAKE_ONE_PARAMETER); } isWinRT = false; if (addMethod.ReturnType == typeof(EventRegistrationToken)) { isWinRT = true; if (parameters2[0].ParameterType != typeof(EventRegistrationToken)) { throw new InvalidOperationException(Strings_Linq.EVENT_WINRT_REMOVE_METHOD_SHOULD_TAKE_ERT); } } delegateType = parameters[0].ParameterType; MethodInfo? method = delegateType.GetMethod("Invoke"); ParameterInfo[] parameters3 = method.GetParameters(); if (parameters3.Length != 2) { throw new InvalidOperationException(Strings_Linq.EVENT_PATTERN_REQUIRES_TWO_PARAMETERS); } if (!typeof(TSender).IsAssignableFrom(parameters3[0].ParameterType)) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.EVENT_SENDER_NOT_ASSIGNABLE, typeof(TSender).FullName)); } if (!typeof(TEventArgs).IsAssignableFrom(parameters3[1].ParameterType)) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.EVENT_ARGS_NOT_ASSIGNABLE, typeof(TEventArgs).FullName)); } if (method.ReturnType != typeof(void)) { throw new InvalidOperationException(Strings_Linq.EVENT_MUST_RETURN_VOID); } } public static EventInfo GetEventEx(this Type type, string name, bool isStatic) { return type.GetEvent(name, isStatic ? (BindingFlags.Static | BindingFlags.Public) : (BindingFlags.Instance | BindingFlags.Public)); } } internal abstract class SafeObserver<TSource> : ISafeObserver<TSource>, IObserver<TSource>, IDisposable { private sealed class WrappingSafeObserver : SafeObserver<TSource> { private readonly IObserver<TSource> _observer; public WrappingSafeObserver(IObserver<TSource> observer) { _observer = observer; } public override void OnNext(TSource value) { bool flag = false; try { _observer.OnNext(value); flag = true; } finally { if (!flag) { Dispose(); } } } public override void OnError(Exception error) { using (this) { _observer.OnError(error); } } public override void OnCompleted() { using (this) { _observer.OnCompleted(); } } } private IDisposable _disposable; public static ISafeObserver<TSource> Wrap(IObserver<TSource> observer) { if (observer is AnonymousObserver<TSource> anonymousObserver) { return anonymousObserver.MakeSafe(); } return new WrappingSafeObserver(observer); } public abstract void OnNext(TSource value); public abstract void OnError(Exception error); public abstract void OnCompleted(); public void SetResource(IDisposable resource) { Disposable.SetSingle(ref _disposable, resource); } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (disposing) { Disposable.TryDispose(ref _disposable); } } } internal class ScheduledObserver<T> : ObserverBase<T>, IScheduledObserver<T>, IObserver<T>, IDisposable { private sealed class SemaphoreSlimRelease : IDisposable { private SemaphoreSlim _dispatcherEvent; public SemaphoreSlimRelease(SemaphoreSlim dispatcherEvent) { Volatile.Write(ref _dispatcherEvent, dispatcherEvent); } public void Dispose() { Interlocked.Exchange(ref _dispatcherEvent, null)?.Release(); } } private int _state; private const int Stopped = 0; private const int Running = 1; private const int Pending = 2; private const int Faulted = 9; private readonly ConcurrentQueue<T> _queue = new ConcurrentQueue<T>(); private bool _failed; private Exception _error; private bool _completed; private readonly IObserver<T> _observer; private readonly IScheduler _scheduler; private readonly ISchedulerLongRunning _longRunning; private IDisposable _disposable; private readonly object _dispatcherInitGate = new object(); private readonly SemaphoreSlim _dispatcherEvent; private readonly IDisposable _dispatcherEventRelease; private IDisposable _dispatcherJob; public ScheduledObserver(IScheduler scheduler, IObserver<T> observer) { _scheduler = scheduler; _observer = observer; _longRunning = _scheduler.AsLongRunning(); if (_longRunning != null) { _dispatcherEvent = new SemaphoreSlim(0); _dispatcherEventRelease = new SemaphoreSlimRelease(_dispatcherEvent); } } private void EnsureDispatcher() { if (_dispatcherJob != null) { return; } lock (_dispatcherInitGate) { if (_dispatcherJob == null) { _dispatcherJob = _longRunning.ScheduleLongRunning(Dispatch); Disposable.TrySetSerial(ref _disposable, StableCompositeDisposable.Create(_dispatcherJob, _dispatcherEventRelease)); } } } private void Dispatch(ICancelable cancel) { do { _dispatcherEvent.Wait(); if (cancel.IsDisposed) { return; } T result = default(T); while (_queue.TryDequeue(out result)) { try { _observer.OnNext(result); } catch { T result2; while (_queue.TryDequeue(out result2)) { } throw; } _dispatcherEvent.Wait(); if (cancel.IsDisposed) { return; } } if (_failed) { _observer.OnError(_error); Dispose(); return; } } while (!_completed); _observer.OnCompleted(); Dispose(); } public void EnsureActive() { EnsureActive(1); } public void EnsureActive(int n) { if (_longRunning != null) { if (n > 0) { _dispatcherEvent.Release(n); } EnsureDispatcher(); } else { EnsureActiveSlow(); } } private void EnsureActiveSlow() { bool flag = false; do { IL_0002: switch (Interlocked.CompareExchange(ref _state, 1, 0)) { default: goto IL_0002; case 0: flag = true; break; case 9: return; case 1: continue; case 2: break; } break; } while (Interlocked.CompareExchange(ref _state, 2, 1) != 1); if (flag) { Disposable.TrySetSerial(ref _disposable, _scheduler.Schedule<object>(null, Run)); } } private void Run(object state, Action<object> recurse) { T result = default(T); while (!_queue.TryDequeue(out result)) { if (_failed) { if (_queue.IsEmpty) { Interlocked.Exchange(ref _state, 0); _observer.OnError(_error); Dispose(); return; } } else if (_completed) { if (_queue.IsEmpty) { Interlocked.Exchange(ref _state, 0); _observer.OnCompleted(); Dispose(); return; } } else { int num = Interlocked.CompareExchange(ref _state, 0, 1); if (num == 1 || num == 9) { return; } _state = 1; } } Interlocked.Exchange(ref _state, 1); try { _observer.OnNext(result); } catch { Interlocked.Exchange(ref _state, 9); T result2; while (_queue.TryDequeue(out result2)) { } throw; } recurse(state); } protected override void OnNextCore(T value) { _queue.Enqueue(value); } protected override void OnErrorCore(Exception exception) { _error = exception; _failed = true; } protected override void OnCompletedCore() { _completed = true; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { Disposable.TryDispose(ref _disposable); } } } internal sealed class ObserveOnObserver<T> : ScheduledObserver<T> { private IDisposable _run; public ObserveOnObserver(IScheduler scheduler, IObserver<T> observer) : base(scheduler, observer) { } public void Run(IObservable<T> source) { Disposable.SetSingle(ref _run, source.SubscribeSafe(this)); } protected override void OnNextCore(T value) { base.OnNextCore(value); EnsureActive(); } protected override void OnErrorCore(Exception exception) { base.OnErrorCore(exception); EnsureActive(); } protected override void OnCompletedCore() { base.OnCompletedCore(); EnsureActive(); } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { Disposable.TryDispose(ref _run); } } } internal interface IScheduledObserver<T> : IObserver<T>, IDisposable { void EnsureActive(); void EnsureActive(int count); } internal sealed class ObserveOnObserverNew<T> : IdentitySink<T> { private readonly IScheduler _scheduler; private readonly ConcurrentQueue<T> _queue; private IDisposable _task; private int _wip; private bool _done; private Exception _error; private bool _disposed; private static readonly Func<IScheduler, ObserveOnObserverNew<T>, IDisposable> DrainShortRunningFunc = (IScheduler scheduler, ObserveOnObserverNew<T> self) => self.DrainShortRunning(scheduler); public ObserveOnObserverNew(IScheduler scheduler, IObserver<T> downstream) : base(downstream) { _scheduler = scheduler; _queue = new ConcurrentQueue<T>(); } protected override void Dispose(bool disposing) { Volatile.Write(ref _disposed, value: true); base.Dispose(disposing); if (disposing) { Disposable.TryDispose(ref _task); Clear(_queue); } } private void Clear(ConcurrentQueue<T> q) { T result; while (q.TryDequeue(out result)) { } } public override void OnCompleted() { Volatile.Write(ref _done, value: true); Schedule(); } public override void OnError(Exception error) { _error = error; Volatile.Write(ref _done, value: true); Schedule(); } public override void OnNext(T value) { _queue.Enqueue(value); Schedule(); } private void Schedule() { if (Interlocked.Increment(ref _wip) == 1) { SingleAssignmentDisposable singleAssignmentDisposable = new SingleAssignmentDisposable(); if (Disposable.TrySetMultiple(ref _task, singleAssignmentDisposable)) { singleAssignmentDisposable.Disposable = _scheduler.Schedule(this, DrainShortRunningFunc); } if (Volatile.Read(ref _disposed)) { Clear(_queue); } } } private IDisposable DrainShortRunning(IScheduler recursiveScheduler) { DrainStep(_queue); if (Interlocked.Decrement(ref _wip) != 0) { IDisposable value = recursiveScheduler.Schedule(this, DrainShortRunningFunc); Disposable.TrySetMultiple(ref _task, value); } return Disposable.Empty; } private void DrainStep(ConcurrentQueue<T> q) { if (Volatile.Read(ref _disposed)) { Clear(q); return; } bool flag = Volatile.Read(ref _done); if (flag) { Exception error = _error; if (error != null) { Volatile.Write(ref _disposed, value: true); ForwardOnError(error); return; } } T result; bool flag2 = !q.TryDequeue(out result); if (flag && flag2) { Volatile.Write(ref _disposed, value: true); ForwardOnCompleted(); } else if (!flag2) { ForwardOnNext(result); } } } internal sealed class ObserveOnObserverLongRunning<TSource> : IdentitySink<TSource> { private readonly ISchedulerLongRunning _scheduler; private readonly ConcurrentQueue<TSource> _queue; private readonly object _suspendGuard; private long _wip; private bool _done; private Exception _error; private bool _disposed; private int _runDrainOnce; private IDisposable _drainTask; private static readonly Action<ObserveOnObserverLongRunning<TSource>, ICancelable> DrainLongRunning = delegate(ObserveOnObserverLongRunning<TSource> self, ICancelable cancelable) { self.Drain(); }; public ObserveOnObserverLongRunning(ISchedulerLongRunning scheduler, IObserver<TSource> observer) : base(observer) { _scheduler = scheduler; _queue = new ConcurrentQueue<TSource>(); _suspendGuard = new object(); } public override void OnCompleted() { Volatile.Write(ref _done, value: true); Schedule(); } public override void OnError(Exception error) { _error = error; Volatile.Write(ref _done, value: true); Schedule(); } public override void OnNext(TSource value) { _queue.Enqueue(value); Schedule(); } private void Schedule() { if (Volatile.Read(ref _runDrainOnce) == 0 && Interlocked.CompareExchange(ref _runDrainOnce, 1, 0) == 0) { Disposable.SetSingle(ref _drainTask, _scheduler.ScheduleLongRunning(this, DrainLongRunning)); } if (Interlocked.Increment(ref _wip) == 1) { lock (_suspendGuard) { Monitor.Pulse(_suspendGuard); } } } protected override void Dispose(bool disposing) { Volatile.Write(ref _disposed, value: true); lock (_suspendGuard) { Monitor.Pulse(_suspendGuard); } Disposable.TryDispose(ref _drainTask); base.Dispose(disposing); } private void Drain() { ConcurrentQueue<TSource> queue = _queue; while (true) { if (Volatile.Read(ref _disposed)) { TSource result; while (queue.TryDequeue(out result)) { } return; } bool num = Volatile.Read(ref _done); TSource result2; bool flag = queue.TryDequeue(out result2); if (num && !flag) { break; } if (flag) { ForwardOnNext(result2); if (Interlocked.Decrement(ref _wip) != 0L) { continue; } } if (Volatile.Read(ref _wip) != 0L || Volatile.Read(ref _disposed)) { continue; } object suspendGuard = _suspendGuard; if (Monitor.TryEnter(suspendGuard)) { if (Volatile.Read(ref _wip) == 0L && !Volatile.Read(ref _disposed)) { Monitor.Wait(suspendGuard); } Monitor.Exit(suspendGuard); } } Exception error = _error; if (error != null) { ForwardOnError(error); } else { ForwardOnCompleted(); } } } internal interface ISink<in TTarget> { void ForwardOnNext(TTarget value); void ForwardOnCompleted(); void ForwardOnError(Exception error); } internal abstract class Sink<TTarget> : ISink<TTarget>, IDisposable { private IDisposable _upstream; private volatile IObserver<TTarget> _observer; protected Sink(IObserver<TTarget> observer) { _observer = observer; } public void Dispose() { if (Interlocked.Exchange(ref _observer, NopObserver<TTarget>.Instance) != NopObserver<TTarget>.Instance) { Dispose(disposing: true); } } protected virtual void Dispose(bool disposing) { Disposable.TryDispose(ref _upstream); } public void ForwardOnNext(TTarget value) { _observer.OnNext(value); } public void ForwardOnCompleted() { _observer.OnCompleted(); Dispose(); } public void ForwardOnError(Exception error) { _observer.OnError(error); Dispose(); } protected void SetUpstream(IDisposable upstream) { Disposable.SetSingle(ref _upstream, upstream); } protected void DisposeUpstream() { Disposable.TryDispose(ref _upstream); } } internal abstract class Sink<TSource, TTarget> : Sink<TTarget>, IObserver<TSource> { private sealed class @_ : IObserver<TTarget> { private readonly Sink<TSource, TTarget> _forward; public _(Sink<TSource, TTarget> forward) { _forward = forward; } public void OnNext(TTarget value) { _forward.ForwardOnNext(value); } public void OnError(Exception error) { _forward.ForwardOnError(error); } public void OnCompleted() { _forward.ForwardOnCompleted(); } } protected Sink(IObserver<TTarget> observer) : base(observer) { } public virtual void Run(IObservable<TSource> source) { SetUpstream(source.SubscribeSafe(this)); } public abstract void OnNext(TSource value); public virtual void OnError(Exception error) { ForwardOnError(error); } public virtual void OnCompleted() { ForwardOnCompleted(); } public IObserver<TTarget> GetForwarder() { return new @_(this); } } internal static class Stubs<T> { public static readonly Action<T> Ignore = delegate { }; public static readonly Func<T, T> I = (T _) => _; } internal static class Stubs { public static readonly Action Nop = delegate { }; public static readonly Action<Exception> Throw = delegate(Exception ex) { ex.Throw(); }; } internal static class TimerStubs { public static readonly System.Threading.Timer Never = new System.Threading.Timer(delegate { }); } internal sealed class SynchronizedObserver<T> : ObserverBase<T> { private readonly object _gate; private readonly IObserver<T> _observer; public SynchronizedObserver(IObserver<T> observer, object gate) { _gate = gate; _observer = observer; } protected override void OnNextCore(T value) { lock (_gate) { _observer.OnNext(value); } } protected override void OnErrorCore(Exception exception) { lock (_gate) { _observer.OnError(exception); } } protected override void OnCompletedCore() { lock (_gate) { _observer.OnCompleted(); } } } internal abstract class TailRecursiveSink<TSource> : IdentitySink<TSource> { private bool _isDisposed; private int _trampoline; private IDisposable _currentSubscription; private readonly Stack<IEnumerator<IObservable<TSource>>> _stack = new Stack<IEnumerator<IObservable<TSource>>>(); protected TailRecursiveSink(IObserver<TSource> observer) : base(observer) { } public void Run(IEnumerable<IObservable<TSource>> sources) { if (TryGetEnumerator(sources, out var result)) { _stack.Push(result); Drain(); } } protected override void Dispose(bool disposing) { if (disposing) { DisposeAll(); } base.Dispose(disposing); } private void Drain() { if (Interlocked.Increment(ref _trampoline) != 1) { return; } do { IL_000f: if (Volatile.Read(ref _isDisposed)) { while (_stack.Count != 0) { _stack.Pop().Dispose(); } Disposable.TryDispose(ref _currentSubscription); } else if (_stack.Count != 0) { IEnumerator<IObservable<TSource>> enumerator = _stack.Peek(); IObservable<TSource> source = null; IObservable<TSource> observable = null; try { if (enumerator.MoveNext()) { source = enumerator.Current; } } catch (Exception error) { enumerator.Dispose(); ForwardOnError(error); Volatile.Write(ref _isDisposed, value: true); goto IL_000f; } try { observable = Helpers.Unpack(source); } catch (Exception error2) { observable = null; if (!Fail(error2)) { Volatile.Write(ref _isDisposed, value: true); } goto IL_000f; } if (observable == null) { _stack.Pop(); enumerator.Dispose(); goto IL_000f; } IEnumerable<IObservable<TSource>> enumerable = Extract(observable); if (enumerable != null) { if (TryGetEnumerator(enumerable, out var result)) { _stack.Push(result); } else { Volatile.Write(ref _isDisposed, value: true); } goto IL_000f; } IDisposable ready = ReadyToken.Ready; if (Disposable.TrySetSingle(ref _currentSubscription, ready) != 0) { goto IL_000f; } IDisposable disposable = observable.SubscribeSafe(this); IDisposable disposable2 = Interlocked.CompareExchange(ref _currentSubscription, disposable, ready); if (disposable2 != ready) { disposable.Dispose(); if (disposable2 == BooleanDisposable.True) { goto IL_000f; } } } else { Volatile.Write(ref _isDisposed, value: true); Done(); } } while (Interlocked.Decrement(ref _trampoline) != 0); } private void DisposeAll() { Volatile.Write(ref _isDisposed, value: true); Drain(); } protected void Recurse() { if (Disposable.TrySetSerial(ref _currentSubscription, null)) { Drain(); } } protected abstract IEnumerable<IObservable<TSource>> Extract(IObservable<TSource> source); private bool TryGetEnumerator(IEnumerable<IObservable<TSource>> sources, out IEnumerator<IObservable<TSource>> result) { try { result = sources.GetEnumerator(); return true; } catch (Exception error) { ForwardOnError(error); result = null; return false; } } protected virtual void Done() { ForwardOnCompleted(); } protected virtual bool Fail(Exception error) { ForwardOnError(error); return false; } } internal static class ReadyToken { private sealed class ReadyDisposable : IDisposable { public void Dispose() { } } internal static readonly IDisposable Ready = new ReadyDisposable(); } public interface IObserver<in TValue, out TResult> { TResult OnNext(TValue value); TResult OnError(Exception exception); TResult OnCompleted(); } [Experimental] public class ListObservable<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IObservable<object> { private readonly IDisposable _subscription; private readonly AsyncSubject<object> _subject = new AsyncSubject<object>(); private readonly List<T> _results = new List<T>(); public T Value { get { Wait(); if (_results.Count == 0) { throw new InvalidOperationException(Strings_Linq.NO_ELEMENTS); } return _results[_results.Count - 1]; } } public T this[int index] { get { Wait(); return _results[index]; } set { Wait(); _results[index] = value; } } public int Count { get { Wait(); return _results.Count; } } public bool IsReadOnly => false; public ListObservable(IObservable<T> source) { if (source == null) { throw new ArgumentNullException("source"); } _subscription = source.Subscribe(_results.Add, _subject.OnError, _subject.OnCompleted); } private void Wait() { _subject.DefaultIfEmpty().Wait(); } public int IndexOf(T item) { Wait(); return _results.IndexOf(item); } public void Insert(int index, T item) { Wait(); _results.Insert(index, item); } public void RemoveAt(int index) { Wait(); _results.RemoveAt(index); } public void Add(T item) { Wait(); _results.Add(item); } public void Clear() { Wait(); _results.Clear(); } public bool Contains(T item) { Wait(); return _results.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { Wait(); _results.CopyTo(array, arrayIndex); } public bool Remove(T item) { Wait(); return _results.Remove(item); } public IEnumerator<T> GetEnumerator() { Wait(); return _results.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IDisposable Subscribe(IObserver<object> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return StableCompositeDisposable.Create(_subscription, _subject.Subscribe(observer)); } } [CompilerGenerated] internal class NamespaceDoc { } public enum NotificationKind { OnNext, OnError, OnCompleted } [Serializable] public abstract class Notification<T> : IEquatable<Notification<T>> { [Serializable] [DebuggerDisplay("OnNext({Value})")] internal sealed class OnNextNotification : Notification<T> { public override T Value { get; } public override Exception Exception => null; public override bool HasValue => true; public override NotificationKind Kind => NotificationKind.OnNext; public OnNextNotification(T value) { Value = value; } public override int GetHashCode() { return EqualityComparer<T>.Default.GetHashCode(Value); } public override bool Equals(Notification<T> other) { if ((object)this == other) { return true; } if ((object)other == null) { return false; } if (other.Kind != 0) { return false; } return EqualityComparer<T>.Default.Equals(Value, other.Value); } public override string ToString() { return string.Format(CultureInfo.CurrentCulture, "OnNext({0})", Value); } public override void Accept(IObserver<T> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } observer.OnNext(Value); } public override TResult Accept<TResult>(IObserver<T, TResult> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return observer.OnNext(Value); } public override void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted) { if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } onNext(Value); } public override TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted) { if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } return onNext(Value); } } [Serializable] [DebuggerDisplay("OnError({Exception})")] internal sealed class OnErrorNotification : Notification<T> { public override T Value { get { Exception.Throw(); return default(T); } } public override Exception Exception { get; } public override bool HasValue => false; public override NotificationKind Kind => NotificationKind.OnError; public OnErrorNotification(Exception exception) { Exception = exception; } public override int GetHashCode() { return Exception.GetHashCode(); } public override bool Equals(Notification<T> other) { if ((object)this == other) { return true; } if ((object)other == null) { return false; } if (other.Kind != NotificationKind.OnError) { return false; } return object.Equals(Exception, other.Exception); } public override string ToString() { return string.Format(CultureInfo.CurrentCulture, "OnError({0})", Exception.GetType().FullName); } public override void Accept(IObserver<T> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } observer.OnError(Exception); } public override TResult Accept<TResult>(IObserver<T, TResult> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return observer.OnError(Exception); } public override void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted) { if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } onError(Exception); } public override TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted) { if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } return onError(Exception); } } [Serializable] [DebuggerDisplay("OnCompleted()")] internal sealed class OnCompletedNotification : Notification<T> { internal static readonly Notification<T> Instance = new OnCompletedNotification(); public override T Value { get { throw new InvalidOperationException(Strings_Core.COMPLETED_NO_VALUE); } } public override Exception Exception => null; public override bool HasValue => false; public override NotificationKind Kind => NotificationKind.OnCompleted; private OnCompletedNotification() { } public override int GetHashCode() { return typeof(T).GetHashCode() ^ 0x213E; } public override bool Equals(Notification<T> other) { if ((object)this == other) { return true; } if ((object)other == null) { return false; } return other.Kind == NotificationKind.OnCompleted; } public override string ToString() { return "OnCompleted()"; } public override void Accept(IObserver<T> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } observer.OnCompleted(); } public override TResult Accept<TResult>(IObserver<T, TResult> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return observer.OnCompleted(); } public override void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted) { if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } onCompleted(); } public override TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted) { if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } return onCompleted(); } } private sealed class NotificationToObservable : ObservableBase<T> { private readonly IScheduler _scheduler; private readonly Notification<T> _parent; public NotificationToObservable(IScheduler scheduler, Notification<T> parent) { _scheduler = scheduler; _parent = parent; } protected override IDisposable SubscribeCore(IObserver<T> observer) { return _scheduler.ScheduleAction((_parent, observer), delegate((Notification<T> _parent, IObserver<T> observer) state) { var (notification, observer2) = state; notification.Accept(observer2); if (notification.Kind == NotificationKind.OnNext) { observer2.OnCompleted(); } }); } } public abstract T Value { get; } public abstract bool HasValue { get; } public abstract Exception Exception { get; } public abstract NotificationKind Kind { get; } protected internal Notification() { } public abstract bool Equals(Notification<T> other); public static bool operator ==(Notification<T> left, Notification<T> right) { if ((object)left == right) { return true; } if ((object)left == null || (object)right == null) { return false; } return left.Equals(right); } public static bool operator !=(Notification<T> left, Notification<T> right) { return !(left == right); } public override bool Equals(object obj) { return Equals(obj as Notification<T>); } public abstract void Accept(IObserver<T> observer); public abstract TResult Accept<TResult>(IObserver<T, TResult> observer); public abstract void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted); public abstract TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted); public IObservable<T> ToObservable() { return ToObservable(ImmediateScheduler.Instance); } public IObservable<T> ToObservable(IScheduler scheduler) { if (scheduler == null) { throw new ArgumentNullException("scheduler"); } return new NotificationToObservable(scheduler, this); } } public static class Notification { public static Notification<T> CreateOnNext<T>(T value) { return new Notification<T>.OnNextNotification(value); } public static Notification<T> CreateOnError<T>(Exception error) { if (error == null) { throw new ArgumentNullException("error"); } return new Notification<T>.OnErrorNotification(error); } public static Notification<T> CreateOnCompleted<T>() { return Notification<T>.OnCompletedNotification.Instance; } } public abstract class ObservableBase<T> : IObservable<T> { public IDisposable Subscribe(IObserver<T> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } AutoDetachObserver<T> autoDetachObserver = new AutoDetachObserver<T>(observer); if (CurrentThreadScheduler.IsScheduleRequired) { ((IScheduler)CurrentThreadScheduler.Instance).ScheduleAction(autoDetachObserver, (Action<AutoDetachObserver<T>>)ScheduledSubscribe); } else { try { autoDetachObserver.SetResource(SubscribeCore(autoDetachObserver)); } catch (Exception error) { if (!autoDetachObserver.Fail(error)) { throw; } } } return autoDetachObserver; } private void ScheduledSubscribe(AutoDetachObserver<T> autoDetachObserver) { try { autoDetachObserver.SetResource(SubscribeCore(autoDetachObserver)); } catch (Exception error) { if (!autoDetachObserver.Fail(error)) { throw; } } } protected abstract IDisposable SubscribeCore(IObserver<T> observer); } internal class ObservableQueryProvider : IQbservableProvider, IQueryProvider { private static MethodInfo _staticAsQueryable; private static MethodInfo AsQueryable { get { if (_staticAsQueryable == null) { _staticAsQueryable = Qbservable.InfoOf((Expression<Func<object>>)(() => ((IEnumerable<object>)null).AsQueryable())).GetGenericMethodDefinition(); } return _staticAsQueryable; } } public IQbservable<TResult> CreateQuery<TResult>(Expression expression) { if (expression == null) { throw new ArgumentNullException("expression"); } if (!typeof(IObservable<TResult>).IsAssignableFrom(expression.Type)) { throw new ArgumentException(Strings_Providers.INVALID_TREE_TYPE, "expression"); } return new ObservableQuery<TResult>(expression); } IQueryable<TElement> IQueryProvider.CreateQuery<TElement>(Expression expression) { if (!(expression is MethodCallExpression methodCallExpression) || methodCallExpression.Method.DeclaringType != typeof(Qbservable) || methodCallExpression.Method.Name != "ToQueryable") { throw new ArgumentException(Strings_Providers.EXPECTED_TOQUERYABLE_METHODCALL, "expression"); } Expression arg = methodCallExpression.Arguments[0]; return Expression.Lambda<Func<IQueryable<TElement>>>(Expression.Call(AsQueryable.MakeGenericMethod(typeof(TElement)), Expression.Call(typeof(Observable).GetMethod("ToEnumerable").MakeGenericMethod(typeof(TElement)), arg)), Array.Empty<ParameterExpression>()).Compile()(); } IQueryable IQueryProvider.CreateQuery(Expression expression) { throw new NotImplementedException(); } TResult IQueryProvider.Execute<TResult>(Expression expression) { throw new NotImplementedException(); } object IQueryProvider.Execute(Expression expression) { throw new NotImplementedException(); } } internal class ObservableQuery { protected object _source; protected Expression _expression; public object Source => _source; public Expression Expression => _expression; } internal class ObservableQuery<TSource> : ObservableQuery, IQbservable<TSource>, IQbservable, IObservable<TSource> { private class ObservableRewriter : ExpressionVisitor { private class Lazy<T> { private readonly Func<T> _factory; private T _value; private bool _initialized; public T Value { get { lock (_factory) { if (!_initialized) { _value = _factory(); _initialized = true; } } return _value; } } public Lazy(Func<T> factory) { _factory = factory; } } private static readonly Lazy<ILookup<string, MethodInfo>> ObservableMethods = new Lazy<ILookup<string, MethodInfo>>(() => GetMethods(typeof(Observable))); protected override Expression VisitConstant(ConstantExpression node) { if (node.Value is ObservableQuery observableQuery) { object source = observableQuery.Source; if (source != null) { return Expression.Constant(source); } return Visit(observableQuery.Expression); } return node; } protected override Expression VisitMethodCall(MethodCallExpression node) { MethodInfo method = node.Method; if (method.DeclaringType.BaseType == typeof(QueryablePattern)) { if (method.Name == "Then") { return Expression.Call(Visit(node.Object), arguments: node.Arguments.Select((Expression arg) => Unquote(Visit(arg))).ToArray(), methodName: "Then", typeArguments: method.GetGenericArguments()); } if (method.Name == "And") { return Expression.Call(Visit(node.Object), arguments: node.Arguments.Select((Expression arg) => Visit(arg)).ToArray(), methodName: "And", typeArguments: method.GetGenericArguments()); } } else { IEnumerable<Expression> enumerable = node.Arguments.AsEnumerable(); bool flag = false; ParameterInfo parameterInfo = method.GetParameters().FirstOrDefault(); if (parameterInfo != null) { Type parameterType = parameterInfo.ParameterType; if (parameterType == typeof(IQbservableProvider)) { flag = true; if (!(Expression.Lambda<Func<IQbservableProvider>>(Visit(node.Arguments[0]), Array.Empty<ParameterExpression>()).Compile()() is ObservableQueryProvider)) { return node; } enumerable = enumerable.Skip(1); } else if (typeof(IQbservable).IsAssignableFrom(parameterType)) { flag = true; } } if (flag) { IList<Expression> arguments3 = VisitQbservableOperatorArguments(method, enumerable); return FindObservableMethod(method, arguments3); } } return base.VisitMethodCall(node); } protected override Expression VisitLambda<T>(Expression<T> node) { return node; } private IList<Expression> VisitQbservableOperatorArguments(MethodInfo method, IEnumerable<Expression> arguments) { if (method.Name == "When") { Expression expression = arguments.Last(); if (expression.NodeType == ExpressionType.NewArrayInit) { NewArrayExpression newArrayExpression = (NewArrayExpression)expression; List<Expression> list = new List<Expression>(); list.Add(Expression.NewArrayInit(typeof(Plan<>).MakeGenericType(method.GetGenericArguments()[0]), newArrayExpression.Expressions.Select((Expression param) => Visit(param)))); return list; } } return arguments.Select((Expression arg) => Visit(arg)).ToList(); } private static MethodCallExpression FindObservableMethod(MethodInfo method, IList<Expression> arguments) { Type type = null; ILookup<string, MethodInfo> lookup = null; if (method.DeclaringType == typeof(Qbservable)) { type = typeof(Observable); lookup = ObservableMethods.Value; } else { type = method.DeclaringType; if (type.IsDefined(typeof(LocalQueryMethodImplementationTypeAttribute), inherit: false)) { type = ((LocalQueryMethodImplementationTypeAttribute)type.GetCustomAttributes(typeof(LocalQueryMethodImplementationTypeAttribute), inherit: false)[0]).TargetType; } lookup = GetMethods(type); } Type[] typeArgs = (method.IsGenericMethod ? method.GetGenericArguments() : null); MethodInfo methodInfo = lookup[method.Name].FirstOrDefault((MethodInfo candidateMethod) => ArgsMatch(candidateMethod, arguments, typeArgs)); if (methodInfo == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Providers.NO_MATCHING_METHOD_FOUND, method.Name, type.Name)); } if (typeArgs != null) { methodInfo = methodInfo.MakeGenericMethod(typeArgs); } ParameterInfo[] parameters = methodInfo.GetParameters(); int i = 0; for (int num = parameters.Length; i < num; i++) { arguments[i] = Unquote(arguments[i]); } return Expression.Call(null, methodInfo, arguments); } private static ILookup<string, MethodInfo> GetMethods(Type type) { return type.GetMethods(BindingFlags.Static | BindingFlags.Public).ToLookup((MethodInfo m) => m.Name); } private static bool ArgsMatch(MethodInfo method, IList<Expression> arguments, Type[] typeArgs) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length != arguments.Count) { return false; } if (!method.IsGenericMethod && typeArgs != null && typeArgs.Length != 0) { return false; } if (method.IsGenericMethodDefinition) { if (typeArgs == null) { return false; } if (method.GetGenericArguments().Length != typeArgs.Length) { return false; } parameters = method.MakeGenericMethod(typeArgs).GetParameters(); } int i = 0; for (int count = arguments.Count; i < count; i++) { Type parameterType = parameters[i].ParameterType; Expression expression = arguments[i]; if (!parameterType.IsAssignableFrom(expression.Type)) { expression = Unquote(expression); if (!parameterType.IsAssignableFrom(expression.Type)) { return false; } } } return true; } private static Expression Unquote(Expression expression) { while (expression.NodeType == ExpressionType.Quote) { expression = ((UnaryExpression)expression).Operand; } return expression; } } public Type ElementType => typeof(TSource); public IQbservableProvider Provider => Qbservable.Provider; internal ObservableQuery(IObservable<TSource> source) { _source = source; _expression = Expression.Constant(this); } internal ObservableQuery(Expression expression) { _expression = expression; } public IDisposable Subscribe(IObserver<TSource> observer) { if (_source == null) { Expression<Func<IObservable<TSource>>> expression = Expression.Lambda<Func<IObservable<TSource>>>(new ObservableRewriter().Visit(_expression), Array.Empty<ParameterExpression>()); _source = expression.Compile()(); } return ((IObservable<TSource>)_source).Subscribe(observer); } public override string ToString() { if (_expression is ConstantExpression constantExpression && constantExpression.Value == this) { if (_source != null) { return _source.ToString(); } return "null"; } return _expression.ToString(); } } public static class Observer { private class AnonymousProgress<T> : IProgress<T> { private readonly Action<T> _progress; public AnonymousProgress(Action<T> progress) { _progress = progress; } public void Report(T value) { _progress(value); } } public static IObserver<T> ToObserver<T>(this Action<Notification<T>> handler) { if (handler == null) { throw new ArgumentNullException("handler"); } return new AnonymousObserver<T>(delegate(T x) { handler(Notification.CreateOnNext(x)); }, delegate(Exception exception) { handler(Notification.CreateOnError<T>(exception)); }, delegate { handler(Notification.CreateOnCompleted<T>()); }); } public static Action<Notification<T>> ToNotifier<T>(this IObserver<T> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return delegate(Notification<T> n) { n.Accept(observer); }; } public static IObserver<T> Create<T>(Action<T> onNext) { if (onNext == null) { throw new ArgumentNullException("onNext"); } return new AnonymousObserver<T>(onNext); } public static IObserver<T> Create<T>(Action<T> onNext, Action<Exception> onError) { if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } return new AnonymousObserver<T>(onNext, onError); } public static IObserver<T> Create<T>(Action<T> onNext, Action onCompleted) { if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } return new AnonymousObserver<T>(onNext, onCompleted); } public static IObserver<T> Create<T>(Action<T> onNext, Action<Exception> onError, Action onCompleted) { if (onNext == null) { throw new ArgumentNullException("onNext"); } if (onError == null) { throw new ArgumentNullException("onError"); } if (onCompleted == null) { throw new ArgumentNullException("onCompleted"); } return new AnonymousObserver<T>(onNext, onError, onCompleted); } public static IObserver<T> AsObserver<T>(this IObserver<T> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return new AnonymousObserver<T>(observer.OnNext, observer.OnError, observer.OnCompleted); } public static IObserver<T> Checked<T>(this IObserver<T> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return new CheckedObserver<T>(observer); } public static IObserver<T> Synchronize<T>(IObserver<T> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return new SynchronizedObserver<T>(observer, new object()); } public static IObserver<T> Synchronize<T>(IObserver<T> observer, bool preventReentrancy) { if (observer == null) { throw new ArgumentNullException("observer"); } if (preventReentrancy) { return new AsyncLockObserver<T>(observer, new AsyncLock()); } return new SynchronizedObserver<T>(observer, new object()); } public static IObserver<T> Synchronize<T>(IObserver<T> observer, object gate) { if (observer == null) { throw new ArgumentNullException("observer"); } if (gate == null) { throw new ArgumentNullException("gate"); } return new SynchronizedObserver<T>(observer, gate); } public static IObserver<T> Synchronize<T>(IObserver<T> observer, AsyncLock asyncLock) { if (observer == null) { throw new ArgumentNullException("observer"); } if (asyncLock == null) { throw new ArgumentNullException("asyncLock"); } return new AsyncLockObserver<T>(observer, asyncLock); } public static IObserver<T> NotifyOn<T>(this IObserver<T> observer, IScheduler scheduler) { if (observer == null) { throw new ArgumentNullException("observer"); } if (scheduler == null) { throw new ArgumentNullException("scheduler"); } return new ObserveOnObserver<T>(scheduler, observer); } public static IObserver<T> NotifyOn<T>(this IObserver<T> observer, SynchronizationContext context) { if (observer == null) { throw new ArgumentNullException("observer"); } if (context == null) { throw new ArgumentNullException("context"); } return new ObserveOnObserver<T>(new SynchronizationContextScheduler(context), observer); } public static IProgress<T> ToProgress<T>(this IObserver<T> observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return new AnonymousProgress<T>(observer.OnNext); } public static IProgress<T> ToProgress<T>(this IObserver<T> observer, IScheduler scheduler) { if (observer == null) { throw new ArgumentNullException("observer"); } if (scheduler == null) { throw new ArgumentNullException("scheduler"); } return new AnonymousProgress<T>(new ObserveOnObserver<T>(scheduler, observer).OnNext); } public static IObserver<T> ToObserver<T>(this IProgress<T> progress) { if (progress == null) { throw new ArgumentNullException("progress"); } return new AnonymousObserver<T>(progress.Report); } } public abstract class ObserverBase<T> : IObserver<T>, IDisposable { private int _isStopped; protected ObserverBase() { _isStopped = 0; } public void OnNext(T value) { if (Volatile.Read(ref _isStopped) == 0) { OnNextCore(value); } } protected abstract void OnNextCore(T value); public void OnError(Exception error) { if (error == null) { throw new ArgumentNullException("error"); } if (Interlocked.Exchange(ref _isStopped, 1) == 0) { OnErrorCore(error); } } protected abstract void OnErrorCore(Exception error); public void OnCompleted() { if (Interlocked.Exchange(ref _isStopped, 1) == 0) { OnCompletedCore(); } } protected abstract void OnCompletedCore(); public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { Volatile.Write(ref _isStopped, 1); } } internal bool Fail(Exception error) { if (Interlocked.Exchange(ref _isStopped, 1) == 0) { OnErrorCore(error); return true; } return false; } } [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Strings_Core { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { resourceMan = new ResourceManager("System.Reactive.Strings_Core", typeof(Strings_Core).GetTypeInfo().Assembly); } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static string CANT_OBTAIN_SCHEDULER => ResourceManager.GetString("CANT_OBTAIN_SCHEDULER", resourceCulture); internal static string COMPLETED_NO_VALUE => ResourceManager.GetString("COMPLETED_NO_VALUE", resourceCulture); internal static string DISPOSABLE_ALREADY_ASSIGNED => ResourceManager.GetString("DISPOSABLE_ALREADY_ASSIGNED", resourceCulture); internal static string DISPOSABLES_CANT_CONTAIN_NULL => ResourceManager.GetString("DISPOSABLES_CANT_CONTAIN_NULL", resourceCulture); internal static string FAILED_CLOCK_MONITORING => ResourceManager.GetSt
UserLibs/Websocket.Client.dll
Decompiled a month ago#define TRACE using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Net.WebSockets; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Websocket.Client.Exceptions; using Websocket.Client.Logging; using Websocket.Client.Logging.LogProviders; using Websocket.Client.Models; using Websocket.Client.Threading; using Websocket.Client.Validations; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("Mariusz Kotas")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright 2020 Mariusz Kotas. All rights reserved.")] [assembly: AssemblyDescription("Client for websocket API with built-in reconnection and error handling")] [assembly: AssemblyFileVersion("4.4.0.0")] [assembly: AssemblyInformationalVersion("4.4.0")] [assembly: AssemblyProduct("Websocket.Client")] [assembly: AssemblyTitle("Websocket.Client")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Marfusios/websocket-client")] [assembly: AssemblyVersion("4.4.0.0")] 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; } } } namespace Websocket.Client { public interface IWebsocketClient : IDisposable { Uri Url { get; set; } IObservable<ResponseMessage> MessageReceived { get; } IObservable<ReconnectionInfo> ReconnectionHappened { get; } IObservable<DisconnectionInfo> DisconnectionHappened { get; } TimeSpan? ReconnectTimeout { get; set; } TimeSpan? ErrorReconnectTimeout { get; set; } string Name { get; set; } bool IsStarted { get; } bool IsRunning { get; } bool IsReconnectionEnabled { get; set; } bool IsTextMessageConversionEnabled { get; set; } ClientWebSocket NativeClient { get; } Encoding MessageEncoding { get; set; } Task Start(); Task StartOrFail(); Task<bool> Stop(WebSocketCloseStatus status, string statusDescription); Task<bool> StopOrFail(WebSocketCloseStatus status, string statusDescription); void Send(string message); void Send(byte[] message); void Send(ArraySegment<byte> message); Task SendInstant(string message); Task SendInstant(byte[] message); Task Reconnect(); Task ReconnectOrFail(); void StreamFakeMessage(ResponseMessage message); } public class DisconnectionInfo { public DisconnectionType Type { get; } public WebSocketCloseStatus? CloseStatus { get; } public string CloseStatusDescription { get; } public string SubProtocol { get; } public Exception Exception { get; } public bool CancelReconnection { get; set; } public bool CancelClosing { get; set; } public DisconnectionInfo(DisconnectionType type, WebSocketCloseStatus? closeStatus, string closeStatusDescription, string subProtocol, Exception exception) { Type = type; CloseStatus = closeStatus; CloseStatusDescription = closeStatusDescription; SubProtocol = subProtocol; Exception = exception; } public static DisconnectionInfo Create(DisconnectionType type, WebSocket client, Exception exception) { return new DisconnectionInfo(type, client?.CloseStatus, client?.CloseStatusDescription, client?.SubProtocol, exception); } } public enum DisconnectionType { Exit, Lost, NoMessageReceived, Error, ByUser, ByServer } public enum ReconnectionType { Initial, Lost, NoMessageReceived, Error, ByUser, ByServer } public class ResponseMessage { public string Text { get; } public byte[] Binary { get; } public WebSocketMessageType MessageType { get; } private ResponseMessage(byte[] binary, string text, WebSocketMessageType messageType) { Binary = binary; Text = text; MessageType = messageType; } public override string ToString() { if (MessageType == WebSocketMessageType.Text) { return Text; } return $"Type binary, length: {Binary?.Length}"; } public static ResponseMessage TextMessage(string data) { return new ResponseMessage(null, data, WebSocketMessageType.Text); } public static ResponseMessage BinaryMessage(byte[] data) { return new ResponseMessage(data, null, WebSocketMessageType.Binary); } } public class WebsocketClient : IWebsocketClient, IDisposable { private static readonly ILog Logger = GetLogger(); private readonly WebsocketAsyncLock _locker = new WebsocketAsyncLock(); private readonly Func<Uri, CancellationToken, Task<WebSocket>> _connectionFactory; private Uri _url; private Timer _lastChanceTimer; private DateTime _lastReceivedMsg = DateTime.UtcNow; private bool _disposing; private bool _reconnecting; private bool _stopping; private bool _isReconnectionEnabled = true; private WebSocket _client; private CancellationTokenSource _cancellation; private CancellationTokenSource _cancellationTotal; private readonly Subject<ResponseMessage> _messageReceivedSubject = new Subject<ResponseMessage>(); private readonly Subject<ReconnectionInfo> _reconnectionSubject = new Subject<ReconnectionInfo>(); private readonly Subject<DisconnectionInfo> _disconnectedSubject = new Subject<DisconnectionInfo>(); private readonly Channel<string> _messagesTextToSendQueue = Channel.CreateUnbounded<string>(new UnboundedChannelOptions { SingleReader = true, SingleWriter = false }); private readonly Channel<ArraySegment<byte>> _messagesBinaryToSendQueue = Channel.CreateUnbounded<ArraySegment<byte>>(new UnboundedChannelOptions { SingleReader = true, SingleWriter = false }); public Uri Url { get { return _url; } set { Websocket.Client.Validations.Validations.ValidateInput(value, "Url"); _url = value; } } public IObservable<ResponseMessage> MessageReceived => Observable.AsObservable<ResponseMessage>((IObservable<ResponseMessage>)_messageReceivedSubject); public IObservable<ReconnectionInfo> ReconnectionHappened => Observable.AsObservable<ReconnectionInfo>((IObservable<ReconnectionInfo>)_reconnectionSubject); public IObservable<DisconnectionInfo> DisconnectionHappened => Observable.AsObservable<DisconnectionInfo>((IObservable<DisconnectionInfo>)_disconnectedSubject); public TimeSpan? ReconnectTimeout { get; set; } = TimeSpan.FromMinutes(1.0); public TimeSpan? ErrorReconnectTimeout { get; set; } = TimeSpan.FromMinutes(1.0); public bool IsReconnectionEnabled { get { return _isReconnectionEnabled; } set { _isReconnectionEnabled = value; if (IsStarted) { if (_isReconnectionEnabled) { ActivateLastChance(); } else { DeactivateLastChance(); } } } } public string Name { get; set; } public bool IsStarted { get; private set; } public bool IsRunning { get; private set; } public bool IsTextMessageConversionEnabled { get; set; } = true; public Encoding MessageEncoding { get; set; } public ClientWebSocket NativeClient => GetSpecificOrThrow(_client); public WebsocketClient(Uri url, Func<ClientWebSocket> clientFactory = null) : this(url, GetClientFactory(clientFactory)) { } public WebsocketClient(Uri url, Func<Uri, CancellationToken, Task<WebSocket>> connectionFactory) { Websocket.Client.Validations.Validations.ValidateInput(url, "url"); _url = url; _connectionFactory = connectionFactory ?? ((Func<Uri, CancellationToken, Task<WebSocket>>)async delegate(Uri uri, CancellationToken token) { ClientWebSocket client = new ClientWebSocket(); await client.ConnectAsync(uri, token).ConfigureAwait(continueOnCapturedContext: false); return client; }); } public void Dispose() { _disposing = true; Logger.Debug(L("Disposing..")); try { _messagesTextToSendQueue?.Writer.Complete(); _messagesBinaryToSendQueue?.Writer.Complete(); _lastChanceTimer?.Dispose(); _cancellation?.Cancel(); _cancellationTotal?.Cancel(); _client?.Abort(); _client?.Dispose(); _cancellation?.Dispose(); _cancellationTotal?.Dispose(); ((SubjectBase<ResponseMessage>)(object)_messageReceivedSubject).OnCompleted(); ((SubjectBase<ReconnectionInfo>)(object)_reconnectionSubject).OnCompleted(); } catch (Exception ex) { Logger.Error(ex, L("Failed to dispose client, error: " + ex.Message)); } IsRunning = false; IsStarted = false; ((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(DisconnectionInfo.Create(DisconnectionType.Exit, _client, null)); ((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnCompleted(); } public Task Start() { return StartInternal(failFast: false); } public Task StartOrFail() { return StartInternal(failFast: true); } public async Task<bool> Stop(WebSocketCloseStatus status, string statusDescription) { bool result = await StopInternal(_client, status, statusDescription, null, failFast: false, byServer: false).ConfigureAwait(continueOnCapturedContext: false); ((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(DisconnectionInfo.Create(DisconnectionType.ByUser, _client, null)); return result; } public async Task<bool> StopOrFail(WebSocketCloseStatus status, string statusDescription) { bool result = await StopInternal(_client, status, statusDescription, null, failFast: true, byServer: false).ConfigureAwait(continueOnCapturedContext: false); ((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(DisconnectionInfo.Create(DisconnectionType.ByUser, _client, null)); return result; } private static Func<Uri, CancellationToken, Task<WebSocket>> GetClientFactory(Func<ClientWebSocket> clientFactory) { if (clientFactory == null) { return null; } return async delegate(Uri uri, CancellationToken token) { ClientWebSocket client = clientFactory(); await client.ConnectAsync(uri, token).ConfigureAwait(continueOnCapturedContext: false); return client; }; } private async Task StartInternal(bool failFast) { if (_disposing) { throw new WebsocketException(L("Client is already disposed, starting not possible")); } if (IsStarted) { Logger.Debug(L("Client already started, ignoring..")); return; } IsStarted = true; Logger.Debug(L("Starting..")); _cancellation = new CancellationTokenSource(); _cancellationTotal = new CancellationTokenSource(); await StartClient(_url, _cancellation.Token, ReconnectionType.Initial, failFast).ConfigureAwait(continueOnCapturedContext: false); StartBackgroundThreadForSendingText(); StartBackgroundThreadForSendingBinary(); } private async Task<bool> StopInternal(WebSocket client, WebSocketCloseStatus status, string statusDescription, CancellationToken? cancellation, bool failFast, bool byServer) { if (_disposing) { throw new WebsocketException(L("Client is already disposed, stopping not possible")); } if (!IsRunning) { Logger.Info(L("Client is already stopped")); return false; } bool result = false; if (client == null) { IsStarted = false; IsRunning = false; return false; } DeactivateLastChance(); try { CancellationToken cancellationToken = cancellation ?? CancellationToken.None; _stopping = true; if (!byServer) { await client.CloseAsync(status, statusDescription, cancellationToken); } else { await client.CloseOutputAsync(status, statusDescription, cancellationToken); } result = true; } catch (Exception ex) { Logger.Error(ex, L("Error while stopping client, message: '" + ex.Message + "'")); if (failFast) { throw new WebsocketException("Failed to stop Websocket client, error: '" + ex.Message + "'", ex); } } finally { IsStarted = false; IsRunning = false; _stopping = false; } return result; } private async Task StartClient(Uri uri, CancellationToken token, ReconnectionType type, bool failFast) { DeactivateLastChance(); try { _client = await _connectionFactory(uri, token).ConfigureAwait(continueOnCapturedContext: false); Listen(_client, token); IsRunning = true; IsStarted = true; ((SubjectBase<ReconnectionInfo>)(object)_reconnectionSubject).OnNext(ReconnectionInfo.Create(type)); _lastReceivedMsg = DateTime.UtcNow; ActivateLastChance(); } catch (Exception e) { DisconnectionInfo disconnectionInfo = DisconnectionInfo.Create(DisconnectionType.Error, _client, e); ((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(disconnectionInfo); if (disconnectionInfo.CancelReconnection) { Logger.Error(e, L("Exception while connecting. Reconnecting canceled by user, exiting. Error: '" + e.Message + "'")); return; } if (failFast) { throw new WebsocketException("Failed to start Websocket client, error: '" + e.Message + "'", e); } if (!ErrorReconnectTimeout.HasValue) { Logger.Error(e, L("Exception while connecting. Reconnecting disabled, exiting. Error: '" + e.Message + "'")); return; } TimeSpan value = ErrorReconnectTimeout.Value; Logger.Error(e, L($"Exception while connecting. Waiting {value.TotalSeconds} sec before next reconnection try. Error: '{e.Message}'")); await Task.Delay(value, token).ConfigureAwait(continueOnCapturedContext: false); await Reconnect(ReconnectionType.Error, failFast: false, e).ConfigureAwait(continueOnCapturedContext: false); } } private bool IsClientConnected() { return _client.State == WebSocketState.Open; } private async Task Listen(WebSocket client, CancellationToken token) { Exception causedException = null; try { ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[4096]); do { byte[] resultArrayWithTrailing = null; int resultArraySize = 0; bool isResultArrayCloned = false; MemoryStream ms = null; WebSocketReceiveResult webSocketReceiveResult; while (true) { webSocketReceiveResult = await client.ReceiveAsync(buffer, token); byte[] array = buffer.Array; int count = webSocketReceiveResult.Count; if (resultArrayWithTrailing == null) { resultArraySize += count; resultArrayWithTrailing = array; isResultArrayCloned = false; } else if (array != null) { if (ms == null) { ms = new MemoryStream(); ms.Write(resultArrayWithTrailing, 0, resultArraySize); } ms.Write(array, buffer.Offset, count); } if (webSocketReceiveResult.EndOfMessage) { break; } if (!isResultArrayCloned) { resultArrayWithTrailing = resultArrayWithTrailing?.ToArray(); isResultArrayCloned = true; } } ms?.Seek(0L, SeekOrigin.Begin); ResponseMessage responseMessage; if (webSocketReceiveResult.MessageType == WebSocketMessageType.Text && IsTextMessageConversionEnabled) { responseMessage = ResponseMessage.TextMessage((ms != null) ? GetEncoding().GetString(ms.ToArray()) : ((resultArrayWithTrailing != null) ? GetEncoding().GetString(resultArrayWithTrailing, 0, resultArraySize) : null)); } else { if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close) { Logger.Trace(L("Received close message")); if (!IsStarted || _stopping) { return; } DisconnectionInfo disconnectionInfo = DisconnectionInfo.Create(DisconnectionType.ByServer, client, null); ((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(disconnectionInfo); if (disconnectionInfo.CancelClosing) { if (IsReconnectionEnabled) { throw new OperationCanceledException("Websocket connection was closed by server"); } continue; } await StopInternal(client, WebSocketCloseStatus.NormalClosure, "Closing", token, failFast: false, byServer: true); if (IsReconnectionEnabled && !ShouldIgnoreReconnection(client)) { ReconnectSynchronized(ReconnectionType.Lost, failFast: false, null); } return; } if (ms != null) { responseMessage = ResponseMessage.BinaryMessage(ms.ToArray()); } else { Array.Resize(ref resultArrayWithTrailing, resultArraySize); responseMessage = ResponseMessage.BinaryMessage(resultArrayWithTrailing); } } ms?.Dispose(); Logger.Trace(L($"Received: {responseMessage}")); _lastReceivedMsg = DateTime.UtcNow; ((SubjectBase<ResponseMessage>)(object)_messageReceivedSubject).OnNext(responseMessage); } while (client.State == WebSocketState.Open && !token.IsCancellationRequested); } catch (TaskCanceledException ex) { causedException = ex; } catch (OperationCanceledException ex2) { causedException = ex2; } catch (ObjectDisposedException ex3) { causedException = ex3; } catch (Exception ex4) { Logger.Error(ex4, L("Error while listening to websocket stream, error: '" + ex4.Message + "'")); causedException = ex4; } if (!ShouldIgnoreReconnection(client) && IsStarted) { ReconnectSynchronized(ReconnectionType.Lost, failFast: false, causedException); } } private bool ShouldIgnoreReconnection(WebSocket client) { bool num = _disposing || _reconnecting || _stopping; bool flag = client != _client; return num || flag; } private Encoding GetEncoding() { if (MessageEncoding == null) { MessageEncoding = Encoding.UTF8; } return MessageEncoding; } private ClientWebSocket GetSpecificOrThrow(WebSocket client) { if (client == null) { return null; } return (client as ClientWebSocket) ?? throw new WebsocketException("Cannot cast 'WebSocket' client to 'ClientWebSocket', provide correct type via factory or don't use this property at all."); } private string L(string msg) { string text = Name ?? "CLIENT"; return "[WEBSOCKET " + text + "] " + msg; } private static ILog GetLogger() { try { return LogProvider.GetCurrentClassLogger(); } catch (Exception value) { Trace.WriteLine($"[WEBSOCKET] Failed to initialize logger, disabling.. Error: {value}"); return LogProvider.NoOpLogger.Instance; } } private DisconnectionType TranslateTypeToDisconnection(ReconnectionType type) { return (DisconnectionType)type; } public Task Reconnect() { return ReconnectInternal(failFast: false); } public Task ReconnectOrFail() { return ReconnectInternal(failFast: true); } private async Task ReconnectInternal(bool failFast) { if (!IsStarted) { Logger.Debug(L("Client not started, ignoring reconnection..")); return; } try { await ReconnectSynchronized(ReconnectionType.ByUser, failFast, null).ConfigureAwait(continueOnCapturedContext: false); } finally { _reconnecting = false; } } private async Task ReconnectSynchronized(ReconnectionType type, bool failFast, Exception causedException) { using (await _locker.LockAsync()) { await Reconnect(type, failFast, causedException); } } private async Task Reconnect(ReconnectionType type, bool failFast, Exception causedException) { IsRunning = false; if (_disposing) { return; } _reconnecting = true; DisconnectionInfo disconnectionInfo = DisconnectionInfo.Create(TranslateTypeToDisconnection(type), _client, causedException); if (type != ReconnectionType.Error) { ((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(disconnectionInfo); if (disconnectionInfo.CancelReconnection) { Logger.Info(L("Reconnecting canceled by user, exiting.")); } } _cancellation.Cancel(); try { _client?.Abort(); } catch (Exception ex) { Logger.Error(ex, L("Exception while aborting client. Error: '" + ex.Message + "'")); } _client?.Dispose(); if (!IsReconnectionEnabled || disconnectionInfo.CancelReconnection) { IsStarted = false; _reconnecting = false; return; } Logger.Debug(L("Reconnecting...")); _cancellation = new CancellationTokenSource(); await StartClient(_url, _cancellation.Token, type, failFast).ConfigureAwait(continueOnCapturedContext: false); _reconnecting = false; } private void ActivateLastChance() { int num = 1000; _lastChanceTimer = new Timer(LastChance, null, num, num); } private void DeactivateLastChance() { _lastChanceTimer?.Dispose(); _lastChanceTimer = null; } private void LastChance(object state) { if (!IsReconnectionEnabled || !ReconnectTimeout.HasValue) { DeactivateLastChance(); return; } double num = Math.Abs(ReconnectTimeout.Value.TotalMilliseconds); if (Math.Abs(DateTime.UtcNow.Subtract(_lastReceivedMsg).TotalMilliseconds) > num) { Logger.Debug(L($"Last message received more than {num:F} ms ago. Hard restart..")); DeactivateLastChance(); ReconnectSynchronized(ReconnectionType.NoMessageReceived, failFast: false, null); } } public void Send(string message) { Websocket.Client.Validations.Validations.ValidateInput(message, "message"); _messagesTextToSendQueue.Writer.TryWrite(message); } public void Send(byte[] message) { Websocket.Client.Validations.Validations.ValidateInput(message, "message"); _messagesBinaryToSendQueue.Writer.TryWrite(new ArraySegment<byte>(message)); } public void Send(ArraySegment<byte> message) { Websocket.Client.Validations.Validations.ValidateInput(message, "message"); _messagesBinaryToSendQueue.Writer.TryWrite(message); } public Task SendInstant(string message) { Websocket.Client.Validations.Validations.ValidateInput(message, "message"); return SendInternalSynchronized(message); } public Task SendInstant(byte[] message) { return SendInternalSynchronized(new ArraySegment<byte>(message)); } public void StreamFakeMessage(ResponseMessage message) { Websocket.Client.Validations.Validations.ValidateInput(message, "message"); ((SubjectBase<ResponseMessage>)(object)_messageReceivedSubject).OnNext(message); } private async Task SendTextFromQueue() { _ = 1; try { while (await _messagesTextToSendQueue.Reader.WaitToReadAsync()) { string message; while (_messagesTextToSendQueue.Reader.TryRead(out message)) { try { await SendInternalSynchronized(message).ConfigureAwait(continueOnCapturedContext: false); } catch (Exception ex) { Logger.Error(ex, L("Failed to send text message: '" + message + "'. Error: " + ex.Message)); } } } } catch (TaskCanceledException) { } catch (OperationCanceledException) { } catch (Exception ex4) { if (!_cancellationTotal.IsCancellationRequested && !_disposing) { Logger.Trace(L("Sending text thread failed, error: " + ex4.Message + ". Creating a new sending thread.")); StartBackgroundThreadForSendingText(); } } } private async Task SendBinaryFromQueue() { _ = 1; try { while (await _messagesBinaryToSendQueue.Reader.WaitToReadAsync()) { ArraySegment<byte> message; while (_messagesBinaryToSendQueue.Reader.TryRead(out message)) { try { await SendInternalSynchronized(message).ConfigureAwait(continueOnCapturedContext: false); } catch (Exception ex) { Logger.Error(ex, L($"Failed to send binary message: '{message}'. Error: {ex.Message}")); } } } } catch (TaskCanceledException) { } catch (OperationCanceledException) { } catch (Exception ex4) { if (!_cancellationTotal.IsCancellationRequested && !_disposing) { Logger.Trace(L("Sending binary thread failed, error: " + ex4.Message + ". Creating a new sending thread.")); StartBackgroundThreadForSendingBinary(); } } } private void StartBackgroundThreadForSendingText() { Task.Factory.StartNew((object? _) => SendTextFromQueue(), TaskCreationOptions.LongRunning, _cancellationTotal.Token); } private void StartBackgroundThreadForSendingBinary() { Task.Factory.StartNew((object? _) => SendBinaryFromQueue(), TaskCreationOptions.LongRunning, _cancellationTotal.Token); } private async Task SendInternalSynchronized(string message) { using (await _locker.LockAsync()) { await SendInternal(message); } } private async Task SendInternal(string message) { if (!IsClientConnected()) { Logger.Debug(L("Client is not connected to server, cannot send: " + message)); return; } Logger.Trace(L("Sending: " + message)); byte[] bytes = GetEncoding().GetBytes(message); ArraySegment<byte> buffer = new ArraySegment<byte>(bytes); await _client.SendAsync(buffer, WebSocketMessageType.Text, endOfMessage: true, _cancellation.Token).ConfigureAwait(continueOnCapturedContext: false); } private async Task SendInternalSynchronized(ArraySegment<byte> message) { using (await _locker.LockAsync()) { await SendInternal(message); } } private async Task SendInternal(ArraySegment<byte> message) { if (!IsClientConnected()) { Logger.Debug(L($"Client is not connected to server, cannot send binary, length: {message.Count}")); } else { Logger.Trace(L($"Sending binary, length: {message.Count}")); await _client.SendAsync(message, WebSocketMessageType.Binary, endOfMessage: true, _cancellation.Token).ConfigureAwait(continueOnCapturedContext: false); } } } } namespace Websocket.Client.Logging { internal interface ILog { bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception = null, params object[] formatParameters); } public interface ILogProvider { Logger GetLogger(string name); IDisposable OpenNestedContext(string message); IDisposable OpenMappedContext(string key, object value, bool destructure = false); } internal static class LogExtensions { internal static readonly object[] EmptyParams = new object[0]; public static bool IsDebugEnabled(this ILog logger) { GuardAgainstNullLogger(logger); return logger.Log(LogLevel.Debug, null, null, EmptyParams); } public static bool IsErrorEnabled(this ILog logger) { GuardAgainstNullLogger(logger); return logger.Log(LogLevel.Error, null, null, EmptyParams); } public static bool IsFatalEnabled(this ILog logger) { GuardAgainstNullLogger(logger); return logger.Log(LogLevel.Fatal, null, null, EmptyParams); } public static bool IsInfoEnabled(this ILog logger) { GuardAgainstNullLogger(logger); return logger.Log(LogLevel.Info, null, null, EmptyParams); } public static bool IsTraceEnabled(this ILog logger) { GuardAgainstNullLogger(logger); return logger.Log(LogLevel.Trace, null, null, EmptyParams); } public static bool IsWarnEnabled(this ILog logger) { GuardAgainstNullLogger(logger); return logger.Log(LogLevel.Warn, null, null, EmptyParams); } public static void Debug(this ILog logger, Func<string> messageFunc) { GuardAgainstNullLogger(logger); logger.Log(LogLevel.Debug, WrapLogInternal(messageFunc), null, EmptyParams); } public static void Debug(this ILog logger, string message) { if (logger.IsDebugEnabled()) { logger.Log(LogLevel.Debug, message.AsFunc(), null, EmptyParams); } } public static void Debug(this ILog logger, string message, params object[] args) { logger.DebugFormat(message, args); } public static void Debug(this ILog logger, Exception exception, string message, params object[] args) { logger.DebugException(message, exception, args); } public static void DebugFormat(this ILog logger, string message, params object[] args) { if (logger.IsDebugEnabled()) { logger.LogFormat(LogLevel.Debug, message, args); } } public static void DebugException(this ILog logger, string message, Exception exception) { if (logger.IsDebugEnabled()) { logger.Log(LogLevel.Debug, message.AsFunc(), exception, EmptyParams); } } public static void DebugException(this ILog logger, string message, Exception exception, params object[] args) { if (logger.IsDebugEnabled()) { logger.Log(LogLevel.Debug, message.AsFunc(), exception, args); } } public static void Error(this ILog logger, Func<string> messageFunc) { GuardAgainstNullLogger(logger); logger.Log(LogLevel.Error, WrapLogInternal(messageFunc), null, EmptyParams); } public static void Error(this ILog logger, string message) { if (logger.IsErrorEnabled()) { logger.Log(LogLevel.Error, message.AsFunc(), null, EmptyParams); } } public static void Error(this ILog logger, string message, params object[] args) { logger.ErrorFormat(message, args); } public static void Error(this ILog logger, Exception exception, string message, params object[] args) { logger.ErrorException(message, exception, args); } public static void ErrorFormat(this ILog logger, string message, params object[] args) { if (logger.IsErrorEnabled()) { logger.LogFormat(LogLevel.Error, message, args); } } public static void ErrorException(this ILog logger, string message, Exception exception, params object[] args) { if (logger.IsErrorEnabled()) { logger.Log(LogLevel.Error, message.AsFunc(), exception, args); } } public static void Fatal(this ILog logger, Func<string> messageFunc) { logger.Log(LogLevel.Fatal, WrapLogInternal(messageFunc), null, EmptyParams); } public static void Fatal(this ILog logger, string message) { if (logger.IsFatalEnabled()) { logger.Log(LogLevel.Fatal, message.AsFunc(), null, EmptyParams); } } public static void Fatal(this ILog logger, string message, params object[] args) { logger.FatalFormat(message, args); } public static void Fatal(this ILog logger, Exception exception, string message, params object[] args) { logger.FatalException(message, exception, args); } public static void FatalFormat(this ILog logger, string message, params object[] args) { if (logger.IsFatalEnabled()) { logger.LogFormat(LogLevel.Fatal, message, args); } } public static void FatalException(this ILog logger, string message, Exception exception, params object[] args) { if (logger.IsFatalEnabled()) { logger.Log(LogLevel.Fatal, message.AsFunc(), exception, args); } } public static void Info(this ILog logger, Func<string> messageFunc) { GuardAgainstNullLogger(logger); logger.Log(LogLevel.Info, WrapLogInternal(messageFunc), null, EmptyParams); } public static void Info(this ILog logger, string message) { if (logger.IsInfoEnabled()) { logger.Log(LogLevel.Info, message.AsFunc(), null, EmptyParams); } } public static void Info(this ILog logger, string message, params object[] args) { logger.InfoFormat(message, args); } public static void Info(this ILog logger, Exception exception, string message, params object[] args) { logger.InfoException(message, exception, args); } public static void InfoFormat(this ILog logger, string message, params object[] args) { if (logger.IsInfoEnabled()) { logger.LogFormat(LogLevel.Info, message, args); } } public static void InfoException(this ILog logger, string message, Exception exception, params object[] args) { if (logger.IsInfoEnabled()) { logger.Log(LogLevel.Info, message.AsFunc(), exception, args); } } public static void Trace(this ILog logger, Func<string> messageFunc) { GuardAgainstNullLogger(logger); logger.Log(LogLevel.Trace, WrapLogInternal(messageFunc), null, EmptyParams); } public static void Trace(this ILog logger, string message) { if (logger.IsTraceEnabled()) { logger.Log(LogLevel.Trace, message.AsFunc(), null, EmptyParams); } } public static void Trace(this ILog logger, string message, params object[] args) { logger.TraceFormat(message, args); } public static void Trace(this ILog logger, Exception exception, string message, params object[] args) { logger.TraceException(message, exception, args); } public static void TraceFormat(this ILog logger, string message, params object[] args) { if (logger.IsTraceEnabled()) { logger.LogFormat(LogLevel.Trace, message, args); } } public static void TraceException(this ILog logger, string message, Exception exception, params object[] args) { if (logger.IsTraceEnabled()) { logger.Log(LogLevel.Trace, message.AsFunc(), exception, args); } } public static void Warn(this ILog logger, Func<string> messageFunc) { GuardAgainstNullLogger(logger); logger.Log(LogLevel.Warn, WrapLogInternal(messageFunc), null, EmptyParams); } public static void Warn(this ILog logger, string message) { if (logger.IsWarnEnabled()) { logger.Log(LogLevel.Warn, message.AsFunc(), null, EmptyParams); } } public static void Warn(this ILog logger, string message, params object[] args) { logger.WarnFormat(message, args); } public static void Warn(this ILog logger, Exception exception, string message, params object[] args) { logger.WarnException(message, exception, args); } public static void WarnFormat(this ILog logger, string message, params object[] args) { if (logger.IsWarnEnabled()) { logger.LogFormat(LogLevel.Warn, message, args); } } public static void WarnException(this ILog logger, string message, Exception exception, params object[] args) { if (logger.IsWarnEnabled()) { logger.Log(LogLevel.Warn, message.AsFunc(), exception, args); } } private static void GuardAgainstNullLogger(ILog logger) { if (logger == null) { throw new ArgumentNullException("logger"); } } private static void LogFormat(this ILog logger, LogLevel logLevel, string message, params object[] args) { logger.Log(logLevel, message.AsFunc(), null, args); } private static Func<T> AsFunc<T>(this T value) where T : class { return value.Return; } private static T Return<T>(this T value) { return value; } internal static Func<string> WrapLogSafeInternal(LoggerExecutionWrapper logger, Func<string> messageFunc) { return delegate { try { return messageFunc(); } catch (Exception exception) { logger.WrappedLogger(LogLevel.Error, () => "Failed to generate log message", exception, EmptyParams); } return null; }; } private static Func<string> WrapLogInternal(Func<string> messageFunc) { return () => messageFunc(); } } public enum LogLevel { Trace, Debug, Info, Warn, Error, Fatal } public static class LogProvider { internal delegate bool IsLoggerAvailable(); internal delegate ILogProvider CreateLogProvider(); internal class NoOpLogger : ILog { internal static readonly NoOpLogger Instance = new NoOpLogger(); public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters) { return false; } } private static readonly Lazy<ILogProvider> ResolvedLogProvider; private static ILogProvider s_currentLogProvider; private static Action<ILogProvider> s_onCurrentLogProviderSet; internal static readonly List<Tuple<IsLoggerAvailable, CreateLogProvider>> LogProviderResolvers; public static bool IsDisabled { get; set; } internal static Action<ILogProvider> OnCurrentLogProviderSet { set { s_onCurrentLogProviderSet = value; RaiseOnCurrentLogProviderSet(); } } internal static ILogProvider CurrentLogProvider => s_currentLogProvider; static LogProvider() { ResolvedLogProvider = new Lazy<ILogProvider>(ForceResolveLogProvider); LogProviderResolvers = new List<Tuple<IsLoggerAvailable, CreateLogProvider>> { new Tuple<IsLoggerAvailable, CreateLogProvider>(SerilogLogProvider.IsLoggerAvailable, () => new SerilogLogProvider()), new Tuple<IsLoggerAvailable, CreateLogProvider>(NLogLogProvider.IsLoggerAvailable, () => new NLogLogProvider()), new Tuple<IsLoggerAvailable, CreateLogProvider>(Log4NetLogProvider.IsLoggerAvailable, () => new Log4NetLogProvider()), new Tuple<IsLoggerAvailable, CreateLogProvider>(LoupeLogProvider.IsLoggerAvailable, () => new LoupeLogProvider()) }; IsDisabled = false; } public static void SetCurrentLogProvider(ILogProvider logProvider) { s_currentLogProvider = logProvider; RaiseOnCurrentLogProviderSet(); } internal static ILog For<T>() { return GetLogger(typeof(T)); } [MethodImpl(MethodImplOptions.NoInlining)] internal static ILog GetCurrentClassLogger() { return GetLogger(new StackFrame(1, needFileInfo: false).GetMethod().DeclaringType); } internal static ILog GetLogger(Type type, string fallbackTypeName = "System.Object") { return GetLogger((type != null) ? type.ToString() : fallbackTypeName); } internal static ILog GetLogger(string name) { ILogProvider logProvider = CurrentLogProvider ?? ResolveLogProvider(); if (logProvider != null) { return new LoggerExecutionWrapper(logProvider.GetLogger(name), () => IsDisabled); } return NoOpLogger.Instance; } internal static IDisposable OpenNestedContext(string message) { ILogProvider logProvider = CurrentLogProvider ?? ResolveLogProvider(); if (logProvider != null) { return logProvider.OpenNestedContext(message); } return new DisposableAction(delegate { }); } internal static IDisposable OpenMappedContext(string key, object value, bool destructure = false) { ILogProvider logProvider = CurrentLogProvider ?? ResolveLogProvider(); if (logProvider != null) { return logProvider.OpenMappedContext(key, value, destructure); } return new DisposableAction(delegate { }); } private static void RaiseOnCurrentLogProviderSet() { if (s_onCurrentLogProviderSet != null) { s_onCurrentLogProviderSet(s_currentLogProvider); } } internal static ILogProvider ResolveLogProvider() { return ResolvedLogProvider.Value; } internal static ILogProvider ForceResolveLogProvider() { try { foreach (Tuple<IsLoggerAvailable, CreateLogProvider> logProviderResolver in LogProviderResolvers) { if (logProviderResolver.Item1()) { return logProviderResolver.Item2(); } } } catch (Exception arg) { Console.WriteLine("Exception occurred resolving a log provider. Logging for this assembly {0} is disabled. {1}", typeof(LogProvider).Assembly.FullName, arg); } return null; } } public delegate bool Logger(LogLevel logLevel, Func<string> messageFunc, Exception exception = null, params object[] formatParameters); internal class LoggerExecutionWrapper : ILog { private interface ICallSiteExtension { bool Log(Logger logger, LogLevel logLevel, Func<string> messageFunc, Exception exception, object[] formatParameters); } private class CallSiteExtension : ICallSiteExtension { bool ICallSiteExtension.Log(Logger logger, LogLevel logLevel, Func<string> messageFunc, Exception exception, object[] formatParameters) { return logger(logLevel, messageFunc, exception, formatParameters); } } internal const string FailedToGenerateLogMessage = "Failed to generate log message"; private readonly ICallSiteExtension _callsiteLogger; private readonly Func<bool> _getIsDisabled; private Func<string> _lastExtensionMethod; internal Logger WrappedLogger { get; } internal LoggerExecutionWrapper(Logger logger, Func<bool> getIsDisabled = null) { WrappedLogger = logger; _callsiteLogger = new CallSiteExtension(); _getIsDisabled = getIsDisabled ?? ((Func<bool>)(() => false)); } public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception = null, params object[] formatParameters) { if (_getIsDisabled()) { return false; } if (messageFunc == null) { return WrappedLogger(logLevel, null, null, LogExtensions.EmptyParams); } Func<string> func = _lastExtensionMethod; if (func == null || !func.Equals(messageFunc)) { func = null; Type declaringType = messageFunc.Method.DeclaringType; if (declaringType == typeof(LogExtensions) || (declaringType != null && declaringType.DeclaringType == typeof(LogExtensions))) { func = messageFunc; } } if (func != null) { _lastExtensionMethod = func; return WrappedLogger(logLevel, LogExtensions.WrapLogSafeInternal(this, messageFunc), exception, formatParameters); } Func<string> messageFunc2 = delegate { try { return messageFunc(); } catch (Exception exception2) { WrappedLogger(LogLevel.Error, () => "Failed to generate log message", exception2); } return null; }; return _callsiteLogger.Log(WrappedLogger, logLevel, messageFunc2, exception, formatParameters); } } } namespace Websocket.Client.Logging.LogProviders { internal class DisposableAction : IDisposable { private readonly Action _onDispose; public DisposableAction(Action onDispose = null) { _onDispose = onDispose; } public void Dispose() { if (_onDispose != null) { _onDispose(); } } } public class LibLogException : Exception { public LibLogException(string message) : base(message) { } public LibLogException(string message, Exception inner) : base(message, inner) { } } internal class Log4NetLogProvider : LogProviderBase { internal class Log4NetLogger { private static object s_levelAll; private static object s_levelDebug; private static object s_levelInfo; private static object s_levelWarn; private static object s_levelError; private static object s_levelFatal; private static Func<object, object, bool> s_isEnabledForDelegate; private static Action<object, object> s_logDelegate; private static Func<object, Type, object, string, Exception, object> s_createLoggingEvent; private static Action<object, string, object> s_loggingEventPropertySetter; private static readonly Lazy<bool> Initialized = new Lazy<bool>(Initialize, LazyThreadSafetyMode.ExecutionAndPublication); private static Exception s_initializeException; private readonly object _logger; internal Log4NetLogger(object logger) { _logger = logger.GetType().GetProperty("Logger").GetValue(logger); } private static bool Initialize() { try { Type type = LogProviderBase.FindType("log4net.Core.Level", "log4net"); if (type == null) { throw new LibLogException("Type log4net.Core.Level was not found."); } List<FieldInfo> source = type.GetFields().ToList(); s_levelAll = source.First((FieldInfo x) => x.Name == "All").GetValue(null); s_levelDebug = source.First((FieldInfo x) => x.Name == "Debug").GetValue(null); s_levelInfo = source.First((FieldInfo x) => x.Name == "Info").GetValue(null); s_levelWarn = source.First((FieldInfo x) => x.Name == "Warn").GetValue(null); s_levelError = source.First((FieldInfo x) => x.Name == "Error").GetValue(null); s_levelFatal = source.First((FieldInfo x) => x.Name == "Fatal").GetValue(null); Type type2 = LogProviderBase.FindType("log4net.Core.ILogger", "log4net"); if (type2 == null) { throw new LibLogException("Type log4net.Core.ILogger, was not found."); } ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); UnaryExpression instanceCast = Expression.Convert(parameterExpression, type2); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object)); UnaryExpression levelCast = Expression.Convert(parameterExpression2, type); s_isEnabledForDelegate = GetIsEnabledFor(type2, type, instanceCast, levelCast, parameterExpression, parameterExpression2); Type loggingEventType = LogProviderBase.FindType("log4net.Core.LoggingEvent", "log4net"); s_createLoggingEvent = GetCreateLoggingEvent(parameterExpression, instanceCast, parameterExpression2, levelCast, loggingEventType); s_logDelegate = GetLogDelegate(type2, loggingEventType, instanceCast, parameterExpression); s_loggingEventPropertySetter = GetLoggingEventPropertySetter(loggingEventType); } catch (Exception ex) { s_initializeException = ex; return false; } return true; } private static Action<object, object> GetLogDelegate(Type loggerType, Type loggingEventType, UnaryExpression instanceCast, ParameterExpression instanceParam) { MethodInfo method = loggerType.GetMethod("Log", loggingEventType); ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "loggingEvent"); UnaryExpression unaryExpression = Expression.Convert(parameterExpression, loggingEventType); return Expression.Lambda<Action<object, object>>(Expression.Call(instanceCast, method, unaryExpression), new ParameterExpression[2] { instanceParam, parameterExpression }).Compile(); } private static Func<object, Type, object, string, Exception, object> GetCreateLoggingEvent(ParameterExpression instanceParam, UnaryExpression instanceCast, ParameterExpression levelParam, UnaryExpression levelCast, Type loggingEventType) { ParameterExpression parameterExpression = Expression.Parameter(typeof(Type)); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string)); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(Exception)); PropertyInfo property = loggingEventType.GetProperty("Repository"); PropertyInfo property2 = loggingEventType.GetProperty("Level"); return Expression.Lambda<Func<object, Type, object, string, Exception, object>>(Expression.New(loggingEventType.GetConstructorPortable(typeof(Type), property.PropertyType, typeof(string), property2.PropertyType, typeof(object), typeof(Exception)), parameterExpression, Expression.Property(instanceCast, "Repository"), Expression.Property(instanceCast, "Name"), levelCast, parameterExpression2, parameterExpression3), new ParameterExpression[5] { instanceParam, parameterExpression, levelParam, parameterExpression2, parameterExpression3 }).Compile(); } private static Func<object, object, bool> GetIsEnabledFor(Type loggerType, Type logEventLevelType, UnaryExpression instanceCast, UnaryExpression levelCast, ParameterExpression instanceParam, ParameterExpression levelParam) { MethodInfo method = loggerType.GetMethod("IsEnabledFor", logEventLevelType); return Expression.Lambda<Func<object, object, bool>>(Expression.Call(instanceCast, method, levelCast), new ParameterExpression[2] { instanceParam, levelParam }).Compile(); } private static Action<object, string, object> GetLoggingEventPropertySetter(Type loggingEventType) { ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "loggingEvent"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string), "key"); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(object), "value"); PropertyInfo property = loggingEventType.GetProperty("Properties"); PropertyInfo property2 = property.PropertyType.GetProperty("Item"); return Expression.Lambda<Action<object, string, object>>(Expression.Assign(Expression.Property(Expression.Property(Expression.Convert(parameterExpression, loggingEventType), property), property2, parameterExpression2), parameterExpression3), new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile(); } public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters) { if (!Initialized.Value) { throw new LibLogException("Unable to log due to problem initializing the log provider. See inner exception for details.", s_initializeException); } if (messageFunc == null) { return IsLogLevelEnable(logLevel); } if (!IsLogLevelEnable(logLevel)) { return false; } IEnumerable<string> patternMatches; string arg = LogMessageFormatter.FormatStructuredMessage(messageFunc(), formatParameters, out patternMatches); Type typeFromHandle = typeof(Log4NetLogger); Type declaringType = messageFunc.Method.DeclaringType; if (declaringType == typeof(LogExtensions) || (declaringType != null && declaringType.DeclaringType == typeof(LogExtensions))) { typeFromHandle = typeof(LogExtensions); } else if (declaringType == typeof(LoggerExecutionWrapper) || (declaringType != null && declaringType.DeclaringType == typeof(LoggerExecutionWrapper))) { typeFromHandle = typeof(LoggerExecutionWrapper); } object arg2 = TranslateLevel(logLevel); object obj = s_createLoggingEvent(_logger, typeFromHandle, arg2, arg, exception); PopulateProperties(obj, patternMatches, formatParameters); s_logDelegate(_logger, obj); return true; } private void PopulateProperties(object loggingEvent, IEnumerable<string> patternMatches, IEnumerable<object> formatParameters) { string[] array = (patternMatches as string[]) ?? patternMatches.ToArray(); if (!array.Any()) { return; } foreach (KeyValuePair<string, object> item in array.Zip(formatParameters, (string key, object value) => new KeyValuePair<string, object>(key, value))) { s_loggingEventPropertySetter(loggingEvent, item.Key, item.Value); } } private bool IsLogLevelEnable(LogLevel logLevel) { object arg = TranslateLevel(logLevel); return s_isEnabledForDelegate(_logger, arg); } private object TranslateLevel(LogLevel logLevel) { return logLevel switch { LogLevel.Trace => s_levelAll, LogLevel.Debug => s_levelDebug, LogLevel.Info => s_levelInfo, LogLevel.Warn => s_levelWarn, LogLevel.Error => s_levelError, LogLevel.Fatal => s_levelFatal, _ => throw new ArgumentOutOfRangeException("logLevel", logLevel, null), }; } } private readonly Func<string, object> _getLoggerByNameDelegate; public static bool ProviderIsAvailableOverride { get; set; } = true; public Log4NetLogProvider() { if (!IsLoggerAvailable()) { throw new LibLogException("log4net.LogManager not found"); } _getLoggerByNameDelegate = GetGetLoggerMethodCall(); } public override Logger GetLogger(string name) { return new Log4NetLogger(_getLoggerByNameDelegate(name)).Log; } internal static bool IsLoggerAvailable() { if (ProviderIsAvailableOverride) { return GetLogManagerType() != null; } return false; } protected override OpenNdc GetOpenNdcMethod() { PropertyInfo property = LogProviderBase.FindType("log4net.LogicalThreadContext", "log4net").GetProperty("Stacks"); PropertyInfo property2 = property.PropertyType.GetProperty("Item"); MethodInfo method = property2.PropertyType.GetMethod("Push"); ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "message"); return Expression.Lambda<OpenNdc>(Expression.Call(Expression.Property(Expression.Property(null, property), property2, Expression.Constant("NDC")), method, parameterExpression), new ParameterExpression[1] { parameterExpression }).Compile(); } protected override OpenMdc GetOpenMdcMethod() { PropertyInfo property = LogProviderBase.FindType("log4net.LogicalThreadContext", "log4net").GetProperty("Properties"); Type propertyType = property.PropertyType; PropertyInfo property2 = propertyType.GetProperty("Item"); MethodInfo method = propertyType.GetMethod("Remove"); ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "key"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string), "value"); MemberExpression instance = Expression.Property(null, property); BinaryExpression body = Expression.Assign(Expression.Property(instance, property2, parameterExpression), parameterExpression2); MethodCallExpression body2 = Expression.Call(instance, method, parameterExpression); Action<string, string> set = Expression.Lambda<Action<string, string>>(body, new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); Action<string> remove = Expression.Lambda<Action<string>>(body2, new ParameterExpression[1] { parameterExpression }).Compile(); return delegate(string key, object value, bool _) { set(key, value.ToString()); return new DisposableAction(delegate { remove(key); }); }; } private static Type GetLogManagerType() { return LogProviderBase.FindType("log4net.LogManager", "log4net"); } private static Func<string, object> GetGetLoggerMethodCall() { Type logManagerType = GetLogManagerType(); Assembly log4netAssembly = Assembly.GetAssembly(logManagerType); MethodInfo method = logManagerType.GetMethod("GetLogger", typeof(Assembly), typeof(string)); ParameterExpression parameterExpression = Expression.Parameter(typeof(Assembly), "repositoryAssembly"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string), "name"); MethodCallExpression body = Expression.Call(null, method, parameterExpression, parameterExpression2); Func<Assembly, string, object> lambda = Expression.Lambda<Func<Assembly, string, object>>(body, new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); return (string name) => lambda(log4netAssembly, name); } } internal static class LogMessageFormatter { private static readonly Regex Pattern = new Regex("(?<!{){@?(?<arg>[^ :{}]+)(?<format>:[^}]+)?}", RegexOptions.Compiled); public static Func<string> SimulateStructuredLogging(Func<string> messageBuilder, object[] formatParameters) { if (formatParameters == null || formatParameters.Length == 0) { return messageBuilder; } IEnumerable<string> patternMatches; return () => FormatStructuredMessage(messageBuilder(), formatParameters, out patternMatches); } private static string ReplaceFirst(string text, string search, string replace) { int num = text.IndexOf(search, StringComparison.Ordinal); if (num < 0) { return text; } return text.Substring(0, num) + replace + text.Substring(num + search.Length); } public static string FormatStructuredMessage(string targetMessage, object[] formatParameters, out IEnumerable<string> patternMatches) { if (formatParameters == null || formatParameters.Length == 0) { patternMatches = Enumerable.Empty<string>(); return targetMessage; } List<string> list = null; foreach (Match item in Pattern.Matches(targetMessage)) { string value = item.Groups["arg"].Value; if (!int.TryParse(value, out var _)) { list = list ?? new List<string>(formatParameters.Length); int num = list.IndexOf(value); if (num == -1) { num = list.Count; list.Add(value); } targetMessage = ReplaceFirst(targetMessage, item.Value, "{" + num + item.Groups["format"].Value + "}"); } } IEnumerable<string> enumerable = list; patternMatches = enumerable ?? Enumerable.Empty<string>(); try { return string.Format(CultureInfo.InvariantCulture, targetMessage, formatParameters); } catch (FormatException innerException) { throw new FormatException("The input string '" + targetMessage + "' could not be formatted using string.Format", innerException); } } } internal abstract class LogProviderBase : ILogProvider { protected delegate IDisposable OpenNdc(string message); protected delegate IDisposable OpenMdc(string key, object value, bool destructure); private static readonly IDisposable NoopDisposableInstance = new DisposableAction(); private readonly Lazy<OpenMdc> _lazyOpenMdcMethod; protected const string ErrorInitializingProvider = "Unable to log due to problem initializing the log provider. See inner exception for details."; private readonly Lazy<OpenNdc> _lazyOpenNdcMethod; protected LogProviderBase() { _lazyOpenNdcMethod = new Lazy<OpenNdc>(GetOpenNdcMethod); _lazyOpenMdcMethod = new Lazy<OpenMdc>(GetOpenMdcMethod); } public abstract Logger GetLogger(string name); public IDisposable OpenNestedContext(string message) { return _lazyOpenNdcMethod.Value(message); } public IDisposable OpenMappedContext(string key, object value, bool destructure = false) { return _lazyOpenMdcMethod.Value(key, value, destructure); } protected virtual OpenNdc GetOpenNdcMethod() { return (string _) => NoopDisposableInstance; } protected virtual OpenMdc GetOpenMdcMethod() { return (string _, object __, bool ___) => NoopDisposableInstance; } protected static Type FindType(string typeName, string assemblyName) { return FindType(typeName, new string[1] { assemblyName }); } protected static Type FindType(string typeName, IReadOnlyList<string> assemblyNames) { return assemblyNames.Select((string assemblyName) => Type.GetType(typeName + ", " + assemblyName)).FirstOrDefault((Type type) => type != null) ?? Type.GetType(typeName); } } internal class LoupeLogProvider : LogProviderBase { internal delegate void WriteDelegate(int severity, string logSystem, int skipFrames, Exception exception, bool attributeToException, int writeMode, string detailsXml, string category, string caption, string description, params object[] args); internal class LoupeLogger { private const string LogSystem = "LibLog"; private readonly string _category; private readonly WriteDelegate _logWriteDelegate; private readonly int _skipLevel; internal LoupeLogger(string category, WriteDelegate logWriteDelegate) { _category = category; _logWriteDelegate = logWriteDelegate; _skipLevel = 1; } public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters) { if (messageFunc == null) { return true; } messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters); _logWriteDelegate(ToLogMessageSeverity(logLevel), "LibLog", _skipLevel, exception, true, 0, null, _category, null, messageFunc()); return true; } private static int ToLogMessageSeverity(LogLevel logLevel) { return logLevel switch { LogLevel.Trace => TraceEventTypeValues.Verbose, LogLevel.Debug => TraceEventTypeValues.Verbose, LogLevel.Info => TraceEventTypeValues.Information, LogLevel.Warn => TraceEventTypeValues.Warning, LogLevel.Error => TraceEventTypeValues.Error, LogLevel.Fatal => TraceEventTypeValues.Critical, _ => throw new ArgumentOutOfRangeException("logLevel"), }; } } private readonly WriteDelegate _logWriteDelegate; private const string LoupeAgentNetCoreDll = "Loupe.Agent.NETCore"; private const string LoupeAgentNetFrameworkDll = "Gibraltar.Agent"; public static bool ProviderIsAvailableOverride { get; set; } = true; public LoupeLogProvider() { if (!IsLoggerAvailable()) { throw new LibLogException("Gibraltar.Agent.Log (Loupe) not found"); } _logWriteDelegate = GetLogWriteDelegate(); } public override Logger GetLogger(string name) { return new LoupeLogger(name, _logWriteDelegate).Log; } public static bool IsLoggerAvailable() { if (ProviderIsAvailableOverride) { return GetLogManagerType() != null; } return false; } private static Type GetTypeFromCoreOrFrameworkDll(string typeName) { return LogProviderBase.FindType(typeName, new string[2] { "Loupe.Agent.NETCore", "Gibraltar.Agent" }); } private static Type GetLogManagerType() { return GetTypeFromCoreOrFrameworkDll("Gibraltar.Agent.Log"); } private static WriteDelegate GetLogWriteDelegate() { Type logManagerType = GetLogManagerType(); Type typeFromCoreOrFrameworkDll = GetTypeFromCoreOrFrameworkDll("Gibraltar.Agent.LogMessageSeverity"); Type typeFromCoreOrFrameworkDll2 = GetTypeFromCoreOrFrameworkDll("Gibraltar.Agent.LogWriteMode"); return (WriteDelegate)logManagerType.GetMethod("Write", typeFromCoreOrFrameworkDll, typeof(string), typeof(int), typeof(Exception), typeof(bool), typeFromCoreOrFrameworkDll2, typeof(string), typeof(string), typeof(string), typeof(string), typeof(object[])).CreateDelegate(typeof(WriteDelegate)); } } internal class NLogLogProvider : LogProviderBase { internal class NLogLogger { private delegate string LoggerNameDelegate(object logger); private delegate void LogEventDelegate(object logger, Type wrapperType, object logEvent); private delegate bool IsEnabledDelegate(object logger); private delegate void LogDelegate(object logger, string message); private delegate void LogExceptionDelegate(object logger, string message, Exception exception); private static Func<string, object, string, object[], Exception, object> s_logEventInfoFact; private static object s_levelTrace; private static object s_levelDebug; private static object s_levelInfo; private static object s_levelWarn; private static object s_levelError; private static object s_levelFatal; private static bool s_structuredLoggingEnabled; private static readonly Lazy<bool> Initialized = new Lazy<bool>(Initialize); private static Exception s_initializeException; private static LoggerNameDelegate s_loggerNameDelegate; private static LogEventDelegate s_logEventDelegate; private static IsEnabledDelegate s_isTraceEnabledDelegate; private static IsEnabledDelegate s_isDebugEnabledDelegate; private static IsEnabledDelegate s_isInfoEnabledDelegate; private static IsEnabledDelegate s_isWarnEnabledDelegate; private static IsEnabledDelegate s_isErrorEnabledDelegate; private static IsEnabledDelegate s_isFatalEnabledDelegate; private static LogDelegate s_traceDelegate; private static LogDelegate s_debugDelegate; private static LogDelegate s_infoDelegate; private static LogDelegate s_warnDelegate; private static LogDelegate s_errorDelegate; private static LogDelegate s_fatalDelegate; private static LogExceptionDelegate s_traceExceptionDelegate; private static LogExceptionDelegate s_debugExceptionDelegate; private static LogExceptionDelegate s_infoExceptionDelegate; private static LogExceptionDelegate s_warnExceptionDelegate; private static LogExceptionDelegate s_errorExceptionDelegate; private static LogExceptionDelegate s_fatalExceptionDelegate; private readonly object _logger; internal NLogLogger(object logger) { _logger = logger; } private static bool Initialize() { try { Type type = LogProviderBase.FindType("NLog.LogLevel", "NLog"); if (type == null) { throw new LibLogException("Type NLog.LogLevel was not found."); } List<FieldInfo> source = type.GetFields().ToList(); s_levelTrace = source.First((FieldInfo x) => x.Name == "Trace").GetValue(null); s_levelDebug = source.First((FieldInfo x) => x.Name == "Debug").GetValue(null); s_levelInfo = source.First((FieldInfo x) => x.Name == "Info").GetValue(null); s_levelWarn = source.First((FieldInfo x) => x.Name == "Warn").GetValue(null); s_levelError = source.First((FieldInfo x) => x.Name == "Error").GetValue(null); s_levelFatal = source.First((FieldInfo x) => x.Name == "Fatal").GetValue(null); Type type2 = LogProviderBase.FindType("NLog.LogEventInfo", "NLog"); if (type2 == null) { throw new LibLogException("Type NLog.LogEventInfo was not found."); } ConstructorInfo constructorPortable = type2.GetConstructorPortable(type, typeof(string), typeof(IFormatProvider), typeof(string), typeof(object[]), typeof(Exception)); ParameterExpression parameterExpression = Expression.Parameter(typeof(string)); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object)); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(string)); ParameterExpression parameterExpression4 = Expression.Parameter(typeof(object[])); ParameterExpression parameterExpression5 = Expression.Parameter(typeof(Exception)); UnaryExpression unaryExpression = Expression.Convert(parameterExpression2, type); s_logEventInfoFact = Expression.Lambda<Func<string, object, string, object[], Exception, object>>(Expression.New(constructorPortable, unaryExpression, parameterExpression, Expression.Constant(null, typeof(IFormatProvider)), parameterExpression3, parameterExpression4, parameterExpression5), new ParameterExpression[5] { parameterExpression, parameterExpression2, parameterExpression3, parameterExpression4, parameterExpression5 }).Compile(); Type loggerType = LogProviderBase.FindType("NLog.Logger", "NLog"); s_loggerNameDelegate = GetLoggerNameDelegate(loggerType); s_logEventDelegate = GetLogEventDelegate(loggerType, type2); s_isTraceEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsTraceEnabled"); s_isDebugEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsDebugEnabled"); s_isInfoEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsInfoEnabled"); s_isWarnEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsWarnEnabled"); s_isErrorEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsErrorEnabled"); s_isFatalEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsFatalEnabled"); s_traceDelegate = GetLogDelegate(loggerType, "Trace"); s_debugDelegate = GetLogDelegate(loggerType, "Debug"); s_infoDelegate = GetLogDelegate(loggerType, "Info"); s_warnDelegate = GetLogDelegate(loggerType, "Warn"); s_errorDelegate = GetLogDelegate(loggerType, "Error"); s_fatalDelegate = GetLogDelegate(loggerType, "Fatal"); s_traceExceptionDelegate = GetLogExceptionDelegate(loggerType, "TraceException"); s_debugExceptionDelegate = GetLogExceptionDelegate(loggerType, "DebugException"); s_infoExceptionDelegate = GetLogExceptionDelegate(loggerType, "InfoException"); s_warnExceptionDelegate = GetLogExceptionDelegate(loggerType, "WarnException"); s_errorExceptionDelegate = GetLogExceptionDelegate(loggerType, "ErrorException"); s_fatalExceptionDelegate = GetLogExceptionDelegate(loggerType, "FatalException"); s_structuredLoggingEnabled = IsStructuredLoggingEnabled(); } catch (Exception ex) { s_initializeException = ex; return false; } return true; } private static IsEnabledDelegate GetIsEnabledDelegate(Type loggerType, string propertyName) { PropertyInfo property = loggerType.GetProperty(propertyName); ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); return Expression.Lambda<IsEnabledDelegate>(Expression.Property(Expression.Convert(parameterExpression, loggerType), property), new ParameterExpression[1] { parameterExpression }).Compile(); } private static LoggerNameDelegate GetLoggerNameDelegate(Type loggerType) { PropertyInfo property = loggerType.GetProperty("Name"); ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); return Expression.Lambda<LoggerNameDelegate>(Expression.Property(Expression.Convert(parameterExpression, loggerType), property), new ParameterExpression[1] { parameterExpression }).Compile(); } private static LogDelegate GetLogDelegate(Type loggerType, string name) { MethodInfo method = loggerType.GetMethod(name, new Type[1] { typeof(string) }); ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); UnaryExpression instance = Expression.Convert(parameterExpression, loggerType); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string)); return Expression.Lambda<LogDelegate>(Expression.Call(instance, method, parameterExpression2), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); } private static LogEventDelegate GetLogEventDelegate(Type loggerType, Type logEventType) { MethodInfo method = loggerType.GetMethod("Log", new Type[2] { typeof(Type), logEventType }); ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); UnaryExpression instance = Expression.Convert(parameterExpression, loggerType); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(Type)); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(object)); UnaryExpression arg = Expression.Convert(parameterExpression3, logEventType); return Expression.Lambda<LogEventDelegate>(Expression.Call(instance, method, parameterExpression2, arg), new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile(); } private static LogExceptionDelegate GetLogExceptionDelegate(Type loggerType, string name) { MethodInfo method = loggerType.GetMethod(name, new Type[2] { typeof(string), typeof(Exception) }); ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); UnaryExpression instance = Expression.Convert(parameterExpression, loggerType); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string)); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(Exception)); return Expression.Lambda<LogExceptionDelegate>(Expression.Call(instance, method, parameterExpression2, parameterExpression3), new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile(); } public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters) { if (!Initialized.Value) { throw new LibLogException("Unable to log due to problem initializing the log provider. See inner exception for details.", s_initializeException); } if (messageFunc == null) { return IsLogLevelEnable(logLevel); } if (s_logEventInfoFact != null) { if (IsLogLevelEnable(logLevel)) { string text = messageFunc(); if (!s_structuredLoggingEnabled) { text = LogMessageFormatter.FormatStructuredMessage(text, formatParameters, out var _); formatParameters = null; } Type typeFromHandle = typeof(NLogLogger); Type declaringType = messageFunc.Method.DeclaringType; if (declaringType == typeof(LogExtensions) || (declaringType != null && declaringType.DeclaringType == typeof(LogExtensions))) { typeFromHandle = typeof(LogExtensions); } else if (declaringType == typeof(LoggerExecutionWrapper) || (declaringType != null && declaringType.DeclaringType == typeof(LoggerExecutionWrapper))) { typeFromHandle = typeof(LoggerExecutionWrapper); } object arg = TranslateLevel(logLevel); object logEvent = s_logEventInfoFact(s_loggerNameDelegate(_logger), arg, text, formatParameters, exception); s_logEventDelegate(_logger, typeFromHandle, logEvent); return true; } return false; } messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters); if (exception != null) { return LogException(logLevel, messageFunc, exception); } switch (logLevel) { case LogLevel.Debug: if (s_isDebugEnabledDelegate(_logger)) { s_debugDelegate(_logger, messageFunc()); return true; } break; case LogLevel.Info: if (s_isInfoEnabledDelegate(_logger)) { s_infoDelegate(_logger, messageFunc()); return true; } break; case LogLevel.Warn: if (s_isWarnEnabledDelegate(_logger)) { s_warnDelegate(_logger, messageFunc()); return true; } break; case LogLevel.Error: if (s_isErrorEnabledDelegate(_logger)) { s_errorDelegate(_logger, messageFunc()); return true; } break; case LogLevel.Fatal: if (s_isFatalEnabledDelegate(_logger)) { s_fatalDelegate(_logger, messageFunc()); return true; } break; default: if (s_isTraceEnabledDelegate(_logger)) { s_traceDelegate(_logger, messageFunc()); return true; } break; } return false; } private bool LogException(LogLevel logLevel, Func<string> messageFunc, Exception exception) { switch (logLevel) { case LogLevel.Debug: if (s_isDebugEnabledDelegate(_logger)) { s_debugExceptionDelegate(_logger, messageFunc(), exception); return true; } break; case LogLevel.Info: if (s_isInfoEnabledDelegate(_logger)) { s_infoExceptionDelegate(_logger, messageFunc(), exception); return true; } break; case LogLevel.Warn: if (s_isWarnEnabledDelegate(_logger)) { s_warnExceptionDelegate(_logger, messageFunc(), exception); return true; } break; case LogLevel.Error: if (s_isErrorEnabledDelegate(_logger)) { s_errorExceptionDelegate(_logger, messageFunc(), exception); return true; } break; case LogLevel.Fatal: if (s_isFatalEnabledDelegate(_logger)) { s_fatalExceptionDelegate(_logger, messageFunc(), exception); return true; } break; default: if (s_isTraceEnabledDelegate(_logger)) { s_traceExceptionDelegate(_logger, messageFunc(), exception); return true; } break; } return false; } private bool IsLogLevelEnable(LogLevel logLevel) { return logLevel switch { LogLevel.Debug => s_isDebugEnabledDelegate(_logger), LogLevel.Info => s_isInfoEnabledDelegate(_logger), LogLevel.Warn => s_isWarnEnabledDelegate(_logger), LogLevel.Error => s_isErrorEnabledDelegate(_logger), LogLevel.Fatal => s_isFatalEnabledDelegate(_logger), _ => s_isTraceEnabledDelegate(_logger), }; } private object TranslateLevel(LogLevel logLevel) { return logLevel switch { LogLevel.Trace => s_levelTrace, LogLevel.Debug => s_levelDebug, LogLevel.Info => s_levelInfo, LogLevel.Warn => s_levelWarn, LogLevel.Error => s_levelError, LogLevel.Fatal => s_levelFatal, _ => throw new ArgumentOutOfRangeException("logLevel", logLevel, null), }; } private static bool IsStructuredLoggingEnabled() { Type type = LogProviderBase.FindType("NLog.Config.ConfigurationItemFactory", "NLog"); if (type != null) { PropertyInfo property = type.GetProperty("ParseMessageTemplates"); if (property != null) { PropertyInfo property2 = type.GetProperty("Default"); if (property2 != null) { object value = property2.GetValue(null, null); if (value != null && property.GetValue(value, null) as bool? != false) { return true; } } } } return false; } } private readonly Func<string, object> _getLoggerByNameDelegate; public static bool ProviderIsAvailableOverride { get; set; } public NLogLogProvider() { if (!IsLoggerAvailable()) { throw new LibLogException("NLog.LogManager not found"); } _getLoggerByNameDelegate = GetGetLoggerMethodCall(); } static NLogLogProvider() { ProviderIsAvailableOverride = true; } public override Logger GetLogger(string name) { return new NLogLogger(_getLoggerByNameDelegate(name)).Log; } public static bool IsLoggerAvailable() { if (ProviderIsAvailableOverride) { return GetLogManagerType() != null; } return false; } protected override OpenNdc GetOpenNdcMethod() { ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "message"); Type type = LogProviderBase.FindType("NLog.NestedDiagnosticsLogicalContext", "NLog"); if (type != null) { MethodInfo method = type.GetMethod("PushObject", typeof(object)); if (method != null) { return Expression.Lambda<OpenNdc>(Expression.Call(null, method, parameterExpression), new ParameterExpression[1] { parameterExpression }).Compile(); } } MethodInfo method2 = LogProviderBase.FindType("NLog.NestedDiagnosticsContext", "NLog").GetMethod("Push", typeof(string)); return Expression.Lambda<OpenNdc>(Expression.Call(null, method2, parameterExpression), new ParameterExpression[1] { parameterExpression }).Compile(); } protected override OpenMdc GetOpenMdcMethod() { ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "key"); Type type = LogProviderBase.FindType("NLog.NestedDiagnosticsLogicalContext", "NLog"); if (type != null && type.GetMethod("PushObject", typeof(object)) != null) { Type type2 = LogProviderBase.FindType("NLog.MappedDiagnosticsLogicalContext", "NLog"); if (type2 != null) { MethodInfo method = type2.GetMethod("SetScoped", typeof(string), typeof(object)); if (method != null) { ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value"); MethodCallExpression body = Expression.Call(null, method, parameterExpression, parameterExpression2); Func<string, object, IDisposable> setMethodLambda = Expression.Lambda<Func<string, object, IDisposable>>(body, new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); return (string key, object value, bool _) => setMethodLambda(key, value); } } } Type type3 = LogProviderBase.FindType("NLog.MappedDiagnosticsContext", "NLog"); MethodInfo method2 = type3.GetMethod("Set", typeof(string), typeof(string)); MethodInfo method3 = type3.GetMethod("Remove", typeof(string)); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(string), "value"); MethodCallExpression body2 = Expression.Call(null, method2, parameterExpression, parameterExpression3); MethodCallExpression body3 = Expression.Call(null, method3, parameterExpression); Action<string, string> set = Expression.Lambda<Action<string, string>>(body2, new ParameterExpression[2] { parameterExpression, parameterExpression3 }).Compile(); Action<string> remove = Expression.Lambda<Action<string>>(body3, new ParameterExpression[1] { parameterExpression }).Compile(); return delegate(string key, object value, bool _) { set(key, value.ToString()); return new DisposableAction(delegate { remove(key); }); }; } private static Type GetLogManagerType() { return LogProviderBase.FindType("NLog.LogManager", "NLog"); } private static Func<string, object> GetGetLoggerMethodCall() { MethodInfo method = GetLogManagerType().GetMethod("GetLogger", typeof(string)); ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "name"); return Expression.Lambda<Func<string, object>>(Expression.Call(null, method, parameterExpression), new ParameterExpression[1] { parameterExpression }).Compile(); } } internal class SerilogLogProvider : LogProviderBase { internal class SerilogLogger { private static object s_debugLevel; private static object s_errorLevel; private static object s_fatalLevel; private static object s_informationLevel; private static object s_verboseLevel; private static object s_warningLevel; private static Func<object, object, bool> s_isEnabled; private static Action<object, object, string, object[]> s_write; private static Action<object, object, Exception, string, object[]> s_writeException; private static readonly Lazy<bool> Initialized = new Lazy<bool>(Initialize); private static Exception s_initializeException; private readonly object _logger; internal SerilogLogger(object logger) { _logger = logger; } private static bool Initialize() { try { Type type = LogProviderBase.FindType("Serilog.Events.LogEventLevel", "Serilog"); if (type == null) { throw new LibLogException("Type Serilog.Events.LogEventLevel was not found."); } s_debugLevel = Enum.Parse(type, "Debug", ignoreCase: false); s_errorLevel = Enum.Parse(type, "Error", ignoreCase: false); s_fatalLevel = Enum.Parse(type, "Fatal", ignoreCase: false); s_informationLevel = Enum.Parse(type, "Information", ignoreCase: false); s_verboseLevel = Enum.Parse(type, "Verbose", ignoreCase: false); s_warningLevel = Enum.Parse(type, "Warning", ignoreCase: false); Type type2 = LogProviderBase.FindType("Serilog.ILogger", "Serilog"); if (type2 == null) { throw new LibLogException("Type Serilog.ILogger was not found."); } MethodInfo method = type2.GetMethod("IsEnabled", type); ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); UnaryExpression instance = Expression.Convert(parameterExpression, type2); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object)); UnaryExpression unaryExpression = Expression.Convert(parameterExpression2, type); s_isEnabled = Expression.Lambda<Func<object, object, bool>>(Expression.Call(instance, method, unaryExpression), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); MethodInfo method2 = type2.GetMethod("Write", type, typeof(string), typeof(object[])); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(string)); ParameterExpression parameterExpression4 = Expression.Parameter(typeof(object[])); s_write = Expression.Lambda<Action<object, object, string, object[]>>(Expression.Call(instance, method2, unaryExpression, parameterExpression3, parameterExpression4), new ParameterExpression[4] { parameterExpression, parameterExpression2, parameterExpression3, parameterExpression4 }).Compile(); MethodInfo method3 = type2.GetMethod("Write", type, typeof(Exception), typeof(string), typeof(object[])); ParameterExpression parameterExpression5 = Expression.Parameter(typeof(Exception)); s_writeException = Expression.Lambda<Action<object, object, Exception, string, object[]>>(Expression.Call(instance, method3, unaryExpression, parameterExpression5, parameterExpression3, parameterExpression4), new ParameterExpression[5] { parameterExpression, parameterExpression2, parameterExpression5, parameterExpression3, parameterExpression4 }).Compile(); } catch (Exception ex) { s_initializeException = ex; return false; } return true; } public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters) { if (!Initialized.Value) { throw new LibLogException("Unable to log due to problem initializing the log provider. See inner exception for details.", s_initializeException); } object obj = TranslateLevel(logLevel); if (messageFunc == null) { return s_isEnabled(_logger, obj); } if (!s_isEnabled(_logger, obj)) { return false; } if (exception != null) { LogException(obj, messageFunc, exception, formatParameters); } else { LogMessage(obj, messageFunc, formatParameters); } return true; } private void LogMessage(object translatedLevel, Func<string> messageFunc, object[] formatParameters) { s_write(_logger, translatedLevel, messageFunc(), formatParameters); } private void LogException(object logLevel, Func<string> messageFunc, Exception exception, object[] formatParams) { s_writeException(_logger, logLevel, exception, messageFunc(), formatParams); } private static object TranslateLevel(LogLevel logLevel) { return logLevel switch { LogLevel.Fatal => s_fatalLevel, LogLevel.Error => s_errorLevel, LogLevel.Warn => s_warningLevel, LogLevel.Info => s_informationLevel, LogLevel.Trace => s_verboseLevel, _ => s_debugLevel, }; } } private readonly Func<string, object> _getLoggerByNameDelegate; private static Func<string, object, bool, IDisposable> s_pushProperty; public static bool ProviderIsAvailableOverride { get; set; } = true; public SerilogLogProvider() { if (!IsLoggerAvailable()) { throw new LibLogException("Serilog.Log not found"); } _getLoggerByNameDelegate = GetForContextMethodCall(); s_pushProperty = GetPushProperty(); } public override Logger GetLogger(string name) { return new SerilogLogger(_getLoggerByNameDelegate(name)).Log; } internal static bool IsLoggerAvailable() { if (ProviderIsAvailableOverride) { return GetLogManagerType() != null; } return false; } protected override OpenNdc GetOpenNdcMethod() { return (string message) => s_pushProperty("NDC", message, arg3: false); } protected override OpenMdc GetOpenMdcMethod() { return (string key, object value, bool destructure) => s_pushProperty(key, value, destructure); } private static Func<string, object, bool, IDisposable> GetPushProperty() { MethodInfo method = LogProviderBase.FindType("Serilog.Context.LogContext", new string[2] { "Serilog", "Serilog.FullNetFx" }).GetMethod("PushProperty", typeof(string), typeof(object), typeof(bool)); ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "name"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value"); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(bool), "destructureObjects"); MethodCallExpression body = Expression.Call(null, method, parameterExpression, parameterExpression2, parameterExpression3); Func<string, object, bool, IDisposable> pushProperty = Expression.Lambda<Func<string, object, bool, IDisposable>>(body, new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile(); return (string key, object value, bool destructure) => pushProperty(key, value, destructure); } private static Type GetLogManagerType() { return LogProviderBase.FindType("Serilog.Log", "Serilog"); } private static Func<string, object> GetForContextMethodCall() { MethodInfo method = GetLogManagerType().GetMethod("ForContext", typeof(string), typeof(object), typeof(bool)); ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "propertyName"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value"); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(bool), "destructureObjects"); MethodCallExpression body = Expression.Call(null, method, new Expression[3] { parameterExpression, parameterExpression2, parameterExpression3 }); Func<string, object, bool, object> func = Expression.Lambda<Func<string, object, bool, object>>(body, new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile(); return (string name) => func("SourceContext", name, arg3: false); } } internal static class TraceEventTypeValues { internal static readonly Type Type; internal static readonly int Verbose; internal static readonly int Information; internal static readonly int Warning; internal static readonly int Error; internal static readonly int Critical; static TraceEventTypeValues() { Type = typeof(Uri).Assembly.GetType("System.Diagnostics.TraceEventType"); if (!(Type == null)) { Verbose = (int)Enum.Parse(Type, "Verbose", ignoreCase: false); Information = (int)Enum.Parse(Type, "Information", ignoreCase: false); Warning = (int)Enum.Parse(Type, "Warning", ignoreCase: false); Error = (int)Enum.Parse(Type, "Error", ignoreCase: false); Critical = (int)Enum.Parse(Type, "Critical", ignoreCase: false); } } } internal static class TypeExtensions { internal static ConstructorInfo GetConstructorPortable(this Type type, params Type[] types) { return type.GetConstructor(types); } internal static MethodInfo GetMethod(this Type type, string name, params Type[] types) { return type.GetMethod(name, types); } } } namespace Websocket.Client.Validations { internal static class Validations { public static void ValidateInput(string value, string name) { if (string.IsNullOrEmpty(value)) { throw new WebsocketBadInputException("Input string parameter '" + name + "' is null or empty. Please correct it."); } } public static void ValidateInput<T>(T value, string name) { if (object.Equals(value, default(T))) { throw new WebsocketBadInputException("Input parameter '" + name + "' is null. Please correct it."); } } public static void ValidateInputCollection<T>(IEnumerable<T> collection, string name) { ValidateInput(collection, name); if (!collection.Any()) { throw new WebsocketBadInputException("Input collection '" + name + "' is empty. Please correct it."); } } public static void ValidateInput(int value, string name, int minValue = int.MinValue, int maxValue = int.MaxValue) { if (value < minValue) { throw new WebsocketBadInputException($"Input parameter '{name}' is lower than {minValue}. Please correct it."); } if (value > maxValue) { throw new WebsocketBadInputException($"Input parameter '{name}' is higher than {maxValue}. Please correct it."); } } public static void ValidateInput(long value, string name, long minValue = long.MinValue, long maxValue = long.MaxValue) { if (value < minValue) { throw new WebsocketBadInputException($"Input parameter '{name}' is lower than {minValue}. Please correct it."); } if (value > maxValue) { throw new WebsocketBadInputException($"Input parameter '{name}' is higher than {maxValue}. Please correct it."); } } public static void ValidateInput(double value, string name, double minValue = double.MinValue, double maxValue = double.MaxValue) { if (value < minValue) { throw new WebsocketBadInputException($"Input parameter '{name}' is lower than {minValue}. Please correct it."); } if (value > maxValue) { throw new WebsocketBadInputException($"Input parameter '{name}' is higher than {maxValue}. Please correct it."); } } } } namespace Websocket.Client.Threading { public class WebsocketAsyncLock { private class Releaser : IDisposable { private readonly SemaphoreSlim _semaphore; public Releaser(SemaphoreSlim semaphore) { _semaphore = semaphore; } public void Dispose() { _semaphore.Release(); } } private readonly Task<IDisposable> _releaserTask; private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); private readonly IDisposable _releaser; public WebsocketAsyncLock() { _releaser = new Releaser(_semaphore); _releaserTask = Task.FromResult(_releaser); } public IDisposable Lock() { _semaphore.Wait(); return _releaser; } public Task<IDisposable> LockAsync() { Task task = _semaphore.WaitAsync(); if (!task.IsCompleted) { return task.ContinueWith((Task _, object? releaser) => (IDisposable)releaser, _releaser, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); } return _releaserTask; } } } namespace Websocket.Client.Models { public class ReconnectionInfo { public ReconnectionType Type { get; } public ReconnectionInfo(ReconnectionType type) { Type = type; } public static ReconnectionInfo Create(ReconnectionType type) { return new ReconnectionInfo(type); } } } namespace Websocket.Client.Exceptions { public class WebsocketBadInputException : WebsocketException { public WebsocketBadInputException() { } public WebsocketBadInputException(string message) : base(message) { } public WebsocketBadInputException(string message, Exception innerException) : base(message, innerException) { } } public class WebsocketException : Exception { public WebsocketException() { } public WebsocketException(string message) : base(message) { } public WebsocketException(string message, Exception innerException) : base(message, innerException) { } } }